diff --git a/CHANGELOG.md b/CHANGELOG.md index f1694c3a36..8f92de0978 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,14 @@ All notable changes to this project will be documented in this file. Take a look **Warning:** Features marked as *experimental* may change or be removed in a future release without notice. Use with caution. - +## [Unreleased] + +### Streamer + +#### Fixed + +* Fixed parsing the table of contents of an EPUB 3 using NCX instead of a Navigation Document. + ## [2.2.0] diff --git a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt index b16fcf0377..347c197b23 100644 --- a/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt +++ b/readium/streamer/src/main/java/org/readium/r2/streamer/parser/epub/EpubParser.kt @@ -181,24 +181,35 @@ class EpubParser( ?: emptyMap() private suspend fun parseNavigationData(packageDocument: PackageDocument, fetcher: Fetcher): Map> = - if (packageDocument.epubVersion < 3.0) { - val ncxItem = - if (packageDocument.spine.toc != null) { - packageDocument.manifest.firstOrNull { it.id == packageDocument.spine.toc } - } else { - packageDocument.manifest.firstOrNull { MediaType.NCX.contains(it.mediaType) } - } - ncxItem?.let { + parseNavigationDocument(packageDocument, fetcher) + ?: parseNcx(packageDocument, fetcher) + ?: emptyMap() + + private suspend fun parseNavigationDocument(packageDocument: PackageDocument, fetcher: Fetcher): Map>? = + packageDocument.manifest + .firstOrNull { it.properties.contains(Vocabularies.ITEM + "nav") } + ?.let { navItem -> + val navPath = Href(navItem.href, baseHref = packageDocument.path).string + fetcher.readAsXmlOrNull(navPath) + ?.let { NavigationDocumentParser.parse(it, navPath) } + } + ?.takeUnless { it.isEmpty() } + + private suspend fun parseNcx(packageDocument: PackageDocument, fetcher: Fetcher): Map>? { + val ncxItem = + if (packageDocument.spine.toc != null) { + packageDocument.manifest.firstOrNull { it.id == packageDocument.spine.toc } + } else { + packageDocument.manifest.firstOrNull { MediaType.NCX.contains(it.mediaType) } + } + + return ncxItem + ?.let { val ncxPath = Href(ncxItem.href, baseHref = packageDocument.path).string fetcher.readAsXmlOrNull(ncxPath)?.let { NcxParser.parse(it, ncxPath) } } - } else { - val navItem = packageDocument.manifest.firstOrNull { it.properties.contains(Vocabularies.ITEM + "nav") } - navItem?.let { - val navPath = Href(navItem.href, baseHref = packageDocument.path).string - fetcher.readAsXmlOrNull(navPath)?.let { NavigationDocumentParser.parse(it, navPath) } - } - }.orEmpty() + ?.takeUnless { it.isEmpty() } + } private suspend fun parseDisplayOptions(fetcher: Fetcher): Map { val displayOptionsXml =