diff --git a/js/Readium.js b/js/Readium.js index b63ea4900..5df32dbc1 100644 --- a/js/Readium.js +++ b/js/Readium.js @@ -13,10 +13,10 @@ define(['readium_shared_js/globals', 'text!version.json', 'jquery', 'underscore', 'readium_shared_js/views/reader_view', 'readium_js/epub-fetch/publication_fetcher', - 'readium_js/epub-model/package_document_parser', 'readium_js/epub-fetch/iframe_zip_loader', 'readium_shared_js/views/iframe_loader' + 'readium_js/epub-model/package_document_parser', 'readium_js/epub-fetch/iframe_zip_loader', 'readium_shared_js/views/iframe_loader', 'readium_shared_js/XmlParse' ], function (Globals, versionText, $, _, ReaderView, PublicationFetcher, - PackageParser, IframeZipLoader, IframeLoader) { + PackageParser, IframeZipLoader, IframeLoader, XmlParse) { var DEBUG_VERSION_GIT = false; @@ -67,6 +67,8 @@ define(['readium_shared_js/globals', 'text!version.json', 'jquery', 'underscore' contentDocumentHtml = contentDocumentHtml.replace(/[\s]*<\/title>/g, '<title>TITLE'); contentDocumentHtml = contentDocumentHtml.replace(//g, 'TITLE'); + contentDocumentHtml = XmlParse.preprocess(contentDocumentHtml); + return contentDocumentHtml; }; diff --git a/js/epub-fetch/content_document_fetcher.js b/js/epub-fetch/content_document_fetcher.js index be6d84b0d..2bcc50c5d 100644 --- a/js/epub-fetch/content_document_fetcher.js +++ b/js/epub-fetch/content_document_fetcher.js @@ -12,8 +12,8 @@ // prior written permission. define( - ['jquery', 'underscore', 'URIjs', './discover_content_type'], - function ($, _, URI, ContentTypeDiscovery) { + ['jquery', 'underscore', 'URIjs', './discover_content_type', 'readium_shared_js/XmlParse'], + function ($, _, URI, ContentTypeDiscovery, XmlParse) { var ContentDocumentFetcher = function (publicationFetcher, spineItem, loadedDocumentUri, publicationResourcesCache, contentDocumentTextPreprocessor) { @@ -44,7 +44,7 @@ define( this.resolveInternalPackageResources = function (resolvedDocumentCallback, onerror) { - _contentDocumentDom = _publicationFetcher.markupParser.parseMarkup(_contentDocumentText, _srcMediaType); + _contentDocumentDom = XmlParse.fromString(_contentDocumentText, _srcMediaType); setBaseUri(_contentDocumentDom, loadedDocumentUri); var resolutionDeferreds = []; @@ -331,6 +331,7 @@ define( function resolveDocumentImages(resolutionDeferreds, onerror) { resolveResourceElements('img', 'src', 'blob', resolutionDeferreds, onerror); resolveResourceElements('image', 'xlink:href', 'blob', resolutionDeferreds, onerror); + resolveResourceElements('image', 'href', 'blob', resolutionDeferreds, onerror); } function resolveDocumentAudios(resolutionDeferreds, onerror) { diff --git a/js/epub-fetch/iframe_zip_loader.js b/js/epub-fetch/iframe_zip_loader.js index bbe7651d7..849843774 100644 --- a/js/epub-fetch/iframe_zip_loader.js +++ b/js/epub-fetch/iframe_zip_loader.js @@ -290,7 +290,7 @@ define(['URIjs', 'readium_shared_js/views/iframe_loader', 'underscore', './disco $.ajax({ url: path, - dataType: 'html', + dataType: 'text', async: true, success: function (result) { diff --git a/js/epub-fetch/markup_parser.js b/js/epub-fetch/markup_parser.js deleted file mode 100644 index e6450f161..000000000 --- a/js/epub-fetch/markup_parser.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// 1. Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or -// other materials provided with the distribution. -// 3. Neither the name of the organization nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. - -define([], - function () { - - var MarkupParser = function (){ - - var self = this; - - this.parseXml = function(xmlString) { - return self.parseMarkup(xmlString, 'text/xml'); - }; - - this.parseMarkup = function(markupString, contentType) { - var parser = new window.DOMParser; - return parser.parseFromString(markupString, contentType); - }; - - }; - - return MarkupParser; -}); diff --git a/js/epub-fetch/publication_fetcher.js b/js/epub-fetch/publication_fetcher.js index f4c240f8f..6aaaad366 100644 --- a/js/epub-fetch/publication_fetcher.js +++ b/js/epub-fetch/publication_fetcher.js @@ -11,15 +11,40 @@ // used to endorse or promote products derived from this software without specific // prior written permission. -define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip_resource_fetcher', - './content_document_fetcher', './resource_cache', './encryption_handler', './discover_content_type', 'readium_shared_js/helpers'], - function ($, URI, MarkupParser, PlainResourceFetcher, ZipResourceFetcher, ContentDocumentFetcher, - ResourceCache, EncryptionHandler, ContentTypeDiscovery, Helpers) { +define(['jquery', 'URIjs', './plain_resource_fetcher', './zip_resource_fetcher', + './content_document_fetcher', './resource_cache', './encryption_handler', './discover_content_type', 'readium_shared_js/helpers', 'readium_shared_js/XmlParse'], + function ($, URI, PlainResourceFetcher, ZipResourceFetcher, ContentDocumentFetcher, + ResourceCache, EncryptionHandler, ContentTypeDiscovery, Helpers, XmlParse) { var PublicationFetcher = function(ebookURL, jsLibRoot, sourceWindow, cacheSizeEvictThreshold, contentDocumentTextPreprocessor, contentType) { var self = this; + var _ebookURLOPF = undefined; + var ebookURLTrimmed = ebookURL; + try { + //.absoluteTo("http://readium.org/epub") + ebookURLTrimmed = new URI(ebookURLTrimmed).search('').hash('').toString(); + } catch(err) { + console.error(err); + console.log(ebookURL); + } + if (/\.opf$/.test(ebookURLTrimmed)) { + + var iSlash = ebookURLTrimmed.lastIndexOf("/"); + if (iSlash >= 0) { + console.log("ebookURL is OPF: " + ebookURL); + + ebookURL = ebookURLTrimmed.substr(0, iSlash+1); + console.log("ebookURL rebased: " + ebookURL); + + _ebookURLOPF = ebookURLTrimmed.substr(iSlash+1, ebookURLTrimmed.length-1); + console.log("ebookURL OPF file (bypass META-INF/container.xml): " + _ebookURLOPF); + } + } else if (/\/META-INF\/container\.xml$/.test(ebookURLTrimmed)) { + ebookURL = ebookURL.substr(0, ebookURL.length-("/META-INF/container.xml".length)+1); + } + self.contentTypePackageReadStrategyMap = { 'application/oebps-package+xml': 'exploded', 'application/epub+zip': 'zipped', @@ -38,8 +63,6 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip var _contentDocumentTextPreprocessor = contentDocumentTextPreprocessor; var _contentType = contentType; - this.markupParser = new MarkupParser(); - this.initialize = function(callback) { var isEpubExploded = isExploded(); @@ -200,7 +223,7 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip this.getXmlFileDom = function (xmlFilePathRelativeToPackageRoot, callback, onerror) { self.getFileContentsFromPackage(xmlFilePathRelativeToPackageRoot, function (xmlFileContents) { - var fileDom = self.markupParser.parseXml(xmlFileContents); + var fileDom = XmlParse.fromString(xmlFileContents, "text/xml"); callback(fileDom); }, onerror); }; @@ -230,7 +253,8 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip } else { _packageDomInitializationDeferred = $.Deferred(); _packageDomInitializationDeferred.done(callback); - self.getPackageFullPath(function (packageFullPath) { + + var func = function (packageFullPath) { _packageFullPath = packageFullPath; _packageDocumentAbsoluteUrl = _resourceFetcher.resolveURI(_packageFullPath); @@ -248,7 +272,14 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip _packageDomInitializationDeferred.resolve(packageDom); _packageDomInitializationDeferred = undefined; }) - }, onerror); + }; + + // We already know which OPF to open, let's bypass META-INF/container.xml rootFile discovery + if (_ebookURLOPF) { + func(_ebookURLOPF); + } else { + self.getPackageFullPath(func, onerror); + } } } }; @@ -257,8 +288,10 @@ define(['jquery', 'URIjs', './markup_parser', './plain_resource_fetcher', './zip // (starting with "/", already relative to the EPUB archive's base folder) // then the returned value is relativeToPackagePath. this.convertPathRelativeToPackageToRelativeToBase = function (relativeToPackagePath) { - - return new URI(relativeToPackagePath).absoluteTo(_packageFullPath).toString(); + var uriStr = new URI(relativeToPackagePath).absoluteTo(_packageFullPath).toString(); + // Note that _packageFullPath is just be a relative path (to the root folder that contains ./META-INF/container.xml), and so is the returned path + //console.log(relativeToPackagePath + " /// " + _packageFullPath + " === " + uriStr); + return uriStr; }; // Note that the relativeToPackagePath parameter can in fact be absolute diff --git a/js/epub-model/package_document.js b/js/epub-model/package_document.js index 5ce3c5658..be8178538 100644 --- a/js/epub-model/package_document.js +++ b/js/epub-model/package_document.js @@ -11,8 +11,8 @@ // used to endorse or promote products derived from this software without specific // prior written permission. -define(['jquery', 'underscore', 'URIjs', 'readium_cfi_js'], - function ($, _, URI, epubCFI) { +define(['jquery', 'underscore', 'URIjs', 'readium_cfi_js', 'readium_shared_js/XmlParse'], + function ($, _, URI, epubCFI, XmlParse) { // Description: This model provides an interface for navigating an EPUB's package document var PackageDocument = function(packageDocumentURL, packageDocumentDOM, resourceFetcher, metadata, spine, manifest) { @@ -86,7 +86,6 @@ define(['jquery', 'underscore', 'URIjs', 'readium_cfi_js'], return metadata; }; - this.getTocItem = function(){ var item = manifest.getNavItem(); @@ -110,28 +109,48 @@ define(['jquery', 'underscore', 'URIjs', 'readium_cfi_js'], return null; }; + this.getTocURI = function() { + var href = this.getToc(); + if (href) { + var tocDocumentAbsoluteURL = new URI(href).absoluteTo(packageDocumentURL).toString(); + + return tocDocumentAbsoluteURL; + } + + return null; + }; + this.getTocText = function(callback) { - var toc = this.getToc(); - if (!toc) { + + var item = this.getTocItem(); + if (!item) { console.error("No TOC?!"); callback(undefined); return; } + + var tocHref = item.href; //this.getToc(); + //var tocContentType = item.media_type; - resourceFetcher.relativeToPackageFetchFileContents(toc, 'text', function (tocDocumentText) { + resourceFetcher.relativeToPackageFetchFileContents(tocHref, 'text', function (tocDocumentText) { callback(tocDocumentText) }, function (err) { - console.error('ERROR fetching TOC from [' + toc + ']:'); + console.error('ERROR fetching TOC from [' + tocHref + ']:'); console.error(err); callback(undefined); }); }; this.getTocDom = function(callback) { - + var that = this; this.getTocText(function (tocText) { if (typeof tocText === 'string') { - var tocDom = (new DOMParser()).parseFromString(tocText, "text/xml"); + + var item = that.getTocItem(); + var tocHref = item.href; //this.getToc(); + var tocContentType = item.media_type; + + var tocDom = XmlParse.fromString(tocText, tocContentType); callback(tocDom); } else { callback(undefined); @@ -151,8 +170,7 @@ define(['jquery', 'underscore', 'URIjs', 'readium_cfi_js'], $ncxOrderedList = getNcxOrderedList($("navMap", tocDom)); callback($ncxOrderedList[0]); } else { - var packageDocumentAbsoluteURL = new URI(packageDocumentURL).absoluteTo(document.URL); - var tocDocumentAbsoluteURL = new URI(that.getToc()).absoluteTo(packageDocumentAbsoluteURL); + var tocDocumentAbsoluteURL = that.getTocURI(); // add a BASE tag to change the TOC document's baseURI. var oldBaseTag = $(tocDom).remove('base'); var newBaseTag = $(''); diff --git a/js/epub-model/package_document_parser.js b/js/epub-model/package_document_parser.js index ea026b89b..de303015f 100644 --- a/js/epub-model/package_document_parser.js +++ b/js/epub-model/package_document_parser.js @@ -11,10 +11,10 @@ // used to endorse or promote products derived from this software without specific // prior written permission. -define(['jquery', 'underscore', '../epub-fetch/markup_parser', 'URIjs', './package_document', - './smil_document_parser', './metadata', './manifest', 'readium_cfi_js'], - function($, _, MarkupParser, URI, PackageDocument, SmilDocumentParser, Metadata, - Manifest, epubCFI) { +define(['jquery', 'underscore', 'URIjs', './package_document', + './smil_document_parser', './metadata', './manifest', 'readium_cfi_js', 'readium_shared_js/XmlParse'], + function($, _, URI, PackageDocument, SmilDocumentParser, Metadata, + Manifest, epubCFI, XmlParse) { // `PackageDocumentParser` is used to parse the xml of an epub package // document and build a javascript object. The constructor accepts an @@ -95,8 +95,7 @@ define(['jquery', 'underscore', '../epub-fetch/markup_parser', 'URIjs', './packa publicationFetcher.relativeToPackageFetchFileContents(pathToIBooksSpecificXml, 'text', function (ibookPropText) { if(ibookPropText) { - var parser = new MarkupParser(); - var propModel = parser.parseXml(ibookPropText); + var propModel = XmlParse.fromString(ibookPropText, "text/xml"); var fixLayoutProp = $("option[name=fixed-layout]", propModel)[0]; if(fixLayoutProp) { var fixLayoutVal = $(fixLayoutProp).text(); diff --git a/js/epub-model/smil_document_parser.js b/js/epub-model/smil_document_parser.js index 843a4d903..8f753d153 100644 --- a/js/epub-model/smil_document_parser.js +++ b/js/epub-model/smil_document_parser.js @@ -54,12 +54,27 @@ define(['jquery', 'underscore'], function ($, _) { var propParse = property.split(':'); var destProperty = propParse[propParse.length - 1]; + var attr = undefined; + if (propParse.length == 1) { // no XML namespace + attr = fromNode.getAttribute(property); + + } else { // XML namespace, such as epub:type + + // Note: no need to use Helpers.getEpubTypeRoleAttributeValue() here, as SMIL / XML guarantees epub:type, unlike XHTML vs. HTML EPUB content documents + if (fromNode.getAttributeNS && propParse[0] == "epub") { + attr = fromNode.getAttributeNS('http://www.idpf.org/2007/ops', destProperty); + } + if (!attr) { + attr = fromNode.getAttribute(property) || fromNode.getAttribute(destProperty); + } + } + if (destProperty === "type") { destProperty = "epubtype"; } - if (fromNode.getAttribute(property) != undefined) { - toItem[destProperty] = fromNode.getAttribute(property); + if (attr) { + toItem[destProperty] = attr; } else if (isRequired) { if (defaultValue !== undefined) { toItem[destProperty] = defaultValue; diff --git a/readium-shared-js b/readium-shared-js index 005aae8b5..c7785239b 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit 005aae8b5e6c5a78b3d4ab02a51e73d4f4cc40c9 +Subproject commit c7785239b2b59d7332f0d722232c9e90390b32c2