EPUB export + a bugfix
git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@56 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
parent
ce61f7bc3b
commit
7644cf2eba
14 changed files with 122 additions and 81 deletions
|
@ -1,7 +1,7 @@
|
|||
Writer2LaTeX version 1.1.1 (development release)
|
||||
Writer2LaTeX version 1.1.2 (development release)
|
||||
================================================
|
||||
|
||||
This is the distribution of Writer2LaTeX version 1.1.1
|
||||
This is the distribution of Writer2LaTeX version 1.1.2
|
||||
|
||||
Latest version can be found at the web site
|
||||
http://writer2latex.sourceforge.net
|
||||
|
@ -14,5 +14,5 @@ Bugs and feature requests should be reported to
|
|||
henrikjust (at) openoffice.org
|
||||
|
||||
|
||||
September 2009
|
||||
April 2010
|
||||
Henrik Just
|
||||
|
|
|
@ -2,6 +2,8 @@ Changelog for Writer2LaTeX version 1.0 -> 1.2
|
|||
|
||||
---------- version 1.1.2 ----------
|
||||
|
||||
[w2x] Bugfix: Corrected problem with relative links (this affected package format only)
|
||||
|
||||
[w2x] Added EPUB export
|
||||
|
||||
[all] API change: The interface ConverterResult supports an additional method
|
||||
|
|
Binary file not shown.
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.2 (2010-03-29)
|
||||
* Version 1.2 (2010-03-31)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -33,7 +33,7 @@ public class ConverterFactory {
|
|||
|
||||
// Version information
|
||||
private static final String VERSION = "1.1.2";
|
||||
private static final String DATE = "2010-03-29";
|
||||
private static final String DATE = "2010-03-31";
|
||||
|
||||
/** Return the Writer2LaTeX version in the form
|
||||
* (major version).(minor version).(patch level)<br/>
|
||||
|
|
|
@ -38,11 +38,11 @@ import org.w3c.dom.Element;
|
|||
import writer2latex.xmerge.NewDOMDocument;
|
||||
|
||||
/** This class creates the required META-INF/container.xml file for an EPUB package
|
||||
* (see http://www.idpf.org/ocf/ocf1.0/download/ocf10.htm)
|
||||
* (see http://www.idpf.org/ocf/ocf1.0/download/ocf10.htm).
|
||||
*/
|
||||
public class ContainerWriter extends NewDOMDocument {
|
||||
|
||||
public ContainerWriter(String sRootFile) {
|
||||
public ContainerWriter() {
|
||||
super("container", "xml");
|
||||
|
||||
// create DOM
|
||||
|
@ -67,7 +67,7 @@ public class ContainerWriter extends NewDOMDocument {
|
|||
container.appendChild(rootfiles);
|
||||
|
||||
Element rootfile = contentDOM.createElement("rootfile");
|
||||
rootfile.setAttribute("full-path", sRootFile);
|
||||
rootfile.setAttribute("full-path", "OEBPS/book.opf");
|
||||
rootfile.setAttribute("media-type", "application/oebps-package+xml");
|
||||
rootfiles.appendChild(rootfile);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ public final class EPUBConverter extends Xhtml11Converter {
|
|||
}
|
||||
|
||||
@Override public ConverterResult convert(InputStream is, String sTargetFileName) throws IOException {
|
||||
setOPS(true);
|
||||
ConverterResult xhtmlResult = super.convert(is, sTargetFileName);
|
||||
|
||||
ConverterResultImpl epubResult = new ConverterResultImpl();
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* version 1.2 (2010-03-29)
|
||||
* version 1.2 (2010-03-31)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -30,6 +30,7 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
|
@ -37,8 +38,9 @@ import writer2latex.api.ConverterResult;
|
|||
import writer2latex.api.OutputFile;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/** This class repackages an XHTML document into EPUB format
|
||||
*
|
||||
/** This class repackages an XHTML document into EPUB format.
|
||||
* Some filenames are hard wired in this implementation: The main directory is OEBPS and
|
||||
* the OPF and NCX files are book.opf and book.ncx respectively
|
||||
*/
|
||||
public class EPUBWriter implements OutputFile {
|
||||
|
||||
|
@ -66,9 +68,12 @@ public class EPUBWriter implements OutputFile {
|
|||
}
|
||||
|
||||
public void write(OutputStream os) throws IOException {
|
||||
// Create a universal unique ID
|
||||
String sUUID = UUID.randomUUID().toString();
|
||||
|
||||
ZipOutputStream zos = new ZipOutputStream(os);
|
||||
|
||||
// Write MIME type as first entry
|
||||
// Write uncompressed MIME type as first entry
|
||||
ZipEntry mimeEntry = new ZipEntry("mimetype");
|
||||
mimeEntry.setMethod(ZipEntry.STORED);
|
||||
mimeEntry.setCrc(0x2CAB616F);
|
||||
|
@ -78,27 +83,27 @@ public class EPUBWriter implements OutputFile {
|
|||
zos.closeEntry();
|
||||
|
||||
// Write container entry next
|
||||
OutputFile containerWriter = new ContainerWriter("OEBPS/book.opf");
|
||||
OutputFile containerWriter = new ContainerWriter();
|
||||
ZipEntry containerEntry = new ZipEntry("META-INF/container.xml");
|
||||
zos.putNextEntry(containerEntry);
|
||||
writeZipEntry(containerWriter,zos);
|
||||
zos.closeEntry();
|
||||
|
||||
// Then manifest
|
||||
OutputFile manifest = new OPFWriter(xhtmlResult, "xxx", "book.ncx", "book.opf");
|
||||
OutputFile manifest = new OPFWriter(xhtmlResult, sUUID);
|
||||
ZipEntry manifestEntry = new ZipEntry("OEBPS/book.opf");
|
||||
zos.putNextEntry(manifestEntry);
|
||||
writeZipEntry(manifest,zos);
|
||||
zos.closeEntry();
|
||||
|
||||
// And content table
|
||||
OutputFile ncx = new NCXWriter(xhtmlResult, "xxx", "book.ncx");
|
||||
OutputFile ncx = new NCXWriter(xhtmlResult, sUUID);
|
||||
ZipEntry ncxEntry = new ZipEntry("OEBPS/book.ncx");
|
||||
zos.putNextEntry(ncxEntry);
|
||||
writeZipEntry(ncx,zos);
|
||||
zos.closeEntry();
|
||||
|
||||
// Finally XHTML content in the OEBPS sub directory
|
||||
// Finally XHTML content
|
||||
Iterator<OutputFile> iter = xhtmlResult.iterator();
|
||||
while (iter.hasNext()) {
|
||||
OutputFile file = iter.next();
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* version 1.2 (2010-03-29)
|
||||
* version 1.2 (2010-03-30)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -39,17 +39,15 @@ import org.w3c.dom.Element;
|
|||
|
||||
import writer2latex.api.ContentEntry;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.NewDOMDocument;
|
||||
|
||||
/** This class creates the required NXC file for an EPUB document
|
||||
* (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html#Section2.4)
|
||||
*
|
||||
* (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html#Section2.4).
|
||||
*/
|
||||
public class NCXWriter extends NewDOMDocument {
|
||||
|
||||
public NCXWriter(ConverterResult cr, String sUUID, String sFileName) {
|
||||
super(Misc.removeExtension(sFileName), "ncx");
|
||||
public NCXWriter(ConverterResult cr, String sUUID) {
|
||||
super("book", "ncx");
|
||||
|
||||
// create DOM
|
||||
Document contentDOM = null;
|
||||
|
@ -64,8 +62,6 @@ public class NCXWriter extends NewDOMDocument {
|
|||
throw new RuntimeException(t);
|
||||
}
|
||||
|
||||
System.out.println("populating the ncx");
|
||||
|
||||
// Populate the DOM tree
|
||||
Element ncx = contentDOM.getDocumentElement();
|
||||
ncx.setAttribute("version", "2005-1");
|
||||
|
@ -83,7 +79,7 @@ public class NCXWriter extends NewDOMDocument {
|
|||
|
||||
Element depth = contentDOM.createElement("meta");
|
||||
depth.setAttribute("name","dtb:depth");
|
||||
depth.setAttribute("content", "1");
|
||||
// Setting the content attribute later
|
||||
head.appendChild(depth);
|
||||
|
||||
Element totalPageCount = contentDOM.createElement("meta");
|
||||
|
@ -107,35 +103,57 @@ public class NCXWriter extends NewDOMDocument {
|
|||
Element navMap = contentDOM.createElement("navMap");
|
||||
ncx.appendChild(navMap);
|
||||
|
||||
Element currentContainer = ncx;
|
||||
int nCurrentLevel = 0;
|
||||
int nDepth = 0;
|
||||
int nPlayOrder = 0;
|
||||
|
||||
Iterator<ContentEntry> content = cr.getContent().iterator();
|
||||
while (content.hasNext()) {
|
||||
ContentEntry entry = content.next();
|
||||
//if (entry.getLevel()==1) {
|
||||
System.out.println("Found content entry "+entry.getTitle());
|
||||
Element navPoint = contentDOM.createElement("navPoint");
|
||||
navPoint.setAttribute("playOrder", Integer.toString(++nPlayOrder));
|
||||
navPoint.setAttribute("id", "text"+nPlayOrder);
|
||||
navMap.appendChild(navPoint);
|
||||
|
||||
Element navLabel = contentDOM.createElement("navLabel");
|
||||
navPoint.appendChild(navLabel);
|
||||
Element navLabelText = contentDOM.createElement("text");
|
||||
navLabel.appendChild(navLabelText);
|
||||
navLabelText.appendChild(contentDOM.createTextNode(entry.getTitle()));
|
||||
|
||||
Element navPointContent = contentDOM.createElement("content");
|
||||
String sHref = entry.getFile().getFileName();
|
||||
if (entry.getTarget()!=null) { sHref+="#"+entry.getTarget(); }
|
||||
navPointContent.setAttribute("src", sHref);
|
||||
navPoint.appendChild(navPointContent);
|
||||
//}
|
||||
int nEntryLevel = Math.max(entry.getLevel(), 1);
|
||||
|
||||
if (nEntryLevel<nCurrentLevel) {
|
||||
// Return to higher level
|
||||
for (int i=nEntryLevel; i<nCurrentLevel; i++) {
|
||||
currentContainer = (Element) currentContainer.getParentNode();
|
||||
}
|
||||
nCurrentLevel = nEntryLevel;
|
||||
}
|
||||
else if (nEntryLevel>nCurrentLevel) {
|
||||
// To lower level (always one step; a jump from e.g. heading 1 to heading 3 in the document
|
||||
// is considered an error)
|
||||
currentContainer = (Element) currentContainer.getLastChild();
|
||||
nCurrentLevel++;
|
||||
}
|
||||
|
||||
Element navPoint = contentDOM.createElement("navPoint");
|
||||
navPoint.setAttribute("playOrder", Integer.toString(++nPlayOrder));
|
||||
navPoint.setAttribute("id", "text"+nPlayOrder);
|
||||
currentContainer.appendChild(navPoint);
|
||||
|
||||
Element navLabel = contentDOM.createElement("navLabel");
|
||||
navPoint.appendChild(navLabel);
|
||||
Element navLabelText = contentDOM.createElement("text");
|
||||
navLabel.appendChild(navLabelText);
|
||||
navLabelText.appendChild(contentDOM.createTextNode(entry.getTitle()));
|
||||
|
||||
Element navPointContent = contentDOM.createElement("content");
|
||||
String sHref = entry.getFile().getFileName();
|
||||
if (entry.getTarget()!=null) { sHref+="#"+entry.getTarget(); }
|
||||
navPointContent.setAttribute("src", sHref);
|
||||
navPoint.appendChild(navPointContent);
|
||||
|
||||
nDepth = Math.max(nDepth, nCurrentLevel);
|
||||
}
|
||||
|
||||
if (nDepth==0) {
|
||||
// TODO: We're in trouble: The document has no headings
|
||||
}
|
||||
|
||||
depth.setAttribute("content", Integer.toString(nDepth));
|
||||
|
||||
setContentDOM(contentDOM);
|
||||
|
||||
System.out.println("finished populating the ncx");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,16 +41,14 @@ import org.w3c.dom.Element;
|
|||
import writer2latex.api.ContentEntry;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.OutputFile;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.NewDOMDocument;
|
||||
|
||||
/** This class writes an OPF-file for an EPUB document (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html)
|
||||
*
|
||||
/** This class writes an OPF-file for an EPUB document (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html).
|
||||
*/
|
||||
public class OPFWriter extends NewDOMDocument {
|
||||
|
||||
public OPFWriter(ConverterResult cr, String sUUID, String sNcxFileName, String sFileName) {
|
||||
super(Misc.removeExtension(sFileName), "opf");
|
||||
public OPFWriter(ConverterResult cr, String sUUID) {
|
||||
super("book", "opf");
|
||||
|
||||
// create DOM
|
||||
Document contentDOM = null;
|
||||
|
@ -123,7 +121,7 @@ public class OPFWriter extends NewDOMDocument {
|
|||
}
|
||||
|
||||
Element item = contentDOM.createElement("item");
|
||||
item.setAttribute("href", sNcxFileName);
|
||||
item.setAttribute("href", "book.ncx");
|
||||
item.setAttribute("media-type", "application/x-dtbncx+xml");
|
||||
item.setAttribute("id", "ncx");
|
||||
manifest.appendChild(item);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.2 (2010-03-15)
|
||||
* Version 1.2 (2010-03-29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -343,11 +343,7 @@ public class DrawConverter extends ConverterHelper {
|
|||
if (node.hasAttribute(XMLString.XLINK_HREF) && !ofr.isInPackage(sHref)) {
|
||||
// Linked image is not yet handled by ImageLoader. This is a temp.
|
||||
// solution (will go away when ImageLoader is finished)
|
||||
sFileName = sHref;
|
||||
// In OpenDocument package format ../ means "leave the package"
|
||||
if (ofr.isOpenDocument() && ofr.isPackageFormat() && sFileName.startsWith("../")) {
|
||||
sFileName=sFileName.substring(3);
|
||||
}
|
||||
sFileName = ofr.fixRelativeLink(sHref);
|
||||
int nExtStart = sHref.lastIndexOf(".");
|
||||
String sExt = nExtStart>=0 ? sHref.substring(nExtStart).toLowerCase() : "";
|
||||
// Accept only relative filenames and supported filetypes:
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
* Copyright: 2002-2010 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.2 (2008-09-30)
|
||||
* Version 1.2 (2010-03-29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -334,6 +334,19 @@ public class OfficeReader {
|
|||
if (sUrl.startsWith("./")) { sUrl=sUrl.substring(2); }
|
||||
return oooDoc.getEmbeddedObject(sUrl)!=null;
|
||||
}
|
||||
|
||||
/** In OpenDocument package format ../ means "leave the package".
|
||||
* Consequently this prefix must be removed to obtain a valid link
|
||||
*
|
||||
* @param sLink
|
||||
* @return the corrected link
|
||||
*/
|
||||
public String fixRelativeLink(String sLink) {
|
||||
if (isOpenDocument() && isPackageFormat() && sLink.startsWith("../")) {
|
||||
return sLink.substring(3);
|
||||
}
|
||||
return sLink;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Accessor methods
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.2 (2010-03-25)
|
||||
* Version 1.2 (2010-03-31)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -44,7 +44,6 @@ import org.w3c.dom.NodeList;
|
|||
import org.w3c.dom.Text;
|
||||
|
||||
import writer2latex.api.Config;
|
||||
import writer2latex.api.ContentEntry;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
//import writer2latex.api.ConverterResult;
|
||||
import writer2latex.base.ContentEntryImpl;
|
||||
|
@ -83,6 +82,7 @@ public class Converter extends ConverterBase {
|
|||
|
||||
// The xhtml output file(s)
|
||||
protected int nType = XhtmlDocument.XHTML10; // the doctype
|
||||
private boolean bOPS = false; // Do we need to be OPS conforming?
|
||||
Vector<XhtmlDocument> outFiles;
|
||||
private int nOutFileIndex;
|
||||
private XhtmlDocument htmlDoc; // current outfile
|
||||
|
@ -157,15 +157,18 @@ public class Converter extends ConverterBase {
|
|||
protected Node importNode(Node node, boolean bDeep) { return htmlDOM.importNode(node,bDeep); }
|
||||
|
||||
protected L10n getL10n() { return l10n; }
|
||||
|
||||
public void setOPS(boolean b) { bOPS = true; }
|
||||
|
||||
public boolean isOPS() { return bOPS; }
|
||||
|
||||
// override
|
||||
public void convertInner() throws IOException {
|
||||
@Override public void convertInner() throws IOException {
|
||||
sTargetFileName = Misc.trimDocumentName(sTargetFileName,XhtmlDocument.getExtension(nType));
|
||||
|
||||
outFiles = new Vector<XhtmlDocument>();
|
||||
nOutFileIndex = -1;
|
||||
|
||||
bNeedHeaderFooter = ofr.isSpreadsheet() || ofr.isPresentation() || config.getXhtmlSplitLevel()>0 || config.getXhtmlUplink().length()>0;
|
||||
bNeedHeaderFooter = !bOPS && (ofr.isSpreadsheet() || ofr.isPresentation() || config.getXhtmlSplitLevel()>0 || config.getXhtmlUplink().length()>0);
|
||||
|
||||
l10n = new L10n();
|
||||
|
||||
|
@ -612,6 +615,8 @@ public class Converter extends ConverterBase {
|
|||
}
|
||||
else { // external link
|
||||
anchor = htmlDOM.createElement("a");
|
||||
|
||||
sHref = ofr.fixRelativeLink(sHref);
|
||||
|
||||
// Workaround for an OOo problem:
|
||||
if (sHref.indexOf("?")==-1) { // No question mark
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.2 (2010-03-26)
|
||||
* Version 1.2 (2010-03-29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -571,11 +571,14 @@ public class TextConverter extends ConverterHelper {
|
|||
|
||||
// Add to toc
|
||||
if (!bInToc) {
|
||||
converter.addTarget(heading,"toc"+(++nTocIndex));
|
||||
String sTarget = "toc"+(++nTocIndex);
|
||||
converter.addTarget(heading,sTarget);
|
||||
|
||||
// Add in external content
|
||||
if (nLevel<=nSplit) {
|
||||
converter.addContentEntry(sLabel+(sLabel.length()>0 ? " " : "")+Misc.getPCDATA(onode), nLevel, null);
|
||||
// Add in external content. For single file output we include all level 1 headings + their target
|
||||
// For multi-file output, the included heading levels depends on the split leve, and we don't include targets
|
||||
if (nLevel<=Math.max(nSplit,1)) {
|
||||
converter.addContentEntry(sLabel+(sLabel.length()>0 ? " " : "")+Misc.getPCDATA(onode), nLevel,
|
||||
nSplit==0 ? sTarget : null);
|
||||
}
|
||||
|
||||
// Add to real toc
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Writer2LaTeX source version 1.1.1
|
||||
Writer2LaTeX source version 1.1.2
|
||||
=================================
|
||||
|
||||
Writer2LaTeX is (c) 2002-2009 by Henrik Just.
|
||||
Writer2LaTeX is (c) 2002-2010 by Henrik Just.
|
||||
The source is available under the terms and conditions of the
|
||||
GNU LESSER GENERAL PUBLIC LICENSE, version 2.1.
|
||||
Please see the file COPYING.TXT for details.
|
||||
|
@ -13,7 +13,7 @@ Overview
|
|||
The source of Writer2LaTeX consists of three major parts:
|
||||
|
||||
* A general purpose java library for converting OpenDocument files into LaTeX,
|
||||
BibTeX, xhtml and xhtml+MathML
|
||||
BibTeX, xhtml, xhtml+MathML and EPUB
|
||||
This is to be found in the packages writer2latex.* and should only be used
|
||||
through the provided api writer2latex.api.*
|
||||
* A command line utility writer2latex.Application
|
||||
|
@ -44,15 +44,15 @@ Writer2LaTeX uses Ant version 1.5 or later (http://ant.apache.org) to build.
|
|||
Some java libraries from OOo are needed to build the filter part of Writer2LaTeX,
|
||||
these are jurt.jar, unoil.jar, ridl.jar and juh.jar.
|
||||
|
||||
To make these files available for the compiler, edit the file build.xml in
|
||||
the writer2latex09 directory as follows:
|
||||
To make these files available for the compiler, edit the file build.xml
|
||||
as follows:
|
||||
|
||||
The lines
|
||||
<property name="OFFICE_HOME" location="/opt/openoffice.org/basis3.0" />
|
||||
<property name="URE_HOME" location="/opt/openoffice.org/ure" />
|
||||
should be modified to point to your OOo installation
|
||||
<property name="OFFICE_CLASSES" location="/usr/share/java/openoffice" />
|
||||
<property name="URE_CLASSES" location="/usr/share/java/openoffice" />
|
||||
should be modified to the directories where your OOo installation keeps these files
|
||||
|
||||
To build, open a command shell, navigate to the writer2latex09 directory and type
|
||||
To build, open a command shell, navigate to the source directory and type
|
||||
|
||||
ant oxt
|
||||
|
||||
|
@ -72,7 +72,7 @@ In addition to oxt, the build file supports the following targets:
|
|||
clean
|
||||
|
||||
|
||||
Henrik Just, November 2009
|
||||
Henrik Just, April 2010
|
||||
|
||||
|
||||
Thanks to Michael Niedermair for writing the original ant build file
|
||||
|
|
Loading…
Add table
Reference in a new issue