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,189 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import { posix } from "path";
|
|
3
|
+
import { PassThrough } from "stream";
|
|
4
|
+
import { open } from "yauzl";
|
|
5
|
+
class EpubArchive {
|
|
6
|
+
#path;
|
|
7
|
+
#zipFile;
|
|
8
|
+
#entries;
|
|
9
|
+
#closed = false;
|
|
10
|
+
constructor(path, zipFile, entries) {
|
|
11
|
+
this.#path = path;
|
|
12
|
+
this.#zipFile = zipFile;
|
|
13
|
+
this.#entries = entries;
|
|
14
|
+
}
|
|
15
|
+
static async open(path) {
|
|
16
|
+
const zipFile = await openZipFile(path);
|
|
17
|
+
const entries = await indexEntries(zipFile);
|
|
18
|
+
return new EpubArchive(path, zipFile, entries);
|
|
19
|
+
}
|
|
20
|
+
close() {
|
|
21
|
+
if (this.#closed) {
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
}
|
|
24
|
+
this.#closed = true;
|
|
25
|
+
this.#zipFile.close();
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
}
|
|
28
|
+
hasEntry(path) {
|
|
29
|
+
return this.#entries.has(normalizeArchivePath(path));
|
|
30
|
+
}
|
|
31
|
+
listEntries() {
|
|
32
|
+
return [...this.#entries.keys()];
|
|
33
|
+
}
|
|
34
|
+
async openReadStream(path) {
|
|
35
|
+
const entry = this.#getEntry(path);
|
|
36
|
+
return await openEntryStream(this.#zipFile, entry);
|
|
37
|
+
}
|
|
38
|
+
async readText(path) {
|
|
39
|
+
const stream = await this.openReadStream(path);
|
|
40
|
+
return (await readStreamToBuffer(stream)).toString("utf8");
|
|
41
|
+
}
|
|
42
|
+
async readBuffer(path) {
|
|
43
|
+
const stream = await this.openReadStream(path);
|
|
44
|
+
return await readStreamToBuffer(stream);
|
|
45
|
+
}
|
|
46
|
+
resolveRelativePath(basePath, href) {
|
|
47
|
+
const normalizedHref = normalizeHref(href);
|
|
48
|
+
if (normalizedHref === "") {
|
|
49
|
+
throw new Error(`Invalid EPUB href: ${href}`);
|
|
50
|
+
}
|
|
51
|
+
return normalizeArchivePath(
|
|
52
|
+
posix.join(posix.dirname(normalizeArchivePath(basePath)), normalizedHref)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
createSectionId(path, fragment) {
|
|
56
|
+
const normalizedPath = normalizeArchivePath(path);
|
|
57
|
+
if (fragment === void 0 || fragment === "") {
|
|
58
|
+
return normalizedPath;
|
|
59
|
+
}
|
|
60
|
+
return `${normalizedPath}#${fragment}`;
|
|
61
|
+
}
|
|
62
|
+
createSyntheticSectionId(path, title) {
|
|
63
|
+
const normalizedPath = normalizeArchivePath(path);
|
|
64
|
+
const hash = createHash("sha1").update(`${normalizedPath}:${title ?? ""}`).digest("hex").slice(0, 10);
|
|
65
|
+
return `toc:${hash}`;
|
|
66
|
+
}
|
|
67
|
+
get path() {
|
|
68
|
+
return this.#path;
|
|
69
|
+
}
|
|
70
|
+
#getEntry(path) {
|
|
71
|
+
const normalizedPath = normalizeArchivePath(path);
|
|
72
|
+
const entry = this.#entries.get(normalizedPath);
|
|
73
|
+
if (entry === void 0) {
|
|
74
|
+
throw new Error(`EPUB entry does not exist: ${normalizedPath}`);
|
|
75
|
+
}
|
|
76
|
+
return entry;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function normalizeArchivePath(path) {
|
|
80
|
+
const normalized = path.replaceAll("\\", "/").trim();
|
|
81
|
+
const withoutFragment = normalized.startsWith("/") ? normalized.slice(1) : normalized;
|
|
82
|
+
return posix.normalize(withoutFragment).replace(/^(\.\/)+/, "").replace(/^\/+/, "");
|
|
83
|
+
}
|
|
84
|
+
function normalizeHref(href) {
|
|
85
|
+
const [path] = href.split("#", 1);
|
|
86
|
+
return normalizeArchivePath(path ?? "");
|
|
87
|
+
}
|
|
88
|
+
function normalizeFragment(fragment) {
|
|
89
|
+
if (fragment === void 0) {
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
const normalized = fragment.startsWith("#") ? fragment.slice(1) : fragment;
|
|
93
|
+
return normalized === "" ? void 0 : normalized;
|
|
94
|
+
}
|
|
95
|
+
function splitHref(href) {
|
|
96
|
+
const [pathPart, fragmentPart] = href.split("#", 2);
|
|
97
|
+
return {
|
|
98
|
+
path: normalizeArchivePath(pathPart ?? ""),
|
|
99
|
+
fragment: normalizeFragment(fragmentPart)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function openZipFile(path) {
|
|
103
|
+
return await new Promise((resolve, reject) => {
|
|
104
|
+
open(path, { autoClose: false, lazyEntries: true }, (error, zipFile) => {
|
|
105
|
+
if (error !== null || zipFile === void 0) {
|
|
106
|
+
reject(error ?? new Error(`Cannot open EPUB archive: ${path}`));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
resolve(zipFile);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async function indexEntries(zipFile) {
|
|
114
|
+
return await new Promise((resolve, reject) => {
|
|
115
|
+
const entries = /* @__PURE__ */ new Map();
|
|
116
|
+
zipFile.on("entry", (entry) => {
|
|
117
|
+
if (entry.fileName.endsWith("/")) {
|
|
118
|
+
zipFile.readEntry();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
entries.set(normalizeArchivePath(entry.fileName), entry);
|
|
122
|
+
zipFile.readEntry();
|
|
123
|
+
});
|
|
124
|
+
zipFile.once("end", () => {
|
|
125
|
+
resolve(entries);
|
|
126
|
+
});
|
|
127
|
+
zipFile.once("error", (error) => {
|
|
128
|
+
reject(error);
|
|
129
|
+
});
|
|
130
|
+
zipFile.readEntry();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function toBuffer(chunk) {
|
|
134
|
+
if (Buffer.isBuffer(chunk)) {
|
|
135
|
+
return chunk;
|
|
136
|
+
}
|
|
137
|
+
if (typeof chunk === "string") {
|
|
138
|
+
return Buffer.from(chunk, "utf8");
|
|
139
|
+
}
|
|
140
|
+
throw new Error("Unexpected ZIP stream chunk type");
|
|
141
|
+
}
|
|
142
|
+
async function readStreamToBuffer(stream) {
|
|
143
|
+
return await new Promise((resolve, reject) => {
|
|
144
|
+
const chunks = [];
|
|
145
|
+
stream.on("data", (chunk) => {
|
|
146
|
+
chunks.push(toBuffer(chunk));
|
|
147
|
+
});
|
|
148
|
+
stream.once("end", () => {
|
|
149
|
+
resolve(Buffer.concat(chunks));
|
|
150
|
+
});
|
|
151
|
+
stream.once("error", (error) => {
|
|
152
|
+
reject(error);
|
|
153
|
+
});
|
|
154
|
+
stream.resume();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async function openEntryStream(zipFile, entry) {
|
|
158
|
+
return await new Promise((resolve, reject) => {
|
|
159
|
+
zipFile.openReadStream(entry, (error, stream) => {
|
|
160
|
+
if (error !== null || stream === void 0) {
|
|
161
|
+
reject(error ?? new Error(`Cannot open EPUB entry: ${entry.fileName}`));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
resolve(normalizeEntryStream(stream));
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function normalizeEntryStream(stream) {
|
|
169
|
+
const normalized = new PassThrough();
|
|
170
|
+
stream.once("error", (error) => {
|
|
171
|
+
normalized.destroy(error);
|
|
172
|
+
});
|
|
173
|
+
normalized.once("close", () => {
|
|
174
|
+
stream.unpipe(normalized);
|
|
175
|
+
if (!stream.destroyed) {
|
|
176
|
+
stream.destroy();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
stream.pipe(normalized);
|
|
180
|
+
return normalized;
|
|
181
|
+
}
|
|
182
|
+
export {
|
|
183
|
+
EpubArchive,
|
|
184
|
+
normalizeArchivePath,
|
|
185
|
+
normalizeFragment,
|
|
186
|
+
normalizeHref,
|
|
187
|
+
splitHref
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/archive.ts"],"sourcesContent":["import { createHash } from \"crypto\";\nimport { posix } from \"path\";\nimport { PassThrough, type Readable } from \"stream\";\nimport type { Entry, ZipFile } from \"yauzl\";\nimport { open } from \"yauzl\";\n\nexport class EpubArchive {\n readonly #path: string;\n readonly #zipFile: ZipFile;\n readonly #entries: ReadonlyMap<string, Entry>;\n #closed = false;\n\n public constructor(\n path: string,\n zipFile: ZipFile,\n entries: ReadonlyMap<string, Entry>,\n ) {\n this.#path = path;\n this.#zipFile = zipFile;\n this.#entries = entries;\n }\n\n public static async open(path: string): Promise<EpubArchive> {\n const zipFile = await openZipFile(path);\n const entries = await indexEntries(zipFile);\n\n return new EpubArchive(path, zipFile, entries);\n }\n\n public close(): Promise<void> {\n if (this.#closed) {\n return Promise.resolve();\n }\n\n this.#closed = true;\n this.#zipFile.close();\n\n return Promise.resolve();\n }\n\n public hasEntry(path: string): boolean {\n return this.#entries.has(normalizeArchivePath(path));\n }\n\n public listEntries(): readonly string[] {\n return [...this.#entries.keys()];\n }\n\n public async openReadStream(path: string): Promise<Readable> {\n const entry = this.#getEntry(path);\n\n return await openEntryStream(this.#zipFile, entry);\n }\n\n public async readText(path: string): Promise<string> {\n const stream = await this.openReadStream(path);\n return (await readStreamToBuffer(stream)).toString(\"utf8\");\n }\n\n public async readBuffer(path: string): Promise<Buffer> {\n const stream = await this.openReadStream(path);\n return await readStreamToBuffer(stream);\n }\n\n public resolveRelativePath(basePath: string, href: string): string {\n const normalizedHref = normalizeHref(href);\n if (normalizedHref === \"\") {\n throw new Error(`Invalid EPUB href: ${href}`);\n }\n\n return normalizeArchivePath(\n posix.join(posix.dirname(normalizeArchivePath(basePath)), normalizedHref),\n );\n }\n\n public createSectionId(path: string, fragment?: string): string {\n const normalizedPath = normalizeArchivePath(path);\n\n if (fragment === undefined || fragment === \"\") {\n return normalizedPath;\n }\n\n return `${normalizedPath}#${fragment}`;\n }\n\n public createSyntheticSectionId(path: string, title?: string): string {\n const normalizedPath = normalizeArchivePath(path);\n const hash = createHash(\"sha1\")\n .update(`${normalizedPath}:${title ?? \"\"}`)\n .digest(\"hex\")\n .slice(0, 10);\n\n return `toc:${hash}`;\n }\n\n public get path(): string {\n return this.#path;\n }\n\n #getEntry(path: string): Entry {\n const normalizedPath = normalizeArchivePath(path);\n const entry = this.#entries.get(normalizedPath);\n\n if (entry === undefined) {\n throw new Error(`EPUB entry does not exist: ${normalizedPath}`);\n }\n\n return entry;\n }\n}\n\nexport function normalizeArchivePath(path: string): string {\n const normalized = path.replaceAll(\"\\\\\", \"/\").trim();\n const withoutFragment = normalized.startsWith(\"/\")\n ? normalized.slice(1)\n : normalized;\n\n return posix\n .normalize(withoutFragment)\n .replace(/^(\\.\\/)+/, \"\")\n .replace(/^\\/+/, \"\");\n}\n\nexport function normalizeHref(href: string): string {\n const [path] = href.split(\"#\", 1);\n\n return normalizeArchivePath(path ?? \"\");\n}\n\nexport function normalizeFragment(\n fragment: string | undefined,\n): string | undefined {\n if (fragment === undefined) {\n return undefined;\n }\n\n const normalized = fragment.startsWith(\"#\") ? fragment.slice(1) : fragment;\n\n return normalized === \"\" ? undefined : normalized;\n}\n\nexport function splitHref(href: string): {\n readonly path: string;\n readonly fragment: string | undefined;\n} {\n const [pathPart, fragmentPart] = href.split(\"#\", 2);\n\n return {\n path: normalizeArchivePath(pathPart ?? \"\"),\n fragment: normalizeFragment(fragmentPart),\n };\n}\n\nasync function openZipFile(path: string): Promise<ZipFile> {\n return await new Promise((resolve, reject) => {\n open(path, { autoClose: false, lazyEntries: true }, (error, zipFile) => {\n if (error !== null || zipFile === undefined) {\n reject(error ?? new Error(`Cannot open EPUB archive: ${path}`));\n return;\n }\n\n resolve(zipFile);\n });\n });\n}\n\nasync function indexEntries(\n zipFile: ZipFile,\n): Promise<ReadonlyMap<string, Entry>> {\n return await new Promise((resolve, reject) => {\n const entries = new Map<string, Entry>();\n\n zipFile.on(\"entry\", (entry: Entry) => {\n if (entry.fileName.endsWith(\"/\")) {\n zipFile.readEntry();\n return;\n }\n\n entries.set(normalizeArchivePath(entry.fileName), entry);\n zipFile.readEntry();\n });\n zipFile.once(\"end\", () => {\n resolve(entries);\n });\n zipFile.once(\"error\", (error: Error) => {\n reject(error);\n });\n\n zipFile.readEntry();\n });\n}\n\nfunction toBuffer(chunk: unknown): Buffer {\n if (Buffer.isBuffer(chunk)) {\n return chunk;\n }\n\n if (typeof chunk === \"string\") {\n return Buffer.from(chunk, \"utf8\");\n }\n\n throw new Error(\"Unexpected ZIP stream chunk type\");\n}\n\nasync function readStreamToBuffer(stream: Readable): Promise<Buffer> {\n return await new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n\n stream.on(\"data\", (chunk: unknown) => {\n chunks.push(toBuffer(chunk));\n });\n stream.once(\"end\", () => {\n resolve(Buffer.concat(chunks));\n });\n stream.once(\"error\", (error: Error) => {\n reject(error);\n });\n stream.resume();\n });\n}\n\nasync function openEntryStream(\n zipFile: ZipFile,\n entry: Entry,\n): Promise<Readable> {\n return await new Promise((resolve, reject) => {\n zipFile.openReadStream(entry, (error, stream) => {\n if (error !== null || stream === undefined) {\n reject(error ?? new Error(`Cannot open EPUB entry: ${entry.fileName}`));\n return;\n }\n\n resolve(normalizeEntryStream(stream));\n });\n });\n}\n\nfunction normalizeEntryStream(stream: Readable): Readable {\n const normalized = new PassThrough();\n\n stream.once(\"error\", (error: Error) => {\n normalized.destroy(error);\n });\n normalized.once(\"close\", () => {\n stream.unpipe(normalized);\n\n if (!stream.destroyed) {\n stream.destroy();\n }\n });\n\n stream.pipe(normalized);\n\n return normalized;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SourceTextStream } from '../types.js';
|
|
2
|
+
import { EpubArchive } from './archive.js';
|
|
3
|
+
import 'stream';
|
|
4
|
+
import 'yauzl';
|
|
5
|
+
|
|
6
|
+
interface EpubSectionTarget {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly fragment: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
interface EpubSectionAnalysis {
|
|
12
|
+
readonly hasContent: boolean;
|
|
13
|
+
readonly wordsCount: number;
|
|
14
|
+
}
|
|
15
|
+
declare class EpubContentLoader {
|
|
16
|
+
#private;
|
|
17
|
+
constructor(archive: EpubArchive, targetsByPath: ReadonlyMap<string, readonly EpubSectionTarget[]>);
|
|
18
|
+
openSection(sectionId: string): Promise<SourceTextStream>;
|
|
19
|
+
}
|
|
20
|
+
declare function analyzeSectionTargets(archive: Pick<EpubArchive, "openReadStream">, targetsByPath: ReadonlyMap<string, readonly EpubSectionTarget[]>): Promise<ReadonlyMap<string, EpubSectionAnalysis>>;
|
|
21
|
+
|
|
22
|
+
export { EpubContentLoader, type EpubSectionAnalysis, type EpubSectionTarget, analyzeSectionTargets };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { Parser } from "htmlparser2";
|
|
2
|
+
const BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
3
|
+
"address",
|
|
4
|
+
"article",
|
|
5
|
+
"aside",
|
|
6
|
+
"blockquote",
|
|
7
|
+
"br",
|
|
8
|
+
"dd",
|
|
9
|
+
"div",
|
|
10
|
+
"dl",
|
|
11
|
+
"dt",
|
|
12
|
+
"figcaption",
|
|
13
|
+
"figure",
|
|
14
|
+
"footer",
|
|
15
|
+
"h1",
|
|
16
|
+
"h2",
|
|
17
|
+
"h3",
|
|
18
|
+
"h4",
|
|
19
|
+
"h5",
|
|
20
|
+
"h6",
|
|
21
|
+
"header",
|
|
22
|
+
"hr",
|
|
23
|
+
"li",
|
|
24
|
+
"main",
|
|
25
|
+
"nav",
|
|
26
|
+
"ol",
|
|
27
|
+
"p",
|
|
28
|
+
"pre",
|
|
29
|
+
"section",
|
|
30
|
+
"table",
|
|
31
|
+
"td",
|
|
32
|
+
"th",
|
|
33
|
+
"tr",
|
|
34
|
+
"ul"
|
|
35
|
+
]);
|
|
36
|
+
const SKIPPED_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
37
|
+
class EpubContentLoader {
|
|
38
|
+
#archive;
|
|
39
|
+
#targetsBySectionId;
|
|
40
|
+
constructor(archive, targetsByPath) {
|
|
41
|
+
this.#archive = archive;
|
|
42
|
+
this.#targetsBySectionId = createTargetsBySectionId(targetsByPath);
|
|
43
|
+
}
|
|
44
|
+
async openSection(sectionId) {
|
|
45
|
+
const target = this.#targetsBySectionId.get(sectionId);
|
|
46
|
+
if (target === void 0) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
const sections = await this.#parseSections(target.path, target.targets);
|
|
50
|
+
return [sections.get(sectionId) ?? ""];
|
|
51
|
+
}
|
|
52
|
+
async #parseSections(path, targets) {
|
|
53
|
+
const stream = await this.#archive.openReadStream(path);
|
|
54
|
+
stream.setEncoding("utf8");
|
|
55
|
+
return await parseHtmlSections(stream, targets);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function analyzeSectionTargets(archive, targetsByPath) {
|
|
59
|
+
const analyses = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const [path, targets] of targetsByPath.entries()) {
|
|
61
|
+
const stream = await archive.openReadStream(path);
|
|
62
|
+
stream.setEncoding("utf8");
|
|
63
|
+
const sections = await parseHtmlSectionTexts(stream, targets);
|
|
64
|
+
for (const target of targets) {
|
|
65
|
+
const text = sections.get(target.id) ?? "";
|
|
66
|
+
analyses.set(target.id, {
|
|
67
|
+
hasContent: text.trim() !== "",
|
|
68
|
+
wordsCount: countWords(text)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return analyses;
|
|
73
|
+
}
|
|
74
|
+
function createTargetsBySectionId(targetsByPath) {
|
|
75
|
+
const targetsBySectionId = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const [path, targets] of targetsByPath.entries()) {
|
|
77
|
+
for (const target of targets) {
|
|
78
|
+
targetsBySectionId.set(target.id, { path, targets });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return targetsBySectionId;
|
|
82
|
+
}
|
|
83
|
+
async function parseHtmlSections(stream, targets) {
|
|
84
|
+
return await parseHtmlSectionTexts(stream, targets);
|
|
85
|
+
}
|
|
86
|
+
async function parseHtmlSectionTexts(stream, targets) {
|
|
87
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
88
|
+
const sections = /* @__PURE__ */ new Map();
|
|
89
|
+
const orderedTargets = [...targets];
|
|
90
|
+
const buffers = orderedTargets.map(() => "");
|
|
91
|
+
const rootSectionIndex = orderedTargets[0]?.fragment === void 0 && orderedTargets[0] !== void 0 ? 0 : -1;
|
|
92
|
+
let currentIndex = rootSectionIndex;
|
|
93
|
+
let skippedTagDepth = 0;
|
|
94
|
+
orderedTargets.forEach((target, index) => {
|
|
95
|
+
sections.set(target.id, "");
|
|
96
|
+
if (target.fragment !== void 0 && !fragments.has(target.fragment)) {
|
|
97
|
+
fragments.set(target.fragment, index);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const parser = new Parser(
|
|
101
|
+
{
|
|
102
|
+
onopentag(name, attributes) {
|
|
103
|
+
const tagName = name.toLowerCase();
|
|
104
|
+
if (SKIPPED_TAGS.has(tagName)) {
|
|
105
|
+
skippedTagDepth += 1;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const anchorId = attributes.id ?? attributes["xml:id"];
|
|
109
|
+
if (anchorId !== void 0) {
|
|
110
|
+
const nextIndex = fragments.get(anchorId);
|
|
111
|
+
if (nextIndex !== void 0 && nextIndex > currentIndex) {
|
|
112
|
+
currentIndex = nextIndex;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (tagName === "br") {
|
|
116
|
+
appendText(buffers, currentIndex, "\n");
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
ontext(text) {
|
|
120
|
+
if (skippedTagDepth > 0) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
appendText(buffers, currentIndex, text);
|
|
124
|
+
},
|
|
125
|
+
onclosetag(name) {
|
|
126
|
+
const tagName = name.toLowerCase();
|
|
127
|
+
if (SKIPPED_TAGS.has(tagName)) {
|
|
128
|
+
skippedTagDepth = Math.max(0, skippedTagDepth - 1);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (BLOCK_TAGS.has(tagName)) {
|
|
132
|
+
appendText(buffers, currentIndex, "\n\n");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{ decodeEntities: true }
|
|
137
|
+
);
|
|
138
|
+
for await (const chunk of stream) {
|
|
139
|
+
parser.write(toTextChunk(chunk));
|
|
140
|
+
}
|
|
141
|
+
parser.end();
|
|
142
|
+
orderedTargets.forEach((target, index) => {
|
|
143
|
+
sections.set(target.id, normalizeSectionText(buffers[index] ?? ""));
|
|
144
|
+
});
|
|
145
|
+
return sections;
|
|
146
|
+
}
|
|
147
|
+
function appendText(buffers, currentIndex, text) {
|
|
148
|
+
if (currentIndex < 0 || currentIndex >= buffers.length) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
buffers[currentIndex] += text;
|
|
152
|
+
}
|
|
153
|
+
function normalizeSectionText(text) {
|
|
154
|
+
return text.replace(/\r\n/gu, "\n").replace(/\n{3,}/gu, "\n\n").trim();
|
|
155
|
+
}
|
|
156
|
+
function toTextChunk(chunk) {
|
|
157
|
+
if (typeof chunk === "string") {
|
|
158
|
+
return chunk;
|
|
159
|
+
}
|
|
160
|
+
if (Buffer.isBuffer(chunk)) {
|
|
161
|
+
return chunk.toString("utf8");
|
|
162
|
+
}
|
|
163
|
+
throw new Error("Unexpected HTML stream chunk type");
|
|
164
|
+
}
|
|
165
|
+
function countWords(text) {
|
|
166
|
+
return [...createWordSegmenter().segment(text)].filter(
|
|
167
|
+
(segment) => segment.isWordLike
|
|
168
|
+
).length;
|
|
169
|
+
}
|
|
170
|
+
let WORD_SEGMENTER;
|
|
171
|
+
function createWordSegmenter() {
|
|
172
|
+
if (WORD_SEGMENTER === void 0) {
|
|
173
|
+
WORD_SEGMENTER = new Intl.Segmenter(void 0, {
|
|
174
|
+
granularity: "word"
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return WORD_SEGMENTER;
|
|
178
|
+
}
|
|
179
|
+
export {
|
|
180
|
+
EpubContentLoader,
|
|
181
|
+
analyzeSectionTargets
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/source/epub/content.ts"],"sourcesContent":["import type { Readable } from \"stream\";\n\nimport { Parser } from \"htmlparser2\";\n\nimport type { SourceTextStream } from \"../types.js\";\nimport type { EpubArchive } from \"./archive.js\";\n\nconst BLOCK_TAGS = new Set([\n \"address\",\n \"article\",\n \"aside\",\n \"blockquote\",\n \"br\",\n \"dd\",\n \"div\",\n \"dl\",\n \"dt\",\n \"figcaption\",\n \"figure\",\n \"footer\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"header\",\n \"hr\",\n \"li\",\n \"main\",\n \"nav\",\n \"ol\",\n \"p\",\n \"pre\",\n \"section\",\n \"table\",\n \"td\",\n \"th\",\n \"tr\",\n \"ul\",\n]);\n\nconst SKIPPED_TAGS = new Set([\"script\", \"style\"]);\n\nexport interface EpubSectionTarget {\n readonly id: string;\n readonly path: string;\n readonly fragment: string | undefined;\n}\n\nexport interface EpubSectionAnalysis {\n readonly hasContent: boolean;\n readonly wordsCount: number;\n}\n\nexport class EpubContentLoader {\n readonly #archive: EpubArchive;\n readonly #targetsBySectionId: ReadonlyMap<\n string,\n {\n readonly path: string;\n readonly targets: readonly EpubSectionTarget[];\n }\n >;\n\n public constructor(\n archive: EpubArchive,\n targetsByPath: ReadonlyMap<string, readonly EpubSectionTarget[]>,\n ) {\n this.#archive = archive;\n this.#targetsBySectionId = createTargetsBySectionId(targetsByPath);\n }\n\n public async openSection(sectionId: string): Promise<SourceTextStream> {\n const target = this.#targetsBySectionId.get(sectionId);\n\n if (target === undefined) {\n return [];\n }\n\n const sections = await this.#parseSections(target.path, target.targets);\n\n return [sections.get(sectionId) ?? \"\"];\n }\n\n async #parseSections(\n path: string,\n targets: readonly EpubSectionTarget[],\n ): Promise<ReadonlyMap<string, string>> {\n const stream = await this.#archive.openReadStream(path);\n stream.setEncoding(\"utf8\");\n\n return await parseHtmlSections(stream, targets);\n }\n}\n\nexport async function analyzeSectionTargets(\n archive: Pick<EpubArchive, \"openReadStream\">,\n targetsByPath: ReadonlyMap<string, readonly EpubSectionTarget[]>,\n): Promise<ReadonlyMap<string, EpubSectionAnalysis>> {\n const analyses = new Map<string, EpubSectionAnalysis>();\n\n for (const [path, targets] of targetsByPath.entries()) {\n const stream = await archive.openReadStream(path);\n stream.setEncoding(\"utf8\");\n const sections = await parseHtmlSectionTexts(stream, targets);\n\n for (const target of targets) {\n const text = sections.get(target.id) ?? \"\";\n\n analyses.set(target.id, {\n hasContent: text.trim() !== \"\",\n wordsCount: countWords(text),\n });\n }\n }\n\n return analyses;\n}\n\nfunction createTargetsBySectionId(\n targetsByPath: ReadonlyMap<string, readonly EpubSectionTarget[]>,\n): ReadonlyMap<\n string,\n {\n readonly path: string;\n readonly targets: readonly EpubSectionTarget[];\n }\n> {\n const targetsBySectionId = new Map<\n string,\n {\n readonly path: string;\n readonly targets: readonly EpubSectionTarget[];\n }\n >();\n\n for (const [path, targets] of targetsByPath.entries()) {\n for (const target of targets) {\n targetsBySectionId.set(target.id, { path, targets });\n }\n }\n\n return targetsBySectionId;\n}\n\nasync function parseHtmlSections(\n stream: Readable,\n targets: readonly EpubSectionTarget[],\n): Promise<ReadonlyMap<string, string>> {\n return await parseHtmlSectionTexts(stream, targets);\n}\n\nasync function parseHtmlSectionTexts(\n stream: Readable,\n targets: readonly EpubSectionTarget[],\n): Promise<ReadonlyMap<string, string>> {\n const fragments = new Map<string, number>();\n const sections = new Map<string, string>();\n const orderedTargets = [...targets];\n const buffers = orderedTargets.map(() => \"\");\n const rootSectionIndex =\n orderedTargets[0]?.fragment === undefined && orderedTargets[0] !== undefined\n ? 0\n : -1;\n let currentIndex = rootSectionIndex;\n let skippedTagDepth = 0;\n\n orderedTargets.forEach((target, index) => {\n sections.set(target.id, \"\");\n if (target.fragment !== undefined && !fragments.has(target.fragment)) {\n fragments.set(target.fragment, index);\n }\n });\n\n const parser = new Parser(\n {\n onopentag(name, attributes) {\n const tagName = name.toLowerCase();\n if (SKIPPED_TAGS.has(tagName)) {\n skippedTagDepth += 1;\n return;\n }\n\n const anchorId = attributes.id ?? attributes[\"xml:id\"];\n if (anchorId !== undefined) {\n const nextIndex = fragments.get(anchorId);\n if (nextIndex !== undefined && nextIndex > currentIndex) {\n currentIndex = nextIndex;\n }\n }\n\n if (tagName === \"br\") {\n appendText(buffers, currentIndex, \"\\n\");\n }\n },\n ontext(text) {\n if (skippedTagDepth > 0) {\n return;\n }\n\n appendText(buffers, currentIndex, text);\n },\n onclosetag(name) {\n const tagName = name.toLowerCase();\n if (SKIPPED_TAGS.has(tagName)) {\n skippedTagDepth = Math.max(0, skippedTagDepth - 1);\n return;\n }\n\n if (BLOCK_TAGS.has(tagName)) {\n appendText(buffers, currentIndex, \"\\n\\n\");\n }\n },\n },\n { decodeEntities: true },\n );\n\n for await (const chunk of stream as AsyncIterable<unknown>) {\n parser.write(toTextChunk(chunk));\n }\n\n parser.end();\n\n orderedTargets.forEach((target, index) => {\n sections.set(target.id, normalizeSectionText(buffers[index] ?? \"\"));\n });\n\n return sections;\n}\n\nfunction appendText(\n buffers: string[],\n currentIndex: number,\n text: string,\n): void {\n if (currentIndex < 0 || currentIndex >= buffers.length) {\n return;\n }\n\n buffers[currentIndex] += text;\n}\n\nfunction normalizeSectionText(text: string): string {\n return text\n .replace(/\\r\\n/gu, \"\\n\")\n .replace(/\\n{3,}/gu, \"\\n\\n\")\n .trim();\n}\n\nfunction toTextChunk(chunk: unknown): string {\n if (typeof chunk === \"string\") {\n return chunk;\n }\n\n if (Buffer.isBuffer(chunk)) {\n return chunk.toString(\"utf8\");\n }\n\n throw new Error(\"Unexpected HTML stream chunk type\");\n}\n\nfunction countWords(text: string): number {\n return [...createWordSegmenter().segment(text)].filter(\n (segment) => segment.isWordLike,\n ).length;\n}\n\nlet WORD_SEGMENTER: Intl.Segmenter | undefined;\n\nfunction createWordSegmenter(): Intl.Segmenter {\n if (WORD_SEGMENTER === undefined) {\n WORD_SEGMENTER = new Intl.Segmenter(undefined, {\n granularity: \"word\",\n });\n }\n\n return WORD_SEGMENTER;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SourceAdapter, SourceDocument } from '../adapter.js';
|
|
2
|
+
import { SourceAsset, SourceSection, SourceTextStream } from '../types.js';
|
|
3
|
+
import { EpubArchive } from './archive.js';
|
|
4
|
+
import { EpubContentLoader } from './content.js';
|
|
5
|
+
import { EpubPackageData } from './package.js';
|
|
6
|
+
import '../meta.js';
|
|
7
|
+
import 'zod';
|
|
8
|
+
import 'stream';
|
|
9
|
+
import 'yauzl';
|
|
10
|
+
|
|
11
|
+
interface SectionDefinition {
|
|
12
|
+
readonly hasContent: boolean;
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly title: string | undefined;
|
|
15
|
+
readonly path: string | undefined;
|
|
16
|
+
readonly fragment: string | undefined;
|
|
17
|
+
readonly wordsCount: number;
|
|
18
|
+
readonly children: readonly SectionDefinition[];
|
|
19
|
+
}
|
|
20
|
+
declare class EpubSourceSection implements SourceSection {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(document: EpubSourceDocument, definition: SectionDefinition);
|
|
23
|
+
get id(): string;
|
|
24
|
+
get hasContent(): boolean;
|
|
25
|
+
get title(): string | undefined;
|
|
26
|
+
get wordsCount(): number;
|
|
27
|
+
get children(): readonly SourceSection[];
|
|
28
|
+
open(): Promise<SourceTextStream>;
|
|
29
|
+
}
|
|
30
|
+
declare class EpubSourceDocument implements SourceDocument {
|
|
31
|
+
#private;
|
|
32
|
+
constructor(packageData: EpubPackageData, cover: SourceAsset | undefined, sections: readonly SectionDefinition[], contentLoader: EpubContentLoader);
|
|
33
|
+
static open(archive: EpubArchive): Promise<EpubSourceDocument>;
|
|
34
|
+
readMeta(): Promise<{
|
|
35
|
+
version: 1;
|
|
36
|
+
sourceFormat: "epub" | "pdf" | "txt" | "markdown";
|
|
37
|
+
title: string | null;
|
|
38
|
+
authors: string[];
|
|
39
|
+
language: string | null;
|
|
40
|
+
identifier: string | null;
|
|
41
|
+
publisher: string | null;
|
|
42
|
+
publishedAt: string | null;
|
|
43
|
+
description: string | null;
|
|
44
|
+
}>;
|
|
45
|
+
readCover(): Promise<SourceAsset | undefined>;
|
|
46
|
+
readSections(): Promise<EpubSourceSection[]>;
|
|
47
|
+
openSection(sectionId: string): Promise<SourceTextStream>;
|
|
48
|
+
}
|
|
49
|
+
declare class EpubSourceAdapter implements SourceAdapter {
|
|
50
|
+
get format(): "epub";
|
|
51
|
+
openSession<T>(path: string, operation: (document: SourceDocument) => Promise<T>): Promise<T>;
|
|
52
|
+
}
|
|
53
|
+
declare const EPUB_SOURCE_ADAPTER: EpubSourceAdapter;
|
|
54
|
+
|
|
55
|
+
export { EPUB_SOURCE_ADAPTER, EpubSourceAdapter, EpubSourceDocument };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { normalizeFragment } from "./archive.js";
|
|
2
|
+
import { EpubArchive } from "./archive.js";
|
|
3
|
+
import {
|
|
4
|
+
analyzeSectionTargets,
|
|
5
|
+
EpubContentLoader
|
|
6
|
+
} from "./content.js";
|
|
7
|
+
import { readEpubNavigation } from "./navigation.js";
|
|
8
|
+
import { readEpubPackage } from "./package.js";
|
|
9
|
+
class EpubSourceSection {
|
|
10
|
+
#document;
|
|
11
|
+
#definition;
|
|
12
|
+
constructor(document, definition) {
|
|
13
|
+
this.#document = document;
|
|
14
|
+
this.#definition = definition;
|
|
15
|
+
}
|
|
16
|
+
get id() {
|
|
17
|
+
return this.#definition.id;
|
|
18
|
+
}
|
|
19
|
+
get hasContent() {
|
|
20
|
+
return this.#definition.hasContent;
|
|
21
|
+
}
|
|
22
|
+
get title() {
|
|
23
|
+
return this.#definition.title;
|
|
24
|
+
}
|
|
25
|
+
get wordsCount() {
|
|
26
|
+
return this.#definition.wordsCount;
|
|
27
|
+
}
|
|
28
|
+
get children() {
|
|
29
|
+
return this.#definition.children.map(
|
|
30
|
+
(child) => new EpubSourceSection(this.#document, child)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
async open() {
|
|
34
|
+
return await this.#document.openSection(this.#definition.id);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
class EpubSourceDocument {
|
|
38
|
+
#packageData;
|
|
39
|
+
#cover;
|
|
40
|
+
#sections;
|
|
41
|
+
#contentLoader;
|
|
42
|
+
constructor(packageData, cover, sections, contentLoader) {
|
|
43
|
+
this.#packageData = packageData;
|
|
44
|
+
this.#cover = cover;
|
|
45
|
+
this.#sections = sections;
|
|
46
|
+
this.#contentLoader = contentLoader;
|
|
47
|
+
}
|
|
48
|
+
static async open(archive) {
|
|
49
|
+
assertArchiveIsSupported(archive);
|
|
50
|
+
const packageData = await readEpubPackage(archive);
|
|
51
|
+
const navigation = await readEpubNavigation(archive, packageData);
|
|
52
|
+
const rawSections = buildSections(archive, navigation);
|
|
53
|
+
const targetsByPath = groupTargetsByPath(rawSections);
|
|
54
|
+
const sectionAnalyses = await analyzeSectionTargets(archive, targetsByPath);
|
|
55
|
+
const sections = hydrateSectionAnalyses(rawSections, sectionAnalyses);
|
|
56
|
+
const cover = await readCoverAsset(archive, packageData);
|
|
57
|
+
return new EpubSourceDocument(
|
|
58
|
+
packageData,
|
|
59
|
+
cover,
|
|
60
|
+
sections,
|
|
61
|
+
new EpubContentLoader(archive, targetsByPath)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
readMeta() {
|
|
65
|
+
return Promise.resolve(this.#packageData.metadata);
|
|
66
|
+
}
|
|
67
|
+
readCover() {
|
|
68
|
+
return Promise.resolve(this.#cover);
|
|
69
|
+
}
|
|
70
|
+
readSections() {
|
|
71
|
+
return Promise.resolve(
|
|
72
|
+
this.#sections.map((section) => new EpubSourceSection(this, section))
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
async openSection(sectionId) {
|
|
76
|
+
return await this.#contentLoader.openSection(sectionId);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
class EpubSourceAdapter {
|
|
80
|
+
get format() {
|
|
81
|
+
return "epub";
|
|
82
|
+
}
|
|
83
|
+
async openSession(path, operation) {
|
|
84
|
+
const archive = await EpubArchive.open(path);
|
|
85
|
+
try {
|
|
86
|
+
const document = await EpubSourceDocument.open(archive);
|
|
87
|
+
return await operation(document);
|
|
88
|
+
} finally {
|
|
89
|
+
await archive.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const EPUB_SOURCE_ADAPTER = new EpubSourceAdapter();
|
|
94
|
+
function assertArchiveIsSupported(archive) {
|
|
95
|
+
if (!archive.hasEntry("META-INF/encryption.xml")) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Encrypted EPUB is not supported: found META-INF/encryption.xml."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
async function readCoverAsset(archive, packageData) {
|
|
103
|
+
if (packageData.coverPath === void 0 || packageData.coverMediaType === void 0) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
path: packageData.coverPath,
|
|
108
|
+
mediaType: packageData.coverMediaType,
|
|
109
|
+
data: await archive.readBuffer(packageData.coverPath)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function buildSections(archive, items) {
|
|
113
|
+
const idCounts = /* @__PURE__ */ new Map();
|
|
114
|
+
return items.map(
|
|
115
|
+
(item, index) => buildSection(archive, item, [index], idCounts)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
function buildSection(archive, item, indexPath, idCounts) {
|
|
119
|
+
const fragment = normalizeFragment(item.fragment);
|
|
120
|
+
const baseId = item.path === void 0 ? `toc:${indexPath.join(".")}` : archive.createSectionId(item.path, fragment);
|
|
121
|
+
const id = createUniqueId(baseId, idCounts);
|
|
122
|
+
return {
|
|
123
|
+
hasContent: item.path !== void 0,
|
|
124
|
+
id,
|
|
125
|
+
title: item.title,
|
|
126
|
+
path: item.path,
|
|
127
|
+
fragment,
|
|
128
|
+
wordsCount: 0,
|
|
129
|
+
children: item.children.map(
|
|
130
|
+
(child, index) => buildSection(archive, child, [...indexPath, index], idCounts)
|
|
131
|
+
)
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function hydrateSectionAnalyses(sections, sectionAnalyses) {
|
|
135
|
+
return sections.map((section) => {
|
|
136
|
+
const analysis = sectionAnalyses.get(section.id);
|
|
137
|
+
return {
|
|
138
|
+
...section,
|
|
139
|
+
hasContent: analysis?.hasContent ?? false,
|
|
140
|
+
wordsCount: analysis?.wordsCount ?? 0,
|
|
141
|
+
children: hydrateSectionAnalyses(section.children, sectionAnalyses)
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function createUniqueId(baseId, idCounts) {
|
|
146
|
+
const currentCount = idCounts.get(baseId) ?? 0;
|
|
147
|
+
idCounts.set(baseId, currentCount + 1);
|
|
148
|
+
return currentCount === 0 ? baseId : `${baseId}~${currentCount + 1}`;
|
|
149
|
+
}
|
|
150
|
+
function groupTargetsByPath(sections) {
|
|
151
|
+
const targetsByPath = /* @__PURE__ */ new Map();
|
|
152
|
+
for (const section of flattenSections(sections)) {
|
|
153
|
+
if (section.path === void 0) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const targets = targetsByPath.get(section.path) ?? [];
|
|
157
|
+
targets.push({
|
|
158
|
+
id: section.id,
|
|
159
|
+
path: section.path,
|
|
160
|
+
fragment: section.fragment
|
|
161
|
+
});
|
|
162
|
+
targetsByPath.set(section.path, targets);
|
|
163
|
+
}
|
|
164
|
+
return targetsByPath;
|
|
165
|
+
}
|
|
166
|
+
function flattenSections(sections) {
|
|
167
|
+
const flattened = [];
|
|
168
|
+
for (const section of sections) {
|
|
169
|
+
flattened.push(section);
|
|
170
|
+
flattened.push(...flattenSections(section.children));
|
|
171
|
+
}
|
|
172
|
+
return flattened;
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
EPUB_SOURCE_ADAPTER,
|
|
176
|
+
EpubSourceAdapter,
|
|
177
|
+
EpubSourceDocument
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=document.js.map
|