diff --git a/source/distro/Readme.txt b/source/distro/Readme.txt index 32bd003..1334ac9 100644 --- a/source/distro/Readme.txt +++ b/source/distro/Readme.txt @@ -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 diff --git a/source/distro/changelog.txt b/source/distro/changelog.txt index cad93e9..49157b4 100644 --- a/source/distro/changelog.txt +++ b/source/distro/changelog.txt @@ -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 diff --git a/source/distro/doc/user-manual.odt b/source/distro/doc/user-manual.odt index 1f3c38e..f7ca5d6 100644 Binary files a/source/distro/doc/user-manual.odt and b/source/distro/doc/user-manual.odt differ diff --git a/source/java/writer2latex/api/ConverterFactory.java b/source/java/writer2latex/api/ConverterFactory.java index 70abdb0..e50e843 100644 --- a/source/java/writer2latex/api/ConverterFactory.java +++ b/source/java/writer2latex/api/ConverterFactory.java @@ -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)
diff --git a/source/java/writer2latex/epub/ContainerWriter.java b/source/java/writer2latex/epub/ContainerWriter.java index 9584e3a..7ef3682 100644 --- a/source/java/writer2latex/epub/ContainerWriter.java +++ b/source/java/writer2latex/epub/ContainerWriter.java @@ -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); diff --git a/source/java/writer2latex/epub/EPUBConverter.java b/source/java/writer2latex/epub/EPUBConverter.java index 281c9a4..9c238f7 100644 --- a/source/java/writer2latex/epub/EPUBConverter.java +++ b/source/java/writer2latex/epub/EPUBConverter.java @@ -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(); diff --git a/source/java/writer2latex/epub/EPUBWriter.java b/source/java/writer2latex/epub/EPUBWriter.java index b250e42..7235c08 100644 --- a/source/java/writer2latex/epub/EPUBWriter.java +++ b/source/java/writer2latex/epub/EPUBWriter.java @@ -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 iter = xhtmlResult.iterator(); while (iter.hasNext()) { OutputFile file = iter.next(); diff --git a/source/java/writer2latex/epub/NCXWriter.java b/source/java/writer2latex/epub/NCXWriter.java index f1ef3d9..d1c6a19 100644 --- a/source/java/writer2latex/epub/NCXWriter.java +++ b/source/java/writer2latex/epub/NCXWriter.java @@ -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 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 (nEntryLevelnCurrentLevel) { + // 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"); - - } } diff --git a/source/java/writer2latex/epub/OPFWriter.java b/source/java/writer2latex/epub/OPFWriter.java index 558010b..a4c2872 100644 --- a/source/java/writer2latex/epub/OPFWriter.java +++ b/source/java/writer2latex/epub/OPFWriter.java @@ -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); diff --git a/source/java/writer2latex/latex/DrawConverter.java b/source/java/writer2latex/latex/DrawConverter.java index 310428d..ec73893 100644 --- a/source/java/writer2latex/latex/DrawConverter.java +++ b/source/java/writer2latex/latex/DrawConverter.java @@ -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: diff --git a/source/java/writer2latex/office/OfficeReader.java b/source/java/writer2latex/office/OfficeReader.java index 9e48bde..02d3e70 100644 --- a/source/java/writer2latex/office/OfficeReader.java +++ b/source/java/writer2latex/office/OfficeReader.java @@ -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 diff --git a/source/java/writer2latex/xhtml/Converter.java b/source/java/writer2latex/xhtml/Converter.java index 65d36a5..66bbd79 100644 --- a/source/java/writer2latex/xhtml/Converter.java +++ b/source/java/writer2latex/xhtml/Converter.java @@ -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 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(); 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 diff --git a/source/java/writer2latex/xhtml/TextConverter.java b/source/java/writer2latex/xhtml/TextConverter.java index 69fe83e..a9129e0 100644 --- a/source/java/writer2latex/xhtml/TextConverter.java +++ b/source/java/writer2latex/xhtml/TextConverter.java @@ -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 diff --git a/source/readme-source.txt b/source/readme-source.txt index b13b526..1689325 100644 --- a/source/readme-source.txt +++ b/source/readme-source.txt @@ -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 - - -should be modified to point to your OOo installation + + +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