wiki-graph-core 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/data/editor/clue_reviewer.jinja +410 -0
- package/data/editor/clue_reviewer_generator.jinja +428 -0
- package/data/editor/revision_feedback.jinja +5 -0
- package/data/editor/text_compressor.jinja +127 -0
- package/data/guaranteed/response_intent_classifier.jinja +8 -0
- package/data/help/commands/archive/next.jinja +29 -0
- package/data/help/commands/gc.jinja +38 -0
- package/data/help/commands/legacy/migrate.jinja +20 -0
- package/data/help/commands/legacy.jinja +19 -0
- package/data/help/commands/maintenance/chapter/add.jinja +41 -0
- package/data/help/commands/maintenance/chapter/list.jinja +33 -0
- package/data/help/commands/maintenance/chapter/move.jinja +36 -0
- package/data/help/commands/maintenance/chapter/remove.jinja +26 -0
- package/data/help/commands/maintenance/chapter/reset.jinja +29 -0
- package/data/help/commands/maintenance/chapter/set-source.jinja +34 -0
- package/data/help/commands/maintenance/chapter/set-summary.jinja +31 -0
- package/data/help/commands/maintenance/chapter/set-title.jinja +29 -0
- package/data/help/commands/maintenance/chapter/tree.jinja +58 -0
- package/data/help/commands/maintenance/chapter.jinja +59 -0
- package/data/help/commands/maintenance/cover.jinja +28 -0
- package/data/help/commands/maintenance/meta.jinja +55 -0
- package/data/help/commands/predicate.jinja +460 -0
- package/data/help/commands/root.jinja +83 -0
- package/data/help/commands/transform.jinja +34 -0
- package/data/help/commands/uri.jinja +274 -0
- package/data/help/topics/config.jinja +88 -0
- package/data/help/topics/format.jinja +72 -0
- package/data/help/topics/readiness.jinja +99 -0
- package/data/help/topics/recipe.jinja +151 -0
- package/data/help/topics/runtime.jinja +62 -0
- package/data/help/topics/uri.jinja +178 -0
- package/data/output/epub/cover.xhtml.jinja +13 -0
- package/data/output/epub/nav.xhtml.jinja +12 -0
- package/data/output/epub/package.opf.xml.jinja +39 -0
- package/data/output/epub/section.xhtml.jinja +12 -0
- package/data/topologization/book_coherence_extraction.jinja +223 -0
- package/data/topologization/chunk_extraction.jinja +233 -0
- package/data/topologization/evidence_choice.jinja +38 -0
- package/data/topologization/translate_chunks.jinja +138 -0
- package/data/topologization/user_focused_extraction.jinja +378 -0
- package/dist/archive/query/archive-view.d.ts +26 -0
- package/dist/archive/query/archive-view.js +4540 -0
- package/dist/archive/query/archive-view.js.map +1 -0
- package/dist/archive/query/continuation-cursor.d.ts +61 -0
- package/dist/archive/query/continuation-cursor.js +363 -0
- package/dist/archive/query/continuation-cursor.js.map +1 -0
- package/dist/archive/query/index.d.ts +29 -0
- package/dist/archive/query/index.js +63 -0
- package/dist/archive/query/index.js.map +1 -0
- package/dist/archive/query/lexical-search.d.ts +22 -0
- package/dist/archive/query/lexical-search.js +137 -0
- package/dist/archive/query/lexical-search.js.map +1 -0
- package/dist/archive/query/search-cache.d.ts +192 -0
- package/dist/archive/query/search-cache.js +1248 -0
- package/dist/archive/query/search-cache.js.map +1 -0
- package/dist/archive/search-index/index.d.ts +26 -0
- package/dist/archive/search-index/index.js +29 -0
- package/dist/archive/search-index/index.js.map +1 -0
- package/dist/archive/search-index/search-index.d.ts +26 -0
- package/dist/archive/search-index/search-index.js +555 -0
- package/dist/archive/search-index/search-index.js.map +1 -0
- package/dist/archive/search-index/search-tokenizer.d.ts +16 -0
- package/dist/archive/search-index/search-tokenizer.js +225 -0
- package/dist/archive/search-index/search-tokenizer.js.map +1 -0
- package/dist/common/cli-command.d.ts +4 -0
- package/dist/common/cli-command.js +7 -0
- package/dist/common/cli-command.js.map +1 -0
- package/dist/common/data-dir.d.ts +3 -0
- package/dist/common/data-dir.js +48 -0
- package/dist/common/data-dir.js.map +1 -0
- package/dist/common/language.d.ts +55 -0
- package/dist/common/language.js +208 -0
- package/dist/common/language.js.map +1 -0
- package/dist/common/llm-scope.d.ts +19 -0
- package/dist/common/llm-scope.js +31 -0
- package/dist/common/llm-scope.js.map +1 -0
- package/dist/common/logging.d.ts +22 -0
- package/dist/common/logging.js +141 -0
- package/dist/common/logging.js.map +1 -0
- package/dist/common/template.d.ts +8 -0
- package/dist/common/template.js +54 -0
- package/dist/common/template.js.map +1 -0
- package/dist/common/tinyld-language.d.ts +6 -0
- package/dist/common/tinyld-language.js +34 -0
- package/dist/common/tinyld-language.js.map +1 -0
- package/dist/common/wiki-graph-dir.d.ts +10 -0
- package/dist/common/wiki-graph-dir.js +41 -0
- package/dist/common/wiki-graph-dir.js.map +1 -0
- package/dist/common/wiki-graph-temp.d.ts +6 -0
- package/dist/common/wiki-graph-temp.js +21 -0
- package/dist/common/wiki-graph-temp.js.map +1 -0
- package/dist/common/wiki-graph-uri.d.ts +28 -0
- package/dist/common/wiki-graph-uri.js +171 -0
- package/dist/common/wiki-graph-uri.js.map +1 -0
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.js +13 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/task-context.d.ts +41 -0
- package/dist/context/task-context.js +111 -0
- package/dist/context/task-context.js.map +1 -0
- package/dist/document/database.d.ts +30 -0
- package/dist/document/database.js +273 -0
- package/dist/document/database.js.map +1 -0
- package/dist/document/document.d.ts +153 -0
- package/dist/document/document.js +615 -0
- package/dist/document/document.js.map +1 -0
- package/dist/document/fragments.d.ts +63 -0
- package/dist/document/fragments.js +371 -0
- package/dist/document/fragments.js.map +1 -0
- package/dist/document/index.d.ts +13 -0
- package/dist/document/index.js +62 -0
- package/dist/document/index.js.map +1 -0
- package/dist/document/schema.d.ts +8 -0
- package/dist/document/schema.js +472 -0
- package/dist/document/schema.js.map +1 -0
- package/dist/document/shared-state-database.d.ts +9 -0
- package/dist/document/shared-state-database.js +193 -0
- package/dist/document/shared-state-database.js.map +1 -0
- package/dist/document/stores.d.ts +203 -0
- package/dist/document/stores.js +1678 -0
- package/dist/document/stores.js.map +1 -0
- package/dist/document/text-streams.d.ts +86 -0
- package/dist/document/text-streams.js +515 -0
- package/dist/document/text-streams.js.map +1 -0
- package/dist/document/types.d.ts +148 -0
- package/dist/document/types.js +69 -0
- package/dist/document/types.js.map +1 -0
- package/dist/editor/clue.d.ts +27 -0
- package/dist/editor/clue.js +158 -0
- package/dist/editor/clue.js.map +1 -0
- package/dist/editor/compressor.d.ts +18 -0
- package/dist/editor/compressor.js +68 -0
- package/dist/editor/compressor.js.map +1 -0
- package/dist/editor/editor.d.ts +39 -0
- package/dist/editor/editor.js +253 -0
- package/dist/editor/editor.js.map +1 -0
- package/dist/editor/feedback.d.ts +16 -0
- package/dist/editor/feedback.js +104 -0
- package/dist/editor/feedback.js.map +1 -0
- package/dist/editor/index.d.ts +17 -0
- package/dist/editor/index.js +5 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/language-review.d.ts +14 -0
- package/dist/editor/language-review.js +35 -0
- package/dist/editor/language-review.js.map +1 -0
- package/dist/editor/log.d.ts +37 -0
- package/dist/editor/log.js +202 -0
- package/dist/editor/log.js.map +1 -0
- package/dist/editor/markup.d.ts +20 -0
- package/dist/editor/markup.js +294 -0
- package/dist/editor/markup.js.map +1 -0
- package/dist/editor/prompt-templates.d.ts +6 -0
- package/dist/editor/prompt-templates.js +11 -0
- package/dist/editor/prompt-templates.js.map +1 -0
- package/dist/editor/response.d.ts +5 -0
- package/dist/editor/response.js +31 -0
- package/dist/editor/response.js.map +1 -0
- package/dist/editor/review.d.ts +34 -0
- package/dist/editor/review.js +189 -0
- package/dist/editor/review.js.map +1 -0
- package/dist/editor/types.d.ts +31 -0
- package/dist/editor/types.js +21 -0
- package/dist/editor/types.js.map +1 -0
- package/dist/evidence-selection/anchor-resolver.d.ts +43 -0
- package/dist/evidence-selection/anchor-resolver.js +783 -0
- package/dist/evidence-selection/anchor-resolver.js.map +1 -0
- package/dist/evidence-selection/anchor-types.d.ts +27 -0
- package/dist/evidence-selection/anchor-types.js +1 -0
- package/dist/evidence-selection/anchor-types.js.map +1 -0
- package/dist/evidence-selection/index.d.ts +8 -0
- package/dist/evidence-selection/index.js +32 -0
- package/dist/evidence-selection/index.js.map +1 -0
- package/dist/evidence-selection/prompt.d.ts +18 -0
- package/dist/evidence-selection/prompt.js +54 -0
- package/dist/evidence-selection/prompt.js.map +1 -0
- package/dist/evidence-selection/quote-score.d.ts +29 -0
- package/dist/evidence-selection/quote-score.js +331 -0
- package/dist/evidence-selection/quote-score.js.map +1 -0
- package/dist/evidence-selection/selection-resolver.d.ts +19 -0
- package/dist/evidence-selection/selection-resolver.js +303 -0
- package/dist/evidence-selection/selection-resolver.js.map +1 -0
- package/dist/evidence-selection/text.d.ts +4 -0
- package/dist/evidence-selection/text.js +66 -0
- package/dist/evidence-selection/text.js.map +1 -0
- package/dist/evidence-selection/types.d.ts +36 -0
- package/dist/evidence-selection/types.js +1 -0
- package/dist/evidence-selection/types.js.map +1 -0
- package/dist/facade/app.d.ts +75 -0
- package/dist/facade/app.js +141 -0
- package/dist/facade/app.js.map +1 -0
- package/dist/facade/build-queue.d.ts +181 -0
- package/dist/facade/build-queue.js +1442 -0
- package/dist/facade/build-queue.js.map +1 -0
- package/dist/facade/chapter-build.d.ts +60 -0
- package/dist/facade/chapter-build.js +1020 -0
- package/dist/facade/chapter-build.js.map +1 -0
- package/dist/facade/chapter.d.ts +168 -0
- package/dist/facade/chapter.js +944 -0
- package/dist/facade/chapter.js.map +1 -0
- package/dist/facade/digest.d.ts +55 -0
- package/dist/facade/digest.js +168 -0
- package/dist/facade/digest.js.map +1 -0
- package/dist/facade/graph.d.ts +60 -0
- package/dist/facade/graph.js +203 -0
- package/dist/facade/graph.js.map +1 -0
- package/dist/facade/import.d.ts +49 -0
- package/dist/facade/import.js +262 -0
- package/dist/facade/import.js.map +1 -0
- package/dist/facade/index.d.ts +39 -0
- package/dist/facade/index.js +171 -0
- package/dist/facade/index.js.map +1 -0
- package/dist/facade/knowledge-graph-build.d.ts +75 -0
- package/dist/facade/knowledge-graph-build.js +897 -0
- package/dist/facade/knowledge-graph-build.js.map +1 -0
- package/dist/facade/llm-sampling.d.ts +11 -0
- package/dist/facade/llm-sampling.js +58 -0
- package/dist/facade/llm-sampling.js.map +1 -0
- package/dist/facade/types.d.ts +8 -0
- package/dist/facade/types.js +1 -0
- package/dist/facade/types.js.map +1 -0
- package/dist/facade/wiki-graph-archive.d.ts +41 -0
- package/dist/facade/wiki-graph-archive.js +130 -0
- package/dist/facade/wiki-graph-archive.js.map +1 -0
- package/dist/gc/files.d.ts +15 -0
- package/dist/gc/files.js +141 -0
- package/dist/gc/files.js.map +1 -0
- package/dist/gc/index.d.ts +2 -0
- package/dist/gc/index.js +5 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/gc/lock.d.ts +3 -0
- package/dist/gc/lock.js +137 -0
- package/dist/gc/lock.js.map +1 -0
- package/dist/gc/runner.d.ts +9 -0
- package/dist/gc/runner.js +129 -0
- package/dist/gc/runner.js.map +1 -0
- package/dist/gc/tmp-gc.d.ts +5 -0
- package/dist/gc/tmp-gc.js +57 -0
- package/dist/gc/tmp-gc.js.map +1 -0
- package/dist/gc/types.d.ts +24 -0
- package/dist/gc/types.js +1 -0
- package/dist/gc/types.js.map +1 -0
- package/dist/gc.cjs +10041 -0
- package/dist/gc.cjs.map +1 -0
- package/dist/gc.d.cts +10 -0
- package/dist/gc.d.ts +2 -0
- package/dist/gc.js +5 -0
- package/dist/gc.js.map +1 -0
- package/dist/guaranteed/classifier.d.ts +10 -0
- package/dist/guaranteed/classifier.js +88 -0
- package/dist/guaranteed/classifier.js.map +1 -0
- package/dist/guaranteed/errors.d.ts +38 -0
- package/dist/guaranteed/errors.js +73 -0
- package/dist/guaranteed/errors.js.map +1 -0
- package/dist/guaranteed/index.d.ts +7 -0
- package/dist/guaranteed/index.js +21 -0
- package/dist/guaranteed/index.js.map +1 -0
- package/dist/guaranteed/request.d.ts +8 -0
- package/dist/guaranteed/request.js +206 -0
- package/dist/guaranteed/request.js.map +1 -0
- package/dist/guaranteed/response.d.ts +12 -0
- package/dist/guaranteed/response.js +98 -0
- package/dist/guaranteed/response.js.map +1 -0
- package/dist/guaranteed/types.d.ts +20 -0
- package/dist/guaranteed/types.js +1 -0
- package/dist/guaranteed/types.js.map +1 -0
- package/dist/index-B8NNnQ8P.d.ts +424 -0
- package/dist/index.cjs +34774 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2462 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +168 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy-sdpub/upgrade.d.ts +7 -0
- package/dist/legacy-sdpub/upgrade.js +795 -0
- package/dist/legacy-sdpub/upgrade.js.map +1 -0
- package/dist/llm/cache.d.ts +13 -0
- package/dist/llm/cache.js +35 -0
- package/dist/llm/cache.js.map +1 -0
- package/dist/llm/client.d.ts +26 -0
- package/dist/llm/client.js +572 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/llm/context.d.ts +22 -0
- package/dist/llm/context.js +78 -0
- package/dist/llm/context.js.map +1 -0
- package/dist/llm/errors.d.ts +7 -0
- package/dist/llm/errors.js +12 -0
- package/dist/llm/errors.js.map +1 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.js +17 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/request-log.d.ts +9 -0
- package/dist/llm/request-log.js +35 -0
- package/dist/llm/request-log.js.map +1 -0
- package/dist/llm/sampling.d.ts +11 -0
- package/dist/llm/sampling.js +67 -0
- package/dist/llm/sampling.js.map +1 -0
- package/dist/llm/types.d.ts +50 -0
- package/dist/llm/types.js +1 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/output/epub/archive.d.ts +9 -0
- package/dist/output/epub/archive.js +81 -0
- package/dist/output/epub/archive.js.map +1 -0
- package/dist/output/epub/book.d.ts +15 -0
- package/dist/output/epub/book.js +76 -0
- package/dist/output/epub/book.js.map +1 -0
- package/dist/output/epub/content.d.ts +9 -0
- package/dist/output/epub/content.js +35 -0
- package/dist/output/epub/content.js.map +1 -0
- package/dist/output/epub/index.d.ts +20 -0
- package/dist/output/epub/index.js +14 -0
- package/dist/output/epub/index.js.map +1 -0
- package/dist/output/epub/model.d.ts +24 -0
- package/dist/output/epub/model.js +1 -0
- package/dist/output/epub/model.js.map +1 -0
- package/dist/output/epub/navigation.d.ts +10 -0
- package/dist/output/epub/navigation.js +39 -0
- package/dist/output/epub/navigation.js.map +1 -0
- package/dist/output/epub/package.d.ts +17 -0
- package/dist/output/epub/package.js +29 -0
- package/dist/output/epub/package.js.map +1 -0
- package/dist/output/epub/shared.d.ts +4 -0
- package/dist/output/epub/shared.js +12 -0
- package/dist/output/epub/shared.js.map +1 -0
- package/dist/output/epub/templates.d.ts +35 -0
- package/dist/output/epub/templates.js +26 -0
- package/dist/output/epub/templates.js.map +1 -0
- package/dist/output/index.d.ts +14 -0
- package/dist/output/index.js +11 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/plain-text.d.ts +18 -0
- package/dist/output/plain-text.js +56 -0
- package/dist/output/plain-text.js.map +1 -0
- package/dist/progress/index.d.ts +3 -0
- package/dist/progress/index.js +14 -0
- package/dist/progress/index.js.map +1 -0
- package/dist/progress/reporter.d.ts +10 -0
- package/dist/progress/reporter.js +79 -0
- package/dist/progress/reporter.js.map +1 -0
- package/dist/progress/tracker.d.ts +37 -0
- package/dist/progress/tracker.js +119 -0
- package/dist/progress/tracker.js.map +1 -0
- package/dist/progress/types.d.ts +28 -0
- package/dist/progress/types.js +1 -0
- package/dist/progress/types.js.map +1 -0
- package/dist/reader/attention/attention.d.ts +39 -0
- package/dist/reader/attention/attention.js +123 -0
- package/dist/reader/attention/attention.js.map +1 -0
- package/dist/reader/attention/index.d.ts +9 -0
- package/dist/reader/attention/index.js +5 -0
- package/dist/reader/attention/index.js.map +1 -0
- package/dist/reader/attention/wave-reflection.d.ts +21 -0
- package/dist/reader/attention/wave-reflection.js +153 -0
- package/dist/reader/attention/wave-reflection.js.map +1 -0
- package/dist/reader/attention/working-memory.d.ts +28 -0
- package/dist/reader/attention/working-memory.js +62 -0
- package/dist/reader/attention/working-memory.js.map +1 -0
- package/dist/reader/chunk-batch/extract.d.ts +13 -0
- package/dist/reader/chunk-batch/extract.js +14 -0
- package/dist/reader/chunk-batch/extract.js.map +1 -0
- package/dist/reader/chunk-batch/extractor.d.ts +17 -0
- package/dist/reader/chunk-batch/extractor.js +337 -0
- package/dist/reader/chunk-batch/extractor.js.map +1 -0
- package/dist/reader/chunk-batch/fragment-projection.d.ts +34 -0
- package/dist/reader/chunk-batch/fragment-projection.js +94 -0
- package/dist/reader/chunk-batch/fragment-projection.js.map +1 -0
- package/dist/reader/chunk-batch/index.d.ts +12 -0
- package/dist/reader/chunk-batch/index.js +13 -0
- package/dist/reader/chunk-batch/index.js.map +1 -0
- package/dist/reader/chunk-batch/language.d.ts +9 -0
- package/dist/reader/chunk-batch/language.js +23 -0
- package/dist/reader/chunk-batch/language.js.map +1 -0
- package/dist/reader/chunk-batch/parser.d.ts +94 -0
- package/dist/reader/chunk-batch/parser.js +640 -0
- package/dist/reader/chunk-batch/parser.js.map +1 -0
- package/dist/reader/chunk-batch/prompt-templates.d.ts +6 -0
- package/dist/reader/chunk-batch/prompt-templates.js +11 -0
- package/dist/reader/chunk-batch/prompt-templates.js.map +1 -0
- package/dist/reader/chunk-batch/types.d.ts +85 -0
- package/dist/reader/chunk-batch/types.js +1 -0
- package/dist/reader/chunk-batch/types.js.map +1 -0
- package/dist/reader/index.d.ts +13 -0
- package/dist/reader/index.js +7 -0
- package/dist/reader/index.js.map +1 -0
- package/dist/reader/reader.d.ts +37 -0
- package/dist/reader/reader.js +82 -0
- package/dist/reader/reader.js.map +1 -0
- package/dist/reader/segment/index.d.ts +2 -0
- package/dist/reader/segment/index.js +5 -0
- package/dist/reader/segment/index.js.map +1 -0
- package/dist/reader/segment/intl-segmenter.d.ts +5 -0
- package/dist/reader/segment/intl-segmenter.js +102 -0
- package/dist/reader/segment/intl-segmenter.js.map +1 -0
- package/dist/reader/segment/segment.d.ts +5 -0
- package/dist/reader/segment/segment.js +9 -0
- package/dist/reader/segment/segment.js.map +1 -0
- package/dist/reader/segment/types.d.ts +14 -0
- package/dist/reader/segment/types.js +1 -0
- package/dist/reader/segment/types.js.map +1 -0
- package/dist/reader/types.d.ts +29 -0
- package/dist/reader/types.js +1 -0
- package/dist/reader/types.js.map +1 -0
- package/dist/serial.d.ts +89 -0
- package/dist/serial.js +476 -0
- package/dist/serial.js.map +1 -0
- package/dist/source/adapter.d.ts +15 -0
- package/dist/source/adapter.js +1 -0
- package/dist/source/adapter.js.map +1 -0
- package/dist/source/epub/archive.d.ts +27 -0
- package/dist/source/epub/archive.js +189 -0
- package/dist/source/epub/archive.js.map +1 -0
- package/dist/source/epub/content.d.ts +22 -0
- package/dist/source/epub/content.js +183 -0
- package/dist/source/epub/content.js.map +1 -0
- package/dist/source/epub/document.d.ts +55 -0
- package/dist/source/epub/document.js +179 -0
- package/dist/source/epub/document.js.map +1 -0
- package/dist/source/epub/index.d.ts +10 -0
- package/dist/source/epub/index.js +6 -0
- package/dist/source/epub/index.js.map +1 -0
- package/dist/source/epub/navigation.d.ts +16 -0
- package/dist/source/epub/navigation.js +215 -0
- package/dist/source/epub/navigation.js.map +1 -0
- package/dist/source/epub/package.d.ts +33 -0
- package/dist/source/epub/package.js +237 -0
- package/dist/source/epub/package.js.map +1 -0
- package/dist/source/epub/xml.d.ts +16 -0
- package/dist/source/epub/xml.js +111 -0
- package/dist/source/epub/xml.js.map +1 -0
- package/dist/source/index.d.ts +12 -0
- package/dist/source/index.js +32 -0
- package/dist/source/index.js.map +1 -0
- package/dist/source/meta.d.ts +30 -0
- package/dist/source/meta.js +22 -0
- package/dist/source/meta.js.map +1 -0
- package/dist/source/plain-text.d.ts +16 -0
- package/dist/source/plain-text.js +86 -0
- package/dist/source/plain-text.js.map +1 -0
- package/dist/source/toc.d.ts +16 -0
- package/dist/source/toc.js +17 -0
- package/dist/source/toc.js.map +1 -0
- package/dist/source/types.d.ts +16 -0
- package/dist/source/types.js +1 -0
- package/dist/source/types.js.map +1 -0
- package/dist/topology/grouping.d.ts +15 -0
- package/dist/topology/grouping.js +18 -0
- package/dist/topology/grouping.js.map +1 -0
- package/dist/topology/index.d.ts +21 -0
- package/dist/topology/index.js +5 -0
- package/dist/topology/index.js.map +1 -0
- package/dist/topology/resource-segmentation.d.ts +13 -0
- package/dist/topology/resource-segmentation.js +111 -0
- package/dist/topology/resource-segmentation.js.map +1 -0
- package/dist/topology/segment-incision.d.ts +18 -0
- package/dist/topology/segment-incision.js +197 -0
- package/dist/topology/segment-incision.js.map +1 -0
- package/dist/topology/snake-detector.d.ts +13 -0
- package/dist/topology/snake-detector.js +520 -0
- package/dist/topology/snake-detector.js.map +1 -0
- package/dist/topology/snake-graph-builder.d.ts +14 -0
- package/dist/topology/snake-graph-builder.js +76 -0
- package/dist/topology/snake-graph-builder.js.map +1 -0
- package/dist/topology/topology.d.ts +29 -0
- package/dist/topology/topology.js +348 -0
- package/dist/topology/topology.js.map +1 -0
- package/dist/topology/weights.d.ts +10 -0
- package/dist/topology/weights.js +84 -0
- package/dist/topology/weights.js.map +1 -0
- package/dist/types-FVIqiLC9.d.cts +24 -0
- package/dist/utils/async-semaphore.d.ts +7 -0
- package/dist/utils/async-semaphore.js +40 -0
- package/dist/utils/async-semaphore.js.map +1 -0
- package/dist/utils/enum.d.ts +5 -0
- package/dist/utils/enum.js +18 -0
- package/dist/utils/enum.js.map +1 -0
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/hash.js +132 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/node-error.d.ts +4 -0
- package/dist/utils/node-error.js +59 -0
- package/dist/utils/node-error.js.map +1 -0
- package/dist/wikg/archive-uri.d.ts +1 -0
- package/dist/wikg/archive-uri.js +37 -0
- package/dist/wikg/archive-uri.js.map +1 -0
- package/dist/wikg/archive.d.ts +28 -0
- package/dist/wikg/archive.js +496 -0
- package/dist/wikg/archive.js.map +1 -0
- package/dist/wikg/index.d.ts +31 -0
- package/dist/wikg/index.js +60 -0
- package/dist/wikg/index.js.map +1 -0
- package/dist/wikg/wikg-coordinator.d.ts +45 -0
- package/dist/wikg/wikg-coordinator.js +1687 -0
- package/dist/wikg/wikg-coordinator.js.map +1 -0
- package/dist/wikg/wiki-graph-archive-file.d.ts +42 -0
- package/dist/wikg/wiki-graph-archive-file.js +78 -0
- package/dist/wikg/wiki-graph-archive-file.js.map +1 -0
- package/dist/wikilink/index.d.ts +10 -0
- package/dist/wikilink/index.js +7 -0
- package/dist/wikilink/index.js.map +1 -0
- package/dist/wikilink/relation-discovery.d.ts +31 -0
- package/dist/wikilink/relation-discovery.js +477 -0
- package/dist/wikilink/relation-discovery.js.map +1 -0
- package/dist/wikilink/types.d.ts +23 -0
- package/dist/wikilink/types.js +1 -0
- package/dist/wikilink/types.js.map +1 -0
- package/dist/wikilink/window.d.ts +7 -0
- package/dist/wikilink/window.js +53 -0
- package/dist/wikilink/window.js.map +1 -0
- package/dist/wikimatch/enrichment.d.ts +10 -0
- package/dist/wikimatch/enrichment.js +55 -0
- package/dist/wikimatch/enrichment.js.map +1 -0
- package/dist/wikimatch/index.d.ts +16 -0
- package/dist/wikimatch/index.js +66 -0
- package/dist/wikimatch/index.js.map +1 -0
- package/dist/wikimatch/option-narrowing.d.ts +17 -0
- package/dist/wikimatch/option-narrowing.js +208 -0
- package/dist/wikimatch/option-narrowing.js.map +1 -0
- package/dist/wikimatch/options.d.ts +14 -0
- package/dist/wikimatch/options.js +155 -0
- package/dist/wikimatch/options.js.map +1 -0
- package/dist/wikimatch/policy-judge.d.ts +17 -0
- package/dist/wikimatch/policy-judge.js +430 -0
- package/dist/wikimatch/policy-judge.js.map +1 -0
- package/dist/wikimatch/range-suppression.d.ts +9 -0
- package/dist/wikimatch/range-suppression.js +27 -0
- package/dist/wikimatch/range-suppression.js.map +1 -0
- package/dist/wikimatch/surface-screening.d.ts +16 -0
- package/dist/wikimatch/surface-screening.js +168 -0
- package/dist/wikimatch/surface-screening.js.map +1 -0
- package/dist/wikimatch/surface-window.d.ts +6 -0
- package/dist/wikimatch/surface-window.js +44 -0
- package/dist/wikimatch/surface-window.js.map +1 -0
- package/dist/wikimatch/types.d.ts +151 -0
- package/dist/wikimatch/types.js +1 -0
- package/dist/wikimatch/types.js.map +1 -0
- package/dist/wikimatch/wikispine.d.ts +43 -0
- package/dist/wikimatch/wikispine.js +399 -0
- package/dist/wikimatch/wikispine.js.map +1 -0
- package/dist/wikimatch/window.d.ts +6 -0
- package/dist/wikimatch/window.js +83 -0
- package/dist/wikimatch/window.js.map +1 -0
- package/dist/wikimatch/words.d.ts +16 -0
- package/dist/wikimatch/words.js +66 -0
- package/dist/wikimatch/words.js.map +1 -0
- package/dist/wikipage/cache.d.ts +18 -0
- package/dist/wikipage/cache.js +404 -0
- package/dist/wikipage/cache.js.map +1 -0
- package/dist/wikipage/fetch-log.d.ts +17 -0
- package/dist/wikipage/fetch-log.js +143 -0
- package/dist/wikipage/fetch-log.js.map +1 -0
- package/dist/wikipage/index.d.ts +14 -0
- package/dist/wikipage/index.js +17 -0
- package/dist/wikipage/index.js.map +1 -0
- package/dist/wikipage/normalizer.d.ts +14 -0
- package/dist/wikipage/normalizer.js +147 -0
- package/dist/wikipage/normalizer.js.map +1 -0
- package/dist/wikipage/rate-limiter.d.ts +13 -0
- package/dist/wikipage/rate-limiter.js +84 -0
- package/dist/wikipage/rate-limiter.js.map +1 -0
- package/dist/wikipage/resolver.d.ts +26 -0
- package/dist/wikipage/resolver.js +325 -0
- package/dist/wikipage/resolver.js.map +1 -0
- package/dist/wikipage/types.d.ts +96 -0
- package/dist/wikipage/types.js +1 -0
- package/dist/wikipage/types.js.map +1 -0
- package/dist/wikipage/wikimedia-client.d.ts +48 -0
- package/dist/wikipage/wikimedia-client.js +397 -0
- package/dist/wikipage/wikimedia-client.js.map +1 -0
- package/dist/worker-BgQ0Xl8T.d.cts +181 -0
- package/dist/worker.cjs +5259 -0
- package/dist/worker.cjs.map +1 -0
- package/dist/worker.d.cts +2 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.js +5 -0
- package/dist/worker.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/document.ts"],"sourcesContent":["import type { SourceAdapter, SourceDocument } from \"../adapter.js\";\nimport type { SourceAsset, SourceSection, SourceTextStream } from \"../types.js\";\nimport { normalizeFragment } from \"./archive.js\";\nimport { EpubArchive } from \"./archive.js\";\nimport {\n analyzeSectionTargets,\n EpubContentLoader,\n type EpubSectionAnalysis,\n type EpubSectionTarget,\n} from \"./content.js\";\nimport { readEpubNavigation, type EpubNavigationItem } from \"./navigation.js\";\nimport { readEpubPackage, type EpubPackageData } from \"./package.js\";\n\ninterface SectionDefinition {\n readonly hasContent: boolean;\n readonly id: string;\n readonly title: string | undefined;\n readonly path: string | undefined;\n readonly fragment: string | undefined;\n readonly wordsCount: number;\n readonly children: readonly SectionDefinition[];\n}\n\nclass EpubSourceSection implements SourceSection {\n readonly #document: EpubSourceDocument;\n readonly #definition: SectionDefinition;\n\n public constructor(\n document: EpubSourceDocument,\n definition: SectionDefinition,\n ) {\n this.#document = document;\n this.#definition = definition;\n }\n\n public get id(): string {\n return this.#definition.id;\n }\n\n public get hasContent(): boolean {\n return this.#definition.hasContent;\n }\n\n public get title(): string | undefined {\n return this.#definition.title;\n }\n\n public get wordsCount(): number {\n return this.#definition.wordsCount;\n }\n\n public get children(): readonly SourceSection[] {\n return this.#definition.children.map(\n (child) => new EpubSourceSection(this.#document, child),\n );\n }\n\n public async open(): Promise<SourceTextStream> {\n return await this.#document.openSection(this.#definition.id);\n }\n}\n\nexport class EpubSourceDocument implements SourceDocument {\n readonly #packageData: EpubPackageData;\n readonly #cover: SourceAsset | undefined;\n readonly #sections: readonly SectionDefinition[];\n readonly #contentLoader: EpubContentLoader;\n\n public constructor(\n packageData: EpubPackageData,\n cover: SourceAsset | undefined,\n sections: readonly SectionDefinition[],\n contentLoader: EpubContentLoader,\n ) {\n this.#packageData = packageData;\n this.#cover = cover;\n this.#sections = sections;\n this.#contentLoader = contentLoader;\n }\n\n public static async open(archive: EpubArchive): Promise<EpubSourceDocument> {\n assertArchiveIsSupported(archive);\n const packageData = await readEpubPackage(archive);\n const navigation = await readEpubNavigation(archive, packageData);\n const rawSections = buildSections(archive, navigation);\n const targetsByPath = groupTargetsByPath(rawSections);\n const sectionAnalyses = await analyzeSectionTargets(archive, targetsByPath);\n const sections = hydrateSectionAnalyses(rawSections, sectionAnalyses);\n const cover = await readCoverAsset(archive, packageData);\n\n return new EpubSourceDocument(\n packageData,\n cover,\n sections,\n new EpubContentLoader(archive, targetsByPath),\n );\n }\n\n public readMeta() {\n return Promise.resolve(this.#packageData.metadata);\n }\n\n public readCover() {\n return Promise.resolve(this.#cover);\n }\n\n public readSections() {\n return Promise.resolve(\n this.#sections.map((section) => new EpubSourceSection(this, section)),\n );\n }\n\n public async openSection(sectionId: string): Promise<SourceTextStream> {\n return await this.#contentLoader.openSection(sectionId);\n }\n}\n\nexport class EpubSourceAdapter implements SourceAdapter {\n public get format() {\n return \"epub\" as const;\n }\n\n public async openSession<T>(\n path: string,\n operation: (document: SourceDocument) => Promise<T>,\n ): Promise<T> {\n const archive = await EpubArchive.open(path);\n\n try {\n const document = await EpubSourceDocument.open(archive);\n\n return await operation(document);\n } finally {\n await archive.close();\n }\n }\n}\n\nexport const EPUB_SOURCE_ADAPTER = new EpubSourceAdapter();\n\nfunction assertArchiveIsSupported(archive: EpubArchive): void {\n if (!archive.hasEntry(\"META-INF/encryption.xml\")) {\n return;\n }\n\n throw new Error(\n \"Encrypted EPUB is not supported: found META-INF/encryption.xml.\",\n );\n}\n\nasync function readCoverAsset(\n archive: EpubArchive,\n packageData: EpubPackageData,\n): Promise<SourceAsset | undefined> {\n if (\n packageData.coverPath === undefined ||\n packageData.coverMediaType === undefined\n ) {\n return undefined;\n }\n\n return {\n path: packageData.coverPath,\n mediaType: packageData.coverMediaType,\n data: await archive.readBuffer(packageData.coverPath),\n };\n}\n\nfunction buildSections(\n archive: EpubArchive,\n items: readonly EpubNavigationItem[],\n): readonly SectionDefinition[] {\n const idCounts = new Map<string, number>();\n\n return items.map((item, index) =>\n buildSection(archive, item, [index], idCounts),\n );\n}\n\nfunction buildSection(\n archive: EpubArchive,\n item: EpubNavigationItem,\n indexPath: readonly number[],\n idCounts: Map<string, number>,\n): SectionDefinition {\n const fragment = normalizeFragment(item.fragment);\n const baseId =\n item.path === undefined\n ? `toc:${indexPath.join(\".\")}`\n : archive.createSectionId(item.path, fragment);\n const id = createUniqueId(baseId, idCounts);\n\n return {\n hasContent: item.path !== undefined,\n id,\n title: item.title,\n path: item.path,\n fragment,\n wordsCount: 0,\n children: item.children.map((child, index) =>\n buildSection(archive, child, [...indexPath, index], idCounts),\n ),\n };\n}\n\nfunction hydrateSectionAnalyses(\n sections: readonly SectionDefinition[],\n sectionAnalyses: ReadonlyMap<string, EpubSectionAnalysis>,\n): readonly SectionDefinition[] {\n return sections.map((section) => {\n const analysis = sectionAnalyses.get(section.id);\n\n return {\n ...section,\n hasContent: analysis?.hasContent ?? false,\n wordsCount: analysis?.wordsCount ?? 0,\n children: hydrateSectionAnalyses(section.children, sectionAnalyses),\n };\n });\n}\n\nfunction createUniqueId(baseId: string, idCounts: Map<string, number>): string {\n const currentCount = idCounts.get(baseId) ?? 0;\n idCounts.set(baseId, currentCount + 1);\n\n return currentCount === 0 ? baseId : `${baseId}~${currentCount + 1}`;\n}\n\nfunction groupTargetsByPath(\n sections: readonly SectionDefinition[],\n): ReadonlyMap<string, readonly EpubSectionTarget[]> {\n const targetsByPath = new Map<string, EpubSectionTarget[]>();\n\n for (const section of flattenSections(sections)) {\n if (section.path === undefined) {\n continue;\n }\n\n const targets = targetsByPath.get(section.path) ?? [];\n targets.push({\n id: section.id,\n path: section.path,\n fragment: section.fragment,\n });\n targetsByPath.set(section.path, targets);\n }\n\n return targetsByPath;\n}\n\nfunction flattenSections(\n sections: readonly SectionDefinition[],\n): readonly SectionDefinition[] {\n const flattened: SectionDefinition[] = [];\n\n for (const section of sections) {\n flattened.push(section);\n flattened.push(...flattenSections(section.children));\n }\n\n return flattened;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { EPUB_SOURCE_ADAPTER, EpubSourceAdapter } from './document.js';
|
|
2
|
+
import '../adapter.js';
|
|
3
|
+
import '../meta.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import '../types.js';
|
|
6
|
+
import './archive.js';
|
|
7
|
+
import 'stream';
|
|
8
|
+
import 'yauzl';
|
|
9
|
+
import './content.js';
|
|
10
|
+
import './package.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/index.ts"],"sourcesContent":["export { EpubSourceAdapter, EPUB_SOURCE_ADAPTER } from \"./document.js\";\n"],"mappings":"AAAA,SAAS,mBAAmB,2BAA2B;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EpubArchive } from './archive.js';
|
|
2
|
+
import { EpubPackageData } from './package.js';
|
|
3
|
+
import 'stream';
|
|
4
|
+
import 'yauzl';
|
|
5
|
+
import '../meta.js';
|
|
6
|
+
import 'zod';
|
|
7
|
+
|
|
8
|
+
interface EpubNavigationItem {
|
|
9
|
+
readonly title: string | undefined;
|
|
10
|
+
readonly path: string | undefined;
|
|
11
|
+
readonly fragment: string | undefined;
|
|
12
|
+
readonly children: readonly EpubNavigationItem[];
|
|
13
|
+
}
|
|
14
|
+
declare function readEpubNavigation(archive: EpubArchive, packageData: EpubPackageData): Promise<readonly EpubNavigationItem[]>;
|
|
15
|
+
|
|
16
|
+
export { type EpubNavigationItem, readEpubNavigation };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { basename, extname, posix } from "path";
|
|
2
|
+
import { parseDocument } from "htmlparser2";
|
|
3
|
+
import { splitHref } from "./archive.js";
|
|
4
|
+
import {} from "./package.js";
|
|
5
|
+
import {
|
|
6
|
+
findChild,
|
|
7
|
+
findChildren,
|
|
8
|
+
getAttribute,
|
|
9
|
+
getDescendantText,
|
|
10
|
+
parseXml
|
|
11
|
+
} from "./xml.js";
|
|
12
|
+
const NON_CONTENT_FILE_NAMES = /* @__PURE__ */ new Set([
|
|
13
|
+
"toc.xhtml",
|
|
14
|
+
"nav.xhtml",
|
|
15
|
+
"contents.xhtml",
|
|
16
|
+
"tableofcontents.xhtml",
|
|
17
|
+
"cover.xhtml",
|
|
18
|
+
"titlepage.xhtml"
|
|
19
|
+
]);
|
|
20
|
+
async function readEpubNavigation(archive, packageData) {
|
|
21
|
+
const navigation = await readNavDocument(archive, packageData) ?? await readNcxDocument(archive, packageData) ?? [];
|
|
22
|
+
if (navigation.length === 0) {
|
|
23
|
+
return buildSpineNavigation(packageData, /* @__PURE__ */ new Set());
|
|
24
|
+
}
|
|
25
|
+
const referencedPaths = collectReferencedPaths(navigation);
|
|
26
|
+
const extras = buildSpineNavigation(packageData, referencedPaths);
|
|
27
|
+
return extras.length === 0 ? navigation : [...navigation, ...extras];
|
|
28
|
+
}
|
|
29
|
+
async function readNavDocument(archive, packageData) {
|
|
30
|
+
if (packageData.navPath === void 0) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
const document = parseDocument(await archive.readText(packageData.navPath), {
|
|
34
|
+
decodeEntities: true
|
|
35
|
+
});
|
|
36
|
+
const nav = findFirstHtmlElement(document, (element) => {
|
|
37
|
+
if (getHtmlTagName(element) !== "nav") {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const type = (element.attribs?.["epub:type"] ?? element.attribs?.type ?? "").split(/\s+/u).map((value) => value.trim().toLowerCase());
|
|
41
|
+
return type.includes("toc");
|
|
42
|
+
});
|
|
43
|
+
if (nav === void 0) {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
const ol = findFirstHtmlElement(
|
|
47
|
+
nav,
|
|
48
|
+
(element) => getHtmlTagName(element) === "ol"
|
|
49
|
+
);
|
|
50
|
+
if (ol === void 0) {
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
const items = getHtmlElementChildren(ol).filter((child) => getHtmlTagName(child) === "li").map((li) => parseNavListItem(archive, packageData.navPath, li)).filter((item) => item !== void 0);
|
|
54
|
+
return items.length === 0 ? void 0 : items;
|
|
55
|
+
}
|
|
56
|
+
async function readNcxDocument(archive, packageData) {
|
|
57
|
+
if (packageData.ncxPath === void 0) {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
const root = parseXml(await archive.readText(packageData.ncxPath));
|
|
61
|
+
const navMap = findChild(root, "navMap");
|
|
62
|
+
if (navMap === void 0) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
const items = findChildren(navMap, "navPoint").map(
|
|
66
|
+
(navPoint) => parseNcxNavPoint(archive, packageData.ncxPath, navPoint)
|
|
67
|
+
).filter((item) => item !== void 0);
|
|
68
|
+
return items.length === 0 ? void 0 : items;
|
|
69
|
+
}
|
|
70
|
+
function parseNavListItem(archive, navPath, item) {
|
|
71
|
+
const label = findHtmlLabelNode(item);
|
|
72
|
+
const title = label === void 0 ? void 0 : normalizeText(collectHtmlText(label));
|
|
73
|
+
const href = label !== void 0 && getHtmlTagName(label) === "a" ? label.attribs?.href : void 0;
|
|
74
|
+
const resolved = resolveHtmlHref(archive, navPath, href);
|
|
75
|
+
const children = getHtmlElementChildren(item).filter((child) => getHtmlTagName(child) === "ol").flatMap((ol) => getHtmlElementChildren(ol)).filter((child) => getHtmlTagName(child) === "li").map((li) => parseNavListItem(archive, navPath, li)).filter((child) => child !== void 0);
|
|
76
|
+
if (title === void 0 && resolved.path === void 0 && children.length === 0) {
|
|
77
|
+
return void 0;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
title,
|
|
81
|
+
path: resolved.path,
|
|
82
|
+
fragment: resolved.fragment,
|
|
83
|
+
children
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function parseNcxNavPoint(archive, ncxPath, navPoint) {
|
|
87
|
+
const navLabel = findChild(navPoint, "navLabel");
|
|
88
|
+
const textElement = navLabel === void 0 ? void 0 : findChild(navLabel, "text");
|
|
89
|
+
const title = textElement === void 0 ? void 0 : normalizeText(getDescendantText(textElement));
|
|
90
|
+
const contentElement = findChild(navPoint, "content");
|
|
91
|
+
const resolved = resolveXmlHref(
|
|
92
|
+
archive,
|
|
93
|
+
ncxPath,
|
|
94
|
+
getAttribute(contentElement ?? navPoint, "src")
|
|
95
|
+
);
|
|
96
|
+
const children = findChildren(navPoint, "navPoint").map((child) => parseNcxNavPoint(archive, ncxPath, child)).filter((child) => child !== void 0);
|
|
97
|
+
if (title === void 0 && resolved.path === void 0 && children.length === 0) {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
title,
|
|
102
|
+
path: resolved.path,
|
|
103
|
+
fragment: resolved.fragment,
|
|
104
|
+
children
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function buildSpineNavigation(packageData, referencedPaths) {
|
|
108
|
+
return packageData.spine.filter(
|
|
109
|
+
(item) => !isNonContentSpineItem(packageData, item.path, referencedPaths)
|
|
110
|
+
).filter((item) => !referencedPaths.has(item.path)).map((item) => ({
|
|
111
|
+
title: getFallbackTitle(item.path),
|
|
112
|
+
path: item.path,
|
|
113
|
+
fragment: void 0,
|
|
114
|
+
children: []
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
function isNonContentSpineItem(packageData, path, referencedPaths) {
|
|
118
|
+
if (packageData.guideNonContentPaths.has(path)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
const lowerName = posix.basename(path).toLowerCase();
|
|
122
|
+
if (packageData.navPath === path) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
return NON_CONTENT_FILE_NAMES.has(lowerName) && !referencedPaths.has(path);
|
|
126
|
+
}
|
|
127
|
+
function collectReferencedPaths(items) {
|
|
128
|
+
const paths = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const item of items) {
|
|
130
|
+
if (item.path !== void 0) {
|
|
131
|
+
paths.add(item.path);
|
|
132
|
+
}
|
|
133
|
+
for (const childPath of collectReferencedPaths(item.children)) {
|
|
134
|
+
paths.add(childPath);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return paths;
|
|
138
|
+
}
|
|
139
|
+
function resolveHtmlHref(archive, basePath, href) {
|
|
140
|
+
if (href === void 0 || href.trim() === "") {
|
|
141
|
+
return { path: void 0, fragment: void 0 };
|
|
142
|
+
}
|
|
143
|
+
const { path, fragment } = splitHref(href);
|
|
144
|
+
return {
|
|
145
|
+
path: path === "" ? void 0 : archive.resolveRelativePath(basePath, path),
|
|
146
|
+
fragment
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function resolveXmlHref(archive, basePath, href) {
|
|
150
|
+
if (href === void 0 || href.trim() === "") {
|
|
151
|
+
return { path: void 0, fragment: void 0 };
|
|
152
|
+
}
|
|
153
|
+
const { path, fragment } = splitHref(href);
|
|
154
|
+
return {
|
|
155
|
+
path: path === "" ? void 0 : archive.resolveRelativePath(basePath, path),
|
|
156
|
+
fragment
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function findFirstHtmlElement(node, predicate) {
|
|
160
|
+
if (isHtmlElement(node) && predicate(node)) {
|
|
161
|
+
return node;
|
|
162
|
+
}
|
|
163
|
+
for (const child of node.children ?? []) {
|
|
164
|
+
const found = findFirstHtmlElement(child, predicate);
|
|
165
|
+
if (found !== void 0) {
|
|
166
|
+
return found;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return void 0;
|
|
170
|
+
}
|
|
171
|
+
function findHtmlLabelNode(node) {
|
|
172
|
+
for (const child of getHtmlElementChildren(node)) {
|
|
173
|
+
const tagName = getHtmlTagName(child);
|
|
174
|
+
if (tagName === "a" || tagName === "span") {
|
|
175
|
+
return child;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const child of getHtmlElementChildren(node)) {
|
|
179
|
+
if (getHtmlTagName(child) === "ol") {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const nested = findHtmlLabelNode(child);
|
|
183
|
+
if (nested !== void 0) {
|
|
184
|
+
return nested;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
function collectHtmlText(node) {
|
|
190
|
+
if (node.type === "text") {
|
|
191
|
+
return node.data ?? "";
|
|
192
|
+
}
|
|
193
|
+
return (node.children ?? []).map(collectHtmlText).join("");
|
|
194
|
+
}
|
|
195
|
+
function getHtmlElementChildren(node) {
|
|
196
|
+
return (node.children ?? []).filter(isHtmlElement);
|
|
197
|
+
}
|
|
198
|
+
function isHtmlElement(node) {
|
|
199
|
+
return node.type === "tag" || node.type === "script" || node.type === "style";
|
|
200
|
+
}
|
|
201
|
+
function getHtmlTagName(node) {
|
|
202
|
+
return node.name?.toLowerCase();
|
|
203
|
+
}
|
|
204
|
+
function getFallbackTitle(path) {
|
|
205
|
+
const stem = basename(path, extname(path)).trim();
|
|
206
|
+
return stem === "" ? void 0 : stem;
|
|
207
|
+
}
|
|
208
|
+
function normalizeText(text) {
|
|
209
|
+
const normalized = text.replace(/\s+/gu, " ").trim();
|
|
210
|
+
return normalized === "" ? void 0 : normalized;
|
|
211
|
+
}
|
|
212
|
+
export {
|
|
213
|
+
readEpubNavigation
|
|
214
|
+
};
|
|
215
|
+
//# sourceMappingURL=navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/navigation.ts"],"sourcesContent":["import { basename, extname, posix } from \"path\";\n\nimport { parseDocument } from \"htmlparser2\";\n\nimport { splitHref } from \"./archive.js\";\nimport type { EpubArchive } from \"./archive.js\";\nimport { type EpubPackageData } from \"./package.js\";\nimport {\n findChild,\n findChildren,\n getAttribute,\n getDescendantText,\n parseXml,\n type XmlElement,\n} from \"./xml.js\";\n\nconst NON_CONTENT_FILE_NAMES = new Set([\n \"toc.xhtml\",\n \"nav.xhtml\",\n \"contents.xhtml\",\n \"tableofcontents.xhtml\",\n \"cover.xhtml\",\n \"titlepage.xhtml\",\n]);\n\ninterface HtmlNode {\n readonly type?: string;\n readonly name?: string;\n readonly data?: string;\n readonly attribs?: Readonly<Record<string, string>>;\n readonly children?: readonly HtmlNode[];\n}\n\nexport interface EpubNavigationItem {\n readonly title: string | undefined;\n readonly path: string | undefined;\n readonly fragment: string | undefined;\n readonly children: readonly EpubNavigationItem[];\n}\n\nexport async function readEpubNavigation(\n archive: EpubArchive,\n packageData: EpubPackageData,\n): Promise<readonly EpubNavigationItem[]> {\n const navigation =\n (await readNavDocument(archive, packageData)) ??\n (await readNcxDocument(archive, packageData)) ??\n [];\n\n if (navigation.length === 0) {\n return buildSpineNavigation(packageData, new Set());\n }\n\n const referencedPaths = collectReferencedPaths(navigation);\n const extras = buildSpineNavigation(packageData, referencedPaths);\n\n return extras.length === 0 ? navigation : [...navigation, ...extras];\n}\n\nasync function readNavDocument(\n archive: EpubArchive,\n packageData: EpubPackageData,\n): Promise<readonly EpubNavigationItem[] | undefined> {\n if (packageData.navPath === undefined) {\n return undefined;\n }\n\n const document = parseDocument(await archive.readText(packageData.navPath), {\n decodeEntities: true,\n }) as HtmlNode;\n const nav = findFirstHtmlElement(document, (element) => {\n if (getHtmlTagName(element) !== \"nav\") {\n return false;\n }\n\n const type = (element.attribs?.[\"epub:type\"] ?? element.attribs?.type ?? \"\")\n .split(/\\s+/u)\n .map((value) => value.trim().toLowerCase());\n\n return type.includes(\"toc\");\n });\n\n if (nav === undefined) {\n return undefined;\n }\n\n const ol = findFirstHtmlElement(\n nav,\n (element) => getHtmlTagName(element) === \"ol\",\n );\n if (ol === undefined) {\n return undefined;\n }\n\n const items = getHtmlElementChildren(ol)\n .filter((child) => getHtmlTagName(child) === \"li\")\n .map((li) => parseNavListItem(archive, packageData.navPath!, li))\n .filter((item): item is EpubNavigationItem => item !== undefined);\n\n return items.length === 0 ? undefined : items;\n}\n\nasync function readNcxDocument(\n archive: EpubArchive,\n packageData: EpubPackageData,\n): Promise<readonly EpubNavigationItem[] | undefined> {\n if (packageData.ncxPath === undefined) {\n return undefined;\n }\n\n const root = parseXml(await archive.readText(packageData.ncxPath));\n const navMap = findChild(root, \"navMap\");\n if (navMap === undefined) {\n return undefined;\n }\n\n const items = findChildren(navMap, \"navPoint\")\n .map((navPoint) =>\n parseNcxNavPoint(archive, packageData.ncxPath!, navPoint),\n )\n .filter((item): item is EpubNavigationItem => item !== undefined);\n\n return items.length === 0 ? undefined : items;\n}\n\nfunction parseNavListItem(\n archive: EpubArchive,\n navPath: string,\n item: HtmlNode,\n): EpubNavigationItem | undefined {\n const label = findHtmlLabelNode(item);\n const title =\n label === undefined ? undefined : normalizeText(collectHtmlText(label));\n const href =\n label !== undefined && getHtmlTagName(label) === \"a\"\n ? label.attribs?.href\n : undefined;\n const resolved = resolveHtmlHref(archive, navPath, href);\n const children = getHtmlElementChildren(item)\n .filter((child) => getHtmlTagName(child) === \"ol\")\n .flatMap((ol) => getHtmlElementChildren(ol))\n .filter((child) => getHtmlTagName(child) === \"li\")\n .map((li) => parseNavListItem(archive, navPath, li))\n .filter((child): child is EpubNavigationItem => child !== undefined);\n\n if (\n title === undefined &&\n resolved.path === undefined &&\n children.length === 0\n ) {\n return undefined;\n }\n\n return {\n title,\n path: resolved.path,\n fragment: resolved.fragment,\n children,\n };\n}\n\nfunction parseNcxNavPoint(\n archive: EpubArchive,\n ncxPath: string,\n navPoint: XmlElement,\n): EpubNavigationItem | undefined {\n const navLabel = findChild(navPoint, \"navLabel\");\n const textElement =\n navLabel === undefined ? undefined : findChild(navLabel, \"text\");\n const title =\n textElement === undefined\n ? undefined\n : normalizeText(getDescendantText(textElement));\n const contentElement = findChild(navPoint, \"content\");\n const resolved = resolveXmlHref(\n archive,\n ncxPath,\n getAttribute(contentElement ?? navPoint, \"src\"),\n );\n const children = findChildren(navPoint, \"navPoint\")\n .map((child) => parseNcxNavPoint(archive, ncxPath, child))\n .filter((child): child is EpubNavigationItem => child !== undefined);\n\n if (\n title === undefined &&\n resolved.path === undefined &&\n children.length === 0\n ) {\n return undefined;\n }\n\n return {\n title,\n path: resolved.path,\n fragment: resolved.fragment,\n children,\n };\n}\n\nfunction buildSpineNavigation(\n packageData: EpubPackageData,\n referencedPaths: ReadonlySet<string>,\n): readonly EpubNavigationItem[] {\n return packageData.spine\n .filter(\n (item) => !isNonContentSpineItem(packageData, item.path, referencedPaths),\n )\n .filter((item) => !referencedPaths.has(item.path))\n .map((item) => ({\n title: getFallbackTitle(item.path),\n path: item.path,\n fragment: undefined,\n children: [],\n }));\n}\n\nfunction isNonContentSpineItem(\n packageData: EpubPackageData,\n path: string,\n referencedPaths: ReadonlySet<string>,\n): boolean {\n if (packageData.guideNonContentPaths.has(path)) {\n return true;\n }\n\n const lowerName = posix.basename(path).toLowerCase();\n if (packageData.navPath === path) {\n return true;\n }\n\n return NON_CONTENT_FILE_NAMES.has(lowerName) && !referencedPaths.has(path);\n}\n\nfunction collectReferencedPaths(\n items: readonly EpubNavigationItem[],\n): ReadonlySet<string> {\n const paths = new Set<string>();\n\n for (const item of items) {\n if (item.path !== undefined) {\n paths.add(item.path);\n }\n\n for (const childPath of collectReferencedPaths(item.children)) {\n paths.add(childPath);\n }\n }\n\n return paths;\n}\n\nfunction resolveHtmlHref(\n archive: EpubArchive,\n basePath: string,\n href: string | undefined,\n): {\n readonly path: string | undefined;\n readonly fragment: string | undefined;\n} {\n if (href === undefined || href.trim() === \"\") {\n return { path: undefined, fragment: undefined };\n }\n\n const { path, fragment } = splitHref(href);\n\n return {\n path: path === \"\" ? undefined : archive.resolveRelativePath(basePath, path),\n fragment,\n };\n}\n\nfunction resolveXmlHref(\n archive: EpubArchive,\n basePath: string,\n href: string | undefined,\n): {\n readonly path: string | undefined;\n readonly fragment: string | undefined;\n} {\n if (href === undefined || href.trim() === \"\") {\n return { path: undefined, fragment: undefined };\n }\n\n const { path, fragment } = splitHref(href);\n\n return {\n path: path === \"\" ? undefined : archive.resolveRelativePath(basePath, path),\n fragment,\n };\n}\n\nfunction findFirstHtmlElement(\n node: HtmlNode,\n predicate: (element: HtmlNode) => boolean,\n): HtmlNode | undefined {\n if (isHtmlElement(node) && predicate(node)) {\n return node;\n }\n\n for (const child of node.children ?? []) {\n const found = findFirstHtmlElement(child, predicate);\n if (found !== undefined) {\n return found;\n }\n }\n\n return undefined;\n}\n\nfunction findHtmlLabelNode(node: HtmlNode): HtmlNode | undefined {\n for (const child of getHtmlElementChildren(node)) {\n const tagName = getHtmlTagName(child);\n if (tagName === \"a\" || tagName === \"span\") {\n return child;\n }\n }\n\n for (const child of getHtmlElementChildren(node)) {\n if (getHtmlTagName(child) === \"ol\") {\n continue;\n }\n\n const nested = findHtmlLabelNode(child);\n if (nested !== undefined) {\n return nested;\n }\n }\n\n return undefined;\n}\n\nfunction collectHtmlText(node: HtmlNode): string {\n if (node.type === \"text\") {\n return node.data ?? \"\";\n }\n\n return (node.children ?? []).map(collectHtmlText).join(\"\");\n}\n\nfunction getHtmlElementChildren(node: HtmlNode): readonly HtmlNode[] {\n return (node.children ?? []).filter(isHtmlElement);\n}\n\nfunction isHtmlElement(node: HtmlNode): boolean {\n return node.type === \"tag\" || node.type === \"script\" || node.type === \"style\";\n}\n\nfunction getHtmlTagName(node: HtmlNode): string | undefined {\n return node.name?.toLowerCase();\n}\n\nfunction getFallbackTitle(path: string): string | undefined {\n const stem = basename(path, extname(path)).trim();\n\n return stem === \"\" ? undefined : stem;\n}\n\nfunction normalizeText(text: string): string | undefined {\n const normalized = text.replace(/\\s+/gu, \" \").trim();\n\n return normalized === \"\" ? undefined : normalized;\n}\n"],"mappings":"AAAA,SAAS,UAAU,SAAS,aAAa;AAEzC,SAAS,qBAAqB;AAE9B,SAAS,iBAAiB;AAE1B,eAAqC;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,MAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAiBD,eAAsB,mBACpB,SACA,aACwC;AACxC,QAAM,aACH,MAAM,gBAAgB,SAAS,WAAW,KAC1C,MAAM,gBAAgB,SAAS,WAAW,KAC3C,CAAC;AAEH,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,qBAAqB,aAAa,oBAAI,IAAI,CAAC;AAAA,EACpD;AAEA,QAAM,kBAAkB,uBAAuB,UAAU;AACzD,QAAM,SAAS,qBAAqB,aAAa,eAAe;AAEhE,SAAO,OAAO,WAAW,IAAI,aAAa,CAAC,GAAG,YAAY,GAAG,MAAM;AACrE;AAEA,eAAe,gBACb,SACA,aACoD;AACpD,MAAI,YAAY,YAAY,QAAW;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,MAAM,QAAQ,SAAS,YAAY,OAAO,GAAG;AAAA,IAC1E,gBAAgB;AAAA,EAClB,CAAC;AACD,QAAM,MAAM,qBAAqB,UAAU,CAAC,YAAY;AACtD,QAAI,eAAe,OAAO,MAAM,OAAO;AACrC,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,QAAQ,UAAU,WAAW,KAAK,QAAQ,SAAS,QAAQ,IACtE,MAAM,MAAM,EACZ,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC;AAE5C,WAAO,KAAK,SAAS,KAAK;AAAA,EAC5B,CAAC;AAED,MAAI,QAAQ,QAAW;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,KAAK;AAAA,IACT;AAAA,IACA,CAAC,YAAY,eAAe,OAAO,MAAM;AAAA,EAC3C;AACA,MAAI,OAAO,QAAW;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,uBAAuB,EAAE,EACpC,OAAO,CAAC,UAAU,eAAe,KAAK,MAAM,IAAI,EAChD,IAAI,CAAC,OAAO,iBAAiB,SAAS,YAAY,SAAU,EAAE,CAAC,EAC/D,OAAO,CAAC,SAAqC,SAAS,MAAS;AAElE,SAAO,MAAM,WAAW,IAAI,SAAY;AAC1C;AAEA,eAAe,gBACb,SACA,aACoD;AACpD,MAAI,YAAY,YAAY,QAAW;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,SAAS,MAAM,QAAQ,SAAS,YAAY,OAAO,CAAC;AACjE,QAAM,SAAS,UAAU,MAAM,QAAQ;AACvC,MAAI,WAAW,QAAW;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,aAAa,QAAQ,UAAU,EAC1C;AAAA,IAAI,CAAC,aACJ,iBAAiB,SAAS,YAAY,SAAU,QAAQ;AAAA,EAC1D,EACC,OAAO,CAAC,SAAqC,SAAS,MAAS;AAElE,SAAO,MAAM,WAAW,IAAI,SAAY;AAC1C;AAEA,SAAS,iBACP,SACA,SACA,MACgC;AAChC,QAAM,QAAQ,kBAAkB,IAAI;AACpC,QAAM,QACJ,UAAU,SAAY,SAAY,cAAc,gBAAgB,KAAK,CAAC;AACxE,QAAM,OACJ,UAAU,UAAa,eAAe,KAAK,MAAM,MAC7C,MAAM,SAAS,OACf;AACN,QAAM,WAAW,gBAAgB,SAAS,SAAS,IAAI;AACvD,QAAM,WAAW,uBAAuB,IAAI,EACzC,OAAO,CAAC,UAAU,eAAe,KAAK,MAAM,IAAI,EAChD,QAAQ,CAAC,OAAO,uBAAuB,EAAE,CAAC,EAC1C,OAAO,CAAC,UAAU,eAAe,KAAK,MAAM,IAAI,EAChD,IAAI,CAAC,OAAO,iBAAiB,SAAS,SAAS,EAAE,CAAC,EAClD,OAAO,CAAC,UAAuC,UAAU,MAAS;AAErE,MACE,UAAU,UACV,SAAS,SAAS,UAClB,SAAS,WAAW,GACpB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,SAAS;AAAA,IACf,UAAU,SAAS;AAAA,IACnB;AAAA,EACF;AACF;AAEA,SAAS,iBACP,SACA,SACA,UACgC;AAChC,QAAM,WAAW,UAAU,UAAU,UAAU;AAC/C,QAAM,cACJ,aAAa,SAAY,SAAY,UAAU,UAAU,MAAM;AACjE,QAAM,QACJ,gBAAgB,SACZ,SACA,cAAc,kBAAkB,WAAW,CAAC;AAClD,QAAM,iBAAiB,UAAU,UAAU,SAAS;AACpD,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA,aAAa,kBAAkB,UAAU,KAAK;AAAA,EAChD;AACA,QAAM,WAAW,aAAa,UAAU,UAAU,EAC/C,IAAI,CAAC,UAAU,iBAAiB,SAAS,SAAS,KAAK,CAAC,EACxD,OAAO,CAAC,UAAuC,UAAU,MAAS;AAErE,MACE,UAAU,UACV,SAAS,SAAS,UAClB,SAAS,WAAW,GACpB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,SAAS;AAAA,IACf,UAAU,SAAS;AAAA,IACnB;AAAA,EACF;AACF;AAEA,SAAS,qBACP,aACA,iBAC+B;AAC/B,SAAO,YAAY,MAChB;AAAA,IACC,CAAC,SAAS,CAAC,sBAAsB,aAAa,KAAK,MAAM,eAAe;AAAA,EAC1E,EACC,OAAO,CAAC,SAAS,CAAC,gBAAgB,IAAI,KAAK,IAAI,CAAC,EAChD,IAAI,CAAC,UAAU;AAAA,IACd,OAAO,iBAAiB,KAAK,IAAI;AAAA,IACjC,MAAM,KAAK;AAAA,IACX,UAAU;AAAA,IACV,UAAU,CAAC;AAAA,EACb,EAAE;AACN;AAEA,SAAS,sBACP,aACA,MACA,iBACS;AACT,MAAI,YAAY,qBAAqB,IAAI,IAAI,GAAG;AAC9C,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM,SAAS,IAAI,EAAE,YAAY;AACnD,MAAI,YAAY,YAAY,MAAM;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,uBAAuB,IAAI,SAAS,KAAK,CAAC,gBAAgB,IAAI,IAAI;AAC3E;AAEA,SAAS,uBACP,OACqB;AACrB,QAAM,QAAQ,oBAAI,IAAY;AAE9B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,QAAW;AAC3B,YAAM,IAAI,KAAK,IAAI;AAAA,IACrB;AAEA,eAAW,aAAa,uBAAuB,KAAK,QAAQ,GAAG;AAC7D,YAAM,IAAI,SAAS;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,gBACP,SACA,UACA,MAIA;AACA,MAAI,SAAS,UAAa,KAAK,KAAK,MAAM,IAAI;AAC5C,WAAO,EAAE,MAAM,QAAW,UAAU,OAAU;AAAA,EAChD;AAEA,QAAM,EAAE,MAAM,SAAS,IAAI,UAAU,IAAI;AAEzC,SAAO;AAAA,IACL,MAAM,SAAS,KAAK,SAAY,QAAQ,oBAAoB,UAAU,IAAI;AAAA,IAC1E;AAAA,EACF;AACF;AAEA,SAAS,eACP,SACA,UACA,MAIA;AACA,MAAI,SAAS,UAAa,KAAK,KAAK,MAAM,IAAI;AAC5C,WAAO,EAAE,MAAM,QAAW,UAAU,OAAU;AAAA,EAChD;AAEA,QAAM,EAAE,MAAM,SAAS,IAAI,UAAU,IAAI;AAEzC,SAAO;AAAA,IACL,MAAM,SAAS,KAAK,SAAY,QAAQ,oBAAoB,UAAU,IAAI;AAAA,IAC1E;AAAA,EACF;AACF;AAEA,SAAS,qBACP,MACA,WACsB;AACtB,MAAI,cAAc,IAAI,KAAK,UAAU,IAAI,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,KAAK,YAAY,CAAC,GAAG;AACvC,UAAM,QAAQ,qBAAqB,OAAO,SAAS;AACnD,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,aAAW,SAAS,uBAAuB,IAAI,GAAG;AAChD,UAAM,UAAU,eAAe,KAAK;AACpC,QAAI,YAAY,OAAO,YAAY,QAAQ;AACzC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,aAAW,SAAS,uBAAuB,IAAI,GAAG;AAChD,QAAI,eAAe,KAAK,MAAM,MAAM;AAClC;AAAA,IACF;AAEA,UAAM,SAAS,kBAAkB,KAAK;AACtC,QAAI,WAAW,QAAW;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAwB;AAC/C,MAAI,KAAK,SAAS,QAAQ;AACxB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAEA,UAAQ,KAAK,YAAY,CAAC,GAAG,IAAI,eAAe,EAAE,KAAK,EAAE;AAC3D;AAEA,SAAS,uBAAuB,MAAqC;AACnE,UAAQ,KAAK,YAAY,CAAC,GAAG,OAAO,aAAa;AACnD;AAEA,SAAS,cAAc,MAAyB;AAC9C,SAAO,KAAK,SAAS,SAAS,KAAK,SAAS,YAAY,KAAK,SAAS;AACxE;AAEA,SAAS,eAAe,MAAoC;AAC1D,SAAO,KAAK,MAAM,YAAY;AAChC;AAEA,SAAS,iBAAiB,MAAkC;AAC1D,QAAM,OAAO,SAAS,MAAM,QAAQ,IAAI,CAAC,EAAE,KAAK;AAEhD,SAAO,SAAS,KAAK,SAAY;AACnC;AAEA,SAAS,cAAc,MAAkC;AACvD,QAAM,aAAa,KAAK,QAAQ,SAAS,GAAG,EAAE,KAAK;AAEnD,SAAO,eAAe,KAAK,SAAY;AACzC;","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BookMeta } from '../meta.js';
|
|
2
|
+
import { EpubArchive } from './archive.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
import 'stream';
|
|
5
|
+
import 'yauzl';
|
|
6
|
+
|
|
7
|
+
interface EpubManifestItem {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly path: string;
|
|
10
|
+
readonly mediaType: string;
|
|
11
|
+
readonly properties: ReadonlySet<string>;
|
|
12
|
+
}
|
|
13
|
+
interface EpubSpineItem {
|
|
14
|
+
readonly idref: string;
|
|
15
|
+
readonly path: string;
|
|
16
|
+
readonly mediaType: string;
|
|
17
|
+
}
|
|
18
|
+
interface EpubPackageData {
|
|
19
|
+
readonly version: 2 | 3;
|
|
20
|
+
readonly opfPath: string;
|
|
21
|
+
readonly metadata: BookMeta;
|
|
22
|
+
readonly manifest: ReadonlyMap<string, EpubManifestItem>;
|
|
23
|
+
readonly manifestByPath: ReadonlyMap<string, EpubManifestItem>;
|
|
24
|
+
readonly spine: readonly EpubSpineItem[];
|
|
25
|
+
readonly navPath: string | undefined;
|
|
26
|
+
readonly ncxPath: string | undefined;
|
|
27
|
+
readonly coverPath: string | undefined;
|
|
28
|
+
readonly coverMediaType: string | undefined;
|
|
29
|
+
readonly guideNonContentPaths: ReadonlySet<string>;
|
|
30
|
+
}
|
|
31
|
+
declare function readEpubPackage(archive: EpubArchive): Promise<EpubPackageData>;
|
|
32
|
+
|
|
33
|
+
export { type EpubManifestItem, type EpubPackageData, type EpubSpineItem, readEpubPackage };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { posix } from "path";
|
|
2
|
+
import { BOOK_META_VERSION } from "../meta.js";
|
|
3
|
+
import { splitHref } from "./archive.js";
|
|
4
|
+
import {
|
|
5
|
+
findChild,
|
|
6
|
+
findChildren,
|
|
7
|
+
getAttribute,
|
|
8
|
+
getDescendantText,
|
|
9
|
+
getLocalName,
|
|
10
|
+
parseXml
|
|
11
|
+
} from "./xml.js";
|
|
12
|
+
const COVER_ITEM_IDS = ["cover-image", "coverimg", "cover-img", "cover"];
|
|
13
|
+
const GUIDE_NON_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
14
|
+
"cover",
|
|
15
|
+
"titlepage",
|
|
16
|
+
"other.titlepage"
|
|
17
|
+
]);
|
|
18
|
+
async function readEpubPackage(archive) {
|
|
19
|
+
const opfPath = await findOpfPath(archive);
|
|
20
|
+
const opf = parseXml(await archive.readText(opfPath));
|
|
21
|
+
const version = parsePackageVersion(getAttribute(opf, "version"));
|
|
22
|
+
const metadataElement = findChild(opf, "metadata");
|
|
23
|
+
const manifestElement = findChild(opf, "manifest");
|
|
24
|
+
const spineElement = findChild(opf, "spine");
|
|
25
|
+
const guideElement = findChild(opf, "guide");
|
|
26
|
+
const manifest = buildManifest(archive, opfPath, manifestElement);
|
|
27
|
+
const manifestByPath = new Map(
|
|
28
|
+
[...manifest.values()].map((item) => [item.path, item])
|
|
29
|
+
);
|
|
30
|
+
const spine = buildSpine(spineElement, manifest);
|
|
31
|
+
const guideNonContentPaths = buildGuideNonContentPaths(
|
|
32
|
+
archive,
|
|
33
|
+
opfPath,
|
|
34
|
+
guideElement
|
|
35
|
+
);
|
|
36
|
+
const metadata = buildMetadata(metadataElement);
|
|
37
|
+
const navPath = findNavPath(manifest);
|
|
38
|
+
const ncxPath = findNcxPath(manifest, spineElement);
|
|
39
|
+
const coverItem = findCoverItem(manifest, metadataElement);
|
|
40
|
+
return {
|
|
41
|
+
version,
|
|
42
|
+
opfPath,
|
|
43
|
+
metadata: {
|
|
44
|
+
...metadata,
|
|
45
|
+
version: BOOK_META_VERSION,
|
|
46
|
+
sourceFormat: "epub"
|
|
47
|
+
},
|
|
48
|
+
manifest,
|
|
49
|
+
manifestByPath,
|
|
50
|
+
spine,
|
|
51
|
+
navPath,
|
|
52
|
+
ncxPath,
|
|
53
|
+
coverPath: coverItem?.path,
|
|
54
|
+
coverMediaType: coverItem?.mediaType,
|
|
55
|
+
guideNonContentPaths
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function findOpfPath(archive) {
|
|
59
|
+
const container = parseXml(await archive.readText("META-INF/container.xml"));
|
|
60
|
+
const rootfiles = findChild(container, "rootfiles");
|
|
61
|
+
const rootfile = rootfiles?.children.find(
|
|
62
|
+
(child) => getLocalName(child.name) === "rootfile"
|
|
63
|
+
);
|
|
64
|
+
const fullPath = rootfile === void 0 ? void 0 : getAttribute(rootfile, "full-path");
|
|
65
|
+
if (fullPath === void 0 || fullPath.trim() === "") {
|
|
66
|
+
throw new Error("EPUB container.xml does not contain an OPF rootfile");
|
|
67
|
+
}
|
|
68
|
+
return fullPath;
|
|
69
|
+
}
|
|
70
|
+
function parsePackageVersion(version) {
|
|
71
|
+
return version?.trim().startsWith("3") === true ? 3 : 2;
|
|
72
|
+
}
|
|
73
|
+
function buildMetadata(metadataElement) {
|
|
74
|
+
if (metadataElement === void 0) {
|
|
75
|
+
return createEmptyMetadata();
|
|
76
|
+
}
|
|
77
|
+
const titles = readMetadataValues(metadataElement, "title");
|
|
78
|
+
const creators = readMetadataValues(metadataElement, "creator");
|
|
79
|
+
const languages = readMetadataValues(metadataElement, "language");
|
|
80
|
+
const identifiers = readMetadataValues(metadataElement, "identifier");
|
|
81
|
+
const publishers = readMetadataValues(metadataElement, "publisher");
|
|
82
|
+
const dates = readMetadataValues(metadataElement, "date");
|
|
83
|
+
const descriptions = readMetadataValues(metadataElement, "description");
|
|
84
|
+
return {
|
|
85
|
+
...createEmptyMetadata(),
|
|
86
|
+
title: titles[0] ?? null,
|
|
87
|
+
authors: [...creators],
|
|
88
|
+
language: languages[0] ?? null,
|
|
89
|
+
identifier: identifiers[0] ?? null,
|
|
90
|
+
publisher: publishers[0] ?? null,
|
|
91
|
+
publishedAt: dates[0] ?? null,
|
|
92
|
+
description: descriptions[0] ?? null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function createEmptyMetadata() {
|
|
96
|
+
return {
|
|
97
|
+
version: BOOK_META_VERSION,
|
|
98
|
+
sourceFormat: "epub",
|
|
99
|
+
title: null,
|
|
100
|
+
authors: [],
|
|
101
|
+
language: null,
|
|
102
|
+
identifier: null,
|
|
103
|
+
publisher: null,
|
|
104
|
+
publishedAt: null,
|
|
105
|
+
description: null
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function readMetadataValues(metadataElement, localName) {
|
|
109
|
+
return metadataElement.children.filter((child) => getLocalName(child.name) === localName).map((child) => normalizeText(getDescendantText(child))).filter((value) => value !== void 0);
|
|
110
|
+
}
|
|
111
|
+
function buildManifest(archive, opfPath, manifestElement) {
|
|
112
|
+
const manifest = /* @__PURE__ */ new Map();
|
|
113
|
+
if (manifestElement === void 0) {
|
|
114
|
+
return manifest;
|
|
115
|
+
}
|
|
116
|
+
for (const item of findChildren(manifestElement, "item")) {
|
|
117
|
+
const id = getAttribute(item, "id");
|
|
118
|
+
const href = getAttribute(item, "href");
|
|
119
|
+
const mediaType = getAttribute(item, "media-type") ?? "";
|
|
120
|
+
if (id === void 0 || href === void 0) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
manifest.set(id, {
|
|
124
|
+
id,
|
|
125
|
+
path: archive.resolveRelativePath(opfPath, href),
|
|
126
|
+
mediaType,
|
|
127
|
+
properties: new Set(
|
|
128
|
+
(getAttribute(item, "properties") ?? "").split(/\s+/u).map((value) => value.trim().toLowerCase()).filter((value) => value !== "")
|
|
129
|
+
)
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return manifest;
|
|
133
|
+
}
|
|
134
|
+
function buildSpine(spineElement, manifest) {
|
|
135
|
+
if (spineElement === void 0) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
return findChildren(spineElement, "itemref").map((itemref) => getAttribute(itemref, "idref")).filter((idref) => idref !== void 0).map((idref) => {
|
|
139
|
+
const item = manifest.get(idref);
|
|
140
|
+
if (item === void 0 || item.mediaType !== "application/xhtml+xml" && item.mediaType !== "text/html") {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
idref,
|
|
145
|
+
path: item.path,
|
|
146
|
+
mediaType: item.mediaType
|
|
147
|
+
};
|
|
148
|
+
}).filter((item) => item !== void 0);
|
|
149
|
+
}
|
|
150
|
+
function buildGuideNonContentPaths(archive, opfPath, guideElement) {
|
|
151
|
+
const paths = /* @__PURE__ */ new Set();
|
|
152
|
+
if (guideElement === void 0) {
|
|
153
|
+
return paths;
|
|
154
|
+
}
|
|
155
|
+
for (const reference of findChildren(guideElement, "reference")) {
|
|
156
|
+
const type = (getAttribute(reference, "type") ?? "").trim().toLowerCase();
|
|
157
|
+
if (!GUIDE_NON_CONTENT_TYPES.has(type)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const href = getAttribute(reference, "href");
|
|
161
|
+
if (href === void 0 || href.trim() === "") {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
paths.add(archive.resolveRelativePath(opfPath, splitHref(href).path));
|
|
165
|
+
}
|
|
166
|
+
return paths;
|
|
167
|
+
}
|
|
168
|
+
function findNavPath(manifest) {
|
|
169
|
+
for (const item of manifest.values()) {
|
|
170
|
+
if (item.properties.has("nav")) {
|
|
171
|
+
return item.path;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return void 0;
|
|
175
|
+
}
|
|
176
|
+
function findNcxPath(manifest, spineElement) {
|
|
177
|
+
const tocId = spineElement === void 0 ? void 0 : getAttribute(spineElement, "toc");
|
|
178
|
+
if (tocId !== void 0) {
|
|
179
|
+
return manifest.get(tocId)?.path;
|
|
180
|
+
}
|
|
181
|
+
for (const item of manifest.values()) {
|
|
182
|
+
if (item.mediaType === "application/x-dtbncx+xml") {
|
|
183
|
+
return item.path;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return void 0;
|
|
187
|
+
}
|
|
188
|
+
function findCoverItem(manifest, metadataElement) {
|
|
189
|
+
for (const item of manifest.values()) {
|
|
190
|
+
if (item.properties.has("cover-image") && item.mediaType.startsWith("image/")) {
|
|
191
|
+
return item;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const coverId = readCoverIdFromMetadata(metadataElement);
|
|
195
|
+
if (coverId !== void 0) {
|
|
196
|
+
const coverItem = manifest.get(coverId);
|
|
197
|
+
if (coverItem?.mediaType.startsWith("image/") === true) {
|
|
198
|
+
return coverItem;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const coverItemId of COVER_ITEM_IDS) {
|
|
202
|
+
const coverItem = manifest.get(coverItemId);
|
|
203
|
+
if (coverItem?.mediaType.startsWith("image/") === true) {
|
|
204
|
+
return coverItem;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
for (const item of manifest.values()) {
|
|
208
|
+
if (item.mediaType.startsWith("image/") && posix.basename(item.path).toLowerCase().includes("cover")) {
|
|
209
|
+
return item;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return void 0;
|
|
213
|
+
}
|
|
214
|
+
function readCoverIdFromMetadata(metadataElement) {
|
|
215
|
+
if (metadataElement === void 0) {
|
|
216
|
+
return void 0;
|
|
217
|
+
}
|
|
218
|
+
for (const meta of findChildren(metadataElement, "meta")) {
|
|
219
|
+
const name = (getAttribute(meta, "name") ?? "").trim().toLowerCase();
|
|
220
|
+
if (name !== "cover") {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const content = getAttribute(meta, "content");
|
|
224
|
+
if (content !== void 0 && content.trim() !== "") {
|
|
225
|
+
return content.trim();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return void 0;
|
|
229
|
+
}
|
|
230
|
+
function normalizeText(text) {
|
|
231
|
+
const normalized = text.replace(/\s+/gu, " ").trim();
|
|
232
|
+
return normalized === "" ? void 0 : normalized;
|
|
233
|
+
}
|
|
234
|
+
export {
|
|
235
|
+
readEpubPackage
|
|
236
|
+
};
|
|
237
|
+
//# sourceMappingURL=package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/package.ts"],"sourcesContent":["import { posix } from \"path\";\n\nimport { BOOK_META_VERSION, type BookMeta } from \"../meta.js\";\nimport { splitHref } from \"./archive.js\";\nimport type { EpubArchive } from \"./archive.js\";\nimport {\n findChild,\n findChildren,\n getAttribute,\n getDescendantText,\n getLocalName,\n parseXml,\n type XmlElement,\n} from \"./xml.js\";\n\nconst COVER_ITEM_IDS = [\"cover-image\", \"coverimg\", \"cover-img\", \"cover\"];\nconst GUIDE_NON_CONTENT_TYPES = new Set([\n \"cover\",\n \"titlepage\",\n \"other.titlepage\",\n]);\n\nexport interface EpubManifestItem {\n readonly id: string;\n readonly path: string;\n readonly mediaType: string;\n readonly properties: ReadonlySet<string>;\n}\n\nexport interface EpubSpineItem {\n readonly idref: string;\n readonly path: string;\n readonly mediaType: string;\n}\n\nexport interface EpubPackageData {\n readonly version: 2 | 3;\n readonly opfPath: string;\n readonly metadata: BookMeta;\n readonly manifest: ReadonlyMap<string, EpubManifestItem>;\n readonly manifestByPath: ReadonlyMap<string, EpubManifestItem>;\n readonly spine: readonly EpubSpineItem[];\n readonly navPath: string | undefined;\n readonly ncxPath: string | undefined;\n readonly coverPath: string | undefined;\n readonly coverMediaType: string | undefined;\n readonly guideNonContentPaths: ReadonlySet<string>;\n}\n\nexport async function readEpubPackage(\n archive: EpubArchive,\n): Promise<EpubPackageData> {\n const opfPath = await findOpfPath(archive);\n const opf = parseXml(await archive.readText(opfPath));\n const version = parsePackageVersion(getAttribute(opf, \"version\"));\n const metadataElement = findChild(opf, \"metadata\");\n const manifestElement = findChild(opf, \"manifest\");\n const spineElement = findChild(opf, \"spine\");\n const guideElement = findChild(opf, \"guide\");\n\n const manifest = buildManifest(archive, opfPath, manifestElement);\n const manifestByPath = new Map(\n [...manifest.values()].map((item) => [item.path, item]),\n );\n const spine = buildSpine(spineElement, manifest);\n const guideNonContentPaths = buildGuideNonContentPaths(\n archive,\n opfPath,\n guideElement,\n );\n const metadata = buildMetadata(metadataElement);\n const navPath = findNavPath(manifest);\n const ncxPath = findNcxPath(manifest, spineElement);\n const coverItem = findCoverItem(manifest, metadataElement);\n\n return {\n version,\n opfPath,\n metadata: {\n ...metadata,\n version: BOOK_META_VERSION,\n sourceFormat: \"epub\",\n },\n manifest,\n manifestByPath,\n spine,\n navPath,\n ncxPath,\n coverPath: coverItem?.path,\n coverMediaType: coverItem?.mediaType,\n guideNonContentPaths,\n };\n}\n\nasync function findOpfPath(archive: EpubArchive): Promise<string> {\n const container = parseXml(await archive.readText(\"META-INF/container.xml\"));\n const rootfiles = findChild(container, \"rootfiles\");\n const rootfile = rootfiles?.children.find(\n (child) => getLocalName(child.name) === \"rootfile\",\n );\n const fullPath =\n rootfile === undefined ? undefined : getAttribute(rootfile, \"full-path\");\n\n if (fullPath === undefined || fullPath.trim() === \"\") {\n throw new Error(\"EPUB container.xml does not contain an OPF rootfile\");\n }\n\n return fullPath;\n}\n\nfunction parsePackageVersion(version: string | undefined): 2 | 3 {\n return version?.trim().startsWith(\"3\") === true ? 3 : 2;\n}\n\nfunction buildMetadata(metadataElement: XmlElement | undefined): BookMeta {\n if (metadataElement === undefined) {\n return createEmptyMetadata();\n }\n\n const titles = readMetadataValues(metadataElement, \"title\");\n const creators = readMetadataValues(metadataElement, \"creator\");\n const languages = readMetadataValues(metadataElement, \"language\");\n const identifiers = readMetadataValues(metadataElement, \"identifier\");\n const publishers = readMetadataValues(metadataElement, \"publisher\");\n const dates = readMetadataValues(metadataElement, \"date\");\n const descriptions = readMetadataValues(metadataElement, \"description\");\n\n return {\n ...createEmptyMetadata(),\n title: titles[0] ?? null,\n authors: [...creators],\n language: languages[0] ?? null,\n identifier: identifiers[0] ?? null,\n publisher: publishers[0] ?? null,\n publishedAt: dates[0] ?? null,\n description: descriptions[0] ?? null,\n };\n}\n\nfunction createEmptyMetadata(): BookMeta {\n return {\n version: BOOK_META_VERSION,\n sourceFormat: \"epub\",\n title: null,\n authors: [],\n language: null,\n identifier: null,\n publisher: null,\n publishedAt: null,\n description: null,\n };\n}\n\nfunction readMetadataValues(\n metadataElement: XmlElement,\n localName: string,\n): readonly string[] {\n return metadataElement.children\n .filter((child) => getLocalName(child.name) === localName)\n .map((child) => normalizeText(getDescendantText(child)))\n .filter((value): value is string => value !== undefined);\n}\n\nfunction buildManifest(\n archive: EpubArchive,\n opfPath: string,\n manifestElement: XmlElement | undefined,\n): ReadonlyMap<string, EpubManifestItem> {\n const manifest = new Map<string, EpubManifestItem>();\n\n if (manifestElement === undefined) {\n return manifest;\n }\n\n for (const item of findChildren(manifestElement, \"item\")) {\n const id = getAttribute(item, \"id\");\n const href = getAttribute(item, \"href\");\n const mediaType = getAttribute(item, \"media-type\") ?? \"\";\n\n if (id === undefined || href === undefined) {\n continue;\n }\n\n manifest.set(id, {\n id,\n path: archive.resolveRelativePath(opfPath, href),\n mediaType,\n properties: new Set(\n (getAttribute(item, \"properties\") ?? \"\")\n .split(/\\s+/u)\n .map((value) => value.trim().toLowerCase())\n .filter((value) => value !== \"\"),\n ),\n });\n }\n\n return manifest;\n}\n\nfunction buildSpine(\n spineElement: XmlElement | undefined,\n manifest: ReadonlyMap<string, EpubManifestItem>,\n): readonly EpubSpineItem[] {\n if (spineElement === undefined) {\n return [];\n }\n\n return findChildren(spineElement, \"itemref\")\n .map((itemref) => getAttribute(itemref, \"idref\"))\n .filter((idref): idref is string => idref !== undefined)\n .map((idref) => {\n const item = manifest.get(idref);\n\n if (\n item === undefined ||\n (item.mediaType !== \"application/xhtml+xml\" &&\n item.mediaType !== \"text/html\")\n ) {\n return undefined;\n }\n\n return {\n idref,\n path: item.path,\n mediaType: item.mediaType,\n } satisfies EpubSpineItem;\n })\n .filter((item): item is EpubSpineItem => item !== undefined);\n}\n\nfunction buildGuideNonContentPaths(\n archive: EpubArchive,\n opfPath: string,\n guideElement: XmlElement | undefined,\n): ReadonlySet<string> {\n const paths = new Set<string>();\n\n if (guideElement === undefined) {\n return paths;\n }\n\n for (const reference of findChildren(guideElement, \"reference\")) {\n const type = (getAttribute(reference, \"type\") ?? \"\").trim().toLowerCase();\n if (!GUIDE_NON_CONTENT_TYPES.has(type)) {\n continue;\n }\n\n const href = getAttribute(reference, \"href\");\n if (href === undefined || href.trim() === \"\") {\n continue;\n }\n\n paths.add(archive.resolveRelativePath(opfPath, splitHref(href).path));\n }\n\n return paths;\n}\n\nfunction findNavPath(\n manifest: ReadonlyMap<string, EpubManifestItem>,\n): string | undefined {\n for (const item of manifest.values()) {\n if (item.properties.has(\"nav\")) {\n return item.path;\n }\n }\n\n return undefined;\n}\n\nfunction findNcxPath(\n manifest: ReadonlyMap<string, EpubManifestItem>,\n spineElement: XmlElement | undefined,\n): string | undefined {\n const tocId =\n spineElement === undefined ? undefined : getAttribute(spineElement, \"toc\");\n\n if (tocId !== undefined) {\n return manifest.get(tocId)?.path;\n }\n\n for (const item of manifest.values()) {\n if (item.mediaType === \"application/x-dtbncx+xml\") {\n return item.path;\n }\n }\n\n return undefined;\n}\n\nfunction findCoverItem(\n manifest: ReadonlyMap<string, EpubManifestItem>,\n metadataElement: XmlElement | undefined,\n): EpubManifestItem | undefined {\n for (const item of manifest.values()) {\n if (\n item.properties.has(\"cover-image\") &&\n item.mediaType.startsWith(\"image/\")\n ) {\n return item;\n }\n }\n\n const coverId = readCoverIdFromMetadata(metadataElement);\n if (coverId !== undefined) {\n const coverItem = manifest.get(coverId);\n if (coverItem?.mediaType.startsWith(\"image/\") === true) {\n return coverItem;\n }\n }\n\n for (const coverItemId of COVER_ITEM_IDS) {\n const coverItem = manifest.get(coverItemId);\n if (coverItem?.mediaType.startsWith(\"image/\") === true) {\n return coverItem;\n }\n }\n\n for (const item of manifest.values()) {\n if (\n item.mediaType.startsWith(\"image/\") &&\n posix.basename(item.path).toLowerCase().includes(\"cover\")\n ) {\n return item;\n }\n }\n\n return undefined;\n}\n\nfunction readCoverIdFromMetadata(\n metadataElement: XmlElement | undefined,\n): string | undefined {\n if (metadataElement === undefined) {\n return undefined;\n }\n\n for (const meta of findChildren(metadataElement, \"meta\")) {\n const name = (getAttribute(meta, \"name\") ?? \"\").trim().toLowerCase();\n if (name !== \"cover\") {\n continue;\n }\n\n const content = getAttribute(meta, \"content\");\n if (content !== undefined && content.trim() !== \"\") {\n return content.trim();\n }\n }\n\n return undefined;\n}\n\nfunction normalizeText(text: string): string | undefined {\n const normalized = text.replace(/\\s+/gu, \" \").trim();\n\n return normalized === \"\" ? undefined : normalized;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface XmlElement {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly attributes: Readonly<Record<string, string>>;
|
|
4
|
+
readonly children: readonly XmlElement[];
|
|
5
|
+
readonly text: string;
|
|
6
|
+
}
|
|
7
|
+
declare function parseXml(content: string): XmlElement;
|
|
8
|
+
declare function findChild(element: XmlElement, localName: string): XmlElement | undefined;
|
|
9
|
+
declare function findChildren(element: XmlElement, localName: string): readonly XmlElement[];
|
|
10
|
+
declare function findDescendant(element: XmlElement, localName: string): XmlElement | undefined;
|
|
11
|
+
declare function findDescendants(element: XmlElement, localName: string): readonly XmlElement[];
|
|
12
|
+
declare function getAttribute(element: XmlElement, name: string): string | undefined;
|
|
13
|
+
declare function getDescendantText(element: XmlElement): string;
|
|
14
|
+
declare function getLocalName(name: string): string;
|
|
15
|
+
|
|
16
|
+
export { type XmlElement, findChild, findChildren, findDescendant, findDescendants, getAttribute, getDescendantText, getLocalName, parseXml };
|