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/wikipage/resolver.ts"],"sourcesContent":["import { WikipageCache } from \"./cache.js\";\nimport { createWikipageFetchLog } from \"./fetch-log.js\";\nimport {\n WikimediaClient,\n replaceTitleUriWithQidUri,\n type SupportedWiki,\n type WikiPageInfo,\n type WikidataEntityInfo,\n} from \"./wikimedia-client.js\";\nimport type {\n CachedDisambiguationRecord,\n CachedPageRecord,\n CachedQidRecord,\n DisambiguationExpansion,\n DisambiguationLinkedQid,\n DisambiguationPageText,\n DisambiguationProfileNormalizer,\n QidResolution,\n WikipageResolveProgressReporter,\n WikipageResolverOptions,\n} from \"./types.js\";\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_LANGUAGE = \"zh\";\nconst DEFAULT_MAX_BATCH_SIZE = 50;\nconst DEFAULT_MIN_REQUEST_INTERVAL_MS = 100;\nconst DEFAULT_RETRY_BASE_DELAY_MS = 1_000;\nconst DEFAULT_RETRY_TIMES = 3;\nconst DEFAULT_USER_AGENT =\n \"WikiGraph/0.3 (https://github.com/oomol-lab/wiki-graph)\";\n\nexport class WikipageResolver {\n readonly #cache: WikipageCache;\n readonly #client: WikimediaClient;\n readonly #maxBatchSize: number;\n readonly #language: string;\n readonly #normalizer: DisambiguationProfileNormalizer | undefined;\n readonly #ownsCache: boolean;\n readonly #progress: WikipageResolveProgressReporter | undefined;\n readonly #wiki: string;\n\n public constructor(input: {\n readonly cache: WikipageCache;\n readonly client: WikimediaClient;\n readonly language: string;\n readonly maxBatchSize: number;\n readonly normalizer: DisambiguationProfileNormalizer | undefined;\n readonly ownsCache: boolean;\n readonly progress: WikipageResolveProgressReporter | undefined;\n readonly wiki: string;\n }) {\n this.#cache = input.cache;\n this.#client = input.client;\n this.#language = input.language;\n this.#maxBatchSize = input.maxBatchSize;\n this.#normalizer = input.normalizer;\n this.#ownsCache = input.ownsCache;\n this.#progress = input.progress;\n this.#wiki = input.wiki;\n }\n\n public static async open(\n options: WikipageResolverOptions = {},\n ): Promise<WikipageResolver> {\n const language = normalizeLanguage(options.language);\n const wiki = options.wiki ?? `${language}wiki`;\n const cache = await WikipageCache.open(options.cacheDatabasePath);\n\n return new WikipageResolver({\n cache,\n client: new WikimediaClient({\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n language,\n requestLog: createWikipageFetchLog(options.logDirPath),\n minRequestIntervalMs:\n options.minRequestIntervalMs ?? DEFAULT_MIN_REQUEST_INTERVAL_MS,\n retryBaseDelayMs:\n options.retryBaseDelayMs ?? DEFAULT_RETRY_BASE_DELAY_MS,\n retryTimes: options.retryTimes ?? DEFAULT_RETRY_TIMES,\n userAgent: options.userAgent ?? DEFAULT_USER_AGENT,\n wiki,\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n }),\n language,\n maxBatchSize: normalizeBatchSize(options.maxBatchSize),\n normalizer: options.normalizer,\n ownsCache: true,\n progress: options.progress,\n wiki,\n });\n }\n\n public async close(): Promise<void> {\n if (this.#ownsCache) {\n await this.#cache.close();\n }\n }\n\n public async resolveQids(\n qids: readonly string[],\n ): Promise<readonly QidResolution[]> {\n const normalizedQids = normalizeQids(qids);\n const qidRecords = await this.#resolveQidRecords(normalizedQids);\n const disambiguationRecords = await this.#resolveDisambiguations(\n [...qidRecords.values()].filter(hasDisambiguationPage),\n );\n\n return normalizedQids.map((qid) => {\n const record = qidRecords.get(qid);\n\n if (record === undefined) {\n return {\n isDisambiguation: false,\n qid,\n };\n }\n\n const disambiguation = disambiguationRecords.get(qid);\n const disambiguationPages = disambiguation?.pages ?? [];\n const primarySitelink = pickPrimarySitelink(record.sitelinks, this.#wiki);\n\n return {\n ...(record.description === undefined\n ? {}\n : { description: record.description }),\n ...(disambiguation === undefined\n ? {}\n : { disambiguation: toDisambiguationExpansion(disambiguation) }),\n ...(disambiguationPages.length === 0 ? {} : { disambiguationPages }),\n isDisambiguation: disambiguationPages.length > 0,\n ...(record.label === undefined ? {} : { label: record.label }),\n qid,\n ...(primarySitelink === undefined ? {} : { sitelink: primarySitelink }),\n ...(record.sitelinks.length === 0\n ? {}\n : { sitelinks: record.sitelinks.map(toSitelink) }),\n };\n });\n }\n\n async #resolveQidRecords(\n qids: readonly string[],\n ): Promise<ReadonlyMap<string, CachedQidRecord>> {\n const cached = new Map(await this.#cache.getQids(qids, this.#language));\n const missing = qids.filter((qid) => !cached.has(qid));\n let resolvedQids = cached.size;\n let resolvedEntities = 0;\n\n await this.#reportProgress(\"qid\", resolvedQids, qids.length);\n\n for (const batch of chunk(missing, this.#maxBatchSize)) {\n const entityInfos = await this.#client.getEntities(batch);\n resolvedEntities += batch.length;\n await this.#reportProgress(\"entity\", resolvedEntities, missing.length);\n const pageInfos = await this.#fetchPageInfos(entityInfos);\n const now = new Date().toISOString();\n const records = batch.map((qid) =>\n createQidRecord(qid, entityInfos.get(qid), pageInfos, now),\n );\n\n await this.#cache.putQids(records, this.#language);\n for (const record of records) {\n cached.set(record.qid, record);\n }\n resolvedQids += batch.length;\n await this.#reportProgress(\"qid\", resolvedQids, qids.length);\n }\n\n return cached;\n }\n\n async #fetchPageInfos(\n entityInfos: ReadonlyMap<string, WikidataEntityInfo>,\n ): Promise<ReadonlyMap<string, WikiPageInfo>> {\n const results = new Map<string, WikiPageInfo>();\n const titlesByWiki = new Map<SupportedWiki, Set<string>>();\n\n for (const entity of entityInfos.values()) {\n for (const sitelink of entity.sitelinks) {\n const titles = titlesByWiki.get(sitelink.wiki) ?? new Set<string>();\n\n titles.add(sitelink.title);\n titlesByWiki.set(sitelink.wiki, titles);\n }\n }\n\n for (const [wiki, titles] of titlesByWiki) {\n for (const batch of chunk([...titles], this.#maxBatchSize)) {\n for (const [title, page] of await this.#client.getPagesByTitles(\n batch,\n wiki,\n )) {\n results.set(pageKey(wiki, title), page);\n }\n await this.#reportProgress(\n \"page\",\n results.size,\n countTitleSetItems(titlesByWiki),\n );\n }\n }\n\n return results;\n }\n\n async #resolveDisambiguations(\n records: readonly CachedQidRecord[],\n ): Promise<ReadonlyMap<string, CachedDisambiguationRecord>> {\n const qids = records.map((record) => record.qid);\n const cached = new Map(\n await this.#cache.getDisambiguations(qids, this.#wiki),\n );\n const missing = records.filter((record) => !cached.has(record.qid));\n let resolvedPages = cached.size;\n\n await this.#reportProgress(\n \"disambiguation-page\",\n resolvedPages,\n qids.length,\n );\n\n for (const record of missing) {\n const expansion = await this.#expandDisambiguation(record);\n\n await this.#cache.putDisambiguations([expansion], this.#wiki);\n cached.set(record.qid, expansion);\n resolvedPages += 1;\n await this.#reportProgress(\n \"disambiguation-page\",\n resolvedPages,\n qids.length,\n );\n }\n\n return cached;\n }\n\n async #expandDisambiguation(\n record: CachedQidRecord,\n ): Promise<CachedDisambiguationRecord> {\n const pages: DisambiguationPageText[] = [];\n\n for (const page of record.sitelinks.filter(\n (item) => item.isDisambiguation,\n )) {\n const parsedPage = await this.#client.parseDisambiguationPage(\n page.title,\n page.wiki,\n );\n const linkedPageInfos = new Map<string, WikiPageInfo>();\n\n for (const batch of chunk(parsedPage.linkedTitles, this.#maxBatchSize)) {\n for (const [title, linkedPage] of await this.#client.getPagesByTitles(\n batch,\n page.wiki,\n )) {\n linkedPageInfos.set(title, linkedPage);\n }\n await this.#reportProgress(\n \"linked-page\",\n linkedPageInfos.size,\n parsedPage.linkedTitles.length,\n );\n }\n\n const titleToQid = new Map<string, string>();\n const linkedQids: DisambiguationLinkedQid[] = [];\n\n for (const title of parsedPage.linkedTitles) {\n const qid = linkedPageInfos.get(title)?.wikibaseItem;\n\n if (qid === undefined) {\n continue;\n }\n\n titleToQid.set(title, qid);\n linkedQids.push({ qid, title });\n }\n\n pages.push({\n linkedQids,\n ...(parsedPage.pageId === undefined\n ? {}\n : { pageId: parsedPage.pageId }),\n text: replaceTitleUriWithQidUri(parsedPage.text, titleToQid),\n title: parsedPage.title,\n wiki: parsedPage.wiki,\n });\n }\n\n const linkedQids = mergeLinkedQids(pages);\n const profile =\n this.#normalizer === undefined || linkedQids.length === 0\n ? undefined\n : await this.#normalizer({\n pageQidLinks: linkedQids,\n pages,\n sourceQid: record.qid,\n ...(record.label === undefined ? {} : { surface: record.label }),\n });\n\n return {\n checkedAt: new Date().toISOString(),\n disambiguationQid: record.qid,\n pages,\n ...(profile === undefined ? {} : { profile }),\n };\n }\n\n async #reportProgress(\n detail: Parameters<WikipageResolveProgressReporter>[0][\"detail\"],\n done: number,\n total: number,\n ): Promise<void> {\n await this.#progress?.({\n detail,\n done: Math.min(Math.max(0, done), Math.max(0, total)),\n total: Math.max(0, total),\n });\n }\n}\n\nfunction createQidRecord(\n qid: string,\n entityInfo: WikidataEntityInfo | undefined,\n pageInfos: ReadonlyMap<string, WikiPageInfo>,\n now: string,\n): CachedQidRecord {\n return {\n checkedAt: now,\n ...(entityInfo?.description === undefined\n ? {}\n : { description: entityInfo.description }),\n ...(entityInfo?.label === undefined ? {} : { label: entityInfo.label }),\n qid,\n sitelinks:\n entityInfo?.sitelinks.flatMap((sitelink): CachedPageRecord[] => {\n const page = pageInfos.get(pageKey(sitelink.wiki, sitelink.title));\n\n if (page === undefined) {\n return [];\n }\n\n return [\n {\n isDisambiguation: page.isDisambiguation,\n ...(page.pageId === undefined ? {} : { pageId: page.pageId }),\n title: page.title,\n wiki: page.wiki,\n },\n ];\n }) ?? [],\n updatedAt: now,\n };\n}\n\nfunction toDisambiguationExpansion(\n record: CachedDisambiguationRecord,\n): DisambiguationExpansion {\n return {\n checkedAt: record.checkedAt,\n disambiguationQid: record.disambiguationQid,\n linkedQids: mergeLinkedQids(record.pages),\n pages: record.pages,\n ...(record.profile === undefined ? {} : { profile: record.profile }),\n };\n}\n\nfunction mergeLinkedQids(\n pages: readonly DisambiguationPageText[],\n): readonly DisambiguationLinkedQid[] {\n const results = new Map<string, DisambiguationLinkedQid>();\n\n for (const page of pages) {\n for (const item of page.linkedQids) {\n results.set(item.qid, item);\n }\n }\n\n return [...results.values()];\n}\n\nfunction countTitleSetItems(\n input: ReadonlyMap<SupportedWiki, Set<string>>,\n): number {\n let count = 0;\n\n for (const titles of input.values()) {\n count += titles.size;\n }\n\n return count;\n}\n\nfunction hasDisambiguationPage(record: CachedQidRecord): boolean {\n return record.sitelinks.some((page) => page.isDisambiguation);\n}\n\nfunction pickPrimarySitelink(\n pages: readonly CachedPageRecord[],\n wiki: string,\n): { readonly title: string; readonly wiki: string } | undefined {\n const preferred = pages.find((page) => page.wiki === wiki) ?? pages[0];\n\n return preferred === undefined ? undefined : toSitelink(preferred);\n}\n\nfunction toSitelink(page: CachedPageRecord): {\n readonly title: string;\n readonly wiki: string;\n} {\n return {\n title: page.title,\n wiki: page.wiki,\n };\n}\n\nfunction pageKey(wiki: SupportedWiki, title: string): string {\n return `${wiki}:${title}`;\n}\n\nfunction normalizeQids(qids: readonly string[]): readonly string[] {\n return [\n ...new Set(\n qids\n .map((qid) => qid.trim().toUpperCase())\n .filter((qid) => /^Q[1-9]\\d*$/u.test(qid)),\n ),\n ];\n}\n\nfunction normalizeLanguage(value: string | undefined): string {\n const normalized = value?.trim().toLowerCase();\n\n if (normalized === \"en\" || normalized === \"zh\") {\n return normalized;\n }\n\n return DEFAULT_LANGUAGE;\n}\n\nfunction normalizeBatchSize(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return DEFAULT_MAX_BATCH_SIZE;\n }\n\n return Math.max(1, Math.floor(value));\n}\n\nfunction chunk<T>(items: readonly T[], size: number): readonly T[][] {\n const batches: T[][] = [];\n\n for (let index = 0; index < items.length; index += size) {\n batches.push(items.slice(index, index + size));\n }\n\n return batches;\n}\n"],"mappings":"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","names":["linkedQids"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
interface WikipageResolverOptions {
|
|
2
|
+
readonly cacheDatabasePath?: string;
|
|
3
|
+
readonly concurrency?: number;
|
|
4
|
+
readonly fetch?: typeof fetch;
|
|
5
|
+
readonly language?: string;
|
|
6
|
+
readonly logDirPath?: string;
|
|
7
|
+
readonly maxBatchSize?: number;
|
|
8
|
+
readonly minRequestIntervalMs?: number;
|
|
9
|
+
readonly normalizer?: DisambiguationProfileNormalizer;
|
|
10
|
+
readonly progress?: WikipageResolveProgressReporter;
|
|
11
|
+
readonly retryBaseDelayMs?: number;
|
|
12
|
+
readonly retryTimes?: number;
|
|
13
|
+
readonly userAgent?: string;
|
|
14
|
+
readonly wiki?: string;
|
|
15
|
+
}
|
|
16
|
+
type WikipageResolveProgressDetail = "disambiguation-page" | "entity" | "linked-page" | "page" | "qid";
|
|
17
|
+
interface WikipageResolveProgress {
|
|
18
|
+
readonly detail: WikipageResolveProgressDetail;
|
|
19
|
+
readonly done: number;
|
|
20
|
+
readonly total: number;
|
|
21
|
+
}
|
|
22
|
+
type WikipageResolveProgressReporter = (event: WikipageResolveProgress) => Promise<void> | void;
|
|
23
|
+
interface QidResolution {
|
|
24
|
+
readonly description?: string;
|
|
25
|
+
readonly disambiguation?: DisambiguationExpansion;
|
|
26
|
+
readonly disambiguationPages?: readonly DisambiguationPageText[];
|
|
27
|
+
readonly isDisambiguation: boolean;
|
|
28
|
+
readonly label?: string;
|
|
29
|
+
readonly qid: string;
|
|
30
|
+
readonly sitelink?: WikipageSitelink;
|
|
31
|
+
readonly sitelinks?: readonly WikipageSitelink[];
|
|
32
|
+
}
|
|
33
|
+
interface WikipageSitelink {
|
|
34
|
+
readonly title: string;
|
|
35
|
+
readonly wiki: string;
|
|
36
|
+
}
|
|
37
|
+
interface DisambiguationExpansion {
|
|
38
|
+
readonly checkedAt: string;
|
|
39
|
+
readonly disambiguationQid: string;
|
|
40
|
+
readonly linkedQids: readonly DisambiguationLinkedQid[];
|
|
41
|
+
readonly pages: readonly DisambiguationPageText[];
|
|
42
|
+
readonly profile?: DisambiguationProfile;
|
|
43
|
+
}
|
|
44
|
+
interface DisambiguationPageText {
|
|
45
|
+
readonly linkedQids: readonly DisambiguationLinkedQid[];
|
|
46
|
+
readonly pageId?: number;
|
|
47
|
+
readonly text: string;
|
|
48
|
+
readonly title: string;
|
|
49
|
+
readonly wiki: "enwiki" | "zhwiki";
|
|
50
|
+
}
|
|
51
|
+
interface DisambiguationLinkedQid {
|
|
52
|
+
readonly qid: string;
|
|
53
|
+
readonly title: string;
|
|
54
|
+
}
|
|
55
|
+
interface CachedQidRecord {
|
|
56
|
+
readonly checkedAt: string;
|
|
57
|
+
readonly description?: string;
|
|
58
|
+
readonly label?: string;
|
|
59
|
+
readonly qid: string;
|
|
60
|
+
readonly sitelinks: readonly CachedPageRecord[];
|
|
61
|
+
readonly updatedAt: string;
|
|
62
|
+
}
|
|
63
|
+
interface CachedDisambiguationRecord {
|
|
64
|
+
readonly checkedAt: string;
|
|
65
|
+
readonly disambiguationQid: string;
|
|
66
|
+
readonly pages: readonly DisambiguationPageText[];
|
|
67
|
+
readonly profile?: DisambiguationProfile;
|
|
68
|
+
}
|
|
69
|
+
interface CachedPageRecord {
|
|
70
|
+
readonly isDisambiguation: boolean;
|
|
71
|
+
readonly pageId?: number;
|
|
72
|
+
readonly title: string;
|
|
73
|
+
readonly wiki: "enwiki" | "zhwiki";
|
|
74
|
+
}
|
|
75
|
+
type DisambiguationMeaningPriority = "other" | "primary" | "secondary";
|
|
76
|
+
interface DisambiguationProfile {
|
|
77
|
+
readonly meanings: readonly DisambiguationProfileMeaning[];
|
|
78
|
+
readonly sourceQid: string;
|
|
79
|
+
readonly surface?: string;
|
|
80
|
+
}
|
|
81
|
+
interface DisambiguationProfileMeaning {
|
|
82
|
+
readonly category?: string;
|
|
83
|
+
readonly information: string;
|
|
84
|
+
readonly name: string;
|
|
85
|
+
readonly priority: DisambiguationMeaningPriority;
|
|
86
|
+
readonly qid: string;
|
|
87
|
+
}
|
|
88
|
+
type DisambiguationProfileNormalizer = (input: DisambiguationProfileNormalizerInput) => Promise<DisambiguationProfile>;
|
|
89
|
+
interface DisambiguationProfileNormalizerInput {
|
|
90
|
+
readonly pageQidLinks: readonly DisambiguationLinkedQid[];
|
|
91
|
+
readonly pages: readonly DisambiguationPageText[];
|
|
92
|
+
readonly sourceQid: string;
|
|
93
|
+
readonly surface?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export type { CachedDisambiguationRecord, CachedPageRecord, CachedQidRecord, DisambiguationExpansion, DisambiguationLinkedQid, DisambiguationMeaningPriority, DisambiguationPageText, DisambiguationProfile, DisambiguationProfileMeaning, DisambiguationProfileNormalizer, DisambiguationProfileNormalizerInput, QidResolution, WikipageResolveProgress, WikipageResolveProgressDetail, WikipageResolveProgressReporter, WikipageResolverOptions, WikipageSitelink };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WikipageFetchLog } from './fetch-log.js';
|
|
2
|
+
|
|
3
|
+
type SupportedWiki = "enwiki" | "zhwiki";
|
|
4
|
+
interface WikimediaClientOptions {
|
|
5
|
+
readonly concurrency: number;
|
|
6
|
+
readonly fetch?: typeof fetch;
|
|
7
|
+
readonly language: string;
|
|
8
|
+
readonly minRequestIntervalMs: number;
|
|
9
|
+
readonly requestLog: WikipageFetchLog;
|
|
10
|
+
readonly retryBaseDelayMs: number;
|
|
11
|
+
readonly retryTimes: number;
|
|
12
|
+
readonly userAgent?: string;
|
|
13
|
+
readonly wiki: string;
|
|
14
|
+
}
|
|
15
|
+
interface WikidataEntityInfo {
|
|
16
|
+
readonly description?: string;
|
|
17
|
+
readonly label?: string;
|
|
18
|
+
readonly qid: string;
|
|
19
|
+
readonly sitelinks: readonly WikidataSitelinkInfo[];
|
|
20
|
+
}
|
|
21
|
+
interface WikidataSitelinkInfo {
|
|
22
|
+
readonly title: string;
|
|
23
|
+
readonly wiki: SupportedWiki;
|
|
24
|
+
}
|
|
25
|
+
interface WikiPageInfo {
|
|
26
|
+
readonly isDisambiguation: boolean;
|
|
27
|
+
readonly pageId?: number;
|
|
28
|
+
readonly title: string;
|
|
29
|
+
readonly wiki: SupportedWiki;
|
|
30
|
+
readonly wikibaseItem?: string;
|
|
31
|
+
}
|
|
32
|
+
interface ParsedDisambiguationPage {
|
|
33
|
+
readonly linkedTitles: readonly string[];
|
|
34
|
+
readonly pageId?: number;
|
|
35
|
+
readonly text: string;
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly wiki: SupportedWiki;
|
|
38
|
+
}
|
|
39
|
+
declare class WikimediaClient {
|
|
40
|
+
#private;
|
|
41
|
+
constructor(options: WikimediaClientOptions);
|
|
42
|
+
getEntities(qids: readonly string[]): Promise<ReadonlyMap<string, WikidataEntityInfo>>;
|
|
43
|
+
getPagesByTitles(titles: readonly string[], wiki?: SupportedWiki): Promise<ReadonlyMap<string, WikiPageInfo>>;
|
|
44
|
+
parseDisambiguationPage(title: string, wiki: SupportedWiki): Promise<ParsedDisambiguationPage>;
|
|
45
|
+
}
|
|
46
|
+
declare function replaceTitleUriWithQidUri(text: string, titleToQid: ReadonlyMap<string, string>): string;
|
|
47
|
+
|
|
48
|
+
export { type ParsedDisambiguationPage, type SupportedWiki, type WikiPageInfo, type WikidataEntityInfo, type WikidataSitelinkInfo, WikimediaClient, type WikimediaClientOptions, replaceTitleUriWithQidUri };
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { DomUtils, parseDocument } from "htmlparser2";
|
|
2
|
+
import { getLogger } from "../common/logging.js";
|
|
3
|
+
import { formatError } from "../utils/node-error.js";
|
|
4
|
+
import { RateLimiter, parseRetryAfterMs } from "./rate-limiter.js";
|
|
5
|
+
const SUPPORTED_WIKIS = ["zhwiki", "enwiki"];
|
|
6
|
+
const TITLE_URI_PREFIX = "wikigraph-title://";
|
|
7
|
+
class WikimediaClient {
|
|
8
|
+
#fetch;
|
|
9
|
+
#language;
|
|
10
|
+
#limiter;
|
|
11
|
+
#requestLog;
|
|
12
|
+
#retryBaseDelayMs;
|
|
13
|
+
#retryTimes;
|
|
14
|
+
#userAgent;
|
|
15
|
+
#wiki;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.#fetch = options.fetch ?? fetch;
|
|
18
|
+
this.#language = options.language;
|
|
19
|
+
this.#requestLog = options.requestLog;
|
|
20
|
+
this.#wiki = options.wiki;
|
|
21
|
+
this.#userAgent = options.userAgent;
|
|
22
|
+
this.#retryBaseDelayMs = Math.max(0, Math.floor(options.retryBaseDelayMs));
|
|
23
|
+
this.#retryTimes = Math.max(0, Math.floor(options.retryTimes));
|
|
24
|
+
this.#limiter = new RateLimiter({
|
|
25
|
+
concurrency: options.concurrency,
|
|
26
|
+
minRequestIntervalMs: options.minRequestIntervalMs
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async getEntities(qids) {
|
|
30
|
+
if (qids.length === 0) {
|
|
31
|
+
return /* @__PURE__ */ new Map();
|
|
32
|
+
}
|
|
33
|
+
const url = new URL("https://www.wikidata.org/w/api.php");
|
|
34
|
+
url.searchParams.set("action", "wbgetentities");
|
|
35
|
+
url.searchParams.set("ids", qids.join("|"));
|
|
36
|
+
url.searchParams.set("props", "labels|descriptions|sitelinks");
|
|
37
|
+
url.searchParams.set("languages", listWikidataLanguages(this.#language));
|
|
38
|
+
url.searchParams.set("sitefilter", SUPPORTED_WIKIS.join("|"));
|
|
39
|
+
url.searchParams.set("format", "json");
|
|
40
|
+
url.searchParams.set("formatversion", "2");
|
|
41
|
+
const json = await this.#fetchJson(url);
|
|
42
|
+
const entities = asRecord(json.entities);
|
|
43
|
+
const results = /* @__PURE__ */ new Map();
|
|
44
|
+
for (const qid of qids) {
|
|
45
|
+
const entity = asRecord(entities[qid]);
|
|
46
|
+
const labels = asRecord(entity.labels);
|
|
47
|
+
const descriptions = asRecord(entity.descriptions);
|
|
48
|
+
results.set(qid, {
|
|
49
|
+
...pickLocalizedValue(labels, this.#language) === void 0 ? {} : { label: pickLocalizedValue(labels, this.#language) },
|
|
50
|
+
...pickLocalizedValue(descriptions, this.#language) === void 0 ? {} : { description: pickLocalizedValue(descriptions, this.#language) },
|
|
51
|
+
qid,
|
|
52
|
+
sitelinks: SUPPORTED_WIKIS.flatMap((wiki) => {
|
|
53
|
+
const title = getNestedString(entity, ["sitelinks", wiki, "title"]);
|
|
54
|
+
return title === void 0 ? [] : [{ title, wiki }];
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
async getPagesByTitles(titles, wiki = normalizeWiki(this.#wiki) ?? "enwiki") {
|
|
61
|
+
if (titles.length === 0) {
|
|
62
|
+
return /* @__PURE__ */ new Map();
|
|
63
|
+
}
|
|
64
|
+
const url = new URL(`${wikiApiBaseURL(wiki)}w/api.php`);
|
|
65
|
+
url.searchParams.set("action", "query");
|
|
66
|
+
url.searchParams.set("titles", titles.join("|"));
|
|
67
|
+
url.searchParams.set("prop", "pageprops");
|
|
68
|
+
url.searchParams.set("ppprop", "disambiguation|wikibase_item");
|
|
69
|
+
url.searchParams.set("format", "json");
|
|
70
|
+
url.searchParams.set("formatversion", "2");
|
|
71
|
+
const json = await this.#fetchJson(url);
|
|
72
|
+
const pages = asArray(asRecord(asRecord(json.query).pages));
|
|
73
|
+
const results = /* @__PURE__ */ new Map();
|
|
74
|
+
for (const pageValue of pages) {
|
|
75
|
+
const page = asRecord(pageValue);
|
|
76
|
+
const title = getString(page.title);
|
|
77
|
+
if (title === void 0) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
results.set(title, {
|
|
81
|
+
isDisambiguation: asRecord(page.pageprops).disambiguation !== void 0,
|
|
82
|
+
...getNumber(page.pageid) === void 0 ? {} : { pageId: getNumber(page.pageid) },
|
|
83
|
+
title,
|
|
84
|
+
wiki,
|
|
85
|
+
...getString(asRecord(page.pageprops).wikibase_item) === void 0 ? {} : {
|
|
86
|
+
wikibaseItem: getString(asRecord(page.pageprops).wikibase_item)
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
async parseDisambiguationPage(title, wiki) {
|
|
93
|
+
const url = new URL(`${wikiApiBaseURL(wiki)}w/api.php`);
|
|
94
|
+
url.searchParams.set("action", "parse");
|
|
95
|
+
url.searchParams.set("page", title);
|
|
96
|
+
url.searchParams.set("prop", "text|properties");
|
|
97
|
+
url.searchParams.set("format", "json");
|
|
98
|
+
url.searchParams.set("formatversion", "2");
|
|
99
|
+
const json = await this.#fetchJson(url);
|
|
100
|
+
const parse = asRecord(json.parse);
|
|
101
|
+
const rendered = renderDisambiguationHtml(getNestedString(parse, ["text"]));
|
|
102
|
+
return {
|
|
103
|
+
linkedTitles: rendered.linkedTitles,
|
|
104
|
+
...getNumber(parse.pageid) === void 0 ? {} : { pageId: getNumber(parse.pageid) },
|
|
105
|
+
text: rendered.text,
|
|
106
|
+
title: getString(parse.title) ?? title,
|
|
107
|
+
wiki
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async #fetchJson(url) {
|
|
111
|
+
let lastError;
|
|
112
|
+
for (let attempt = 0; attempt <= this.#retryTimes; attempt += 1) {
|
|
113
|
+
try {
|
|
114
|
+
return await this.#limiter.use(
|
|
115
|
+
async () => await this.#fetchJsonOnce(url, attempt + 1)
|
|
116
|
+
);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
lastError = error;
|
|
119
|
+
if (!isRetryableError(error) || attempt >= this.#retryTimes) {
|
|
120
|
+
this.#requestLog.warnFailed();
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
await delay(getRetryDelayMs(error, attempt, this.#retryBaseDelayMs));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
127
|
+
}
|
|
128
|
+
async #fetchJsonOnce(url, attempt) {
|
|
129
|
+
const startedAt = Date.now();
|
|
130
|
+
let response;
|
|
131
|
+
try {
|
|
132
|
+
response = await this.#fetch(
|
|
133
|
+
url,
|
|
134
|
+
this.#userAgent === void 0 ? void 0 : {
|
|
135
|
+
headers: {
|
|
136
|
+
"User-Agent": this.#userAgent
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
await this.#appendFetchLog({
|
|
142
|
+
attempt,
|
|
143
|
+
durationMs: Date.now() - startedAt,
|
|
144
|
+
error,
|
|
145
|
+
startedAt,
|
|
146
|
+
url
|
|
147
|
+
});
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
151
|
+
if (retryAfterMs !== void 0) {
|
|
152
|
+
this.#limiter.blockFor(retryAfterMs);
|
|
153
|
+
}
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const responseText = isTextResponse(response) ? await response.text() : void 0;
|
|
156
|
+
await this.#appendFetchLog({
|
|
157
|
+
attempt,
|
|
158
|
+
durationMs: Date.now() - startedAt,
|
|
159
|
+
response,
|
|
160
|
+
...responseText === void 0 ? {} : { responseText },
|
|
161
|
+
startedAt,
|
|
162
|
+
url
|
|
163
|
+
});
|
|
164
|
+
throw new WikimediaRequestError(url, response.status, retryAfterMs);
|
|
165
|
+
}
|
|
166
|
+
await this.#appendFetchLog({
|
|
167
|
+
attempt,
|
|
168
|
+
durationMs: Date.now() - startedAt,
|
|
169
|
+
response,
|
|
170
|
+
startedAt,
|
|
171
|
+
url
|
|
172
|
+
});
|
|
173
|
+
return asRecord(await response.json());
|
|
174
|
+
}
|
|
175
|
+
async #appendFetchLog(entry) {
|
|
176
|
+
try {
|
|
177
|
+
await this.#requestLog.append(entry);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
getLogger({ component: "wikipage" }).warn(
|
|
180
|
+
`Failed to write wikipage fetch log entry: ${formatError(error)}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function isTextResponse(response) {
|
|
186
|
+
const contentType = response.headers.get("content-type");
|
|
187
|
+
if (contentType === null) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return /(?:json|text|xml|javascript|html)/iu.test(contentType);
|
|
191
|
+
}
|
|
192
|
+
class WikimediaRequestError extends Error {
|
|
193
|
+
retryAfterMs;
|
|
194
|
+
status;
|
|
195
|
+
url;
|
|
196
|
+
constructor(url, status, retryAfterMs) {
|
|
197
|
+
super(`Wikimedia request failed with ${status}: ${url.toString()}`);
|
|
198
|
+
this.retryAfterMs = retryAfterMs;
|
|
199
|
+
this.status = status;
|
|
200
|
+
this.url = url;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function replaceTitleUriWithQidUri(text, titleToQid) {
|
|
204
|
+
return text.replace(
|
|
205
|
+
/\[\[([^\]|]+)\|wikigraph-title:\/\/([^\]\s]+)\]\]/gu,
|
|
206
|
+
(_match, label, encodedTitle) => {
|
|
207
|
+
const title = decodeURIComponent(encodedTitle);
|
|
208
|
+
const qid = titleToQid.get(title);
|
|
209
|
+
return qid === void 0 ? label : `[[${label}|wikg://qid=${qid}]]`;
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
function renderDisambiguationHtml(html) {
|
|
214
|
+
if (html === void 0 || html.trim() === "") {
|
|
215
|
+
return {
|
|
216
|
+
linkedTitles: [],
|
|
217
|
+
text: ""
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
const linkedTitles = /* @__PURE__ */ new Set();
|
|
221
|
+
const document = parseDocument(html);
|
|
222
|
+
const text = renderNodes(DomUtils.getChildren(document), {
|
|
223
|
+
linkedTitles,
|
|
224
|
+
listDepth: 0
|
|
225
|
+
}).replace(/[ \t]+\n/gu, "\n").replace(/\n{3,}/gu, "\n\n").trim();
|
|
226
|
+
return {
|
|
227
|
+
linkedTitles: [...linkedTitles],
|
|
228
|
+
text
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function renderNodes(nodes, context) {
|
|
232
|
+
return nodes.map((node) => renderNode(node, context)).join("");
|
|
233
|
+
}
|
|
234
|
+
function renderNode(node, context) {
|
|
235
|
+
const record = asRecord(node);
|
|
236
|
+
const nodeType = getString(record.type);
|
|
237
|
+
if (nodeType === "text") {
|
|
238
|
+
return normalizeInlineText(getString(record.data) ?? "");
|
|
239
|
+
}
|
|
240
|
+
if (nodeType !== "tag" && nodeType !== "script" && nodeType !== "style") {
|
|
241
|
+
return "";
|
|
242
|
+
}
|
|
243
|
+
const element = node;
|
|
244
|
+
if (shouldSkipElement(element)) {
|
|
245
|
+
return "";
|
|
246
|
+
}
|
|
247
|
+
const name = element.name.toLowerCase();
|
|
248
|
+
if (name === "a") {
|
|
249
|
+
return renderLink(element, context);
|
|
250
|
+
}
|
|
251
|
+
if (/^h[1-6]$/u.test(name)) {
|
|
252
|
+
const level = Math.min(6, Math.max(1, Number(name.slice(1))));
|
|
253
|
+
const marker = "=".repeat(level);
|
|
254
|
+
const heading = renderNodes(element.children ?? [], context).trim();
|
|
255
|
+
return heading === "" ? "" : `
|
|
256
|
+
${marker} ${heading} ${marker}
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
if (name === "li") {
|
|
260
|
+
const indent = " ".repeat(Math.max(0, context.listDepth - 1));
|
|
261
|
+
const content = renderNodes(element.children ?? [], {
|
|
262
|
+
...context,
|
|
263
|
+
listDepth: context.listDepth + 1
|
|
264
|
+
}).trim();
|
|
265
|
+
return content === "" ? "" : `
|
|
266
|
+
${indent}* ${content}`;
|
|
267
|
+
}
|
|
268
|
+
if (name === "ul" || name === "ol") {
|
|
269
|
+
return `${renderNodes(element.children ?? [], context)}
|
|
270
|
+
`;
|
|
271
|
+
}
|
|
272
|
+
if (isBlockElement(name)) {
|
|
273
|
+
const content = renderNodes(element.children ?? [], context).trim();
|
|
274
|
+
return content === "" ? "" : `
|
|
275
|
+
${content}
|
|
276
|
+
`;
|
|
277
|
+
}
|
|
278
|
+
return renderNodes(element.children ?? [], context);
|
|
279
|
+
}
|
|
280
|
+
function renderLink(node, context) {
|
|
281
|
+
const content = renderNodes(node.children ?? [], context).trim();
|
|
282
|
+
const title = extractWikiLinkTitle(node);
|
|
283
|
+
if (title === void 0) {
|
|
284
|
+
return content;
|
|
285
|
+
}
|
|
286
|
+
context.linkedTitles.add(title);
|
|
287
|
+
return `[[${content === "" ? title : content}|${TITLE_URI_PREFIX}${encodeURIComponent(title)}]]`;
|
|
288
|
+
}
|
|
289
|
+
function extractWikiLinkTitle(node) {
|
|
290
|
+
const title = node.attribs.title;
|
|
291
|
+
const href = node.attribs.href;
|
|
292
|
+
if (title !== void 0 && title !== "" && !title.includes(":")) {
|
|
293
|
+
return title;
|
|
294
|
+
}
|
|
295
|
+
if (href === void 0 || !href.startsWith("/wiki/")) {
|
|
296
|
+
return void 0;
|
|
297
|
+
}
|
|
298
|
+
const decoded = decodeURIComponent(href.slice("/wiki/".length)).replaceAll(
|
|
299
|
+
"_",
|
|
300
|
+
" "
|
|
301
|
+
);
|
|
302
|
+
return decoded === "" || decoded.includes(":") ? void 0 : decoded;
|
|
303
|
+
}
|
|
304
|
+
function shouldSkipElement(node) {
|
|
305
|
+
const name = node.name.toLowerCase();
|
|
306
|
+
if (["script", "style", "table", "sup"].includes(name)) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
const className = node.attribs.class ?? "";
|
|
310
|
+
return [
|
|
311
|
+
"catlinks",
|
|
312
|
+
"metadata",
|
|
313
|
+
"mw-editsection",
|
|
314
|
+
"mw-empty-elt",
|
|
315
|
+
"navbox",
|
|
316
|
+
"noprint",
|
|
317
|
+
"reference",
|
|
318
|
+
"reflist",
|
|
319
|
+
"shortdescription",
|
|
320
|
+
"toc"
|
|
321
|
+
].some((item) => className.split(/\s+/u).includes(item));
|
|
322
|
+
}
|
|
323
|
+
function isBlockElement(name) {
|
|
324
|
+
return ["blockquote", "br", "dd", "div", "dl", "dt", "p", "section"].includes(
|
|
325
|
+
name
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
function normalizeInlineText(value) {
|
|
329
|
+
return value.replace(/\s+/gu, " ");
|
|
330
|
+
}
|
|
331
|
+
function listWikidataLanguages(language) {
|
|
332
|
+
return [.../* @__PURE__ */ new Set([language, "zh", "en"])].join("|");
|
|
333
|
+
}
|
|
334
|
+
function pickLocalizedValue(values, language) {
|
|
335
|
+
for (const candidate of [language, "zh", "en"]) {
|
|
336
|
+
const value = getNestedString(values, [candidate, "value"]);
|
|
337
|
+
if (value !== void 0) {
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
function wikiApiBaseURL(wiki) {
|
|
344
|
+
return wiki === "zhwiki" ? "https://zh.wikipedia.org/" : "https://en.wikipedia.org/";
|
|
345
|
+
}
|
|
346
|
+
function normalizeWiki(value) {
|
|
347
|
+
return value === "zhwiki" || value === "enwiki" ? value : void 0;
|
|
348
|
+
}
|
|
349
|
+
function isRetryableError(error) {
|
|
350
|
+
if (error instanceof WikimediaRequestError) {
|
|
351
|
+
return error.status === 429 || error.status === 500 || error.status === 502 || error.status === 503 || error.status === 504;
|
|
352
|
+
}
|
|
353
|
+
return error instanceof TypeError;
|
|
354
|
+
}
|
|
355
|
+
function getRetryDelayMs(error, attempt, baseDelayMs) {
|
|
356
|
+
if (error instanceof WikimediaRequestError && error.retryAfterMs !== void 0) {
|
|
357
|
+
return error.retryAfterMs;
|
|
358
|
+
}
|
|
359
|
+
if (baseDelayMs <= 0) {
|
|
360
|
+
return 0;
|
|
361
|
+
}
|
|
362
|
+
const exponentialDelayMs = baseDelayMs * 2 ** attempt;
|
|
363
|
+
const jitterMs = Math.floor(Math.random() * Math.min(baseDelayMs, 250));
|
|
364
|
+
return exponentialDelayMs + jitterMs;
|
|
365
|
+
}
|
|
366
|
+
async function delay(ms) {
|
|
367
|
+
if (ms <= 0) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
await new Promise((resolveDelay) => {
|
|
371
|
+
setTimeout(resolveDelay, ms);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function asRecord(value) {
|
|
375
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
376
|
+
}
|
|
377
|
+
function asArray(value) {
|
|
378
|
+
return Array.isArray(value) ? value : [];
|
|
379
|
+
}
|
|
380
|
+
function getString(value) {
|
|
381
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
382
|
+
}
|
|
383
|
+
function getNumber(value) {
|
|
384
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
385
|
+
}
|
|
386
|
+
function getNestedString(value, path) {
|
|
387
|
+
let current = value;
|
|
388
|
+
for (const part of path) {
|
|
389
|
+
current = asRecord(current)[part];
|
|
390
|
+
}
|
|
391
|
+
return getString(current);
|
|
392
|
+
}
|
|
393
|
+
export {
|
|
394
|
+
WikimediaClient,
|
|
395
|
+
replaceTitleUriWithQidUri
|
|
396
|
+
};
|
|
397
|
+
//# sourceMappingURL=wikimedia-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/wikipage/wikimedia-client.ts"],"sourcesContent":["import { DomUtils, parseDocument } from \"htmlparser2\";\n\nimport { getLogger } from \"../common/logging.js\";\nimport { formatError } from \"../utils/node-error.js\";\nimport type { WikipageFetchLog } from \"./fetch-log.js\";\nimport { RateLimiter, parseRetryAfterMs } from \"./rate-limiter.js\";\n\nexport type SupportedWiki = \"enwiki\" | \"zhwiki\";\n\nexport interface WikimediaClientOptions {\n readonly concurrency: number;\n readonly fetch?: typeof fetch;\n readonly language: string;\n readonly minRequestIntervalMs: number;\n readonly requestLog: WikipageFetchLog;\n readonly retryBaseDelayMs: number;\n readonly retryTimes: number;\n readonly userAgent?: string;\n readonly wiki: string;\n}\n\nexport interface WikidataEntityInfo {\n readonly description?: string;\n readonly label?: string;\n readonly qid: string;\n readonly sitelinks: readonly WikidataSitelinkInfo[];\n}\n\nexport interface WikidataSitelinkInfo {\n readonly title: string;\n readonly wiki: SupportedWiki;\n}\n\nexport interface WikiPageInfo {\n readonly isDisambiguation: boolean;\n readonly pageId?: number;\n readonly title: string;\n readonly wiki: SupportedWiki;\n readonly wikibaseItem?: string;\n}\n\nexport interface ParsedDisambiguationPage {\n readonly linkedTitles: readonly string[];\n readonly pageId?: number;\n readonly text: string;\n readonly title: string;\n readonly wiki: SupportedWiki;\n}\n\ninterface MediaWikiPage {\n readonly ns?: unknown;\n readonly pageid?: unknown;\n readonly pageprops?: {\n readonly disambiguation?: unknown;\n readonly wikibase_item?: unknown;\n };\n readonly title?: unknown;\n}\n\nconst SUPPORTED_WIKIS: readonly SupportedWiki[] = [\"zhwiki\", \"enwiki\"];\nconst TITLE_URI_PREFIX = \"wikigraph-title://\";\n\ninterface HtmlElement {\n readonly attribs: Record<string, string | undefined>;\n readonly children?: readonly unknown[];\n readonly name: string;\n}\n\nexport class WikimediaClient {\n readonly #fetch: typeof fetch;\n readonly #language: string;\n readonly #limiter: RateLimiter;\n readonly #requestLog: WikipageFetchLog;\n readonly #retryBaseDelayMs: number;\n readonly #retryTimes: number;\n readonly #userAgent: string | undefined;\n readonly #wiki: string;\n\n public constructor(options: WikimediaClientOptions) {\n this.#fetch = options.fetch ?? fetch;\n this.#language = options.language;\n this.#requestLog = options.requestLog;\n this.#wiki = options.wiki;\n this.#userAgent = options.userAgent;\n this.#retryBaseDelayMs = Math.max(0, Math.floor(options.retryBaseDelayMs));\n this.#retryTimes = Math.max(0, Math.floor(options.retryTimes));\n this.#limiter = new RateLimiter({\n concurrency: options.concurrency,\n minRequestIntervalMs: options.minRequestIntervalMs,\n });\n }\n\n public async getEntities(\n qids: readonly string[],\n ): Promise<ReadonlyMap<string, WikidataEntityInfo>> {\n if (qids.length === 0) {\n return new Map();\n }\n\n const url = new URL(\"https://www.wikidata.org/w/api.php\");\n url.searchParams.set(\"action\", \"wbgetentities\");\n url.searchParams.set(\"ids\", qids.join(\"|\"));\n url.searchParams.set(\"props\", \"labels|descriptions|sitelinks\");\n url.searchParams.set(\"languages\", listWikidataLanguages(this.#language));\n url.searchParams.set(\"sitefilter\", SUPPORTED_WIKIS.join(\"|\"));\n url.searchParams.set(\"format\", \"json\");\n url.searchParams.set(\"formatversion\", \"2\");\n\n const json = await this.#fetchJson(url);\n const entities = asRecord(json.entities);\n const results = new Map<string, WikidataEntityInfo>();\n\n for (const qid of qids) {\n const entity = asRecord(entities[qid]);\n const labels = asRecord(entity.labels);\n const descriptions = asRecord(entity.descriptions);\n\n results.set(qid, {\n ...(pickLocalizedValue(labels, this.#language) === undefined\n ? {}\n : { label: pickLocalizedValue(labels, this.#language)! }),\n ...(pickLocalizedValue(descriptions, this.#language) === undefined\n ? {}\n : { description: pickLocalizedValue(descriptions, this.#language)! }),\n qid,\n sitelinks: SUPPORTED_WIKIS.flatMap((wiki) => {\n const title = getNestedString(entity, [\"sitelinks\", wiki, \"title\"]);\n\n return title === undefined ? [] : [{ title, wiki }];\n }),\n });\n }\n\n return results;\n }\n\n public async getPagesByTitles(\n titles: readonly string[],\n wiki: SupportedWiki = normalizeWiki(this.#wiki) ?? \"enwiki\",\n ): Promise<ReadonlyMap<string, WikiPageInfo>> {\n if (titles.length === 0) {\n return new Map();\n }\n\n const url = new URL(`${wikiApiBaseURL(wiki)}w/api.php`);\n url.searchParams.set(\"action\", \"query\");\n url.searchParams.set(\"titles\", titles.join(\"|\"));\n url.searchParams.set(\"prop\", \"pageprops\");\n url.searchParams.set(\"ppprop\", \"disambiguation|wikibase_item\");\n url.searchParams.set(\"format\", \"json\");\n url.searchParams.set(\"formatversion\", \"2\");\n\n const json = await this.#fetchJson(url);\n const pages = asArray(asRecord(asRecord(json.query).pages));\n const results = new Map<string, WikiPageInfo>();\n\n for (const pageValue of pages) {\n const page = asRecord(pageValue) as MediaWikiPage;\n const title = getString(page.title);\n\n if (title === undefined) {\n continue;\n }\n\n results.set(title, {\n isDisambiguation: asRecord(page.pageprops).disambiguation !== undefined,\n ...(getNumber(page.pageid) === undefined\n ? {}\n : { pageId: getNumber(page.pageid)! }),\n title,\n wiki,\n ...(getString(asRecord(page.pageprops).wikibase_item) === undefined\n ? {}\n : {\n wikibaseItem: getString(asRecord(page.pageprops).wikibase_item)!,\n }),\n });\n }\n\n return results;\n }\n\n public async parseDisambiguationPage(\n title: string,\n wiki: SupportedWiki,\n ): Promise<ParsedDisambiguationPage> {\n const url = new URL(`${wikiApiBaseURL(wiki)}w/api.php`);\n url.searchParams.set(\"action\", \"parse\");\n url.searchParams.set(\"page\", title);\n url.searchParams.set(\"prop\", \"text|properties\");\n url.searchParams.set(\"format\", \"json\");\n url.searchParams.set(\"formatversion\", \"2\");\n\n const json = await this.#fetchJson(url);\n const parse = asRecord(json.parse);\n const rendered = renderDisambiguationHtml(getNestedString(parse, [\"text\"]));\n\n return {\n linkedTitles: rendered.linkedTitles,\n ...(getNumber(parse.pageid) === undefined\n ? {}\n : { pageId: getNumber(parse.pageid)! }),\n text: rendered.text,\n title: getString(parse.title) ?? title,\n wiki,\n };\n }\n\n async #fetchJson(url: URL): Promise<Record<string, unknown>> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.#retryTimes; attempt += 1) {\n try {\n return await this.#limiter.use(\n async () => await this.#fetchJsonOnce(url, attempt + 1),\n );\n } catch (error) {\n lastError = error;\n\n if (!isRetryableError(error) || attempt >= this.#retryTimes) {\n this.#requestLog.warnFailed();\n throw error;\n }\n\n await delay(getRetryDelayMs(error, attempt, this.#retryBaseDelayMs));\n }\n }\n\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n async #fetchJsonOnce(\n url: URL,\n attempt: number,\n ): Promise<Record<string, unknown>> {\n const startedAt = Date.now();\n let response: Response;\n\n try {\n response = await this.#fetch(\n url,\n this.#userAgent === undefined\n ? undefined\n : {\n headers: {\n \"User-Agent\": this.#userAgent,\n },\n },\n );\n } catch (error) {\n await this.#appendFetchLog({\n attempt,\n durationMs: Date.now() - startedAt,\n error,\n startedAt,\n url,\n });\n throw error;\n }\n\n const retryAfterMs = parseRetryAfterMs(response.headers.get(\"retry-after\"));\n\n if (retryAfterMs !== undefined) {\n this.#limiter.blockFor(retryAfterMs);\n }\n if (!response.ok) {\n const responseText = isTextResponse(response)\n ? await response.text()\n : undefined;\n\n await this.#appendFetchLog({\n attempt,\n durationMs: Date.now() - startedAt,\n response,\n ...(responseText === undefined ? {} : { responseText }),\n startedAt,\n url,\n });\n throw new WikimediaRequestError(url, response.status, retryAfterMs);\n }\n\n await this.#appendFetchLog({\n attempt,\n durationMs: Date.now() - startedAt,\n response,\n startedAt,\n url,\n });\n\n return asRecord(await response.json());\n }\n\n async #appendFetchLog(\n entry: Parameters<WikipageFetchLog[\"append\"]>[0],\n ): Promise<void> {\n try {\n await this.#requestLog.append(entry);\n } catch (error) {\n getLogger({ component: \"wikipage\" }).warn(\n `Failed to write wikipage fetch log entry: ${formatError(error)}`,\n );\n }\n }\n}\n\nfunction isTextResponse(response: Response): boolean {\n const contentType = response.headers.get(\"content-type\");\n\n if (contentType === null) {\n return false;\n }\n\n return /(?:json|text|xml|javascript|html)/iu.test(contentType);\n}\n\nclass WikimediaRequestError extends Error {\n public readonly retryAfterMs: number | undefined;\n public readonly status: number;\n public readonly url: URL;\n\n public constructor(\n url: URL,\n status: number,\n retryAfterMs: number | undefined,\n ) {\n super(`Wikimedia request failed with ${status}: ${url.toString()}`);\n this.retryAfterMs = retryAfterMs;\n this.status = status;\n this.url = url;\n }\n}\n\nexport function replaceTitleUriWithQidUri(\n text: string,\n titleToQid: ReadonlyMap<string, string>,\n): string {\n return text.replace(\n /\\[\\[([^\\]|]+)\\|wikigraph-title:\\/\\/([^\\]\\s]+)\\]\\]/gu,\n (_match: string, label: string, encodedTitle: string) => {\n const title = decodeURIComponent(encodedTitle);\n const qid = titleToQid.get(title);\n\n return qid === undefined ? label : `[[${label}|wikg://qid=${qid}]]`;\n },\n );\n}\n\nfunction renderDisambiguationHtml(html: string | undefined): {\n readonly linkedTitles: readonly string[];\n readonly text: string;\n} {\n if (html === undefined || html.trim() === \"\") {\n return {\n linkedTitles: [],\n text: \"\",\n };\n }\n\n const linkedTitles = new Set<string>();\n const document = parseDocument(html);\n const text = renderNodes(DomUtils.getChildren(document), {\n linkedTitles,\n listDepth: 0,\n })\n .replace(/[ \\t]+\\n/gu, \"\\n\")\n .replace(/\\n{3,}/gu, \"\\n\\n\")\n .trim();\n\n return {\n linkedTitles: [...linkedTitles],\n text,\n };\n}\n\nfunction renderNodes(\n nodes: readonly unknown[],\n context: {\n readonly linkedTitles: Set<string>;\n readonly listDepth: number;\n },\n): string {\n return nodes.map((node) => renderNode(node, context)).join(\"\");\n}\n\nfunction renderNode(\n node: unknown,\n context: {\n readonly linkedTitles: Set<string>;\n readonly listDepth: number;\n },\n): string {\n const record = asRecord(node);\n const nodeType = getString(record.type);\n\n if (nodeType === \"text\") {\n return normalizeInlineText(getString(record.data) ?? \"\");\n }\n if (nodeType !== \"tag\" && nodeType !== \"script\" && nodeType !== \"style\") {\n return \"\";\n }\n\n const element = node as HtmlElement;\n if (shouldSkipElement(element)) {\n return \"\";\n }\n\n const name = element.name.toLowerCase();\n\n if (name === \"a\") {\n return renderLink(element, context);\n }\n if (/^h[1-6]$/u.test(name)) {\n const level = Math.min(6, Math.max(1, Number(name.slice(1))));\n const marker = \"=\".repeat(level);\n const heading = renderNodes(element.children ?? [], context).trim();\n\n return heading === \"\" ? \"\" : `\\n${marker} ${heading} ${marker}\\n`;\n }\n if (name === \"li\") {\n const indent = \" \".repeat(Math.max(0, context.listDepth - 1));\n const content = renderNodes(element.children ?? [], {\n ...context,\n listDepth: context.listDepth + 1,\n }).trim();\n\n return content === \"\" ? \"\" : `\\n${indent}* ${content}`;\n }\n if (name === \"ul\" || name === \"ol\") {\n return `${renderNodes(element.children ?? [], context)}\\n`;\n }\n if (isBlockElement(name)) {\n const content = renderNodes(element.children ?? [], context).trim();\n\n return content === \"\" ? \"\" : `\\n${content}\\n`;\n }\n\n return renderNodes(element.children ?? [], context);\n}\n\nfunction renderLink(\n node: HtmlElement,\n context: {\n readonly linkedTitles: Set<string>;\n readonly listDepth: number;\n },\n): string {\n const content = renderNodes(node.children ?? [], context).trim();\n const title = extractWikiLinkTitle(node);\n\n if (title === undefined) {\n return content;\n }\n\n context.linkedTitles.add(title);\n\n return `[[${content === \"\" ? title : content}|${TITLE_URI_PREFIX}${encodeURIComponent(title)}]]`;\n}\n\nfunction extractWikiLinkTitle(node: HtmlElement): string | undefined {\n const title = node.attribs.title;\n const href = node.attribs.href;\n\n if (title !== undefined && title !== \"\" && !title.includes(\":\")) {\n return title;\n }\n if (href === undefined || !href.startsWith(\"/wiki/\")) {\n return undefined;\n }\n\n const decoded = decodeURIComponent(href.slice(\"/wiki/\".length)).replaceAll(\n \"_\",\n \" \",\n );\n\n return decoded === \"\" || decoded.includes(\":\") ? undefined : decoded;\n}\n\nfunction shouldSkipElement(node: HtmlElement): boolean {\n const name = node.name.toLowerCase();\n\n if ([\"script\", \"style\", \"table\", \"sup\"].includes(name)) {\n return true;\n }\n\n const className = node.attribs.class ?? \"\";\n\n return [\n \"catlinks\",\n \"metadata\",\n \"mw-editsection\",\n \"mw-empty-elt\",\n \"navbox\",\n \"noprint\",\n \"reference\",\n \"reflist\",\n \"shortdescription\",\n \"toc\",\n ].some((item) => className.split(/\\s+/u).includes(item));\n}\n\nfunction isBlockElement(name: string): boolean {\n return [\"blockquote\", \"br\", \"dd\", \"div\", \"dl\", \"dt\", \"p\", \"section\"].includes(\n name,\n );\n}\n\nfunction normalizeInlineText(value: string): string {\n return value.replace(/\\s+/gu, \" \");\n}\n\nfunction listWikidataLanguages(language: string): string {\n return [...new Set([language, \"zh\", \"en\"])].join(\"|\");\n}\n\nfunction pickLocalizedValue(\n values: Record<string, unknown>,\n language: string,\n): string | undefined {\n for (const candidate of [language, \"zh\", \"en\"]) {\n const value = getNestedString(values, [candidate, \"value\"]);\n\n if (value !== undefined) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction wikiApiBaseURL(wiki: SupportedWiki): string {\n return wiki === \"zhwiki\"\n ? \"https://zh.wikipedia.org/\"\n : \"https://en.wikipedia.org/\";\n}\n\nfunction normalizeWiki(value: string): SupportedWiki | undefined {\n return value === \"zhwiki\" || value === \"enwiki\" ? value : undefined;\n}\n\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof WikimediaRequestError) {\n return (\n error.status === 429 ||\n error.status === 500 ||\n error.status === 502 ||\n error.status === 503 ||\n error.status === 504\n );\n }\n\n return error instanceof TypeError;\n}\n\nfunction getRetryDelayMs(\n error: unknown,\n attempt: number,\n baseDelayMs: number,\n): number {\n if (\n error instanceof WikimediaRequestError &&\n error.retryAfterMs !== undefined\n ) {\n return error.retryAfterMs;\n }\n\n if (baseDelayMs <= 0) {\n return 0;\n }\n\n const exponentialDelayMs = baseDelayMs * 2 ** attempt;\n const jitterMs = Math.floor(Math.random() * Math.min(baseDelayMs, 250));\n\n return exponentialDelayMs + jitterMs;\n}\n\nasync function delay(ms: number): Promise<void> {\n if (ms <= 0) {\n return;\n }\n\n await new Promise<void>((resolveDelay) => {\n setTimeout(resolveDelay, ms);\n });\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction asArray(value: unknown): readonly unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction getNestedString(\n value: Record<string, unknown>,\n path: readonly string[],\n): string | undefined {\n let current: unknown = value;\n\n for (const part of path) {\n current = asRecord(current)[part];\n }\n\n return getString(current);\n}\n"],"mappings":"AAAA,SAAS,UAAU,qBAAqB;AAExC,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAE5B,SAAS,aAAa,yBAAyB;AAsD/C,MAAM,kBAA4C,CAAC,UAAU,QAAQ;AACrE,MAAM,mBAAmB;AAQlB,MAAM,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEF,YAAY,SAAiC;AAClD,SAAK,SAAS,QAAQ,SAAS;AAC/B,SAAK,YAAY,QAAQ;AACzB,SAAK,cAAc,QAAQ;AAC3B,SAAK,QAAQ,QAAQ;AACrB,SAAK,aAAa,QAAQ;AAC1B,SAAK,oBAAoB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,gBAAgB,CAAC;AACzE,SAAK,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,UAAU,CAAC;AAC7D,SAAK,WAAW,IAAI,YAAY;AAAA,MAC9B,aAAa,QAAQ;AAAA,MACrB,sBAAsB,QAAQ;AAAA,IAChC,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,YACX,MACkD;AAClD,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,oBAAI,IAAI;AAAA,IACjB;AAEA,UAAM,MAAM,IAAI,IAAI,oCAAoC;AACxD,QAAI,aAAa,IAAI,UAAU,eAAe;AAC9C,QAAI,aAAa,IAAI,OAAO,KAAK,KAAK,GAAG,CAAC;AAC1C,QAAI,aAAa,IAAI,SAAS,+BAA+B;AAC7D,QAAI,aAAa,IAAI,aAAa,sBAAsB,KAAK,SAAS,CAAC;AACvE,QAAI,aAAa,IAAI,cAAc,gBAAgB,KAAK,GAAG,CAAC;AAC5D,QAAI,aAAa,IAAI,UAAU,MAAM;AACrC,QAAI,aAAa,IAAI,iBAAiB,GAAG;AAEzC,UAAM,OAAO,MAAM,KAAK,WAAW,GAAG;AACtC,UAAM,WAAW,SAAS,KAAK,QAAQ;AACvC,UAAM,UAAU,oBAAI,IAAgC;AAEpD,eAAW,OAAO,MAAM;AACtB,YAAM,SAAS,SAAS,SAAS,GAAG,CAAC;AACrC,YAAM,SAAS,SAAS,OAAO,MAAM;AACrC,YAAM,eAAe,SAAS,OAAO,YAAY;AAEjD,cAAQ,IAAI,KAAK;AAAA,QACf,GAAI,mBAAmB,QAAQ,KAAK,SAAS,MAAM,SAC/C,CAAC,IACD,EAAE,OAAO,mBAAmB,QAAQ,KAAK,SAAS,EAAG;AAAA,QACzD,GAAI,mBAAmB,cAAc,KAAK,SAAS,MAAM,SACrD,CAAC,IACD,EAAE,aAAa,mBAAmB,cAAc,KAAK,SAAS,EAAG;AAAA,QACrE;AAAA,QACA,WAAW,gBAAgB,QAAQ,CAAC,SAAS;AAC3C,gBAAM,QAAQ,gBAAgB,QAAQ,CAAC,aAAa,MAAM,OAAO,CAAC;AAElE,iBAAO,UAAU,SAAY,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,CAAC;AAAA,QACpD,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,iBACX,QACA,OAAsB,cAAc,KAAK,KAAK,KAAK,UACP;AAC5C,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO,oBAAI,IAAI;AAAA,IACjB;AAEA,UAAM,MAAM,IAAI,IAAI,GAAG,eAAe,IAAI,CAAC,WAAW;AACtD,QAAI,aAAa,IAAI,UAAU,OAAO;AACtC,QAAI,aAAa,IAAI,UAAU,OAAO,KAAK,GAAG,CAAC;AAC/C,QAAI,aAAa,IAAI,QAAQ,WAAW;AACxC,QAAI,aAAa,IAAI,UAAU,8BAA8B;AAC7D,QAAI,aAAa,IAAI,UAAU,MAAM;AACrC,QAAI,aAAa,IAAI,iBAAiB,GAAG;AAEzC,UAAM,OAAO,MAAM,KAAK,WAAW,GAAG;AACtC,UAAM,QAAQ,QAAQ,SAAS,SAAS,KAAK,KAAK,EAAE,KAAK,CAAC;AAC1D,UAAM,UAAU,oBAAI,IAA0B;AAE9C,eAAW,aAAa,OAAO;AAC7B,YAAM,OAAO,SAAS,SAAS;AAC/B,YAAM,QAAQ,UAAU,KAAK,KAAK;AAElC,UAAI,UAAU,QAAW;AACvB;AAAA,MACF;AAEA,cAAQ,IAAI,OAAO;AAAA,QACjB,kBAAkB,SAAS,KAAK,SAAS,EAAE,mBAAmB;AAAA,QAC9D,GAAI,UAAU,KAAK,MAAM,MAAM,SAC3B,CAAC,IACD,EAAE,QAAQ,UAAU,KAAK,MAAM,EAAG;AAAA,QACtC;AAAA,QACA;AAAA,QACA,GAAI,UAAU,SAAS,KAAK,SAAS,EAAE,aAAa,MAAM,SACtD,CAAC,IACD;AAAA,UACE,cAAc,UAAU,SAAS,KAAK,SAAS,EAAE,aAAa;AAAA,QAChE;AAAA,MACN,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,wBACX,OACA,MACmC;AACnC,UAAM,MAAM,IAAI,IAAI,GAAG,eAAe,IAAI,CAAC,WAAW;AACtD,QAAI,aAAa,IAAI,UAAU,OAAO;AACtC,QAAI,aAAa,IAAI,QAAQ,KAAK;AAClC,QAAI,aAAa,IAAI,QAAQ,iBAAiB;AAC9C,QAAI,aAAa,IAAI,UAAU,MAAM;AACrC,QAAI,aAAa,IAAI,iBAAiB,GAAG;AAEzC,UAAM,OAAO,MAAM,KAAK,WAAW,GAAG;AACtC,UAAM,QAAQ,SAAS,KAAK,KAAK;AACjC,UAAM,WAAW,yBAAyB,gBAAgB,OAAO,CAAC,MAAM,CAAC,CAAC;AAE1E,WAAO;AAAA,MACL,cAAc,SAAS;AAAA,MACvB,GAAI,UAAU,MAAM,MAAM,MAAM,SAC5B,CAAC,IACD,EAAE,QAAQ,UAAU,MAAM,MAAM,EAAG;AAAA,MACvC,MAAM,SAAS;AAAA,MACf,OAAO,UAAU,MAAM,KAAK,KAAK;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,KAA4C;AAC3D,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,KAAK,aAAa,WAAW,GAAG;AAC/D,UAAI;AACF,eAAO,MAAM,KAAK,SAAS;AAAA,UACzB,YAAY,MAAM,KAAK,eAAe,KAAK,UAAU,CAAC;AAAA,QACxD;AAAA,MACF,SAAS,OAAO;AACd,oBAAY;AAEZ,YAAI,CAAC,iBAAiB,KAAK,KAAK,WAAW,KAAK,aAAa;AAC3D,eAAK,YAAY,WAAW;AAC5B,gBAAM;AAAA,QACR;AAEA,cAAM,MAAM,gBAAgB,OAAO,SAAS,KAAK,iBAAiB,CAAC;AAAA,MACrE;AAAA,IACF;AAEA,UAAM,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,SAAS,CAAC;AAAA,EAC5E;AAAA,EAEA,MAAM,eACJ,KACA,SACkC;AAClC,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI;AAEJ,QAAI;AACF,iBAAW,MAAM,KAAK;AAAA,QACpB;AAAA,QACA,KAAK,eAAe,SAChB,SACA;AAAA,UACE,SAAS;AAAA,YACP,cAAc,KAAK;AAAA,UACrB;AAAA,QACF;AAAA,MACN;AAAA,IACF,SAAS,OAAO;AACd,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,YAAY,KAAK,IAAI,IAAI;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM;AAAA,IACR;AAEA,UAAM,eAAe,kBAAkB,SAAS,QAAQ,IAAI,aAAa,CAAC;AAE1E,QAAI,iBAAiB,QAAW;AAC9B,WAAK,SAAS,SAAS,YAAY;AAAA,IACrC;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,eAAe,eAAe,QAAQ,IACxC,MAAM,SAAS,KAAK,IACpB;AAEJ,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,YAAY,KAAK,IAAI,IAAI;AAAA,QACzB;AAAA,QACA,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,QACrD;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,IAAI,sBAAsB,KAAK,SAAS,QAAQ,YAAY;AAAA,IACpE;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA,YAAY,KAAK,IAAI,IAAI;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,SAAS,MAAM,SAAS,KAAK,CAAC;AAAA,EACvC;AAAA,EAEA,MAAM,gBACJ,OACe;AACf,QAAI;AACF,YAAM,KAAK,YAAY,OAAO,KAAK;AAAA,IACrC,SAAS,OAAO;AACd,gBAAU,EAAE,WAAW,WAAW,CAAC,EAAE;AAAA,QACnC,6CAA6C,YAAY,KAAK,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,UAA6B;AACnD,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AAEvD,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA,EACT;AAEA,SAAO,sCAAsC,KAAK,WAAW;AAC/D;AAEA,MAAM,8BAA8B,MAAM;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACL,KACA,QACA,cACA;AACA,UAAM,iCAAiC,MAAM,KAAK,IAAI,SAAS,CAAC,EAAE;AAClE,SAAK,eAAe;AACpB,SAAK,SAAS;AACd,SAAK,MAAM;AAAA,EACb;AACF;AAEO,SAAS,0BACd,MACA,YACQ;AACR,SAAO,KAAK;AAAA,IACV;AAAA,IACA,CAAC,QAAgB,OAAe,iBAAyB;AACvD,YAAM,QAAQ,mBAAmB,YAAY;AAC7C,YAAM,MAAM,WAAW,IAAI,KAAK;AAEhC,aAAO,QAAQ,SAAY,QAAQ,KAAK,KAAK,eAAe,GAAG;AAAA,IACjE;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,MAGhC;AACA,MAAI,SAAS,UAAa,KAAK,KAAK,MAAM,IAAI;AAC5C,WAAO;AAAA,MACL,cAAc,CAAC;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,eAAe,oBAAI,IAAY;AACrC,QAAM,WAAW,cAAc,IAAI;AACnC,QAAM,OAAO,YAAY,SAAS,YAAY,QAAQ,GAAG;AAAA,IACvD;AAAA,IACA,WAAW;AAAA,EACb,CAAC,EACE,QAAQ,cAAc,IAAI,EAC1B,QAAQ,YAAY,MAAM,EAC1B,KAAK;AAER,SAAO;AAAA,IACL,cAAc,CAAC,GAAG,YAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEA,SAAS,YACP,OACA,SAIQ;AACR,SAAO,MAAM,IAAI,CAAC,SAAS,WAAW,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE;AAC/D;AAEA,SAAS,WACP,MACA,SAIQ;AACR,QAAM,SAAS,SAAS,IAAI;AAC5B,QAAM,WAAW,UAAU,OAAO,IAAI;AAEtC,MAAI,aAAa,QAAQ;AACvB,WAAO,oBAAoB,UAAU,OAAO,IAAI,KAAK,EAAE;AAAA,EACzD;AACA,MAAI,aAAa,SAAS,aAAa,YAAY,aAAa,SAAS;AACvE,WAAO;AAAA,EACT;AAEA,QAAM,UAAU;AAChB,MAAI,kBAAkB,OAAO,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,QAAQ,KAAK,YAAY;AAEtC,MAAI,SAAS,KAAK;AAChB,WAAO,WAAW,SAAS,OAAO;AAAA,EACpC;AACA,MAAI,YAAY,KAAK,IAAI,GAAG;AAC1B,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,UAAM,SAAS,IAAI,OAAO,KAAK;AAC/B,UAAM,UAAU,YAAY,QAAQ,YAAY,CAAC,GAAG,OAAO,EAAE,KAAK;AAElE,WAAO,YAAY,KAAK,KAAK;AAAA,EAAK,MAAM,IAAI,OAAO,IAAI,MAAM;AAAA;AAAA,EAC/D;AACA,MAAI,SAAS,MAAM;AACjB,UAAM,SAAS,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,YAAY,CAAC,CAAC;AAC7D,UAAM,UAAU,YAAY,QAAQ,YAAY,CAAC,GAAG;AAAA,MAClD,GAAG;AAAA,MACH,WAAW,QAAQ,YAAY;AAAA,IACjC,CAAC,EAAE,KAAK;AAER,WAAO,YAAY,KAAK,KAAK;AAAA,EAAK,MAAM,KAAK,OAAO;AAAA,EACtD;AACA,MAAI,SAAS,QAAQ,SAAS,MAAM;AAClC,WAAO,GAAG,YAAY,QAAQ,YAAY,CAAC,GAAG,OAAO,CAAC;AAAA;AAAA,EACxD;AACA,MAAI,eAAe,IAAI,GAAG;AACxB,UAAM,UAAU,YAAY,QAAQ,YAAY,CAAC,GAAG,OAAO,EAAE,KAAK;AAElE,WAAO,YAAY,KAAK,KAAK;AAAA,EAAK,OAAO;AAAA;AAAA,EAC3C;AAEA,SAAO,YAAY,QAAQ,YAAY,CAAC,GAAG,OAAO;AACpD;AAEA,SAAS,WACP,MACA,SAIQ;AACR,QAAM,UAAU,YAAY,KAAK,YAAY,CAAC,GAAG,OAAO,EAAE,KAAK;AAC/D,QAAM,QAAQ,qBAAqB,IAAI;AAEvC,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,UAAQ,aAAa,IAAI,KAAK;AAE9B,SAAO,KAAK,YAAY,KAAK,QAAQ,OAAO,IAAI,gBAAgB,GAAG,mBAAmB,KAAK,CAAC;AAC9F;AAEA,SAAS,qBAAqB,MAAuC;AACnE,QAAM,QAAQ,KAAK,QAAQ;AAC3B,QAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,UAAU,UAAa,UAAU,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG;AAC/D,WAAO;AAAA,EACT;AACA,MAAI,SAAS,UAAa,CAAC,KAAK,WAAW,QAAQ,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,mBAAmB,KAAK,MAAM,SAAS,MAAM,CAAC,EAAE;AAAA,IAC9D;AAAA,IACA;AAAA,EACF;AAEA,SAAO,YAAY,MAAM,QAAQ,SAAS,GAAG,IAAI,SAAY;AAC/D;AAEA,SAAS,kBAAkB,MAA4B;AACrD,QAAM,OAAO,KAAK,KAAK,YAAY;AAEnC,MAAI,CAAC,UAAU,SAAS,SAAS,KAAK,EAAE,SAAS,IAAI,GAAG;AACtD,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,KAAK,QAAQ,SAAS;AAExC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,CAAC,SAAS,UAAU,MAAM,MAAM,EAAE,SAAS,IAAI,CAAC;AACzD;AAEA,SAAS,eAAe,MAAuB;AAC7C,SAAO,CAAC,cAAc,MAAM,MAAM,OAAO,MAAM,MAAM,KAAK,SAAS,EAAE;AAAA,IACnE;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,OAAuB;AAClD,SAAO,MAAM,QAAQ,SAAS,GAAG;AACnC;AAEA,SAAS,sBAAsB,UAA0B;AACvD,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,GAAG;AACtD;AAEA,SAAS,mBACP,QACA,UACoB;AACpB,aAAW,aAAa,CAAC,UAAU,MAAM,IAAI,GAAG;AAC9C,UAAM,QAAQ,gBAAgB,QAAQ,CAAC,WAAW,OAAO,CAAC;AAE1D,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,MAA6B;AACnD,SAAO,SAAS,WACZ,8BACA;AACN;AAEA,SAAS,cAAc,OAA0C;AAC/D,SAAO,UAAU,YAAY,UAAU,WAAW,QAAQ;AAC5D;AAEA,SAAS,iBAAiB,OAAyB;AACjD,MAAI,iBAAiB,uBAAuB;AAC1C,WACE,MAAM,WAAW,OACjB,MAAM,WAAW,OACjB,MAAM,WAAW,OACjB,MAAM,WAAW,OACjB,MAAM,WAAW;AAAA,EAErB;AAEA,SAAO,iBAAiB;AAC1B;AAEA,SAAS,gBACP,OACA,SACA,aACQ;AACR,MACE,iBAAiB,yBACjB,MAAM,iBAAiB,QACvB;AACA,WAAO,MAAM;AAAA,EACf;AAEA,MAAI,eAAe,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,cAAc,KAAK;AAC9C,QAAM,WAAW,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,aAAa,GAAG,CAAC;AAEtE,SAAO,qBAAqB;AAC9B;AAEA,eAAe,MAAM,IAA2B;AAC9C,MAAI,MAAM,GAAG;AACX;AAAA,EACF;AAEA,QAAM,IAAI,QAAc,CAAC,iBAAiB;AACxC,eAAW,cAAc,EAAE;AAAA,EAC7B,CAAC;AACH;AAEA,SAAS,SAAS,OAAyC;AACzD,SAAO,OAAO,UAAU,YAAY,UAAU,OACzC,QACD,CAAC;AACP;AAEA,SAAS,QAAQ,OAAoC;AACnD,SAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AACzC;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAC7D;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IACrD,QACA;AACN;AAEA,SAAS,gBACP,OACA,MACoB;AACpB,MAAI,UAAmB;AAEvB,aAAW,QAAQ,MAAM;AACvB,cAAU,SAAS,OAAO,EAAE,IAAI;AAAA,EAClC;AAEA,SAAO,UAAU,OAAO;AAC1B;","names":[]}
|