From 8ad9c996f9d008f14d6da0060fde5dc7578783c9 Mon Sep 17 00:00:00 2001 From: Samuel Holtzkampf Date: Thu, 3 Dec 2015 15:23:58 +0200 Subject: [PATCH] Adding the api --- .gitignore | 4 + pom.xml | 55 ++ .../epub/creator/EpubConstants.java | 100 +++ .../epub/creator/api/OpfCreator.java | 41 ++ .../epub/creator/api/TocCreator.java | 41 ++ .../epub/creator/impl/OpfCreatorDefault.java | 202 ++++++ .../epub/creator/impl/TocCreatorDefault.java | 220 +++++++ .../epub/creator/model/Content.java | 336 ++++++++++ .../epub/creator/model/EpubBook.java | 429 +++++++++++++ .../epub/creator/model/Landmark.java | 86 +++ .../epub/creator/model/TocLink.java | 116 ++++ .../epub/creator/util/EpubWriter.java | 217 +++++++ .../epub/creator/util/MediaTypeUtil.java | 101 +++ src/main/resources/epub-mediatypes.properties | 51 ++ .../epub/creator/EpubCreatorTest.java | 41 ++ src/test/resources/P1010832.jpg | Bin 0 -> 89562 bytes src/test/resources/epub-spec.css | 581 ++++++++++++++++++ src/test/resources/epub30-overview.xhtml | 11 + src/test/resources/epub30-publications.xhtml | 333 ++++++++++ src/test/resources/epub30-terminology.xhtml | 11 + src/test/resources/epub_logo_color.jpg | Bin 0 -> 134445 bytes src/test/resources/idpflogo_web_125.jpg | Bin 0 -> 19659 bytes 22 files changed, 2976 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/coza/opencollab/epub/creator/EpubConstants.java create mode 100644 src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java create mode 100644 src/main/java/coza/opencollab/epub/creator/api/TocCreator.java create mode 100644 src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java create mode 100644 src/main/java/coza/opencollab/epub/creator/impl/TocCreatorDefault.java create mode 100644 src/main/java/coza/opencollab/epub/creator/model/Content.java create mode 100644 src/main/java/coza/opencollab/epub/creator/model/EpubBook.java create mode 100644 src/main/java/coza/opencollab/epub/creator/model/Landmark.java create mode 100644 src/main/java/coza/opencollab/epub/creator/model/TocLink.java create mode 100644 src/main/java/coza/opencollab/epub/creator/util/EpubWriter.java create mode 100644 src/main/java/coza/opencollab/epub/creator/util/MediaTypeUtil.java create mode 100644 src/main/resources/epub-mediatypes.properties create mode 100644 src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java create mode 100644 src/test/resources/P1010832.jpg create mode 100644 src/test/resources/epub-spec.css create mode 100644 src/test/resources/epub30-overview.xhtml create mode 100644 src/test/resources/epub30-publications.xhtml create mode 100644 src/test/resources/epub30-terminology.xhtml create mode 100644 src/test/resources/epub_logo_color.jpg create mode 100644 src/test/resources/idpflogo_web_125.jpg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..241b5c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +test.epub +nb-configuration.xml +nbactions.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2699634 --- /dev/null +++ b/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + coza.opencollab + epub-creator + 1.0.0-SNAPSHOT + jar + + + junit + junit + 4.10 + test + + + net.sourceforge.htmlcleaner + htmlcleaner + 2.8 + + + commons-io + commons-io + 2.4 + + + commons-collections + commons-collections + 3.2.1 + + + + + UTF-8 + 1.7 + 1.7 + + + + + oc-nexus-releases + OpenCollab Nexus Release Repo + + http://nexus.opencollab.co.za/nexus/content/repositories/releases + + + + oc-nexus-snapshot + OpenCollab Nexus Snapshot Repo + + http://nexus.opencollab.co.za/nexus/content/repositories/snapshots + + + + + \ No newline at end of file diff --git a/src/main/java/coza/opencollab/epub/creator/EpubConstants.java b/src/main/java/coza/opencollab/epub/creator/EpubConstants.java new file mode 100644 index 0000000..bb5a5dc --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/EpubConstants.java @@ -0,0 +1,100 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator; + +/** + * Constants used as default values in the EpubCreator and EpubBook. This is set + * according to the EPUB 3 standards. + * + * @author OpenCollab + */ +public class EpubConstants { + + private EpubConstants() { + } + + /** + * Used to wrap plain text in a valid XHTML document + */ + public static final String HTML_WRAPPER = "{0}{1}"; + + /** + * Template of the OPF file + */ + public static final String OPF_XML = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + /** + * Template of a valid table of contents navigation(TOC) XHTML document + */ + public static final String TOC_XML = "\n" + + "\n" + + " \n" + + " \n" + + " {0} \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + /** + * Template of a valid EPUB3 container XML + */ + public static final String CONTAINER_XML = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""; + + /** + * Default folder used to save content in + */ + public static final String CONTENT_FOLDER = "content"; + + /** + * The default href of the toc file + */ + public static final String TOC_FILE_NAME = "toc.xhtml"; + + /** + * The default href of the opf file + */ + public static final String OPF_FILE_NAME = "book.opf"; + +} diff --git a/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java b/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java new file mode 100644 index 0000000..c9bf84a --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/api/OpfCreator.java @@ -0,0 +1,41 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.api; + +import coza.opencollab.epub.creator.model.EpubBook; + +/** + * Service to create the Package Document that carries bibliographic and + * structural meta data about an EPUB Publication + * + * @author OpenCollab + */ +public interface OpfCreator { + + /** + * Creates the OPF file text from the EpubBook data + * + * @param book the ePub book to generate the OPF for + * @return the generated OPF markup + */ + public String createOpfString(EpubBook book); + +} diff --git a/src/main/java/coza/opencollab/epub/creator/api/TocCreator.java b/src/main/java/coza/opencollab/epub/creator/api/TocCreator.java new file mode 100644 index 0000000..fb298a3 --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/api/TocCreator.java @@ -0,0 +1,41 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.api; + +import coza.opencollab.epub.creator.model.Content; +import coza.opencollab.epub.creator.model.EpubBook; + +/** + * Service to create the EPUB navigation document + * + * @author OpenCollab + */ +public interface TocCreator { + + /** + * Creates the EPUB TOC navigation document Content object + * + * @param book the EpubBook to create the TOC for + * @return the TOC Content object + */ + public Content createTocFromBook(EpubBook book); + +} diff --git a/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java b/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java new file mode 100644 index 0000000..239baa6 --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/impl/OpfCreatorDefault.java @@ -0,0 +1,202 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.impl; + +import coza.opencollab.epub.creator.EpubConstants; +import coza.opencollab.epub.creator.api.OpfCreator; +import coza.opencollab.epub.creator.model.Content; +import coza.opencollab.epub.creator.model.EpubBook; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.htmlcleaner.CleanerProperties; +import org.htmlcleaner.ContentNode; +import org.htmlcleaner.HtmlCleaner; +import org.htmlcleaner.PrettyXmlSerializer; +import org.htmlcleaner.Serializer; +import org.htmlcleaner.TagNode; + +/** + * Default implementation of the OpfCreator. This follows EPUB3 standards to + * create the OPF file content. + * + * @author OpenCollab + */ +public class OpfCreatorDefault implements OpfCreator { + + /** + * The template XML used to create the OPF file. This is settable if a + * different template needs to be used. + */ + private String opfXML = EpubConstants.OPF_XML; + + /** + * HtmlCleaner used to clean the XHTML document + */ + private final HtmlCleaner cleaner; + + /** + * XmlSerializer used to format to XML String output + */ + private final Serializer htmlSetdown; + + public OpfCreatorDefault() { + cleaner = new HtmlCleaner(); + CleanerProperties htmlProperties = cleaner.getProperties(); + htmlProperties.setOmitHtmlEnvelope(true); + htmlProperties.setAdvancedXmlEscape(false); + htmlProperties.setUseEmptyElementTags(true); + htmlSetdown = new PrettyXmlSerializer(htmlProperties); + } + + /** + * {@inheritDoc} + */ + @Override + public String createOpfString(EpubBook book) { + TagNode tagNode = cleaner.clean(opfXML); + addMetaDataTags(tagNode, book); + addManifestTags(tagNode, book); + addSpineTags(tagNode, book); + return htmlSetdown.getAsString(tagNode); + } + + /** + * Add the required meta data + * + * @param tagNode the HTML tagNode of the OPF template + * @param book the EpubBook + */ + private void addMetaDataTags(TagNode tagNode, EpubBook book) { + TagNode metaNode = tagNode.findElementByName("metadata", true); + addNodeData(metaNode, "dc:identifier", book.getId()); + addNodeData(metaNode, "dc:title", book.getTitle()); + addNodeData(metaNode, "dc:language", book.getLanguage()); + addNodeData(metaNode, "meta", new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'").format(new Date())); + if (book.getAuthor() != null) { + TagNode creatorNode = new TagNode("dc:creator"); + creatorNode.addChild(new ContentNode(book.getAuthor())); + metaNode.addChild(creatorNode); + } + } + + /** + * Adds a item tag to the manifest for each Content object. + * + * The manifest contains all Content that will be added to the EPUB as files + * + * @param tagNode the HTML tagNode of the OPF template + * @param book the EpubBook + */ + private void addManifestTags(TagNode tagNode, EpubBook book) { + TagNode manifestNode = tagNode.findElementByName("manifest", true); + for (Content content : book.getContents()) { + manifestNode.addChild(buildItemNode(content)); + } + } + + /** + * Builds an item tag from the Content object + * + * @param content + * @return + */ + private TagNode buildItemNode(Content content) { + TagNode itemNode = new TagNode("item"); + itemNode.addAttribute("href", content.getHref()); + itemNode.addAttribute("id", content.getId()); + itemNode.addAttribute("media-type", content.getMediaType()); + if (content.getProperties() != null) { + itemNode.addAttribute("properties", content.getProperties()); + } + if (content.hasFallBack()) { + itemNode.addAttribute("fallback", content.getFallBack().getId()); + } + return itemNode; + } + + /** + * Adds item ref tags for all Content objects that must be added to the + * spine. + * + * The spine contains all the resources that will be shown when reading the + * book from start to end + * + * @param tagNode the HTML tagNode of the OPF template + * @param book the EpubBook + */ + private void addSpineTags(TagNode tagNode, EpubBook book) { + TagNode spineNode = tagNode.findElementByName("spine", true); + for (Content content : book.getContents()) { + if (content.isSpine()) { + spineNode.addChild(buildItemrefNode(content)); + } + } + } + + /** + * Builds an item ref tag from the Content object + * + * @param content + * @return + */ + private TagNode buildItemrefNode(Content content) { + TagNode itemNode = new TagNode("itemref"); + itemNode.addAttribute("idref", content.getId()); + if (!content.isLinear()) { + itemNode.addAttribute("linear", "no"); + } + return itemNode; + } + + /** + * Adds a ContentNode (value) with to a child element of the TagNode + * + * {value} + * + * @param tagNode + * @param elementName + * @param value + */ + private void addNodeData(TagNode tagNode, String elementName, String value) { + TagNode editNode = tagNode.findElementByName(elementName, true); + editNode.addChild(new ContentNode(value)); + } + + /** + * The base XML used for the OPF file. + * + * @return the OPF XML text + */ + public String getOpfXML() { + return opfXML; + } + + /** + * The base XML used for the OPF file. This is optional as there is a EPUB3 + * standard default but it can be overridden. + * + * @param opfXML the OPF XML to set + */ + public void setOpfXML(String opfXML) { + this.opfXML = opfXML; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/impl/TocCreatorDefault.java b/src/main/java/coza/opencollab/epub/creator/impl/TocCreatorDefault.java new file mode 100644 index 0000000..c4182ed --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/impl/TocCreatorDefault.java @@ -0,0 +1,220 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.impl; + +import coza.opencollab.epub.creator.EpubConstants; +import coza.opencollab.epub.creator.api.TocCreator; +import coza.opencollab.epub.creator.model.Content; +import coza.opencollab.epub.creator.model.EpubBook; +import coza.opencollab.epub.creator.model.Landmark; +import coza.opencollab.epub.creator.model.TocLink; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.collections.CollectionUtils; +import org.htmlcleaner.CleanerProperties; +import org.htmlcleaner.ContentNode; +import org.htmlcleaner.HtmlCleaner; +import org.htmlcleaner.PrettyXmlSerializer; +import org.htmlcleaner.Serializer; +import org.htmlcleaner.TagNode; + +/** + * Default implementation of the TocCreator. This follows EPUB3 standards to + * create the Navigation Document file content. + * + * @author OpenCollab + */ +public class TocCreatorDefault implements TocCreator { + + /** + * HtmlCleaner used to alter the XHTML document + */ + private final HtmlCleaner cleaner; + + private String href = EpubConstants.TOC_FILE_NAME; + + private String tocHtml = EpubConstants.TOC_XML; + + /** + * XmlSerializer used to format to XML String output + */ + private final Serializer htmlSetdown; + + public TocCreatorDefault() { + cleaner = new HtmlCleaner(); + CleanerProperties htmlProperties = cleaner.getProperties(); + htmlProperties.setOmitHtmlEnvelope(false); + htmlProperties.setAdvancedXmlEscape(false); + htmlProperties.setUseEmptyElementTags(true); + htmlSetdown = new PrettyXmlSerializer(htmlProperties); + } + + /** + * {@inheritDoc} + */ + @Override + public Content createTocFromBook(EpubBook book) { + List links = book.getTocLinks(); + if (book.isAutoToc()) { + links = generateAutoLinks(book); + } + List landmarks = book.getLandmarks(); + String tocString = createTocHtml(links, landmarks, getTocHtml()); + Content toc = new Content("application/xhtml+xml", getHref(), tocString.getBytes()); + toc.setProperties("nav"); + toc.setId("toc"); + toc.setLinear(false); + return toc; + } + + /** + * Builds the TOC HTML content from the EpubBook TocLinks + * + * @param book the EpubBook + * @return the TOC HTML String + */ + private String createTocHtml(List links, List landmarks, String tocHtml) { + TagNode tagNode = cleaner.clean(tocHtml); + if (!CollectionUtils.isEmpty(links)) { + addTocLinks(tagNode, links); + } + if (!CollectionUtils.isEmpty(landmarks)) { + addLandmarks(tagNode, landmarks); + } + return htmlSetdown.getAsString(tagNode); + } + + /** + * Recursive method adding links and sub links to the TOC Navigation + * Document + * + * @param tagNode + * @param links + */ + private void addTocLinks(TagNode tagNode, List links) { + TagNode navNode = tagNode.findElementByAttValue("epub:type", "toc", true, false); + TagNode parentNode = navNode.findElementByName("ol", true); + for (TocLink toc : links) { + TagNode linkNode = buildLinkNode(toc); + if (!CollectionUtils.isEmpty(toc.getTocChildLinks())) { + TagNode olNode = new TagNode("ol"); + addTocLinks(olNode, toc.getTocChildLinks()); + linkNode.addChild(olNode); + } + parentNode.addChild(linkNode); + } + } + + /** + * Adds landmarks to the Navigation Document + * + * @param tagNode + * @param links + */ + private void addLandmarks(TagNode tagNode, List landmarks) { + TagNode navNode = tagNode.findElementByAttValue("epub:type", "landmarks", true, false); + TagNode parentNode = navNode.findElementByName("ol", true); + for (Landmark landmark : landmarks) { + TagNode landmarkNode = buildLandMarkNode(landmark); + parentNode.addChild(landmarkNode); + } + } + + /** + * Builds an link tag for the TOC + * + * @param content + * @return + */ + private TagNode buildLinkNode(TocLink link) { + TagNode linkNode = new TagNode("li"); + TagNode aNode = new TagNode("a"); + aNode.addAttribute("href", link.getHref()); + aNode.addChild(new ContentNode(link.getTitle())); + if (link.getAltTitle() != null) { + aNode.addAttribute("title", link.getHref()); + } + linkNode.addChild(aNode); + return linkNode; + } + + /** + * Builds an link tag for the TOC landmarks + * + * @param content + * @return + */ + private TagNode buildLandMarkNode(Landmark landmark) { + TagNode linkNode = new TagNode("li"); + TagNode aNode = new TagNode("a"); + aNode.addAttribute("href", landmark.getHref()); + aNode.addAttribute("epub:type", landmark.getType()); + aNode.addChild(new ContentNode(landmark.getTitle())); + linkNode.addChild(aNode); + return linkNode; + } + + /** + * Generates a list of TocLinks for all Content that should be included in + * the Navigation Document. This will only be used when auto TOC is set + * + * @param book + * @return + */ + private List generateAutoLinks(EpubBook book) { + List links = new ArrayList(); + for (Content content : book.getContents()) { + if (content.isToc()) { + links.add(new TocLink(content.getHref(), content.getId(), null)); + } + } + return links; + } + + /** + * @return the HREF + */ + public String getHref() { + return href; + } + + /** + * @param href the HREF to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * @return the tocHtml + */ + public String getTocHtml() { + return tocHtml; + } + + /** + * @param tocHtml the tocHtml to set + */ + public void setTocHtml(String tocHtml) { + this.tocHtml = tocHtml; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/model/Content.java b/src/main/java/coza/opencollab/epub/creator/model/Content.java new file mode 100644 index 0000000..6c77a5b --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/model/Content.java @@ -0,0 +1,336 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.model; + +import coza.opencollab.epub.creator.util.MediaTypeUtil; +import java.io.IOException; +import java.io.InputStream; +import org.apache.commons.io.IOUtils; + +/** + * Representation of content in the book + * + * @author OpenCollab + */ +public class Content { + + /** + * The MediaType get set as the media-type attribute value in the OPF + * manifest items + */ + private String mediaType; + + /** + * The HREF get set as the HREF attribute value in the OPF manifest items + */ + private String href; + + /** + * The id get set as the id attribute value in the OPF manifest items and + * the id ref in the spine. This must be unique + */ + private String id; + + /** + * The properties get set as the properties attribute value in the OPF + * manifest items. This is used for the TOC and cover-image content objects + */ + private String properties; + + /** + * The file content + */ + private byte[] content; + + /** + * Specifies if it is a linear item in the spine + */ + private boolean linear = true; + + /** + * Specifies if it must be added to the spine + */ + private boolean spine = true; + + /** + * Specifies if it must be added to the TOC (Navigation Document) + */ + private boolean toc = false; + + /** + * The fallback content + */ + private Content fallBack; + + /** + * Creates new instance of Content + * + * @param mediaType the mime type + * @param href the link to the content item + * @param content the file byte array + */ + public Content(String mediaType, String href, byte[] content) { + if (mediaType == null) { + this.mediaType = MediaTypeUtil.getMediaTypeFromFilename(href); + } else { + this.mediaType = mediaType; + } + this.href = href; + this.content = content; + } + + /** + * Creates new instance of Content + * + * @param href the link to the content item + * @param content the file byte array + */ + public Content(String href, byte[] content) { + this(MediaTypeUtil.getMediaTypeFromFilename(href), href, content); + } + + /** + * Creates a new instance of Content + * + * @param mediaType the mime type + * @param href the link to the content item + * @param id used as the id attribute value in the OPF manifest items and + * the id ref in the spine + * @param properties the properties attribute value in the OPF + * @param content the file byte array + */ + public Content(String mediaType, String href, String id, String properties, byte[] content) { + this(mediaType, href, content); + this.id = id; + this.properties = properties; + this.content = content; + } + + /** + * Creates a new instance of Content + * + * @param href the link to the content item + * @param id used as the id attribute value in the OPF manifest items and + * the id ref in the spine + * @param properties the properties attribute value in the OPF + * @param content the file byte array + */ + public Content(String href, String id, String properties, byte[] content) { + this(MediaTypeUtil.getMediaTypeFromFilename(href), href, id, properties, content); + } + + /** + * Creates new instance of Content + * + * @param mediaType the mime type + * @param href the link to the content item + * @param content the file byte array + * @throws java.io.IOException if content could not be converted to byte + * array + */ + public Content(String mediaType, String href, InputStream content) throws IOException { + this(mediaType, href, IOUtils.toByteArray(content)); + } + + /** + * Creates new instance of Content + * + * @param href the link to the content item + * @param content the file byte array + * @throws java.io.IOException if content could not be converted to byte + * array + */ + public Content(String href, InputStream content) throws IOException { + this(MediaTypeUtil.getMediaTypeFromFilename(href), href, IOUtils.toByteArray(content)); + } + + /** + * Creates a new instance of Content + * + * @param mediaType the mime type + * @param href the link to the content item + * @param id used as the id attribute value in the OPF manifest items and + * the id ref in the spine + * @param properties the properties attribute value in the OPF + * @param content the file byte array + * @throws java.io.IOException if content could not be converted to byte + * array + */ + public Content(String mediaType, String href, String id, String properties, InputStream content) throws IOException { + this(mediaType, href, id, properties, IOUtils.toByteArray(content)); + } + + /** + * Creates a new instance of Content + * + * @param href the link to the content item + * @param id used as the id attribute value in the OPF manifest items and + * the id ref in the spine + * @param properties the properties attribute value in the OPF + * @param content the file byte array + * @throws java.io.IOException if content could not be converted to byte + * array + */ + public Content(String href, String id, String properties, InputStream content) throws IOException { + this(MediaTypeUtil.getMediaTypeFromFilename(href), href, id, properties, IOUtils.toByteArray(content)); + } + + /** + * Indicates whether a fallback content has been set + * + * @return the fallback flag + */ + public boolean hasFallBack() { + return fallBack != null; + } + + /** + * @return the mediaType + */ + public String getMediaType() { + return mediaType; + } + + /** + * @param mediaType the mediaType to set + */ + public void setMediaType(String mediaType) { + this.mediaType = mediaType; + } + + /** + * @return the HREF + */ + public String getHref() { + return href; + } + + /** + * @param href the HREF to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the properties + */ + public String getProperties() { + return properties; + } + + /** + * @param properties the properties to set + */ + public void setProperties(String properties) { + this.properties = properties; + } + + /** + * @return the content + */ + public byte[] getContent() { + return content; + } + + /** + * @param content the content to set + */ + public void setContent(byte[] content) { + this.content = content; + } + + /** + * @return the linear + */ + public boolean isLinear() { + return linear; + } + + /** + * @param linear the linear to set + */ + public void setLinear(boolean linear) { + this.linear = linear; + } + + /** + * @return the spine + */ + public boolean isSpine() { + return spine; + } + + /** + * @param spine the spine to set + */ + public void setSpine(boolean spine) { + this.spine = spine; + } + + /** + * @return the TOC + */ + public boolean isToc() { + return toc; + } + + /** + * @param toc the TOC to set + */ + public void setToc(boolean toc) { + this.toc = toc; + } + + /** + * @return the fallBack + */ + public Content getFallBack() { + return fallBack; + } + + /** + * The spine parameter will be set to false as we do not want to add the + * fallback content to the spine. To override default behavior call + * getFallBack to set spine property. + * + * @param fallBack the fallBack to set + */ + public void setFallBack(Content fallBack) { + fallBack.setSpine(false); + this.fallBack = fallBack; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java b/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java new file mode 100644 index 0000000..0a06d8b --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/model/EpubBook.java @@ -0,0 +1,429 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.model; + +import coza.opencollab.epub.creator.EpubConstants; +import coza.opencollab.epub.creator.util.EpubWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Representation of an EPUB book + * + * @author OpenCollab + */ +public class EpubBook { + + /** + * A list of the the content files, this includes the cover, HTML pages, CSS + * JavaScript or any other resource + */ + private List contents; + /** + * Indicates whether the TOC must be created automatically. If this is false + * the tocLinks must be set + */ + private boolean autoToc = true; + /** + * The 2 letter language code set in the dc:language meta data + */ + private String language; + /** + * The id used as the meta data dc:identifier + */ + private String id; + /** + * The title of the book + */ + private String title; + /** + * The author, this is set as the meta data dc:creator value + */ + private String author; + /** + * Unique content id that is incremental set on content with no id + */ + private int contentId = 1; + /** + * List of the links that must be added to the TOC, they can be nested + */ + private List tocLinks; + /** + * List of the landmarks to be added to the TOC + */ + private List landmarks; + /** + * Instance of the EpubWriter to write the book to file or stream + */ + private final EpubWriter epubCreator; + + /** + * Unique set of href's used to make sure we do not add duplicates + */ + private final Set uniqueHrefs; + + /** + * The href can not be repeated in the OPF, thus is we want to add the same + * content in more than one place we have to create duplicate Content + * objects but with different href's + */ + private int hrefUniquePostfix = 1; + + /** + * Constructs EPUBBook + */ + public EpubBook() { + this.epubCreator = new EpubWriter(); + this.contents = new ArrayList<>(); + this.tocLinks = new ArrayList<>(); + this.uniqueHrefs = new HashSet(); + } + + /** + * Constructs EPUBBook + * + * @param language the 2 letter language code set in the dc:language meta + * data + * @param id the id used as the meta data dc:identifier + * @param title the title of the book + * @param author the author, this is set as the meta data dc:creator value + */ + public EpubBook(String language, String id, String title, String author) { + this(); + this.language = language; + this.id = id; + this.title = title; + this.author = author; + } + + /** + * Checks if href unique, adds postfix if not + * + * @param content + */ + private void checkHref(Content content) { + content.setHref(removeLeadingFileSeparator(content.getHref())); + if (uniqueHrefs.contains(content.getHref())) { + content.setHref(incrementHref(content.getHref())); + } + uniqueHrefs.add(content.getHref()); + } + + /** + * Checks if href unique, adds postfix if not + * + * @param href + */ + private String checkHref(String href) { + href = removeLeadingFileSeparator(href); + if (uniqueHrefs.contains(href)) { + return incrementHref(href); + } + return href; + } + + /** + * Increment href. Checks for file extensions + * + * @param href + * @return + */ + private String incrementHref(String href) { + if (href.contains(".")) { + return href.replace(".", "_" + hrefUniquePostfix++ + "."); + } + return href + "_" + hrefUniquePostfix++; + } + + /** + * Remove the leading file separator + * + * @param href + * @return + */ + private String removeLeadingFileSeparator(String href) { + if (href.startsWith("/") || href.startsWith("\\")) { + return href.substring(1); + } + return href; + } + + /** + * Adds content to the content list and checks the id. Only adds unique + * href's + * + * @param content the EpubBook content - TOC, pages, files + * @return boolean indicating if the content has been added + */ + public boolean addContent(Content content) { + checkContentId(content); + checkHref(content); + contents.add(content); + return true; + } + + /** + * Inserts content at a specific index. Only adds unique href's + * + * @param content the EpubBook content - TOC, pages, files + * @param index index where the content will be inserted + * @return boolean indicating if the content has been added + */ + public boolean insertContent(Content content, int index) { + checkContentId(content); + checkHref(content); + contents.add(index, content); + return true; + } + + /** + * Wraps a String in the HTML wrapper and adds create a content object that + * is added to the content list. Returns null if the href is not unique + * + * @param title the title of the page + * @param href used as unique link + * @param content text content to be added + * @return the Content object generated from the text + */ + public Content addTextContent(String title, String href, String content) { + href = checkHref(href); + String contentString = MessageFormat.format(EpubConstants.HTML_WRAPPER, title, content); + Content textContent = new Content("application/xhtml+xml", href, contentString.getBytes()); + addContent(textContent); + return textContent; + } + + /** + * Creates and adds file Content to the book + * + * @param contents the byte array content + * @param mediaType the mime type + * @param href used as unique link + * @param toc flag whether it must be added to the TOC + * @param spine flag whether it must be added to the spine + * @return a reference to the newly created Content object + */ + public Content addContent(byte[] contents, String mediaType, String href, boolean toc, boolean spine) { + Content content = new Content(mediaType, href, contents); + content.setToc(toc); + content.setSpine(spine); + addContent(content); + return content; + } + + /** + * Creates and adds an InputStream to the book + * + * @param contents the InputStream to the content + * @param mediaType the mime type + * @param href used as unique link + * @param toc flag whether it must be added to the TOC + * @param spine flag whether it must be added to the spine + * @return a reference to the newly created Content object + * @throws java.io.IOException if the InputStream can not be converted to + * byte[] + */ + public Content addContent(InputStream contents, String mediaType, String href, boolean toc, boolean spine) throws IOException { + Content content = new Content(mediaType, href, contents); + content.setToc(toc); + content.setSpine(spine); + addContent(content); + return content; + } + + /** + * Checks if Content object has an id and adds an unique if not + * + * @param content + */ + private void checkContentId(Content content) { + if (content.getId() == null) { + content.setId(id.replaceAll("[^a-zA-Z0-9\\-]", "_") + "_" + (contentId++)); + } + } + + /** + * Adds an file as the cover image + * + * @param coverImage the cover image + * @param mediaType the mime type of the cover image + * @param href used to name the cover image + */ + public void addCoverImage(byte[] coverImage, String mediaType, String href) { + Content cover = new Content(mediaType, href, coverImage); + cover.setProperties("cover-image"); + cover.setSpine(false); + addContent(cover); + } + + /** + * Creates the EPUB zip container and writes it to the OutputStream + * + * @param out the OutputStream + * @throws Exception if the content can not be zipped and written + */ + public void writeToStream(OutputStream out) throws Exception { + epubCreator.writeEpubToStream(this, out); + } + + /** + * Creates the EPUB zip container and writes it to the File + * + * @param fileName to store as + * @throws Exception if the content can not be zipped and stored + */ + public void writeToFile(String fileName) throws Exception { + epubCreator.writeEpubToFile(this, fileName); + } + + /** + * @return the contents + */ + public List getContents() { + return contents; + } + + /** + * @param contents the content to set + */ + public void setContents(List contents) { + this.contents = contents; + } + + /** + * @return the autoToc + */ + public boolean isAutoToc() { + return autoToc; + } + + /** + * @param autoToc the autoToc to set + */ + public void setAutoToc(boolean autoToc) { + this.autoToc = autoToc; + } + + /** + * @return the language + */ + public String getLanguage() { + return language; + } + + /** + * @param language the language to set + */ + public void setLanguage(String language) { + this.language = language; + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * @param title the title to set + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * @return the tocLinks + */ + public List getTocLinks() { + return tocLinks; + } + + /** + * @param tocLinks the tocLinks to set + */ + public void setTocLinks(List tocLinks) { + this.tocLinks = tocLinks; + } + + /** + * @return the landmarks + */ + public List getLandmarks() { + return landmarks; + } + + /** + * @param landmarks the landmarks to set + */ + public void setLandmarks(List landmarks) { + this.landmarks = landmarks; + } + + /** + * @return the author + */ + public String getAuthor() { + return author; + } + + /** + * @param author the author to set + */ + public void setAuthor(String author) { + this.author = author; + } + + /** + * @return the epubCreator + */ + public EpubWriter getEpubCreator() { + return epubCreator; + } + + /** + * @return the uniqueHrefs + */ + public Set getUniqueHrefs() { + return uniqueHrefs; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/model/Landmark.java b/src/main/java/coza/opencollab/epub/creator/model/Landmark.java new file mode 100644 index 0000000..e6e495a --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/model/Landmark.java @@ -0,0 +1,86 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.model; + +/** + * Represents a landmark object in the Navigation document landmarks section + * + * @author OpenCollab + */ +public class Landmark { + + /** + * The href of the referenced landmark + */ + private String href; + /** + * The title to display + */ + private String title; + /** + * The type (cover,title-page,frontmatter,bodymatter,backmatter,toc, loi,lot + * (list of tables),preface,bibliography,index,glossary,acknowledgments + */ + private String type; + + /** + * @return the href + */ + public String getHref() { + return href; + } + + /** + * @param href the href to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * @param title the title to set + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/model/TocLink.java b/src/main/java/coza/opencollab/epub/creator/model/TocLink.java new file mode 100644 index 0000000..46c62c6 --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/model/TocLink.java @@ -0,0 +1,116 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.model; + +import java.util.List; + +/** + * Represents a link in the table of contents, this object can have nested child + * links + * + * @author OpenCollab + */ +public class TocLink { + + /** + * The href + */ + private String href; + + /** + * The displayed text + */ + private String title; + + /** + * Can be set for accessibility if the pronunciation of a link heading may + * be ambiguous due to embedded images, math content, or other content + * without intrinsic text. Will be included as an 'title' attribute + */ + private String altTitle; + + /** + * Any nested links + */ + private List tocChildLinks; + + public TocLink(String href, String title, String altTitle) { + this.href = href; + this.title = title; + this.altTitle = altTitle; + } + + /** + * @return the href + */ + public String getHref() { + return href; + } + + /** + * @param href the href to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * @param title the title to set + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * @return the altTitle + */ + public String getAltTitle() { + return altTitle; + } + + /** + * @param altTitle the altTitle to set + */ + public void setAltTitle(String altTitle) { + this.altTitle = altTitle; + } + + /** + * @return the tocChildLinks + */ + public List getTocChildLinks() { + return tocChildLinks; + } + + /** + * @param tocChildLinks the tocChildLinks to set + */ + public void setTocChildLinks(List tocChildLinks) { + this.tocChildLinks = tocChildLinks; + } +} diff --git a/src/main/java/coza/opencollab/epub/creator/util/EpubWriter.java b/src/main/java/coza/opencollab/epub/creator/util/EpubWriter.java new file mode 100644 index 0000000..2fb25ca --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/util/EpubWriter.java @@ -0,0 +1,217 @@ +/* Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.util; + +import coza.opencollab.epub.creator.EpubConstants; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import coza.opencollab.epub.creator.api.OpfCreator; +import coza.opencollab.epub.creator.api.TocCreator; +import coza.opencollab.epub.creator.impl.OpfCreatorDefault; +import coza.opencollab.epub.creator.impl.TocCreatorDefault; +import coza.opencollab.epub.creator.model.Content; +import coza.opencollab.epub.creator.model.EpubBook; +import java.util.List; + +/** + * The EpubWriter creates the EPUB zip bundle. + * + * @author OpenCollab + */ +public class EpubWriter { + + private String containerXML = EpubConstants.CONTAINER_XML; + + private String contentFolder = EpubConstants.CONTENT_FOLDER; + + private String opfFileName = EpubConstants.OPF_FILE_NAME; + + private OpfCreator opfCreator = new OpfCreatorDefault(); + + private TocCreator tocCreator = new TocCreatorDefault(); + + /** + * Writes the EPUB book zip container and contents to a file + * + * @param book the EpubBook + * @param fileName name of the file to be written + * @throws IOException if file could not be written + */ + public void writeEpubToFile(EpubBook book, String fileName) throws IOException { + try (FileOutputStream file = new FileOutputStream(new File(fileName))) { + writeEpubToStream(book, file); + } + } + + /** + * Writes the EPUB book zip container and contents to an OutputStream + * + * @param book the EpubBook + * @param out the OutputStream to write to + * @throws IOException if file could not be written + */ + public void writeEpubToStream(EpubBook book, OutputStream out) throws IOException { + try (ZipOutputStream resultStream = new ZipOutputStream(out)) { + List contents = book.getContents(); + addMimeType(resultStream); + contents.add(0, getTocCreator().createTocFromBook(book)); + addStringToZip(resultStream, "META-INF/container.xml", MessageFormat.format(containerXML, contentFolder)); + addStringToZip(resultStream, contentFolder + "/" + getOpfFileName(), getOpfCreator().createOpfString(book)); + addContent(resultStream, contents); + } + } + + /** + * Adds the zip/EPUB mime type to the EPUB zip file + * + * @param resultStream + * @throws IOException + */ + private void addMimeType(ZipOutputStream resultStream) throws IOException { + ZipEntry mimetypeZipEntry = new ZipEntry("mimetype"); + mimetypeZipEntry.setMethod(ZipEntry.STORED); + byte[] mimetypeBytes = "application/epub+zip".getBytes("UTF-8"); + mimetypeZipEntry.setSize(mimetypeBytes.length); + mimetypeZipEntry.setCrc(calculateCrc(mimetypeBytes)); + resultStream.putNextEntry(mimetypeZipEntry); + resultStream.write(mimetypeBytes); + } + + /** + * Calculates the CRC32 of data for the zip entry + * + * @param data + * @return + */ + private long calculateCrc(byte[] data) { + CRC32 crc = new CRC32(); + crc.update(data); + return crc.getValue(); + } + + /** + * Adds string content as an zip entry with the specified file name + * + * @param resultStream + * @param fileName + * @param content + * @throws IOException + */ + private void addStringToZip(ZipOutputStream resultStream, String fileName, String content) throws IOException { + resultStream.putNextEntry(new ZipEntry(fileName)); + Writer out = new OutputStreamWriter(resultStream, "UTF-8"); + out.write(content); + out.flush(); + } + + /** + * Adds the content objects zip entries + * + * @param resultStream + * @param contents + * @throws IOException + */ + private void addContent(ZipOutputStream resultStream, List contents) throws IOException { + for (Content content : contents) { + resultStream.putNextEntry(new ZipEntry(contentFolder + "/" + content.getHref())); + resultStream.write(content.getContent()); + } + } + + /** + * @return the CONTAINER_XML + */ + public String getContainerXML() { + return containerXML; + } + + /** + * @param containerXML the CONTAINER_XML to set + */ + public void setContainerXML(String containerXML) { + this.containerXML = containerXML; + } + + /** + * @return the CONTENT_FOLDER + */ + public String getContentFolder() { + return contentFolder; + } + + /** + * @param contentFolder the CONTENT_FOLDER to set + */ + public void setContentFolder(String contentFolder) { + this.contentFolder = contentFolder; + } + + /** + * @return the OPF_FILE_NAME + */ + public String getOpfFileName() { + return opfFileName; + } + + /** + * @param opfFileName the OPF_FILE_NAME to set + */ + public void setOpfFileName(String opfFileName) { + this.opfFileName = opfFileName; + } + + /** + * @return the opfCreator + */ + public OpfCreator getOpfCreator() { + return opfCreator; + } + + /** + * @param opfCreator the opfCreator to set + */ + public void setOpfCreator(OpfCreator opfCreator) { + this.opfCreator = opfCreator; + } + + /** + * @return the tocCreator + */ + public TocCreator getTocCreator() { + return tocCreator; + } + + /** + * @param tocCreator the tocCreator to set + */ + public void setTocCreator(TocCreator tocCreator) { + this.tocCreator = tocCreator; + } + +} diff --git a/src/main/java/coza/opencollab/epub/creator/util/MediaTypeUtil.java b/src/main/java/coza/opencollab/epub/creator/util/MediaTypeUtil.java new file mode 100644 index 0000000..914c8ba --- /dev/null +++ b/src/main/java/coza/opencollab/epub/creator/util/MediaTypeUtil.java @@ -0,0 +1,101 @@ +/* + * The MIT License + * + * Copyright 2014 OpenCollab. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package coza.opencollab.epub.creator.util; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Used to map file extensions to Mime types from a properties file + * + * @author OpenCollab + */ +public class MediaTypeUtil { + + private static Map mediaTypeMap = setMediaFromProperties(); + + /** + * Created a map of media types for specific file extensions, read from the + * epub-mediatypes.properties file + * + * @return a map of all the media types in the properties file + */ + private static Map setMediaFromProperties() { + Properties properties = new Properties(); + try { + properties.load(MediaTypeUtil.class.getClassLoader().getResourceAsStream("epub-mediatypes.properties")); + } catch (IOException ex) { + Logger.getLogger(MediaTypeUtil.class.getName()).log(Level.SEVERE, + "Could not read the 'epub-mediatypes.properties' file to populate the media types. " + + "Please use MediaTypeUtil.setMediaTypeMap(Map aMediaTypeMap) to set the map.", ex); + return new HashMap<>(); + } + + Map mappings = new HashMap<>(); + + Enumeration elements = properties.propertyNames(); + while (elements.hasMoreElements()) { + String keyProps = (String) elements.nextElement(); + String valProps = properties.getProperty(keyProps); + mappings.put(keyProps, valProps); + } + return mappings; + } + + /** + * Returns the correct media type for a specific file extension + * + * @param ext the file extension + * @return the mime type + */ + public static String getMediaTypeFromExt(String ext) { + return mediaTypeMap.get(ext.toLowerCase()); + } + + /** + * Returns the correct media type for a specific file name + * + * @param fileName the full filename + * @return the mime type + */ + public static String getMediaTypeFromFilename(String fileName) { + String ext = fileName.substring(fileName.lastIndexOf(".") + 1); + return getMediaTypeFromExt(ext); + } + + /** + * Allows you to override the media type map + * + * @param aMediaTypeMap the mediaTypeMap to set + */ + public static void setMediaTypeMap(Map aMediaTypeMap) { + mediaTypeMap = aMediaTypeMap; + } + +} diff --git a/src/main/resources/epub-mediatypes.properties b/src/main/resources/epub-mediatypes.properties new file mode 100644 index 0000000..7bc9785 --- /dev/null +++ b/src/main/resources/epub-mediatypes.properties @@ -0,0 +1,51 @@ +# The MIT License +# +# Copyright 2014 OpenCollab. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Mapping of file extensions to the correct media type, this file will be used +# in MediaTypeUtil + +xhtml=application/xhtml+xml +html=application/xhtml+xml +htm=application/xhtml+xml +jpg=image/jpeg +jpeg=image/jpeg +gif=image/gif +png=image/png +svg=image/svg+xml +ncx=application/x-dtbncx+xml +otf=application/vnd.ms-opentype +woff=application/font-woff +smil=application/smil+xml +pls=application/pls+xml +mp3=audio/mpeg +mp4=audio/mp4 +css=text/css +js=text/javascript +epub=application/epub+zip +tff=application/x-truetype-font +ogg=audio/ogg +xpgt=application/adobe-page-template+xml +pdf=application/pdf +docx=application/vnd.openxmlformats-officedocument.wordprocessingml.document +doc=application/msword +xls=application/vnd.ms-excel +xlsx=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet \ No newline at end of file diff --git a/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java b/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java new file mode 100644 index 0000000..b121530 --- /dev/null +++ b/src/test/java/coza/opencollab/epub/creator/EpubCreatorTest.java @@ -0,0 +1,41 @@ +package coza.opencollab.epub.creator; + +import coza.opencollab.epub.creator.model.EpubBook; +import java.io.File; +import java.io.FileOutputStream; +import junit.framework.Assert; +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +/** + * + * @author OpenCollab + */ +public class EpubCreatorTest { + + @Test + public void testEpubCreate() { + try (FileOutputStream file = new FileOutputStream(new File("test.epub"))) { + EpubBook book = new EpubBook("en", "Samuel .-__Id1", "Samuel Test Book", "Samuel Holtzkampf"); + + book.addContent(this.getClass().getResourceAsStream("/epub30-overview.xhtml"), + "application/xhtml+xml", "xhtml/epub30-overview.xhtml", true, true).setId("Overview"); + book.addContent(this.getClass().getResourceAsStream("/idpflogo_web_125.jpg"), + "image/jpeg", "img/idpflogo_web_125.jpg", false, false); + book.addContent(this.getClass().getResourceAsStream("/epub-spec.css"), + "text/css", "css/epub-spec.css", false, false); + book.addTextContent("TestHtml", "xhtml/samuelTest2.xhtml", "Samuel test one two four!!!!!\nTesting two").setToc(true); + book.addTextContent("TestHtml", "xhtml/samuelTest.xhtml", "Samuel test one two three\nTesting two").setToc(true); + book.addCoverImage(IOUtils.toByteArray(this.getClass().getResourceAsStream("/P1010832.jpg")), + "image/jpeg", "images/P1010832.jpg"); + + + book.writeToStream(file); + // TODO : real tests to see if document correct, this is just to test that creation is succesfull + Assert.assertEquals("test", "test"); + } catch (Exception ex) { + System.out.println(ex); + Assert.assertEquals("test", "test1"); + } + } +} diff --git a/src/test/resources/P1010832.jpg b/src/test/resources/P1010832.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e2e26ef2590be6b32cbd7c30ea8b658a974cd5c6 GIT binary patch literal 89562 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 literal 0 HcmV?d00001 diff --git a/src/test/resources/epub-spec.css b/src/test/resources/epub-spec.css new file mode 100644 index 0000000..15af5a9 --- /dev/null +++ b/src/test/resources/epub-spec.css @@ -0,0 +1,581 @@ +@charset "utf-8"; + +body { + margin-top: 2em; + margin-left: 6em; + margin-right: 15em; + margin-bottom: 2em; + font-family: arial, helvetica, sans-serif; + color: black; + background: white; +} + +/***************************************************************************/ +/* dl **************************************************************/ +/***************************************************************************/ + +dl dt { + font-weight: bold; +} + +dt span.term { + color: #005A9C; + font-weight: normal; +} + +dd > dl { + margin-top: 1px; + padding-top: 0px; + margin-bottom: 1px; + padding-bottom: 0px; +} + +/***************************************************************************/ +/* ul **************************************************************/ +/***************************************************************************/ + +ul.conformance-list li { + list-style-type: none; +} + +/***************************************************************************/ +/* glosslist *********************************************************/ +/***************************************************************************/ + +*.glosslist dl { + margin-left: 2em +} +*.glosslist dl dt { + color: #005A9C +} + +*.glossentry { + font-size: .9em; +} + +/***************************************************************************/ +/* misc block ********************************************************/ +/***************************************************************************/ + +p.informative, p.normative { + font-weight: bold; + font-size: 100%; + color: #8B0000; + padding: 5px 0px 10px; +} + +.biblioentry:target { + border: 1px dashed rgb(200,200,225); +} + + +/***************************************************************************/ +/* misc inline *******************************************************/ +/***************************************************************************/ + +code, span.property, a.codelink { + color: #660099; + font-family: monospace; + font-weight: bold +} +*.RFC2119 { + font-style: italic; + font-size: 80%; +} + +*.todo, *.TODO { + background-color: yellow +} + +/* vocab */ +*.subproplabel, *.subpropref { + font-style: italic; + font-size: 90%; +} + +/***************************************************************************/ +/* elem-synopsis ****************************************************/ +/***************************************************************************/ + +*.elem-synopsis { + border: 1px solid rgb(200,200,225); + border-top: 1px solid rgb(210,210,245); + border-left: 1px solid rgb(210,210,245); + background: rgb(240,240,255); + padding-left: 1em; + padding-right: 1em; + margin-bottom: 2em; + -moz-box-shadow: 5px 5px 5px #888; + -webkit-box-shadow: 5px 5px 5px #888; +} + +/* special case for the code.option fields in elem-synopsis */ +code.option { + color: black; + font-family: arial, helvetica, sans-serif; + font-weight: normal +} +/* for the special case when an attlist occurs outside of an elem-synopsis*/ +div.section > div.elem-synopsis-attlist { + border: 2px solid rgb(200,200,225); + background: rgb(230,230,255); + padding: 1em +} + + +/***************************************************************************/ +/* toc ***************************************************************/ +/***************************************************************************/ + +div.toc dl dt { + font-weight: normal +} + +*.toc p, div.list-of-examples p { + font: small-caps 105% sans-serif; + color: #005A9C; +} + +*.toc { + margin-top: 3em +} + +nav#toc li { + list-style-type:none; +} + +nav#toc > ol > li > span > a { + color: #0000ff +} +nav#toc > ol > li > ol > li > a { + color: #0033ff +} +nav#toc > ol > li > ol > li > ol > li > a { + font-size: .9em; + color: #0066ff; +} +nav#toc > ol > li > ol > li > ol > li > ol > li > a { + font-size: .9em; + color: #0099ff +} +nav#toc > ol > li > ol > li > ol > li > ol > li > ol > li > a { + font-size: .9em; + color: #0099ff +} +nav#toc > ol > li > ol > li > ol > li > ol > li > ol > li > ol > li > a { + font-size: .9em; + color: #0099ff +} + +nav#toc > ol > li > ol > li > ol > li > ol > li > ol > li > ol > li > ol > li > a { + font-size: .9em; + color: #0099ff +} + +/***************************************************************************/ +/* examples **********************************************************/ +/***************************************************************************/ + +div.informalexample { + margin: 1.5em auto 2em auto; +} + +div.informalexample > p { + margin: 0px 20px; + font-style: italic; + font-size: .8em +} + +div.informalexample > p code { + color: black; +} + +pre { + font-family: "Courier New", Courier, Monospace; + color: #000; + background-color: #eee; + margin: 0; + border: 1px solid #ddd; + padding: 9px; + overflow: auto; + white-space: pre-wrap; + white-space: -moz-pre-wrap !important; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + +} + +pre.synopsis, p.syntax { + background-color:rgb(253,253,253); + border: 1px solid rgb(220,220,220); + border-left: 1px solid rgb(230,230,230); + border-top: 1px solid rgb(230,230,230); + margin-bottom: 1em; + -moz-box-shadow: 5px 5px 5px #888; + -webkit-box-shadow: 5px 5px 5px #888; + -box-shadow: 5px 5px 5px #888; +} + +p.syntax { + font-family: courier, fixed, monospace; + padding: 9px; +} + +/***************************************************************************/ +/* note, caution *****************************************************/ +/***************************************************************************/ + +.caution .note { + font-style : italic; + font-size : .9em; +} + +div.note, div.caution { + margin: 2em 1em; + border: solid gray 1px; + background-color: rgb(255,255,224); + padding: .5em +} + + +div.caution { + background-color: rgb(255,235,205) +} + +div.note > *, div.caution > * { + /* margin: .25em 0em; + padding: 0em; */ +} + +div.note > h2, div.note > h3, div.note > h4, div.note > h5, +div.caution > h2, div.caution > h3, div.caution > h4, div.caution > h5 { + font-size: 1em; + font-style: italic; + font-variant: small-caps; + float: left; + padding: .18em .6em .18em .5em; + margin: -1em -0.5em -0.5em auto; + width: auto; + border: solid 1px; + background: white; +} + +/***************************************************************************/ +/* headings ************************************************************/ +/***************************************************************************/ + +h1, h2, h3, h4, h5, h6 { + text-align: left; + color: #005A9C; +} +h1 { + font: 170% sans-serif; + padding-bottom: 1em; +} +h2 { + font: 140% sans-serif; + padding-top: 2em; + border-bottom: 1px solid #005A9C +} +h3 { + font: 120% sans-serif; + padding-top: 1.5em; +} +h4 { + font: bold 110% sans-serif; + padding-top: 1.2em; +} +h5 { + font: italic 105% sans-serif +} +h6 { + font: italic 100% sans-serif +} +p.bridgehead { + font: 110% sans-serif; + padding-top: 0.7em; + color: #005A9C; +} + + +/***************************************************************************/ +/* links *******************************************************************/ +/***************************************************************************/ + +a.glossterm { + color: black; + text-decoration: none; + border-bottom : 1px dotted rgb(210,210,210); +} +a.biblioref { + color: #0000FF; + text-decoration: none; +} +a.glossterm:hover, a.biblioref:hover { + text-decoration: underline; + background-color: white; + color: #0000FF; +} + +/***************************************************************************/ +/* "link here" anchor *****************************************************/ +/***************************************************************************/ + +a.hidden-reveal { + color: #005A9C; +} +a.hidden-reveal:link { + text-decoration: none; + color: #005A9C; +} +a.hidden-reveal:visited { + text-decoration: none; + color: #005A9C; +} +a.hidden-reveal:hover { + text-decoration: underline; + background-color: #005A9C; + color: #FFFFFF; +} +a.hidden-reveal:active { + text-decoration: none; + color: #005A9C; +} + +/***************************************************************************/ +/* frontmatter ********************************************************/ +/***************************************************************************/ + +*.releaseinfo { + font-size: 140%; + color: #005A9C; + margin-right: 0.4em +} +*.pubdate { + font-size: 140%; + color: #005A9C +} +*.legalnotice { + font-size: 90% +} +dl.printhistory { + margin-top: 2em; + margin-bottom: 2em +} +dl.printhistory dt { + font: small-caps 105% sans-serif; + color: #005A9C; + margin-top: 0.4em; + margin-bottom: 0.4em +} +div.authorgroup p.editor { + margin-left: 2em; + font-size: 90% +} + +/***************************************************************************/ +/* table *************************************************************/ +/***************************************************************************/ + +table { + border: 1px solid #005A9C; + border-spacing: 0px; + padding: 1em; + margin-top: 1.5em; + margin-bottom: 2em; + -moz-box-shadow: 2px 2px 2px rgb(240,240,240); + -webkit-box-shadow: 2px 2px 2px rgb(190,190,190); + -box-shadow: 2px 2px 2px rgb(190,190,190); +} +th { + border: 1px solid #005A9C; + font-weight: bold; + padding: 0.5em; + font-weight: bold; + color: #005A9C; + font-size: 90% +} +td { + border: 1px solid #005A9C; + padding: 0.5em; + text-align: left +} +td *, td > * { + text-align: left; +} +table, tbody { + padding: 0; +} + +caption { + text-align: left; + font-size: 90% +} +/* the xsl renders db:simplelist as single-column tables */ +table.simplelist, table.simplelist th, table.simplelist td, table.simplelist tr { + border-style: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -box-shadow: none; +} + +/* ensure confomity of width for property tables */ +div.informaltable > table { + border-spacing: 0px; + border: 1px solid rgb(210,210,225); + font-size: 1em; + width: 100% +} + +div.informaltable > table td, div.informaltable > table th { + border: none; +} + +div.informaltable > table td.rdfa-property { + padding: 3px; + text-indent: 15px; + color: rgb(0,90,156); + background-color: rgb(240,240,255); + border-bottom: 1px solid rgb(210,210,225); +} +td.rdfa-property > code { + color: rgb(0,50,116); + font-weight: bold; + font-size: 1.1em +} +div.informaltable > table td.rdfa-property-header { + width: 150px; + text-align: center; + padding: 3px; + border-right: 1px solid rgb(210,210,225); + color: rgb(0,90,156); + background-color: rgb(240,240,255); +} +td.rdfa-property-desc { + padding: 3px +} + +td.rdfa-cardinality > p { + padding: 0em; + margin: 0em +} + +/* the core media types table */ +table#tbl-core-media-types > thead > tr > th, +table#tbl-epubReadingSystem-properties > thead > tr > th, +table#tbl-epubReadingSystem-features > thead > tr > th { + background-color: rgb(240,240,255); + text-align: left; + white-space:nowrap; +} + +table#tbl-core-media-types > tbody > tr > th { + text-align: left; + font-weight: normal; + font-style: italic; + padding: 3px; +} + +table#tbl-core-media-types td, table#tbl-core-media-types th, table#tbl-core-media-types tr { + border-color: #005A9C; + margin: 0em; +} + +table#tbl-core-media-types td code, table#tbl-core-media-types td a { + white-space:nowrap; +} + +table.productionset, table.productionset td { + border : none; + background-color : #EEE; +} + +td[headers="tbl-cmt-appl"] { + font-size: .9em; +} + +/* ns prefix table in contentdocs */ +table#tbl-nspfx { + border:none; + border-spacing: 0px; + margin-left: 1em; +} + +span.italic { + font-style: italic; +} + +span.link-marker { + float: left; +} + +/* display prop examples as block */ + +code.prop-example { + display: block; +} + +/* participant listings */ +ul.personlist { + list-style-type: none; + padding-left: 1em; + margin-bottom: 2em; +} + +*.personlist span.affiliation { + color: rgb(75,75,75); +} + +*.personlist span.wg-role { + font-style: italic; +} + +/* +span.surname { + text-transform: uppercase; +} +*/ + +table.productionset tbody tr { + border: none; +} + +table.productionset tbody tr td { + border: none; + border-bottom: 1px solid #CCC; +} + +table.productionset tbody tr td a { + text-decoration: none; + border-bottom: 1px dotted #0000ff; +} + +table.productionset tbody tr td a:hover { + text-decoration: underline; +} + +table.productionset tbody tr td a:visited, +table.productionset tbody tr td a:active, +table.productionset tbody tr td a:hover { + color: #0000ff; +} + + +p.diff, p.errata { + font-size: 0.9em; + font-style: italic +} + +code { + font-style: normal; +} + +div.informalexample > p code { + font-size: 1.2em; +} + +/* vocab experimental term labels */ +strong.experimental { + color: rgb(255,0,0) +} \ No newline at end of file diff --git a/src/test/resources/epub30-overview.xhtml b/src/test/resources/epub30-overview.xhtml new file mode 100644 index 0000000..b98ce6c --- /dev/null +++ b/src/test/resources/epub30-overview.xhtml @@ -0,0 +1,11 @@ + +EPUB 3 Overview +
+ IDPF Logo +
+

EPUB 3 Overview

Recommended Specification 11 October 2011

This version
http://www.idpf.org/epub/30/spec/epub30-overview-20111011.html
Latest version
http://www.idpf.org/epub/30/spec/epub30-overview.html
Previous version
http://www.idpf.org/epub/30/spec/epub30-overview-20110908.html

A diff of changes from the previous draft is available at this link.

Editors

Garth Conboy, Google Inc.

Matt Garrish, Invited Expert

Markus Gylling, DAISY Consortium

William McCoy, International Digital Publishing Forum (IDPF)

MURATA Makoto, JEPA EPUB Study Group

Daniel Weck, DAISY Consortium

 1 Introduction

 1.1 Overview

The EPUB® specification is a distribution and interchange format standard for digital publications and documents. EPUB defines a means of representing, packaging and encoding structured and semantically enhanced Web content — including HTML5, CSS, SVG, images, and other resources — for distribution in a single-file format.

EPUB 3, the third major release of the standard, consists of a set of four specifications, each defining an important component of an overall EPUB Publication:

  • EPUB Publications 3.0 [Publications30], which defines publication-level semantics and overarching conformance requirements for EPUB Publications.

  • EPUB Content Documents 3.0 [ContentDocs30], which defines profiles of XHTML, SVG and CSS for use in the context of EPUB Publications.

  • EPUB Open Container Format (OCF) 3.0 [OCF3], which defines a file format and processing model for encapsulating a set of related resources into a single-file (ZIP) EPUB Container.

  • EPUB Media Overlays 3.0 [MediaOverlays30], which defines a format and a processing model for synchronization of text and audio.

EPUB has been widely adopted as the format for digital books (eBooks), and these new specifications significantly increase the format's capabilities in order to better support a wider range of publication requirements, including complex layouts, rich media and interactivity, and global typography features. The expectation is that EPUB 3 will be utilized for a broad range of content, including books, magazines and educational, professional and scientific publications.

This document provides a starting point for content authors and software developers wishing to understand these specifications. It consists of non-normative overview material, including a roadmap to the four building-block specification documents that compose EPUB 3.

Another non-normative document, EPUB 3 Changes from EPUB 2.0.1 [EPUB3Changes], describes changes in EPUB 3 from the previous version, but is intended primarily for Authors and EPUB Reading System vendors migrating from EPUB 2.0.1 to EPUB 3 and for those who anticipate supporting both versions.

 1.2 Roadmap

This section provides an overview of the EPUB 3 specifications by explaining in brief the components of a Publication. Links to additional information within this document and to the specifications are included.

An EPUB Publication, at its most basic level, is a bundled collection of resources that can be reliably and predictably ingested by an EPUB Reading System in order to render its contents to a User. Some of these resources facilitate the discovery and processing of the EPUB Publication, while others make up the content of the source publication. The latter, EPUB Content Documents, are described in Content Documents and are fully defined in [ContentDocs30].

A Publication's resources are typically bundled for distribution as a ZIP-based archive with the file extension .epub. As conformant ZIP archives, Publications can be unzipped by many software programs, simplifying both their production and consumption. The container format is introduced in Container and defined in [OCF3].

The container format not only provides a means of determining that the zipped content represents an EPUB Publication (the mimetype file), but also provides a universally-named directory of informative resources (/META-INF). Key among these is the container.xml file, which directs Reading Systems to the root file of the Publication, the Package Document.

The Package Document is itself a kind of information warehouse for the Publication, storing metadata about the specific work contained in the Publication, providing an exhaustive list of resources and defining a default reading order. The Package Document is introduced in Package Document and defined in [Publications30].

The preceding components of an EPUB Publication are not new to EPUB 3, and will be familiar to anyone who has worked with Publications before, although they have been changed and enhanced in this version. A new core addition to EPUB 3, however, is the Media Overlay Document, which defines a means of synchronizing text and audio playback. The Overlay Document is introduced in Multimedia and defined in [MediaOverlays30].

The following example shows the resources a minimal "Hello World" Publication might contain:

+mimetype
+META-INF/container.xml
+Content/HelloWorld.opf
+Content/HelloWorld.xhtml
+

While conceptually simple, an EPUB Publication is more than just a collection of HTML pages and dependent assets in a ZIP package as represented in this example. The following sections of this document delve into more detail about the primary features and functionality that Publications provide to enhance the reading experience.

 2 Features

This section covers the major features of EPUB, including important components and topics that apply to the process of authoring EPUB Publications as a whole.

 2.1 Package Document

Every EPUB Publication includes a single Package Document, which specifies all the Publication's constituent content documents and their required resources, defines a reading order for linear consumption, and associates Publication-level metadata and navigation information.

The Package Document represents a significant improvement on a typical Web site. A Web site, for example, embeds references to its resources within its content, which, while a simple and flexible means of identifying resources, makes it difficult to enumerate all the resources required to render it. In addition, there is no standard way for a Web site to define that a sequence of pages make up a larger publication, which is precisely what EPUB's spine element does (i.e., it provides an external declarative means to explicitly specify navigation through a collection of documents). Finally, the Package Document defines a standard way to represent metadata globally applicable to a collection of pages.

The Package Document and other Publication-level constructs are specified in [Publications30].

 2.2 Navigation

 2.2.1 Reading Order

A key concept of EPUB is that a Publication consists of multiple resources that may be completely navigated and consumed by a person or program in some specific order.

Many publications have an obvious reading order, or logical progression through their content. A novel is an example of a highly sequential document — it typically has a beginning, middle and end — but not all publications are so ordered: a cookbook or collection of photographic images might be considered to be more like a database. All documents do, however, have at least one logical ordering of all their top-level content items, whether by date, topic, location or some other criteria (e.g., a cookbook is typically ordered by type of recipe).

Every EPUB Publication defines at least one such logical ordering of all its top-level content (the spine [Publications30]), as well as a declarative table of contents (the EPUB Navigation Document [ContentDocs30]). Publications make these data structures available in a machine-readable way external to the content, simplifying their discovery and use.

EPUB Publications are not limited to the linear ordering of their contents, nor do they preclude linking in arbitrary ways — just like the Web, EPUB Publications are built on hypertext — but the basic consumption and navigation can be reliably accomplished in a way that is not true for a set of HTML pages.

 2.2.2 Navigation Document

Every EPUB Publication contains a special XHTML Content Document called the EPUB Navigation Document, which uses the HTML5 nav element to define human- and machine-readable navigation information.

The Navigation Document supersedes the NCX document [OPS2], and the inclusion of NCX documents is only recommended for forward compatibility in older Reading Systems. The Navigation Document, while maintaining the baseline accessibility and navigation support and features of the NCX, introduces new functionality and rendering features to enhance navigation for all Users. Prime among these are better support for internationalization (as an XHTML5 document itself, the Navigation Document natively supports ruby annotations) and support for embedded grammars (MathML and SVG can be included within navigation links).

As XHTML Content Documents, Navigation Documents also provide a flexible means of tailoring the navigation display using CSS and the hidden attribute [ContentDocs30] while not impacting access to information for accessible Reading Systems.

The structure and semantics of Navigation Documents are defined in EPUB Navigation Documents [ContentDocs30].

 2.3 Linking

The new EPUB Canonical Fragment Identifier (epubcfi) Specification [EPUBCFI] defines a standardized method for linking into a Publication.

Required support for this scheme in Reading Systems means that EPUB now has an interoperable linking mechanism, one that can, for example, facilitate the sharing of bookmarks and reading locations across devices.

 2.4 Metadata

EPUB Publications provide a rich array of options for adding Publication metadata. The Package Document includes a dedicated metadata section [Publications30] for general information about the Publication, allowing titles, authors, identifiers and other information about the Publication to be easily accessed. It also provides the means to attach complete bibliographic records to a Publication using the link element [Publications30].

The Package Document also allows a Unique Identifier to be established for a Publication using the unique-identifier attribute [Publications30]. The required last-modified date in the Package metadata section can be joined with this identifier to define a Package Identifier, which provides a means of distinguishing EPUB Publications that represent different versions of the same Manifestation (see Publication Identifiers [Publications30]). The Package Identifier addresses the issue of how to release a Publication without changing its Unique Identifier while still identifying it as a new version.

XHTML Content Documents also include the means of annotating document markup with rich metadata, making them more semantically meaningful and useful both for processing and accessibility purposes (Semantic Inflection [ContentDocs30]).

 2.5 Content Documents

Every EPUB Publication contains one or more EPUB Content Documents, as defined in [ContentDocs30]. These are XHTML or SVG documents that describe the readable content of a Publication and reference associated media resources (e.g., images, audio and video clips).

XHTML Content Documents are defined by a profile of HTML5 that requires the use of XML serialization [HTML5] in order to ensure that content can be reliably manipulated and rendered. This profile also adds two additional EPUB-specific language constructs: the epub:type attribute [ContentDocs30] for element-level metadata and the epub:trigger element [ContentDocs30] for declaratively associating controls with multimedia elements.

These additions do not affect the ability of an HTML5 User Agent [HTML5] to render EPUB XHTML Content Documents, but Publications might not render identically in all User Agents depending on their support.

 2.6 Rendering and CSS

A key concept of EPUB is that content presentation should adapt to the User rather than the User having to adapt to a particular presentation of content. HTML was originally designed to support dynamic rendering of structured content, but over time HTML as supported in Web browsers has become focused on the needs of Web applications, and most popular Web sites now have fixed-format layouts.

EPUB Publications, however, are designed to maximize accessibility for the visually impaired, and Reading Systems typically perform text line layout and pagination on the fly, adapting to the size of the display area, the User's preferred font size, and other environmental factors. This behavior is not guaranteed in EPUB; images, vector graphics, video and other non-reflowable content may be included, and some Reading Systems might not paginate on the fly, or at all. Nevertheless, supporting dynamic adaptive layout and accessibility has been a primary design consideration throughout the evolution of the EPUB standard.

EPUB Content Documents may optionally reference EPUB Style Sheets, allowing Authors to define the desired rendering properties. EPUB 3 defines a profile of CSS based on CSS 2.1 [CSS2.1] for this purpose, together with capabilities defined by various CSS3 Modules and several additional properties specific to EPUB.

CSS3 properties were selected based on their current level of support in Web browsers, but support for them in Reading Systems and User Agents is not guaranteed (EPUB-defined properties may similarly be ignored).

EPUB 3 also supports CSS styles that enable both horizontal and vertical layout and both left-to-right and right-to-left writing, but Reading Systems might not support all of these capabilities. Reading Systems may also support different rendering options than the Author intended. Refer to CSS in the Global Language Support section for more information.

EPUB 3 also supports the ability to include multiple style sheets that allow users, for example, to select between day/night reading modes or to change the rendering direction of the text. Refer to Alternate Style Tags [ContentDocs30] for more information.

 2.7 Multimedia

EPUB 3 supports audio and video embedded in [content documents] via the new [HTML5] audio and video elements, inheriting all the functionality and features these elements provide. (For information on supported audio formats, please refer to Core Media Types [Publications30]. For recommendations on embedding video, refer to Reading System Conformance [Publications30].)

Another key new multimedia feature in EPUB 3 is the inclusion of Media Overlay Documents [MediaOverlays30]. When pre-recorded narration is available for a Publication, Media Overlays provide the ability to synchronize that audio with the text of a Content Document (see also Aural Renditions and Media Overlays).

 2.8 Fonts

EPUB 3 supports two closely-related font formats — OpenType [OpenType] and WOFF [WOFF] — to accommodate both traditional publishing workflows and emerging Web-based workflows. Word processing programs used to create Publications are likely to have access only to a collection of installed OpenType fonts, for example, whereas Web-archival EPUB generators will likely only have access to WOFF resources (which cannot be converted to OpenType without undesirable, and potentially unlicensed, stripping of WOFF metadata).

EPUB 3 also supports both obfuscated and regular font resources for both OpenType and WOFF font formats. Support for obfuscated font resources is required to accommodate font licensing restrictions for many commercially-available fonts.

 2.9 Scripting

EPUB strives to treat content declaratively — as data that can be manipulated, not programs that must be executed — but does support scripting as defined in HTML5 and SVG (refer to Scripted Content Documents [ContentDocs30] for more information).

It is important to note, however, that scripting support is optional for Reading Systems and may be disabled for security reasons.

Authors should also note that scripting in an EPUB Publication can create security considerations that are different from scripting within a Web browser. For example, typical same-origin policies are not applicable to content that has been downloaded to a User's local system. Therefore, it is strongly encouraged that scripting be limited to container constrained contexts, as further described in Scripted Content Documents — Content Conformance [ContentDocs30].

Scripting consequently should be used only when essential to the User experience, since it greatly increases the likelihood that content will not be portable across all Reading Systems and creates barriers to accessibility and content reusability.

 2.10 Text-to-speech

EPUB 3 provides the following text-to-speech (TTS) facilities for controlling aspects of speech synthesis, such as pronunciation, prosody and voice characteristics:

Pronunciation Lexicons

The inclusion of generic pronunciation lexicons using the W3C PLS format [PLS] enables Authors to provide pronunciation rules that apply to the entire EPUB Publication. Refer to PLS Documents [ContentDocs30] for more information.

Inline SSML Phonemes

The incorporation of SSML phonemes functionality [SSML] directly into a EPUB Content Document [ContentDocs30] enables fine-grained pronunciation control, taking precedence over default pronunciation rules and/or referenced pronunciation lexicons (as provided by the PLS format mentioned above). Refer to SSML Attributes [ContentDocs30] for more information.

CSS Speech Features

The inclusion of a select set of features from the CSS 3 Speech Module [CSS3Speech] (previously known as CSS 2.1 Aural Stylesheets [CSS2.1]) enables Authors to control further speech synthesis characteristics. Refer to CSS 3.0 Speech [ContentDocs30] for more information.

 2.11 Container

An EPUB Publication is transported and interchanged as a single file (a "portable document") that contains the Package Document, all Content Documents and all other required resources for processing the Publication. The single-file container format for EPUB is based on the widely adopted ZIP format. An XML manifest that specifies the location in the ZIP archive of the Package Document must be found at a well-defined location within the archive.

This approach provides a clear contract between any creator of an EPUB Publication and any system which consumes such Publications, as well as a reliable representation that is independent of network transport or file system specifics.

An EPUB Publication's representation as a container file is specified in [OCF3].

 3 Global Language Support

 3.1 Metadata

EPUB 3 supports alternate representations of all text metadata items in the package metadata section to improve global distribution of Publications. The alternate-script property can be combined with the xml:lang attribute to include and identify alternate script renditions of language-specific metadata.

Using this property, a Japanese Publication could, for example, include an alternate Roman-script representation of the author's name and/or one or more representations of the title in Romance languages. Refer to the alternate-script property [Publications30] for more information.

The page-progression-direction attribute also allows the content flow direction to be globally specified for all Content Documents to facilitate rendering (see the page-progression-direction [Publications30]).

 3.2 Content Documents

XHTML Content Documents leverage the new HTML5 directionality features to improve support for bidirectional content rendering: the bdi element allows an instance of directional text to be isolated from the surrounding content, the bdo element allows directionality to be overridden for its child content and the dir attribute allows the directionality of any element to be explicitly set.

XHTML Content Documents also support ruby annotations for pronunciation support (which makes them supported in Navigation Document links, as well).

SVG Content Documents support the rendering of bidirectional text, but do not include support for ruby.

 3.3 CSS

EPUB 3's support for new CSS3 modules enables typography for many different languages and cultures. Some specific enhancements include:

  • support for vertical writing, which also provides Reading Systems the ability to allow users to toggle direction;

  • better handling of emphasis, such as the inclusion of bōten;

  • better control over line breaking, so that breaks can occur at the character level for languages that do not use spaces to delimit new words; and

  • better control over hyphenation, to further facilitate line breaking.

 3.4 Fonts

EPUB 3 does not require that Reading Systems come with any particular set of built-in system fonts. As occurs in Web contexts, Users in a particular locale may have installed fonts that omit characters required for other locales, and Reading Systems may utilize intrinsic fonts or font engines that do not utilize operating system installed fonts. As a result, the text content of a Publication might not natively render as intended on all Reading Systems.

To address this problem, EPUB 3 supports the embedding of fonts to facilitate the rendering of text content, and this practice is recommended in order to ensure content is rendered as intended.

Support for embedded fonts also ensures that Publication-specific characters and glyphs can be embedded for proper display.

 3.5 Text-to-speech

EPUB 3's support for PLS documents and SSML attributes increases the pronunciation control that Authors have over the rendering of any natural language in text-to-speech-enabled Reading Systems. Refer to Text-to-speech in the Features section for more information on these capabilities.

The combination of CSS Speech and inline SSML phonemes also allows fine control over ruby.

 3.6 Container

The OCF container format supports UTF-8, allowing for internationalized file and directory naming of content resources.

 4 Accessibility

A major goal of EPUB is to facilitate content accessibility, and a variety of features in EPUB 3 support this requirement. This section reviews these features, detailing some established best practices for ensuring that EPUB Publications are accessible where applicable.

It is important to note that while accessibility is important in its own right, accessible content is also more valuable content: an accessible Publication will be adaptable to more devices and be easier to reuse, in whole or in part, via human and automated workflows. The EPUB Working Group strongly recommends that Authors use EPUB tools that generate accessible content.

 4.1 Navigation

EPUB 3 improves on NCX documents with the addition of EPUB Navigation Documents. As noted in Content Documents above, the new features these provide represent a more universal and flexible navigation system.

The need to navigate a document is not exclusively an accessibility issue, but a complete Navigation Document is key for all Users to be able to easily and fully access the contents of a document. The primary toc nav element (as defined in The toc nav Element [ContentDocs30]) should fully reflect the structure of the Publication, as a result.

For highly structured documents where it might not be desirable to display the complete table of contents to Users, the display level can be modified using the [HTML5] hidden attribute without minimizing the information that is available for accessible Reading Systems.

Authors are also encouraged to supply additional nav elements if their Publications contain non-structural points of interest, such as figures, tables, etc. in order to further enhance access to the content.

 4.2 Semantic Markup

HTML5 supports a number of new elements intended to make markup more semantically meaningful (e.g., section, nav, aside) and introduces more clearly defined semantics for some HTML4 elements. These elements, in conjunction with best practices for authoring well-structured Web content, should be utilized when creating EPUB XHTML Content Documents. These additions allow content to be better grouped and defined, both for representing the structure of documents and to facilitate their logical navigation. XHTML Content Documents also natively support the inclusion of ARIA role and state attributes and events, enhancing the ability of Assistive Technologies to interact with the content.

EPUB 3 further introduces the epub:type [ContentDocs30] attribute, which is meant to be functionally equivalent to the W3C Role Attribute [Role]. This attribute allows any element in an XHTML Content Document to include additional information about its purpose and meaning within the work, using controlled vocabularies and terms. Refer to Semantic Inflection [ContentDocs30] for more information.

 4.3 Dynamic Layouts

The design center of EPUB is dynamic layout: content is typically intended to be formatted on the fly rather than being typeset in a paginated manner in advance (i.e., expecting a particular sized "page"). This core capability is useful, for example, for optimizing rendering onto different sized device screens or window sizes, and it facilitates and simplifies content accessibility.

While it is possible to incorporate more highly formatted content in EPUB — for example via bitmap images or SVG graphics, or even use of CSS explicit positioning and/or table elements to achieve particular visual layouts — Authors are strongly discouraged from utilizing such techniques. They are not reliable in EPUB since many Reading Systems render content in a paginated manner rather than creating a single scrolling Viewport and since each Reading System may define its own pagination algorithm. If these techniques are required to convey the content of the publication (for example, for graphic novels), fallbacks [Publications30] should always be included.

In general, it is preferable to achieve visual richness by using EPUB Style Sheets without absolute sizing or positioning.

 4.4 Aural Renditions and Media Overlays

Aural renditions of content are important for accessibility and are a desirable feature for many other Users. A baseline to facilitate aural rendering is to utilize semantic HTML designed for dynamic layout. Refer to Text-to-speech for more information on how to use the native facilities that EPUB XHTML Documents include.

Media Overlays provide the ability to synchronize the text and audio content of a Publication, a feature already familiar to readers of DAISY Digital Talking Books. Overlays transcend the accessibility domain in their usefulness: the synchronization of text and audio as a tool for learning to read, for example, being of benefit in many circumstances.

 4.5 Fallbacks

Not all formats are accessible in their native format, and not all Users prefer to read in the default format provided. EPUB defines a variety of means for providing fallbacks so that alternate renditions of a Publication can be made available in these cases.

Publication and content-level fallbacks are defined in Restrictions and Fallbacks [Publications30]. These allow for the alternate rendition of specific resources within a Publication, such as SVG images or video clips.

In addition, multiple instances of a complete work can be delivered in a single Publication by defining multiple rootfile elements in the OCF container file (as described in Container – META-INF/container.xml [OCF3]). This kind of fallback may be used, for example, so that a formatted graphic novel defined via a sequence of SVG pages can be accompanied by an accessible text version defined via XHTML.

 4.6 Scripting

EPUB 3 adopts a progressive enhancement approach for scripted content, whereby scripting must not interfere with the integrity of the document (i.e., must not result in information loss when scripting is not available). Consequently, although documents that do employ scripting may provide fallbacks [ContentDocs30] to further facilitate access to their contents, the documents must be accessible without them.

Several mechanisms in EPUB can further minimize and constrain scripting within Publications to improve accessibility:

  • The declarative trigger element [ContentDocs30] added to the EPUB HTML5 profile enables image or textual elements to act as controls for audio and video playback (for example, to start, stop and pause playback). This element eliminates the common use of scripting to include similar functionality.

  • The mediaType element [Publications30] provides a means of encapsulating script-based support for rendering custom XML vocabularies or other custom content types, as well as future-proofs Publications in case such content types are natively supported in future Reading Systems.

  • The semantic inflection capability provided by the type attribute [ContentDocs30] enables Authors to provide hints to Reading Systems about content properties. One use case is to define elements such as images and video as having a zoomable property value, in which case a Reading System may provide a means for Users to access an expanded view that is out-of-line with the normal layout. Such rollover effects are typically implemented via scripting in Web contexts, but scripting cannot be readily implemented given the wide variety of layouts that a Reading System may generate.

  • The switch element [ContentDocs30] provides a declaractive means for Authors to tailor the content displayed to Users without having to resort to scripted solutions.

Best practices for accessible scripting in Web documents, such as provided in [WAI-ARIA], should always be consulted, and use of scripting should be reserved for situations in which interactivity is critical to the User experience.

diff --git a/src/test/resources/epub30-publications.xhtml b/src/test/resources/epub30-publications.xhtml new file mode 100644 index 0000000..24af9b2 --- /dev/null +++ b/src/test/resources/epub30-publications.xhtml @@ -0,0 +1,333 @@ + +EPUB Publications 3.0 +
+ IDPF Logo +
+

EPUB Publications 3.0

Recommended Specification 11 October 2011

This version
http://www.idpf.org/epub/30/spec/epub30-publications-20111011.html
Latest version
http://www.idpf.org/epub/30/spec/epub30-publications.html
Previous version
http://www.idpf.org/epub/30/spec/epub30-publications-20110908.html

A diff of changes from the previous draft is available at this link.

Please refer to the errata for this document, which may include some normative corrections.

Editors

Markus Gylling, DAISY Consortium

William McCoy, International Digital Publishing Forum (IDPF)

Matt Garrish, Invited Expert

 1 Overview

 1.1 Purpose and Scope

This section is informative

This specification, EPUB Publications 3.0, defines publication-level semantics and conformance requirements for EPUB® 3, including the format of the Package Document and rules for how this document and other Publication Resources are associated to create a conforming EPUB Publication.

This specification is one of a family of related specifications that compose EPUB 3, the third major revision of an interchange and delivery format for digital publications based on XML and Web Standards. It is meant to be read and understood in concert with the other specifications that make up EPUB 3:

  • The EPUB 3 Overview [EPUB3Overview], which provides an informative overview of EPUB and a roadmap to the rest of the EPUB 3 documents. The Overview should be read first.

  • EPUB Content Documents 3.0 [ContentDocs30], which defines profiles of XHTML, SVG and CSS for use in the context of EPUB Publications.

  • EPUB Open Container Format (OCF) 3.0 [OCF3], which defines a file format and processing model for encapsulating a set of related resources into a single-file (ZIP) EPUB Container.

  • EPUB Media Overlays 3.0 [MediaOverlays30], which defines a format and a processing model for synchronization of text and audio.

This specification supersedes Open Package Format 2.0.1 [OPF2]. Refer to [EPUB3Changes] for information on differences between this specification and its predecessor.

 1.3 Conformance Statements

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

All sections of this specification are normative except where identified by the informative status label "This section is informative". The application of informative status to sections and appendices applies to all child content and subsections they may contain.

All examples in this specification are informative.

 2 EPUB Publications

This section defines conformance requirements for EPUB Publications and EPUB Reading Systems at the Publication level. Conformance requirements particular to specific Publication Resources and processing contexts are located in the specifications referenced herein.

 2.1 Content Conformance

An EPUB Publication must meet all of the following criteria:

All Publication Resources

 All Publication Resources it contains must be represented in the Package Document (as defined in manifest), adhere to the constraints for Core Media Types and Fallback and be located as per Publication Resource Locations.

The Package Document

 It must contain exactly one Package Document, which must conform to the content requirements defined in Package Document — Content Conformance.

Content Documents

 It must contain at least one EPUB Content Document conformant to the content requirements defined in EPUB Content Documents [ContentDocs30].

The EPUB Navigation Document

 It must contain exactly one EPUB Navigation Document conformant to the content requirements defined in EPUB Navigation Documents — Content Conformance [ContentDocs30].

EPUB Style Sheets

 It may contain zero or more EPUB Style Sheets conformant to the content requirements defined in EPUB Style Sheets — Content Conformance [ContentDocs30].

EPUB Pronunciation Lexicons

 It may contain zero or more PLS Documents conformant to the content requirements defined in PLS Documents — Content Conformance [ContentDocs30].

Media Overlay Documents

 It may contain zero or more Media Overlay Documents conformant to the content requirements defined in [MediaOverlays30].

Additional Publication Resources

 It may contain zero or more Publication Resources in addition to those listed above, each of which must adhere to the requirements in All Publication Resources.

Container

 It must be packaged in a EPUB Container as defined in [OCF3].

 2.2 Reading System Conformance

An EPUB Reading System must meet all of the following criteria:

EPUB 3 Processing

 It must process the EPUB Container as defined in [OCF3].

 It must process the Package Document as defined in Package Document — Reading System Conformance, and honor all presentation logic expressed through the Package Document (e.g., the reading order, fallback chains and bindings).

 It must not fail catastrophically if it encounters two distinct EPUB Publications with the same Unique Identifier.

 Unless specified as conditional behavior in this section, it must support all Core Media Type Resources.

 It may support an arbitrary set of Foreign Resource types, and must process fallbacks for unsupported Foreign Resources as defined in Restrictions and Fallbacks if not.

 It must process XHTML Content Documents as defined in XHTML Content Documents — Reading System Conformance [ContentDocs30].

 It must process SVG Content Documents as defined in SVG Content Documents — Reading System Conformance [ContentDocs30].

 If it has a CSS Viewport, it must support visual rendering of XHTML Content Documents as defined in EPUB Style Sheets — Reading System Conformance [ContentDocs30].

 If it has the capability to render raster images, it must support the raster image Core Media Types.

 If it has the capability to render vector images, it must support the vector image Core Media Types.

 If it has the capability to render pre-recorded audio, it must support the MP3 audio Core Media Type, should support the MP4 audio Core Media Type and should support Media Overlays [MediaOverlays30].

 If it supports Text-to-Speech (TTS) rendering, it should support PLS Documents [ContentDocs30], the CSS3 Speech features of the EPUB CSS Profile [ContentDocs30] and SSML attributes [ContentDocs30] in XHTML Content Documents.

 It must support the EPUB Canonical Fragment Identifiers scheme [EPUBCFI] for linking, and may support additional linking schemes as defined in the EPUB Linking Scheme Registry.

note

It is recommended that Reading Systems support at least one of the [H.264] and [VP8] video codecs, but this is not a conformance requirement; a Reading System may support no video codecs at all. Content creators and Reading System developers should take into consideration factors such as breadth of adoption, video playback quality, and technology usage royalty requirements when making a choice to include or implement video in either (or potentially, both) formats.

Backward Compatibility

 It should process EPUB version 2 Publications as defined in [OPF2], [OPS2] and [OCF2].

 It must attempt to process any Publication whose Package Document version attribute designates a version lower than 3.0 or which omits the version attribute.

Forward Compatibility

 It should attempt to process any Publication whose Package Document version attribute designates a version higher than 3.0 or which omits the version attribute.

XML Processing

 It must be a conformant non-validating processor [XML].

  It must be a conformant processor as defined in [XMLNS].

 It must support xml-stylesheet processing instructions [ASSOCSS], and may support additional processing instructions.

 It must be a conformant application as defined by [XML Base].

note

A conforming Reading System is not necessarily a single dedicated program or device, but may exist as a distributed system.

 3 Package Documents

 3.1 Introduction

This section is informative

The Package Document carries bibliographic and structural metadata about an EPUB Publication, and is thus the primary source of information about how to process and display it.

The Package Document is an XML document consisting of a set of container elements, each dedicated to housing information about a particular aspect of the Publication. These containers effectively centralize metadata for the Publication, detail the individual resources that compose it and provide reading order and other information for rendering the Publication to a User.

The following list summarizes the information a Package Document contains:

  • Publication metadata — mechanisms for including and/or referencing metadata applicable to the entire Publication and particular resources within it.

  • A Publication manifest — identifies (via IRI) and describes (via MIME media type) the set of resources that collectively compose the Publication.

  • A spine — an ordered sequence of ID references to top-level resources in the manifest from which all other resources in the set can be reached or utilized. The spine defines the default reading order of the Publication.

  • Fallback chains — an optional means for Publications to define an ordered list of top-level resources that can be considered content equivalents that a Reading System can choose between for rendering.

  • Bindings — an optional means of associating script-based implementations with custom media types.

 3.2 Content Conformance

A Package Document must meet all of the following criteria:

Document Properties

  It must meet the conformance constraints for XML documents defined in XML Conformance.

 It must be valid to the Package Document schema, as defined in Appendix A, Package Document Schema, and conform to all content conformance constraints expressed in Package Document Definition.

File Properties

 The Package Document filename should use the file extension .opf.

Package Documents have the MIME media type application/oebps-package+xml [RFC4839].

 3.3 Reading System Conformance

An EPUB Reading System must meet all of the following criteria:

Processing

 It must process the Package Document in conformance with all Reading System conformance constraints expressed in Package Document Definition.

 3.4 Package Document Definition

All elements [XML] defined in this section are in the http://www.idpf.org/2007/opf namespace [XMLNS] unless otherwise specified.

 3.4.1 The package Element

The package element is the root container of the Package Document and encapsulates Publication metadata and resource information.

Element Name

package

Usage

The package element is the root element of the Package Document.

Attributes
version [required]

Specifies the EPUB specification version to which the Publication conforms.

The attribute must have the value 3.0 to indicate compliance with this version of the specification.

unique-identifier [required]

An IDREF [XML] that identifies the dc:identifier element that provides the package's preferred, or primary, identifier.

Refer to Publication Identifiers for more information.

prefix [optional]

Declaration mechanism for prefixes not reserved by this specification.

Refer to The prefix Attribute for more information.

xml:lang [optional]

Specifies the language used in the contents and attribute values of the carrying element and its descendants, as defined in section 2.12 Language Identification of [XML].

dir [optional]

Specifies the base text direction of the content and attribute values of the carrying element and its descendants.

Inherent directionality specified using [Unicode] takes precedence over this attribute.

Allowed values are ltr (left-to-right) or rtl (right-to-left).

id [optional]

The ID [XML] of this element, which must be unique within the document scope.

Content Model

In this order: metadata [required], manifest [required], spine [required], guide [optional/deprecated], bindings [optional]

 3.4.2 The metadata Element

The metadata element encapsulates Publication meta information.

Element Name

metadata

Usage

Required first child of package.

Attributes

The metadata element has no attributes defined in this specification.

Content Model

In any order: dc:identifier [1 or more], dc:title [1 or more], dc:language [1 or more], DCMES Optional Elements [0 or more], meta [1 or more], OPF2 meta [0 or more], link [0 or more]

The minimal required metadata that Publications must include consists of three elements from the Dublin Core Metadata Element Set [DCMES]title, identifier and language — together with the modified property from DCMI Metadata Terms [DCTERMS]. Refer to the example at the end of this section for an instance of a complete minimal metadata set.

Additional optional metadata is expressed using the DCMES optional elements and the meta element.

Examples

The following example represents the minimal set of metadata that all Publications must contain.

<package … unique-identifier="pub-id">
+    …
+    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <dc:identifier id="pub-id">urn:uuid:A1B0D67E-2E81-4DF5-9E67-A64CBE366809</dc:identifier>
+        <dc:title>Norwegian Wood</dc:title>
+        <dc:language>en</dc:language>
+        <meta property="dcterms:modified">2011-01-01T12:00:00Z</meta>
+    </metadata>
+    …
+</package>
+

 3.4.3 The DCMES identifier Element

The [DCMES] identifier element contains a single identifier associated with the EPUB Publication, such as a UUID, DOI, ISBN or ISSN.

Element Name

dc:identifier

Namespace

http://purl.org/dc/elements/1.1/

Usage

Required child of metadata. Repeatable.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

The id attribute is required on the identifier element containing the unique identifier. See below.

Content Model

Text

Every metadata section must include at least one identifier element containing an unambiguous identifier for the Publication. Multiple identifier elements are permitted, but only one can be marked as the Unique Identifier via the package element unique-identifier attribute.

The following example shows the unique identifier element for a Publication.

<package … unique-identifier="pub-id">
+    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <dc:identifier id="pub-id">urn:uuid:A1B0D67E-2E81-4DF5-9E67-A64CBE366809</dc:identifier>
+        …
+    </metadata>
+</package>

This specification makes a distinction between the Unique Identifier for an EPUB Publication and the identifier that uniquely identifies a specific version of it (i.e., to be able to differentiate EPUB Publications containing different versions of the same Manifestation). Two copies of an EPUB that are bit-for-bit identical are the same version and must retain the same last modified date. If they are not bit-for-bit identical, they represent different versions, and must have different last modified dates.

To identify a specific version of a packaged Publication, a Package Identifier can be constructed by combining the Unique Identifier with the last modified date of the Publication. Changes between versions may include minor typographic or markup corrections, without affecting the Unique Identifier. Significant revisions to the content that result in a new edition require a change of the Unique Identifier. For more information on the semantics and requirements of the Package Identifier, refer to Package Identifier.

This specification imposes no additional restrictions or requirements on identifiers except that they must be at least one character in length. It is strongly recommended that all identifiers be fully qualified URIs, however.

Reading Systems must trim all leading and trailing whitespace from the element value, as defined by the XML specification [XML], before processing the value.

To determine whether an identifier conforms to an established system or has been granted by an issuing authority, Reading Systems should parse the value of the property. For additional precision (e.g., if the scheme cannot be determined from the value or could lead to an ambiguous result), Authors may attach an identifier-type property to assist in Reading System identification. When included, the identifier-type property should take precedence over value parsing the identifier.

The following example shows how an identifier can be additionally marked as a DOI using the identifier-type property.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    <dc:identifier id="pub-id">urn:doi:10.1016/j.iheduc.2008.03.001</dc:identifier>
+    <meta refines="#pub-id" property="identifier-type" scheme="onix:codelist5">06</meta>
+    …
+</metadata>
+

This specification does not require or endorse the use of any specific scheme for identifiers, and imposes no restrictions or requirements on identifier-type identifiers beyond those specified in the property definition.

When an EPUB Publication is derived from another publication, the identifier for that source publication may be included in the Publication metadata, and must be represented using the DCMES source element.

 3.4.4 The DCMES title Element

The [DCMES] title element represents an instance of a name given to the EPUB Publication.

Element Name

dc:title

Namespace

http://purl.org/dc/elements/1.1/

Usage

Required child of metadata. Repeatable.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

xml:lang [optional]

Specifies the language used in the contents and attribute values of the carrying element and its descendants, as defined in section 2.12 Language Identification of [XML].

dir [optional]

Specifies the base text direction of the content and attribute values of the carrying element and its descendants.

Inherent directionality specified using [Unicode] takes precedence over this attribute.

Allowed values are ltr (left-to-right) or rtl (right-to-left).

Content Model

Text

Every metadata section must include at least one title element containing the title for the Publication. Multiple title elements are permitted, but the title-type property should be attached to indicate the type of title (e.g., the main title of a work, a subtitle, etc.).

The following example shows how to indicate different title types.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:title id="t1">A Dictionary of Modern English Usage</dc:title>
+    <meta refines="#t1" property="title-type">main</meta>
+    
+    <dc:title id="t2">First Edition</dc:title>
+    <meta refines="#t2" property="title-type">edition</meta>
+    
+    <dc:title id="t3">Fowler's</dc:title>
+    <meta refines="#t3" property="title-type">short</meta>
+    …
+</metadata>
+

When adding the title-type property, Authors should designate only one title element as containing the main title for the Publication. If no means of determining title types is provided, or understood, Reading Systems must treat the first title element in document order as the main title. This specification does not define how additional title elements should be processed in such situations.

The optional display-seq property may also be attached to each title to indicate their primacy for display and other rendering purposes.

The following example shows how to indicate display sequence.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:title id="t1">The Red and the Black</dc:title>
+    <meta refines="#t1" property="title-type">main</meta>
+    <meta refines="#t1" property="display-seq">1</meta>
+    
+    <dc:title id="t2">A Chronicle of the Nineteenth Century</dc:title>
+    <meta refines="#t2" property="title-type">subtitle</meta>
+    <meta refines="#t2" property="display-seq">2</meta>
+    
+    <dc:title id="t3">A Chronicle of 1830</dc:title>
+    <meta refines="#t3" property="title-type">subtitle</meta>
+    <meta refines="#t3" property="display-seq">3</meta>
+    …
+</metadata>
+

This specification imposes no additional restrictions or requirements on titles except that they must be at least one character in length.

Reading Systems must trim all leading and trailing whitespace from the element value, as defined by the XML specification [XML], before processing the value.

Examples

The following example shows how the title "THE LORD OF THE RINGS, Part One: The Fellowship of the Ring" could be classified.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    <dc:title id="t1">The Fellowship of the Ring</dc:title>
+    <meta refines="#t1" property="title-type">main</meta>
+    
+    <dc:title id="t2">The Lord of the Rings</dc:title>
+    <meta refines="#t2" property="title-type">collection</meta>
+    <meta refines="#t2" property="group-position">1</meta>
+    
+    <dc:title id="t3">THE LORD OF THE RINGS, Part One: The Fellowship of the Ring</dc:title>
+    <meta refines="#t3" property="title-type">extended</meta> 
+    …
+</metadata>
+

The following example shows how the complex title "The Great Cookbooks of the World: Mon premier guide de cuisson, un Mémoire. The New French Cuisine Masters, Volume Two. Special Anniversary Edition" could be classified.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    <dc:title id="t1" xml:lang="fr">Mon premier guide de cuisson, un Mémoire</dc:title>
+    <meta refines="#t1" property="title-type">main</meta>
+    <meta refines="#t1" property="display-seq">2</meta>
+    
+    <dc:title id="t2">The Great Cookbooks of the World</dc:title>
+    <meta refines="#t2" property="title-type">collection</meta>
+    <meta refines="#t2" property="display-seq">1</meta>
+    
+    <dc:title id="t3">The New French Cuisine Masters</dc:title>
+    <meta refines="#t3" property="title-type">collection</meta>
+    <meta refines="#t3" property="group-position">2</meta>
+    <meta refines="#t3" property="display-seq">3</meta>
+    
+    <dc:title id="t4">Special Anniversary Edition</dc:title>
+    <meta refines="#t4" property="title-type">edition</meta>
+    <meta refines="#t4" property="display-seq">4</meta>
+    
+    <dc:title id="t5">The Great Cookbooks of the World: 
+        Mon premier guide de cuisson, un Mémoire. 
+        The New French Cuisine Masters, Volume Two. 
+        Special Anniversary Edition</dc:title>
+    <meta refines="#t5" property="title-type">extended</meta>
+    …
+</metadata>
+

 3.4.5 The DCMES language Element

The [DCMES] language element specifies the language of the Publication content.

Element Name

dc:language

Namespace

http://purl.org/dc/elements/1.1/

Usage

Required child of metadata.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

Content Model

Text

Every metadata section must include at least one language element with a value conforming to [RFC5646].

The following example shows a Publication is in U.S. English.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:language>en-US</dc:language>
+    …
+</metadata>
+

Additional language elements may be included for multilingual Publications, but each element's value must conform to [RFC5646].

Reading Systems must trim all leading and trailing whitespace from the element value, as defined by the XML specification [XML], before processing the value.

 3.4.6 The DCMES Optional Elements

All elements from the [DCMES] element set — except for identifier, language and title, as defined above — are designated as optional. These elements all conform to the following generalized definition:

Element Name

contributor | coverage | creator | date | description | format | publisher | relation | rights | source | subject | type

Namespace

http://purl.org/dc/elements/1.1/

Usage

Optional child of metadata. Repeatable.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

xml:lang* [optional]

Specifies the language used in the contents and attribute values of the carrying element and its descendants, as defined in section 2.12 Language Identification of [XML].

dir* [optional]

Specifies the base text direction of the content and attribute values of the carrying element and its descendants.

Inherent directionality specified using [Unicode] takes precedence over this attribute.

Allowed values are ltr (left-to-right) or rtl (right-to-left).

Content Model

Text

* The xml:lang and dir attributes are permitted only on the following elements: contributor, coverage, creator, description, publisher, relation, rights and subject.

The value of all optional [DCMES] elements must be at least one character in length.

Reading Systems must trim all leading and trailing whitespace from the element value, as defined by the XML specification [XML], before processing the value.

Except as detailed below, this specification does not modify the [DCMES] definitions for these elements.

The DCMES contributor Element

The contributor element is used to represent the name of a person, organization, etc. that played a secondary role in the creation of the content of a Publication.

The use of the contributor element is identical to the use of the creator element in all other respects, as detailed in the next section.

The DCMES creator Element

The creator element represents the name of a person, organization, etc. responsible for the creation of the content of a Publication. The role property can be attached to the element to indicate the function the creator played in the creation of the content.

The following example shows how to represent a creator as an author using a MARC relators term.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:creator id="creator">Haruki Murakami</dc:creator>
+    <meta refines="#creator" property="role" scheme="marc:relators" id="role">aut</meta>
+    …
+</metadata>
+

The creator element should contain the name of the creator as a Reading System will present it to a User. The file-as property may be attached to include a normalized form of the name, and the alternate-script property can be used to represent a creator's name in another language or script.

The following example shows the different ways a creator's name can be included to facilitate processing and rendering.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:creator id="creator">Haruki Murakami</dc:creator>
+    <meta refines="#creator" property="role" scheme="marc:relators" id="role">aut</meta>
+    <meta refines="#creator" property="alternate-script" xml:lang="ja">村上 春樹</meta>
+    <meta refines="#creator" property="file-as">Murakami, Haruki</meta>
+    …
+</metadata>
+

If a Publication has more than one creator, each should be included in a separate creator element. The order in which to render the creator names should be specified using the display-seq property.

The following example shows how to indicate the display order for creator elements.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:creator id="creator01">Lewis Carroll</dc:creator>
+    <meta refines="#creator01" property="role" scheme="marc:relators">aut</meta>
+    <meta refines="#creator01" property="display-seq">1</meta>
+    
+    <dc:creator id="creator02">John Tenniel</dc:creator>
+    <meta refines="#creator02" property="role" scheme="marc:relators">ill</meta>
+    <meta refines="#creator02" property="display-seq">2</meta>
+    …
+</metadata>
+

If no means of establishing the primacy of creators is included, Reading Systems must use the order of creator elements.

Secondary contributors should be represented using DCMES contributor elements.

The DCMES date Element

The date element must only be used to define the publication date of the EPUB Publication. The publication date is not the same as the last modified date (the last time the content was changed), which must be included using the [DCTERMS] modified property.

For compliance with EPUB 2 Reading Systems, the date string should conform to Date and Time Formats.

The following example shows a publication date.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:date>2000-01-01T00:00:00Z</dc:date>
+    …
+</metadata>
+

Additional dates should be expressed using the specialized date properties available in the [DCTERMS] vocabulary, or similar.

The publication date may be common to all instances of a Publication or may change from instance to instance (if the Publication gets generated on demand, for example).

Only one date element is allowed.

The DCMES source Element

The source element must only be used to specify the identifier of the source publication from which this EPUB Publication is derived.

The following example shows the ISBN identifier for a Publication together with the source ISBN identifier for the print work it was derived from.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:identifier id="isbn-id">urn:isbn:9780101010101</dc:identifier>
+    <meta refines="#isbn-id" property="identifier-type" scheme="onix:codelist5">15</meta>
+    
+    <dc:source id="src-id">urn:isbn:9780375704024</dc:source>
+    <meta refines="#src-id" property="identifier-type" scheme="onix:codelist5">15</meta>
+    …
+</metadata>
+

The source element allows the print source of the pagination of a Publication to be determined.

Only one source element is allowed.

The DCMES type Element

The type element is used to indicate that the given Publication is of a specialized type (e.g., annotations packaged in EPUB format or a dictionary).

This specification does not define values for this element, however. The development of specialized Publication types, and the assignment of formal identifiers to represent them, will occur independently of this specification.

Only one type element is allowed.

 3.4.7 The meta Element

The meta element provides a generic means of including package metadata, allowing the expression of primary metadata about the package or content and refinement of that metadata.

Element Name

meta

Usage

As child of the metadata element. Repeatable.

Attributes
property [required]

A property.

Refer to Vocabulary Association Mechanisms for more information.

refines [context dependent]

Identifies the expression or resource augmented by this element. The value of the attribute must be a relative IRI [RFC3987] pointing to the resource or element it describes.

The refines attribute is optional depending on the type of metadata being expressed. When omitted, the meta element defines a primary expression.

id [optional]

The ID [XML] of this element, which must be unique within the document scope.

scheme [optional]

A property data type value indicating the source the value of the element is drawn from.

Content Model

Text

Each meta element defines a metadata expression, where the property attribute defines the statement being made in the expression and the text content of the element represents the assertion.

This specification defines two types of metadata expressions that can be defined using the meta element:

  • A primary expression is one in which the expression defined in the meta element establishes some aspect of the EPUB Publication. A meta element that omits a refines attribute defines a primary expression.

  • A subexpression is one in which the expression defined in the meta element enhances the meaning of the expression or resource referenced in its refines attribute. A subexpression may refine a media clip, for example, by expressing its duration, or refine a creator or contributor expression by defining the person's role.

    Subexpressions are not limited to refining only primary expressions and resources; they may be used to refine the meaning of other subexpressions, thereby creating chains of information.

note

All of the [DCMES] elements represent primary expressions, and permit refinement by meta element subexpressions.

This specification reserves a set of vocabularies for use in the property attribute, but terms from any vocabulary may be used so long as a prefix is declared for the vocabulary.

The scheme attribute can be used to identify the system or scheme that a meta element's value is drawn from. The value of the scheme attribute is a property data type that resolves to the resource that defines the scheme.

The following example shows how a subexpression can be attached to an creator to indicate it represents an author. The scheme indicates the value is drawn from the MARC relators terms.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:creator id="creator">Haruki Murakami</dc:creator>
+    <meta refines="#creator" property="role" scheme="marc:relators" id="role">aut</meta>
+    …
+</metadata>
+

If a Reading System does not recognize the scheme attribute value, it should treat the value of the element as a string.

Reading Systems should ignore all meta elements whose property attributes define expressions they do not recognize. A Reading System must not fail when encountering unknown expressions.

In order to ensure that a Package Identifier can be constructed, the metadata element must contain exactly one meta element defining a [DCTERMS] modified property for the Publication. Additional modified properties may be included, but they must have a different subject (i.e., they must include a refines attribute pointing to an element or resource).

Every meta element must express a value that is at least one character in length after whitespace normalization.

Unless an individual property explicitly defines a different whitespace normalization algorithm, Reading Systems must trim all leading and trailing whitespace from the meta element values, as defined by the XML specification [XML], before further processing them.

Examples

The following example represents a more complete set of metadata that typical Publications will contain.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    …
+    <dc:identifier id="pub-id">urn:uuid:A1B0D67E-2E81-4DF5-9E67-A64CBE366809</dc:identifier>
+    <meta refines="#pub-id" property="identifier-type" scheme="xsd:string">uuid</meta>
+    
+    <dc:identifier id="isbn-id">urn:isbn:9780101010101</dc:identifier>
+    <meta refines="#isbn-id" property="identifier-type" scheme="onix:codelist5">15</meta>
+    
+    <dc:source id="src-id">urn:isbn:9780375704024</dc:source>
+    <meta refines="#src-id" property="identifier-type" scheme="onix:codelist5">15</meta>
+    
+    <dc:title id="title">Norwegian Wood</dc:title>
+    <meta refines="#title" property="title-type">main</meta>
+    
+    <dc:language>en</dc:language>
+    
+    <dc:creator id="creator">Haruki Murakami</dc:creator>
+    <meta refines="#creator" property="role" scheme="marc:relators" id="role">aut</meta>
+    <meta refines="#creator" property="alternate-script" xml:lang="ja">村上 春樹</meta>
+    <meta refines="#creator" property="file-as">Murakami, Haruki</meta>
+    
+    <meta property="dcterms:modified">2011-01-01T12:00:00Z</meta>
+    
+</metadata>
+

The following example shows an identifier that has been issued by a metadata authority.

<package version="3.0" 
+         unique-identifier="pub-id"
+         xmlns="http://www.idpf.org/2007/opf">
+    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <dc:identifier id="pub-id">urn:uuid:1234-5678</dc:identifier>
+        <dc:identifier id="isbn-id">urn:isbn:9780101010101</dc:identifier>
+        
+        <meta refines="#isbn-id" property="meta-auth" id="meta-authority-01">Metadata Authority Inc.</meta>
+        <link refines="#meta-authority-01" rel="xml-signature" href="../META-INF/Signatures.xml#MAI-Signature"/>
+        …
+    </metadata>
+</package>
+
+<!-- in Signatures.xml -->
+<signatures>
+    <Signature Id="MAI-Signature" xmlns="http://www.w3.org/2000/09/xmldsig#">
+        …
+    </Signature>
+</signatures>
+

 3.4.8 The meta Element (OPF2) [OBSOLETE]

The meta element defined in [OPF2] has been obsoleted and replaced by the new meta element, but may be included as an optional repeatable child of the metadata element for forwards compatibility purposes.

EPUB 3 Reading Systems must ignore this element.

 3.4.10 The manifest Element

The manifest element provides an exhaustive list of the Publication Resources that constitute the EPUB Publication, each represented by an item element.

Element name

manifest

Usage

Required second child of package, following metadata.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

Content Model

One or more item elements [required]

note

This specification supports internationalized resource naming, so elements and attributes that reference Publication Resources accept IRIs as their value. For compatibility with older Reading Systems that only accept URIs, resource names should be restricted to the ASCII character set.

 3.4.11 The item Element

The item element represents a Publication Resource.

Element Name

item

Usage

As a child of manifest. Repeatable.

Attributes
id [required]

The ID [XML] of this element, which must be unique within the document scope.

href [required]

An IRI [RFC3987] specifying the location of the Publication Resource described by this item.

media-type [required]

A media type [RFC2046] that specifies the type and format of the Publication Resource described by this item.

fallback [conditionally required]

An IDREF [XML] that identifies the fallback for a non-Core Media Type.

Refer to Manifest Fallbacks for more information.

properties [optional]

A space-separated list of property values.

Refer to Manifest item Properties for a set of properties defined by this specification.

media-overlay [optional]

An IDREF [XML] that identifies the Media Overlay Document for the resource described by this item.

Refer to Packaging [MediaOverlays30] for more information.

Content Model

Empty

Each item element in the manifest identifies a Publication Resource by the IRI provided in its href attribute. The IRI may be absolute or relative. In the case of relative IRIs, Reading Systems must use the IRI of the Package Document as the base when resolving these to absolute IRIs. The resulting absolute IRI must be unique within the manifest scope.

All Publication Resources must be referenced from the manifest, regardless of whether they are included in the EPUB Container or made available remotely. Refer to Publication Resource Locations for media type-specific requirements regarding resource locations.

The Publication Resource identified by an item element must conform to the applicable specification(s) as inferred from the MIME media type provided in the media-type attribute. Core Media Type Resources must use the media type designated in EPUB Core Media Types.

All Foreign Resources must provide a fallback as defined in Restrictions and Fallbacks.

All Publication Resources must declare any applicable descriptive metadata properties as defined in Manifest item Properties via the item element properties attribute. Exactly one item must be declared as the EPUB Navigation Document using the nav property.

Reading Systems must ignore all descriptive metadata properties that they do not recognize.

The manifest is not self-referencing: it must not include an item element that refers to the Package Document itself.

note

The order of item elements in the manifest is not significant. The presentation sequence of content documents is provided in the spine.

Examples

The following example shows a manifest that only contains Core Media Type Resources.

<manifest>
+    <item id="nav" 
+          href="nav.xhtml" 
+          properties="nav"
+          media-type="application/xhtml+xml"/>
+    <item id="intro" 
+          href="intro.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c1" 
+          href="chap1.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c1-answerkey" 
+          href="chap1-answerkey.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c2" 
+          href="chap2.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c2-answerkey" 
+          href="chap2-answerkey.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c3" 
+          href="chap3.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="c3-answerkey" 
+          href="chap3-answerkey.xhtml" 
+          media-type="application/xhtml+xml"/>    
+    <item id="notes" 
+          href="notes.xhtml" 
+          media-type="application/xhtml+xml"/>
+    <item id="cover" 
+          href="./images/cover.svg" 
+          properties="cover-image"
+          media-type="image/svg+xml"/>
+    <item id="f1" 
+          href="./images/fig1.jpg" 
+          media-type="image/jpeg"/>
+    <item id="f2" 
+          href="./images/fig2.jpg" 
+          media-type="image/jpeg"/>
+    <item id="css" 
+          href="./style/book.css" 
+          media-type="text/css"/>   
+    <item id="pls" 
+          href="./speech/dict.pls" 
+          media-type="application/pls+xml"/>
+</manifest>
+

The following example shows a manifest that references two Foreign Resources, and therefore uses the fallback chain mechanism to supply content alternatives. The fallback chain terminates with a Core Media Type.

<manifest>
+    <item id="item1" 
+          href="chap1_docbook.xml" 
+          media-type="application/docbook+xml" 
+          fallback="fall1"/>
+    <item id="fall1" 
+          href="chap1.xml" 
+          media-type="application/z3986-auth+xml" 
+          fallback="fall2" />
+    <item id="fall2" 
+          href="chap1.xhtml" 
+          media-type="application/xhtml+xml"/> 
+    … 
+</manifest>
+

note

Refer also to the Manifest item properties examples for use of the properties attribute.

 3.4.12 The spine Element

The spine element defines the default reading order of the EPUB Publication content by defining an ordered list of manifest item references.

Element name

spine

Usage

Required third child of package, following manifest.

Attributes
id [optional]

The ID [XML] of this element, which must be unique within the document scope.

toc [optional]

An IDREF [XML] that identifies the manifest item that represents the superseded NCX.

Refer to NCX Superseded for more information.

page-progression-direction [optional]

The global direction in which the Publication content flows.

Allowed values are ltr (left-to-right), rtl (right-to-left) and default.

When the default value is specified, the Author is expressing no preference and the Reading System may chose the rendering direction. This value must be assumed when the attribute is not specified.

Content Model

Multiple itemref elements [required]

The spine represents an ordered subset of the Publication Resources listed in the manifest, with content items not being referenced being ancillary to those that do.

Reading Systems must provide a means of rendering a Publication in the order defined by the spine, which includes: 1) recognizing the first primary (linear='yes') item in the spine as the beginning of the main reading order of the Publication; and, 2) rendering successive primary items in the order given in the spine.

note

Although the page-progression-direction attribute sets the global flow direction for a Publication, individual Content Documents and parts of Content Documents may override this setting (e.g., via the direction and writing-mode CSS properties). Reading Systems may also provide mechanisms to override the default direction (e.g., buttons or settings that allow the application of alternate style sheets).

NCX Superseded

The NCX feature defined in [OPF2] is superseded by the EPUB Navigation Document [ContentDocs30]. EPUB 3 Publications may include an NCX (as defined in OPF 2.0.1) for EPUB 2 Reading System forwards compatibility purposes, but EPUB 3 Reading Systems must ignore the NCX in favor of the EPUB Navigation Document.

note

As the EPUB 2 NCX and the EPUB 3 Navigation Document use different mechanisms for identification in the Package Document (the spine toc attribute and the nav property on the manifest item element, respectively) they can co-exist without conflict in an EPUB 3 Publication.

 3.4.13 The itemref Element

The child itemref elements of the spine represent a sequential list of Publication Resources (typically EPUB Content Documents). The order of the itemref elements defines the default reading order of the Publication.

Element Name

itemref

Usage

As a child of spine. Repeatable.

Attributes
idref [required]

An IDREF [XML] that identifies a manifest item.

linear [optional]

Specifies whether the referenced content is primary.

The value of the attribute must be yes or no. The default value is yes.

id [optional]

The ID [XML] of this element, which must be unique within the document scope.

properties [optional]

A space-separated list of property values.

Refer to Spine itemref Properties for a set of properties defined by this specification.

Content Model

Empty

Each itemref element must reference an item in the manifest via its idref attribute.

Each referenced manifest item must be either a) an EPUB Content Document or b) another type of Publication Resource which, regardless of whether it is a Core Media Type Resource or a Foreign Resource, must include an EPUB Content Document in its fallback chain.

note

Although the EPUB Navigation Document is required in EPUB Publications, it is optional to include it in the spine.

The itemref element linear attribute indicates whether referenced item is considered primary (yes) or auxiliary (no) in the spine. This attribute may be used to enable Reading Systems to distinguish presentation of body content from supplementary content which might be, for example, presented in a popup window or omitted from an aural rendition.

Any applicable descriptive metadata properties, such as those defined in the Spine itemref Properties, should be declared via the properties attribute.

Reading Systems must ignore all metadata properties expressed in the properties attribute that they do not recognize.

Examples

The following example shows a spine element corresponding to the manifest example above.

<spine page-progression-direction="ltr">
+    <itemref idref="intro"/>
+    <itemref idref="c1"/>
+    <itemref idref="c1-answerkey" linear="no"/>
+    <itemref idref="c2"/>
+    <itemref idref="c2-answerkey" linear="no"/>
+    <itemref idref="c3"/>
+    <itemref idref="c3-answerkey" linear="no"/>
+    <itemref idref="notes" linear="no"/>
+</spine>
+

 3.4.14 The guide Element [DEPRECATED]

The guide element [OPF2] is deprecated in favor of the landmarks feature in the EPUB Navigation Document. Refer to The landmarks nav Element [ContentDocs30] for more information.

Authors may include the guide element in the Package Document for EPUB 2 Reading System forwards compatibility purposes. EPUB 3 Reading Systems must ignore the guide element when provided in EPUB 3 Publications whose EPUB Navigation Document includes the landmarks feature.

 3.4.15 The bindings Element

The bindings element defines a set of custom handlers for media types not supported by this specification.

Element Name

bindings

Usage

Optional fourth or fifth child of package, following spine or guide.

Attributes

None.

Content Model

One or more mediaType elements [required]

The package element may contain at most one bindings element.

The bindings element provides a means for Authors to include more sophisticated fallbacks than would otherwise be possible with the [HTML5] object element's intrinsic fallback mechanisms. When present, Reading Systems that support scripting must utilize the bindings element to handle object elements that reference unsupported media types.

Each of the bindings element's child mediaType elements defines a unique handler for one of the foreign media types referenced in the Publication's XHTML Content Documents.

When an unsupported media type is encountered during processing of a document, the Reading System must look up the handler in the bindings element by checking the media-type attribute of each mediaType element for a match (and before attempting any other type of fallback processing). If a match is found, the XHTML Content Document referenced in the element's handler attribute must be instantiated instead of the referenced resource. If no match is found, the Reading System should continue with normal fallback processing (i.e., check for an intrinsic fallback for the object).

The Reading System must instantiate the designated handler as if it had been referenced from the object element's data attribute with the following parameters:

src

the value of which must be an IRI [RFC3987] to the resource (i.e., the value of the object element's data attribute).

type

the value of which must be the resource media type (i.e., the value of the object element's media-type attribute).

Any additional param children of the object element must be similarly added as parameters using the param's name attribute as the new parameter name and its value attribute as the new value.

For example, the following object element containing a foreign media type:

<object data="horse.ogg" media-type="audio/ogg"/>
+    <param name="autoplay" value="false">
+</object>
+        

would result in the following query string being sent to the handler XHTML Content Document after processing:

src=horse.ogg&type=audio/ogg&autoplay=false

All IRI reserved characters, plus the characters <, >, ", space, {, }, |, \, ^ and `, in the generated query string must be encoded and decoded as per [RFC3987].

object elements that reference media types handled by the bindings element are only processed in spine-referenced XHTML Content Documents (i.e., they are ignored in container-constrained scripting contexts).

Example

The following partial example illustrates how bindings can be used to provide a slideshow.

Consider a Publication with the following Package Document:

<package …>
+    …
+    <manifest>
+        <item id="pict1" 
+            href="images/Pict1.jpg" 
+            media-type="image/jpeg"/>
+        …
+        <item id="content" 
+            href="content.xhtml" 
+            media-type="application/xhtml+xml"/>
+        <item id="impl" 
+            href="impl.xhtml" 
+            media-type="application/xhtml+xml" 
+            properties="scripted"/>
+        <item id="slideshow" 
+            href="slideshow.xml" 
+            media-type="application/x-demo-slideshow"/>
+    </manifest>
+    
+    <bindings>
+        <mediaType handler="impl"
+            media-type="application/x-demo-slideshow"/>
+    </bindings>
+    …
+</package>
+

and the following content in the file content.xhtml:

<html …>
+    …
+    <body>
+        …
+        <object data="slideshow.xml" 
+            type="application/x-demo-slideshow">
+            <img src="images/Pict1.jpg"/>
+            <img src="images/Pict2.jpg"/>
+            <img src="images/Pict3.jpg"/>
+            <img src="images/Pict4.jpg"/>
+        </object>
+        …
+    </body>
+</html>
+

and the following content in the file slideshow.xml:

<slides>
+    <slide src="images/Pict1.jpg" dur="3"/>
+    <slide src="images/Pict2.jpg" dur="3"/>
+    <slide src="images/Pict3.jpg" dur="3"/>
+    <slide src="images/Pict4.jpg" dur="3"/>
+</slides>
+

Depending on the capabilities of the User's Reading System, they will see one of the following renditions of the slideshow:

  • If the Reading System supports the native slideshow format, it will render a rotating set of images as specified in slideshow.xml.

  • If the Reading System cannot support the slideshow media type but supports scripting, it can check the bindings element in the Package Document for a scripted fallback. There it will find a reference to the item element containing the handler document (impl.xhtml). The Reading System can now load this document to render a JavaScripted equivalent of the slideshow (source not shown).

  • If the Reading System does not support the slideshow media type and also does not support scripting, it will use the fallback images specified in the object element to show a static set of all the images.

 3.4.16 The mediaType Element

The mediaType element associates a Foreign Resource media type with a handler XHTML Content Document.

Element Name

mediaType

Usage

As a child of bindings. Repeatable.

Attributes
media-type [required]

A media type [RFC2046] that specifies the type and format of the resource to be handled.

handler [required]

An IDREF [XML] that identifies the manifest XHTML Content Document to be invoked to handle content of the type specified in this element

Content Model

Empty

Each child mediaType of a bindings element must define a unique content type in its media-type attribute, and the media type specified must not be a Core Media Type.

The required handler attribute must reference the ID [XML] of an item in the manifest of the default implementation for this media type. The referenced item must be an XHTML Content Document.

All XHTML Content Documents designated as handlers must have the scripted property set in their manifest item's properties attribute.

 4 Package Metadata

 4.1 Publication Identifiers

 4.1.1 Unique Identifier

The Package Document's author is responsible for including a primary identifier that is unique to one and only one particular EPUB Publication. This Unique Identifier, whether chosen or assigned, must be stored in a dc:identifier element in the Package metadata and be referenced as the Unique Identifier in the package element unique-identifier attribute.

Although not static, changes to the Unique Identifier for a Publication should be made as infrequently as possible. New identifiers should not be issued when updating metadata, fixing errata or making other minor changes to the Publication.

 4.1.2 Package Identifier

The Unique Identifier of an EPUB Publication typically should not change with each minor revision to the package or its contents, as Unique Identifiers are intended to have maximal persistence both for referencing and distribution purposes. Each release of a Publication normally requires that the new version be uniquely identifiable, however, which results in the contradictory need for reliable Unique Identifiers that are changeable.

To redress this problem of identifying minor modifications and releases without changing the Unique Identifier, this specification defines the semantics for a Package Identifier, or means of distinguishing and sequentially ordering Publications with the same Unique Identifier. The Package Identifier is not an actual property in the package metadata section, but is a value that can be obtained from two required pieces of metadata: the Unique Identifier and the last modification date of the Publication.

When the taken together, the combined value represents a unique identity that can be used to distinguish any particular version of an EPUB Manifestation from another. To ensure that a Package Identifier can be constructed, the Publication must include exactly one [DCTERMS] modified property containing the last modification date (see meta). The value of this property must be an XML Schema [XSD-DATATYPES] dateTime conformant date of the form:

CCYY-MM-DDThh:mm:ssZ

The modification date must be expressed in Coordinated Universal Time (UTC) and must be terminated by the Z time zone indicator.

Although not a part of the package metadata, for referencing and other purposes this specification requires that all string representations of the identifier be constructed using the at sign (@) as the separator (i.e., of the form "id@date"). Whitespace must not be included when concatenating the strings.

The following example shows how a Unique Identifier and modification date are combined to form the Package Identifier.

<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
+    <dc:identifier id="pub-id">urn:uuid:A1B0D67E-2E81-4DF5-9E67-A64CBE366809</dc:identifier>
+    <meta property="dcterms:modified">2011-01-01T12:00:00Z</meta>
+    …
+</metadata>
+
+results in the Package ID:
+
+urn:uuid:A1B0D67E-2E81-4DF5-9E67-A64CBE366809@2011-01-01T12:00:00Z
+

Note that it is possible that the separator character may occur in the Unique Identifier, as these identifiers may be any string value. The Package Identifier consequently must be split on the last instance of the at sign when decomposing it into its component parts.

The Package Identifier does not supersede the Unique Identifier, but represents the means by which different versions of the same Publication can be distinguished and identified in distribution channels and by Reading Systems. The sequential, chronological order inherent in the required format of the timestamp also places Publications in order without requiring knowledge of the exact identifier that came before.

The Package Identifier consequently allows a set of Publications to be inspected to determine if they represent the same version of the same Publication, different versions of a single Publication, or any combination of differing and similar Publications.

 4.2 Vocabulary Association Mechanisms

 4.2.1 Overview

This section is informative

The property, properties, rel and scheme attributes use the property data type to represent terms from metadata vocabularies. Similar to a CURIE [RDFa10], the property data type represents an IRI [RFC3987] in compact form and simplifies the authoring of metadata from standardized vocabularies.

A property value is an expression that consists of a prefix and a reference, where the prefix — whether literal or implied — is a shorthand mapping of an IRI that typically resolves to a term vocabulary. When the prefix is converted to its IRI representation and combined with the reference, the resulting IRI normally resolves to a fragment within that vocabulary that contains human- and/or machine-readable information about the term.

To assist Reading Systems in processing property values, the means of establishing the IRI a prefix maps to is required, and this specification defines three such mechanisms:

  • a default vocabulary — defines the mapping when a property value does not include a prefix;

  • a set of reserved prefixes — these mappings are predefined (i.e., all Reading Systems recognize them) and can be used without having to be declared; and

  • the prefix attribute — a declarative means of creating new prefix mappings on the root package element.

 4.2.2 Default Vocabulary

The default vocabulary is a vocabulary that does not require a prefix to be declared in order to use its terms in package metadata, and whose terms must always be unprefixed.

To facilitate the inclusion of package metadata, this specification defines the Package Metadata Vocabulary as the default vocabulary for Package Documents.

If a property value does not include a prefix, the IRI [RFC3987] stem http://idpf.org/epub/vocab/package/# must be used to generate the resulting IRI.

The IRI associated with the Package Metadata Vocabulary must not be assigned a prefix using the prefix attribute.

 4.2.3 Reserved Vocabularies

This specification exclusively defines the following set of prefixes for use in package metadata.

Reserved metadata prefixes
Prefix IRI
dcterms http://purl.org/dc/terms/
marc http://id.loc.gov/vocabulary/
media http://www.idpf.org/epub/vocab/overlays/#
onix http://www.editeur.org/ONIX/book/codelists/current.html#
xsd http://www.w3.org/2001/XMLSchema#

The prefixes listed in the previous table must not be redeclared using the prefix attribute declaration mechanism. Similarly, the IRIs associated with each prefix must not be assigned to another prefix.

 4.2.4 The prefix Attribute

The prefix attribute defines additional prefix mappings not reserved by the specification.

The value of the prefix attribute is a whitespace-separated list of one or more prefix-to-IRI mappings of the form:

(EBNF productions ISO/IEC 14977)
prefixes=mapping , { whitespace, { whitespace } , mapping } ; 
mapping=prefix , ":" , space , { space } , ? xsd:anyURI ? ; 
prefix=? xsd:NCName ? ; 
space=#x20 ; 
whitespace=(#x20 | #x9 | #xD | #xA) ; 

The following example shows prefixes for the Friend of a Friend (foaf) and DBPedia (dbp) vocabularies being declared using the prefix attribute.

<package … 
+	prefix="foaf: http://xmlns.com/foaf/spec/
+		 dbp: http://dbpedia.org/ontology/">
+	…
+</package>

The prefix attribute must not be used to redefine the default vocabulary or the predefined prefixes.

The prefix '_' is reserved for future compatibility with RDFa [RDFa10] processing, so must not be defined.

 4.2.5 The property Data Type

 4.2.5.1 Syntax

The property data type is a compact means of expressing an IRI [RFC3987] and consists of an optional prefix separated from a reference by a colon.

(EBNF productions ISO/IEC 14977)
property=[ prefix , ":" ] , reference; 
prefix=? xsd:NCName ? ; 
reference=? irelative-ref ? ;/* as defined in [RFC3987] */

The property data type is derived from the CURIE data type defined in [RDFa10], and represents a subset of CURIEs.

The following example shows a property value composed of the prefix dcterms and the reference modified.

<meta property="dcterms:modified">2011-01-01T12:00:00Z</meta>

After processing, this property would expand to the following IRI:

http://purl.org/dc/terms/modified

as the dcterms: prefix is a reserved prefix that maps to the IRI http://purl.org/dc/terms/.

When a prefix is omitted from the property value, the expressed reference represents a term from the default vocabulary.

The following example shows a property value taken from the default vocabulary.

<meta … property="role">aut</meta>

This property would expand to:

http://idpf.org/epub/vocab/package/#role

when the IRI for the default vocabulary is concatenated with the reference.

An empty string does not represent a valid property value, even though it is valid to the definition above.

 4.2.5.2 Processing

A Reading System must use the following rules to create an IRI [RFC3987] from a property:

  • If the property consists only of a reference, the IRI is obtained by concatenating the IRI stem associated with the default vocabulary to the reference.

  • If the property consists of a prefix and reference, the IRI is obtained by concatenating the IRI stem associated with the prefix to the reference. If no matching prefix has been defined, the property is invalid.

The resulting IRI must be valid to [RFC3987]. Reading Systems are not required to resolve this IRI, however.

 4.3 Package Metadata Vocabulary

 4.3.1 Overview

This section is informative

The following sections both define a set of properties for use in package metadata and constitute a referenceable vocabulary. This vocabulary is the default vocabulary reserved by this specification for the use of unprefixed terms in package metadata.

The properties defined in this vocabulary are referenceable using the base IRI http://idpf.org/epub/vocab/package/#.

note

Property usage examples in the following sections have been drawn from the metadata and meta examples whenever possible. Refer to those examples for fuller context.

 4.3.2 Metadata meta Properties

The meta element properties enhance Publication metadata by providing additional level(s) of detail.

These properties must reference the expression or resource they augment in the refines attribute on their parent meta element.

The following tables detail the available properties.

alternate-script
Description:

The alternate-script property provides an alternate expression of the associated property value in a language and script identified by the xml:lang attribute.

This property is typically attached to creator and title properties for internationalization purposes.

Allowed value(s): xsd:string
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends:All properties.
Example: <meta refines="#creator" property="alternate-script" xml:lang="ja">村上 春樹</meta>
display-seq
Description:

The display-seq property indicates the numeric position in which to display the current property relative to identical metadata properties (e.g., to indicate the order in which to render multiple titles).

When the display-seq property is attached to some, but not all, of the members in a set, only the elements identified as having a sequence should be included in any rendering.

Allowed value(s): xsd:unsignedInt
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends:All properties.
Example: <meta refines="#t2" property="display-seq">1</meta>
file-as
Description:The file-as property provides the normalized form of the associated property for sorting.
Allowed value(s): xsd:string
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends:All properties.
Example: <meta refines="#creator" property="file-as">Murakami, Haruki</meta>
group-position
Description:

The group-position property indicates the numeric position in which the Publication is ordered relative to other works belonging to the same group (whether all EPUBs or not).

The group-position property can be attached to any metadata property that establishes the group (such as a series title).

A Publication can belong to more than one group.

Allowed value(s): A single xsd:unsignedInt or series of decimal-separated numbers (e.g., 1 or 2.2.1).
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends: All properties.
Example: <meta refines="#t3" property="group-position">2</meta>
identifier-type
Description:

The identifier-type property indicates the form or nature of an identifier.

When the identifier-type value is drawn from a code list or other formal enumeration, the scheme attribute should be attached to identify its source.

Allowed value(s):xsd:string
Extends:identifier
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Example: <meta refines="#src-id" property="identifier-type" scheme="onix:codelist5">15</meta>
meta-auth
Description:The meta-auth property provides the name of a party or authority responsible for an instance of package metadata.
Allowed value(s): xsd:string
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends:All properties.
Example: <meta refines="isbn-id" property="meta-auth" id="meta-authority-01">Metadata Authority Inc.</meta>
role
Description:

The role property describes the nature of work performed by a creator or contributor (e.g., that the person is the author or editor of a work).

When the role value is drawn from a code list or other formal enumeration, the scheme attribute should be attached to identify its source.

Allowed value(s):xsd:string
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Extends: contributor, creator
Example: <meta refines="#creator" property="role" scheme="marc:relators">aut</meta>
title-type
Description:

The title-type property indicates the form or nature of a title.

When the title-type value is drawn from a code list or other formal enumeration, the scheme attribute should be attached to identify its source. When a scheme is not specified, Reading Systems should recognize the following title type values: main, subtitle, short, collection, edition and expanded.

Allowed value(s):xsd:string
Extends:title
Cardinality:

In the metadata section: zero or more

Attached to other metadata: zero or one

Example: <meta refines="#title" property="title-type">main</meta>

 4.3.4 Manifest item Properties

The following tables define properties for use in the manifest item element properties attribute.

The Applies to field indicates which Publication Resource type(s) the given property may be specified on, the Cardinality field indicates the number of times the property must appear within the Package Document scope, and the Usage field indicates usage conditions.

cover-image
Description:The cover-image property identifies the described Publication Resource as the cover image for the Publication.
Applies to:All raster and vector image types
Cardinality:Zero or one
Usage:Optional.
mathml
Description:The mathml property indicates that the described Publication Resource contains one or more instances of MathML markup.
Applies to:EPUB Content Documents
Cardinality:Zero or more
Usage:Must be set if and only if the criterion specified in Description above is met.
nav
Description:The nav property indicates that the described Publication Resource constitutes the EPUB Navigation Document of the Publication.
Applies to:The EPUB Navigation Document
Cardinality:Exactly one
Usage:Required.
remote-resources
Description:

The remote-resources property indicates that the described Publication Resource contains one or more internal references to other Publication Resources that are located outside of the EPUB Container.

(refer to Publication Resource Locations for more information).

Applies to:All Publication Resources with the capability of internal referencing (e.g., XHTML Content Documents, SVG Content Documents, EPUB Style Sheets and Media Overlay Documents).
Cardinality:Zero or more
Usage:Must be set if and only if the criterion specified in Description above is met.
scripted
Description:The scripted property indicates that the described Publication Resource is a Scripted Content Document (i.e., contains scripted content and/or elements from HTML5 forms).
Applies to:EPUB Content Documents
Cardinality:Zero or more
Usage:Must be set if and only if the criterion specified in Description above is met.
svg
Description:The svg property indicates that the described Publication Resource contains one or more instances of SVG markup.
Applies to:XHTML Content Documents; the value is implied for SVG Content Documents.
Cardinality:Zero or more
Usage:Must be set if and only if the criterion specified in Description above is met.
switch
Description:The switch property indicates that the described Publication Resource contains one or more instances of the epub:switch element.
Applies to:XHTML Content Documents.
Cardinality:Zero or more
Usage:Must be set if and only if the criterion specified in Description above is met.

The mathml, remote-resources, scripted, svg and switch properties must be specified whenever the resource referenced by an item matches their respective definitions. These properties do not apply recursively to content included into a resource (e.g., via the HTML5 iframe element). For example, if a non-scripted XHTML Content Document embeds a scripted Content Document, only the embedded document's manifest item properties attribute will have the scripted value.

Examples

The following example shows a manifest item element that represents the EPUB Navigation Document of a Publication.

<item properties="nav" id="c1" href="c1.xhtml" media-type="application/xhtml+xml" />
+

The following example shows a manifest item element that represents the cover image of a Publication.

<item properties="cover-image" id="ci" href="cover.svg" media-type="image/svg+xml" />
+

The following example shows a manifest item element representing a Scripted Content Document that also contains embedded MathML.

<item properties="scripted mathml" id="c2" href="c2.xhtml" media-type="application/xhtml+xml" />
+

 4.3.5 Spine itemref Properties

The following tables define properties for use in the itemref element properties attribute.

The Cardinality field indicates the number of times the property must appear within the Package Document scope, and the Usage field indicates usage conditions.

page-spread-left
Description:The page-spread-left property indicates that the first page of the associated item's EPUB Content Document represents the left-hand side of a two-page spread.
Cardinality:Zero or more
Usage:Optional. This property must not be specified on an itemref that also specifies the page-spread-right property.
page-spread-right
Description:The page-spread-right property indicates that the first page of the associated item's EPUB Content Document represents the right-hand side of a two-page spread.
Cardinality:Zero or more
Usage:Optional. This property must not be specified on an itemref that also specifies the page-spread-left property.

Examples

The following example shows how a two-page spread of a map might be indicated in the spine.

<spine>
+	<itemref idref="title"/>
+	<itemref idref="ps-1-l" properties="page-spread-left"/>
+	<itemref idref="ps-1-r" properties="page-spread-right"/>
+	<itemref idref="toc"/>
+	…
+</spine>

 5 Publication Resources

 5.1 Core Media Types

The following table lists the EPUB 3 Core Media Types. When a Publication Resource conforms to a Core Media Type specification, it is a Core Media Type Resource and can be included in the Publication without the provision of fallbacks (refer to Restrictions and Fallbacks for more information).

The columns in the table represent the following information:

Media Type

The MIME media type [RFC2046] used to represent the given Publication Resource in the manifest.

Content Type Definition

The specification to which the given Core Media Type Resource must conform.

Applies to

The Publication Resource type(s) that the Media Type and Content Type Definition applies to.

EPUB Core Media Types
Media Type Content Type Definition Applies to
Image Types
image/gif [GIF] GIF Images
image/jpeg [JPEG] JPEG Images
image/png [PNG] PNG Images
image/svg+xml SVG Content Documents [ContentDocs30] SVG documents
Application Types
application/xhtml+xml XHTML Content Documents [ContentDocs30] XHTML Content Documents and the EPUB Navigation Document.
application/x-dtbncx+xml [OPF2] The superseded NCX
application/vnd.ms-opentype [OpenType] OpenType fonts
application/font-woff [WOFF] WOFF fonts
application/smil+xml [MediaOverlays30] EPUB Media Overlay documents
application/pls+xml [PLS] Text-to-Speech (TTS) Pronunciation lexicons
Audio Types
audio/mpeg [MP3] MP3 audio
audio/mp4 [AAC LC], [MP4] AAC LC audio using MP4 container
Text Types
text/css EPUB Style Sheets [ContentDocs30] EPUB Style Sheets.
text/javascript [RFC4329] Scripts

note

This specification does not define any video codecs as Core Media Types. Refer to the note in EPUB Publications — Reading System Conformance above for informative recommendations on support for video codecs in EPUB Publications.

 5.2 Restrictions and Fallbacks

 5.2.1 Foreign Resource Restrictions

All Publication Resources of an EPUB Publication must be Core Media Type Resources or must provide a Core Media Type fallback. The cases in which Foreign Resource may be used, and the requirement and rules for Core Media Type fallback provision in such cases, are detailed below.

Intrinsic Fallback in EPUB Content Documents

 Foreign Resources may be referenced from EPUB Content Document elements that have explicit intrinsic fallback mechanisms (e.g., the [HTML5] object, canvas, audio and video elements). A Core Media Type resource must be provided via the given element's intrinsic fallback mechanism in such cases.

 For the [HTML5] video element, the image referenced by the poster attribute and text content embedded within the video element are also considered valid Core Media Type fallbacks in addition to the video element's intrinsic fallback capabilities. For the purpose of providing a last resort fallback for Reading Systems that do not support video or the given video format(s), at least one of these should be included with each occurrence of the video element.

 For the [HTML5] audio element, text content embedded within the element is also considered a valid Core Media Type fallback in addition to the audio element's intrinsic fallback capabilities. For the purpose of providing a last resort fallback for Reading Systems that do not support audio, embedded text content should be included with each occurrence of the audio element.

  In this version of this specification, the [HTML5] track element is exempt from the Core Media Type usage rule: Foreign Resources may be referenced from track without the provision of a Core Media Type fallback.

Intrinsic Fallback in EPUB Style Sheets

 Fonts embedded in Content Documents or EPUB Style Sheets using the @font-face mechanism may be Foreign Resources. Reading Systems must use the rules for matching font styles [CSS3Fonts] when identifying a fallback for an unsupported font type.

Spine Resources

 Foreign Resources may be referenced directly from spine itemref elements, and in this case Manifest fallbacks must be provided.

 5.2.2 Manifest Fallbacks

Fallbacks must be provided for each Publication Resource referenced in a spine itemref element that is not an EPUB Content Document.

Fallbacks are provided using the fallback attribute on the manifest item element that represents the Publication Resource. The fallback attribute's IDREF [XML] value must resolve to another item in the manifest. This fallback item may itself specify another fallback item, and so on.

The ordered list of all the ID references that can be reached starting from a given item's fallback attribute represents the fallback chain for that item. The order of the resources in the fallback chain represents the Authors' preferred fallback order.

A Reading System that does not support the Media Type of a given Publication Resource must traverse the fallback chain until it has identified at least one supported Publication Resource to be used in place of the unsupported resource. If the Reading System supports multiple Publication Resources in the fallback chain, it may select the resource to use based on specific properties of that resource, otherwise it should honor the Authors' preferred fallback order.

A fallback chain must contain at least one EPUB Content Document and must not contain any circular- or self-references to items in the chain.

Fallbacks may also be provided for Top-level Content Documents that are EPUB Content Documents; a Reading System may choose to utilize such fallbacks in order to find the optimal version of a Content Document to render in a given context. An example of when this feature can be utilized is when providing fallbacks for scripted content [ContentDocs30].

 5.3 Publication Resource Locations

All Publication Resources must be located in the EPUB Container, with the following exceptions:

  •  Audio resources may be located in the Container or remotely.

  •  Video resources may be located in the Container or remotely.

Authors should prefer locating audio and video resources in the Container to allow the user access to the entire presentation regardless of connectivity status.

note

The above rules for Publication Resource locations apply regardless of whether the given resource is a Core Media Type Resource or a Foreign Resource.

note

The inclusion of remote resources in an EPUB Publication is indicated via the remote-resources property on the manifest item element.

 5.4 XML Conformance

Any Publication Resource that is an XML-Based Media Type must meet the following constraints:

The above constraints apply regardless of whether the given Publication Resource is a Core Media Type Resource or a Foreign Resource.

 Appendix A. Package Document Schema

The schema for Package Documents is available at http://www.idpf.org/epub/30/schema/package-30.nvdl.

This schema is normative.

note

Validation using this schema will require a processor that supports [NVDL], [RelaxNG] and [ISOSchematron].

Note, however, that the NVDL schema layer can be substituted by a multi-pass validation using the embedded RELAX NG and ISO Schematron schemas alone.

 Appendix B. The application/oebps-package+xml Media Type

This appendix registers the media type application/oebps-package+xml for the EPUB Package Document. This registration supersedes [RFC4839].

The Package Document is an XML file that describes an EPUB Publication [Publications30]. It identifies the resources in the Publication and provides metadata information. The Package Document and its related standards are maintained and defined by the International Digital Publishing Forum (IDPF).

MIME media type name:

application

MIME subtype name:

oebps-package+xml

Required parameters:

None.

Optional parameters:

None.

Encoding considerations:

Package Documents are UTF-8 or UTF-16 encoded XML.

Security considerations:

Package Documents contain well-formed XML conforming to the XML 1.0 specification.

Clearly, it is possible to author malicious files which, for example, contain malformed data. Most XML parsers protect themselves from such attacks by rigorously enforcing conformance.

All processors that read Package Documents should rigorously check the size and validity of data retrieved.

There is no current provision in the EPUB Publications 3.0 standard for encryption, signing, or authentication within the Package Document format.

Interoperability considerations:

None.

Published specification:

This media type registration is for the EPUB Package Document, as described by the EPUB Publications 3.0 specification located at http://www.idpf.org/epub/30/spec/epub30-publications.html.

The EPUB Publications 3.0 specification supersedes the Open Packaging Format 2.0.1 specification, which is located at http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm and which also uses the application/oepbs-package+xml media type.

Applications which use this media type:

This media type is in wide use for the distribution of ebooks in the EPUB format. The following list of applications is not exhaustive.

  • Adobe Digital Editions

  • Aldiko

  • Azardi

  • Apple iBooks

  • Barnes & Noble Nook

  • Calibre

  • Google Books

  • Ibis Reader

  • MobiPocket reader

  • Sony Reader

  • Stanza

Additional information:
Magic number(s):

none

File extension(s):

.opf

Macintosh File Type Code(s):

TEXT

Fragment Identifiers:

The IDPF maintains a registry of linking schemes at http://idpf.org/epub/linking/. Some of these schemes define custom fragment identifiers that resolve to application/oebps-package+xml documents.

Person & email address to contact for further information:

William McCoy, bmccoy@idpf.org

Intended usage:

COMMON

Author/Change controller:

International Digital Publishing Forum (http://www.idpf.org)

diff --git a/src/test/resources/epub30-terminology.xhtml b/src/test/resources/epub30-terminology.xhtml new file mode 100644 index 0000000..1cbe6b8 --- /dev/null +++ b/src/test/resources/epub30-terminology.xhtml @@ -0,0 +1,11 @@ + +Terminology +
+ IDPF Logo +
+

Terminology

+
+ +
Author

The person(s) or organization responsible for the creation of an EPUB Publication, which is not necessarily the creator of the content and resources it contains.

EPUB Container (or Container)

The ZIP-based packaging and distribution format for EPUB Publications defined in [OCF3].

EPUB Content Document

A Publication Resource that conforms to one of the EPUB Content Document definitions (XHTML or SVG).

An EPUB Content Document is a Core Media Type, and may therefore be included in the EPUB Publication without the provision of fallbacks.

EPUB Navigation Document

A specialization of the XHTML Content Document, containing human- and machine-readable global navigation information, conforming to the constraints expressed in EPUB Navigation Documents [ContentDocs30].

Scripted Content Document

An EPUB Content Document that includes scripting or an XHTML Content Document that contains HTML5 forms elements.

Refer to Scripted Content Documents [ContentDocs30] for more information.

SVG Content Document

An EPUB Content Document conforming to the constraints expressed in SVG Content Documents [ContentDocs30].

XHTML Content Document

An EPUB Content Document conforming to the profile of [HTML5] defined in XHTML Content Documents [ContentDocs30].

XHTML Content Documents use the XHTML syntax of [HTML5].

Top-level Content Document

An EPUB Content Document referenced directly from the spine

Core Media Type

A set of Publication Resource types for which no fallback is required. Refer to Publication Resources for more information.

EPUB Publication (or Publication)

A logical document entity consisting of a set of interrelated resources and packaged in an EPUB Container, as defined by this specification and its sibling specifications.

EPUB Reading System (or Reading System)

A system that processes EPUB Publications for presentation to a User in a manner conformant with this specification and its sibling specifications.

Manifest

A list of all Publication Resources that constitute the EPUB Publication.

Refer to manifest for more information.

Manifestation

The digital (or physical) embodiment of a work of intellectual content. Changes to the content such as significant revision, abridgement, translation, or the realization of the content in a different digital or physical form result in a new manifestation. There may be many individual but identical copies of a manifestation, termed 'instances' or 'items'. The ISBN is an example of a manifestation identifier, and is shared by all instances of that manifestation.

All instances of a manifestation need not be bit-for-bit identical, as minor corrections or revisions are not judged to create a new manifestation or work.

Media Overlay Document

An XML document that associates the XHTML Content Document with pre-recorded audio narration in order to provide a synchronized playback experience, as defined in [MediaOverlays30].

OCF Processor

A software application that processes EPUB Containers according to this specification.

Package Document

A Publication Resource carrying bibliographical and structural metadata about the EPUB Publication, as defined in Package Documents.

Package Identifier

The Package Identifier allows any instance of an EPUB Publication to be compared against another to determine if they are identical, different versions of the same Manifestation, or unrelated.

Refer to Package Identifier for more information.

Core Media Type Resource

A Publication Resource that is a Core Media Type and may therefore be included in the EPUB Publication without the provision of fallbacks.

Publication Resource

A resource that contains content or instructions that contribute to the logic and rendering of the EPUB Publication. In the absence of this resource, the Publication might not render as intended by the Author. Examples of Publication Resources include the Package Document, EPUB Content Documents, EPUB Style Sheets, audio, video, images, embedded fonts and scripts.

With the exception of the Package Document itself, Publication Resources must be listed in the manifest and must be bundled in the EPUB container file unless specified otherwise in Publication Resource Locations.

Examples of resources that are not Publication Resources include those identified by the Package Document link element and those identified in outbound hyperlinks that resolve outside the EPUB Container (e.g., referenced from an [HTML5] a element href attribute).

Foreign Resource

A Publication Resource that is not a Core Media Type. A Foreign Resource requires at least one fallback, as defined in Restrictions and Fallbacks.

Spine

An ordered list of Publication Resources, typically EPUB Content Documents, representing the default reading order of the Publication.

Refer to spine for more information.

EPUB Style Sheet (or Style Sheet)

A CSS Style Sheet conforming to the CSS profile defined in EPUB Style Sheets [ContentDocs30].

Text-to-Speech (TTS)

The rendering of the textual content of an EPUB Publication as artificial human speech using a synthesized voice.

Unique Identifier

The Unique Identifier is the primary identifier for an EPUB Publication, as identified by the unique-identifier attribute. The Unique Identifier may be shared by one or many Manifestations of the same work that conform to the EPUB standard and embody the same content, where the differences between the Manifestations are limited to those changes that take account of differences between EPUB Reading Systems (and which themselves may require changes in the ISBN).

The Unique Identifier is less granular than the ISBN. However, significant revision, abridgement, etc. of the content requires a new Unique Identifier.

User

An individual that consumes an EPUB Publication using an EPUB Reading System.

Viewport

The region of an EPUB Reading System in which the content of an EPUB Publication is rendered visually to a User.

CSS Viewport

A Viewport capable of displaying CSS-styled content.

SVG Viewport

A Viewport capable of displaying SVG images.

+ + diff --git a/src/test/resources/epub_logo_color.jpg b/src/test/resources/epub_logo_color.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41cd08e2d185c6b5392de4af7703ef3db36ee385 GIT binary patch literal 134445 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