@wdprlib/parser 3.1.2 → 4.0.0
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/dist/index.cjs +10456 -8230
- package/dist/index.d.cts +313 -337
- package/dist/index.d.ts +313 -337
- package/dist/index.js +10460 -8234
- package/package.json +5 -3
- package/src/index.ts +170 -0
- package/src/lexer/anchor.ts +48 -0
- package/src/lexer/index.ts +21 -0
- package/src/lexer/lexer.ts +201 -0
- package/src/lexer/options.ts +19 -0
- package/src/lexer/punctuation.ts +70 -0
- package/src/lexer/quoted-string.ts +16 -0
- package/src/lexer/runs.ts +85 -0
- package/src/lexer/spacing-actions.ts +24 -0
- package/src/lexer/state.ts +103 -0
- package/src/lexer/syntax-actions.ts +80 -0
- package/src/lexer/text-actions.ts +41 -0
- package/src/lexer/token-actions.ts +136 -0
- package/src/lexer/token-factory.ts +62 -0
- package/src/lexer/tokenize.ts +18 -0
- package/src/lexer/tokens.ts +141 -0
- package/src/parser/constants.ts +175 -0
- package/src/parser/depth/index.ts +111 -0
- package/src/parser/depth/stack.ts +82 -0
- package/src/parser/index.ts +18 -0
- package/src/parser/parse/block.ts +42 -0
- package/src/parser/parse/context.ts +26 -0
- package/src/parser/parse/footnotes.ts +25 -0
- package/src/parser/parse/index.ts +42 -0
- package/src/parser/parse/options.ts +34 -0
- package/src/parser/parse/parser.ts +79 -0
- package/src/parser/parse/plain-non-ascii.ts +129 -0
- package/src/parser/parse/result.ts +57 -0
- package/src/parser/parse/source.ts +11 -0
- package/src/parser/postprocess/divAdjacentParagraph.ts +76 -0
- package/src/parser/postprocess/index.ts +15 -0
- package/src/parser/postprocess/spanStrip/clean-element.ts +168 -0
- package/src/parser/postprocess/spanStrip/cleanup.ts +25 -0
- package/src/parser/postprocess/spanStrip/empty-spans.ts +36 -0
- package/src/parser/postprocess/spanStrip/escaped.ts +78 -0
- package/src/parser/postprocess/spanStrip/factory.ts +23 -0
- package/src/parser/postprocess/spanStrip/index.ts +8 -0
- package/src/parser/postprocess/spanStrip/merge.ts +117 -0
- package/src/parser/postprocess/spanStrip/predicates.ts +59 -0
- package/src/parser/postprocess/spanStrip/split.ts +67 -0
- package/src/parser/preprocess/expr/chars.ts +15 -0
- package/src/parser/preprocess/expr/evaluate.ts +22 -0
- package/src/parser/preprocess/expr/index.ts +45 -0
- package/src/parser/preprocess/expr/kind.ts +19 -0
- package/src/parser/preprocess/expr/parse.ts +103 -0
- package/src/parser/preprocess/expr/scan.ts +34 -0
- package/src/parser/preprocess/expr/types.ts +14 -0
- package/src/parser/preprocess/index.ts +38 -0
- package/src/parser/preprocess/typography.ts +132 -0
- package/src/parser/preprocess/utils/bracket-depths.ts +98 -0
- package/src/parser/preprocess/utils/index.ts +13 -0
- package/src/parser/preprocess/utils/raw-regions.ts +153 -0
- package/src/parser/preprocess/whitespace/detection.ts +39 -0
- package/src/parser/preprocess/whitespace/index.ts +79 -0
- package/src/parser/preprocess/whitespace/leading-spaces.ts +11 -0
- package/src/parser/preprocess/whitespace/patterns.ts +23 -0
- package/src/parser/rules/block/align/body.ts +46 -0
- package/src/parser/rules/block/align/element.ts +13 -0
- package/src/parser/rules/block/align/index.ts +90 -0
- package/src/parser/rules/block/align/syntax.ts +113 -0
- package/src/parser/rules/block/bibliography/body.ts +81 -0
- package/src/parser/rules/block/bibliography/entries.ts +49 -0
- package/src/parser/rules/block/bibliography/entry-content.ts +73 -0
- package/src/parser/rules/block/bibliography/entry-key.ts +83 -0
- package/src/parser/rules/block/bibliography/index.ts +90 -0
- package/src/parser/rules/block/bibliography/open.ts +53 -0
- package/src/parser/rules/block/block-list/bare-content.ts +105 -0
- package/src/parser/rules/block/block-list/bare-paragraph.ts +60 -0
- package/src/parser/rules/block/block-list/index.ts +51 -0
- package/src/parser/rules/block/block-list/item-content.ts +132 -0
- package/src/parser/rules/block/block-list/li-content.ts +107 -0
- package/src/parser/rules/block/block-list/li-item.ts +77 -0
- package/src/parser/rules/block/block-list/list-block.ts +100 -0
- package/src/parser/rules/block/block-list/open.ts +51 -0
- package/src/parser/rules/block/block-list/tags.ts +50 -0
- package/src/parser/rules/block/blockquote/build.ts +62 -0
- package/src/parser/rules/block/blockquote/index.ts +80 -0
- package/src/parser/rules/block/blockquote/line.ts +79 -0
- package/src/parser/rules/block/blockquote/lines.ts +39 -0
- package/src/parser/rules/block/center/index.ts +72 -0
- package/src/parser/rules/block/center/open.ts +27 -0
- package/src/parser/rules/block/clear-float/index.ts +51 -0
- package/src/parser/rules/block/clear-float/syntax.ts +43 -0
- package/src/parser/rules/block/code/attributes.ts +30 -0
- package/src/parser/rules/block/code/content.ts +57 -0
- package/src/parser/rules/block/code/index.ts +100 -0
- package/src/parser/rules/block/collapsible/attributes.ts +95 -0
- package/src/parser/rules/block/collapsible/body.ts +69 -0
- package/src/parser/rules/block/collapsible/index.ts +117 -0
- package/src/parser/rules/block/collapsible/open.ts +51 -0
- package/src/parser/rules/block/collapsible/orphans.ts +31 -0
- package/src/parser/rules/block/collapsible/tags.ts +17 -0
- package/src/parser/rules/block/comment/consume.ts +37 -0
- package/src/parser/rules/block/comment/index.ts +47 -0
- package/src/parser/rules/block/content-separator/index.ts +49 -0
- package/src/parser/rules/block/content-separator/syntax.ts +33 -0
- package/src/parser/rules/block/definition-list/collect.ts +40 -0
- package/src/parser/rules/block/definition-list/index.ts +63 -0
- package/src/parser/rules/block/definition-list/item-key.ts +95 -0
- package/src/parser/rules/block/definition-list/item-value.ts +56 -0
- package/src/parser/rules/block/definition-list/items.ts +54 -0
- package/src/parser/rules/block/div/body.ts +41 -0
- package/src/parser/rules/block/div/close.ts +41 -0
- package/src/parser/rules/block/div/failed.ts +117 -0
- package/src/parser/rules/block/div/index.ts +112 -0
- package/src/parser/rules/block/div/nesting.ts +37 -0
- package/src/parser/rules/block/div/open.ts +59 -0
- package/src/parser/rules/block/div/paragraph-strip.ts +44 -0
- package/src/parser/rules/block/embed-block/content.ts +53 -0
- package/src/parser/rules/block/embed-block/index.ts +91 -0
- package/src/parser/rules/block/embed-block/open.ts +52 -0
- package/src/parser/rules/block/embed-block/tags.ts +5 -0
- package/src/parser/rules/block/footnoteblock/attributes.ts +73 -0
- package/src/parser/rules/block/footnoteblock/index.ts +82 -0
- package/src/parser/rules/block/footnoteblock/open.ts +53 -0
- package/src/parser/rules/block/heading/index.ts +87 -0
- package/src/parser/rules/block/heading/open.ts +50 -0
- package/src/parser/rules/block/heading/toc-text.ts +26 -0
- package/src/parser/rules/block/horizontal-rule/index.ts +44 -0
- package/src/parser/rules/block/horizontal-rule/syntax.ts +21 -0
- package/src/parser/rules/block/html/body.ts +114 -0
- package/src/parser/rules/block/html/diagnostics.ts +11 -0
- package/src/parser/rules/block/html/index.ts +95 -0
- package/src/parser/rules/block/html/open.ts +36 -0
- package/src/parser/rules/block/iframe/attributes.ts +106 -0
- package/src/parser/rules/block/iframe/index.ts +73 -0
- package/src/parser/rules/block/iframe/open.ts +58 -0
- package/src/parser/rules/block/iframe/source.ts +24 -0
- package/src/parser/rules/block/iframe/url.ts +38 -0
- package/src/parser/rules/block/iftags/body.ts +48 -0
- package/src/parser/rules/block/iftags/condition.ts +24 -0
- package/src/parser/rules/block/iftags/index.ts +108 -0
- package/src/parser/rules/block/include/arguments.ts +48 -0
- package/src/parser/rules/block/include/index.ts +75 -0
- package/src/parser/rules/block/include/location.ts +24 -0
- package/src/parser/rules/block/include/variables.ts +37 -0
- package/src/parser/rules/block/index.ts +127 -0
- package/src/parser/rules/block/list/index.ts +73 -0
- package/src/parser/rules/block/list/line.ts +77 -0
- package/src/parser/rules/block/list/native.ts +89 -0
- package/src/parser/rules/block/math/content.ts +54 -0
- package/src/parser/rules/block/math/index.ts +106 -0
- package/src/parser/rules/block/math/name.ts +35 -0
- package/src/parser/rules/block/module/backlinks/index.ts +31 -0
- package/src/parser/rules/block/module/backlinks/types.ts +21 -0
- package/src/parser/rules/block/module/body.ts +92 -0
- package/src/parser/rules/block/module/categories/index.ts +34 -0
- package/src/parser/rules/block/module/categories/types.ts +21 -0
- package/src/parser/rules/block/module/css/index.ts +37 -0
- package/src/parser/rules/block/module/element.ts +33 -0
- package/src/parser/rules/block/module/iftags/condition.ts +109 -0
- package/src/parser/rules/block/module/iftags/index.ts +26 -0
- package/src/parser/rules/block/module/iftags/preprocess.ts +140 -0
- package/src/parser/rules/block/module/iftags/resolve.ts +73 -0
- package/src/parser/rules/block/module/iftags/types.ts +63 -0
- package/src/parser/rules/block/module/include/directive.ts +91 -0
- package/src/parser/rules/block/module/include/index.ts +29 -0
- package/src/parser/rules/block/module/include/references.ts +42 -0
- package/src/parser/rules/block/module/include/resolve/cache.ts +44 -0
- package/src/parser/rules/block/module/include/resolve/index.ts +106 -0
- package/src/parser/rules/block/module/include/resolve/iterate.ts +202 -0
- package/src/parser/rules/block/module/include/resolve/replace.ts +31 -0
- package/src/parser/rules/block/module/include/resolve/types.ts +105 -0
- package/src/parser/rules/block/module/include/scanner.ts +121 -0
- package/src/parser/rules/block/module/index.ts +134 -0
- package/src/parser/rules/block/module/join/index.ts +34 -0
- package/src/parser/rules/block/module/join/types.ts +23 -0
- package/src/parser/rules/block/module/listpages/compiler.ts +73 -0
- package/src/parser/rules/block/module/listpages/extract.ts +76 -0
- package/src/parser/rules/block/module/listpages/extraction/listpages.ts +42 -0
- package/src/parser/rules/block/module/listpages/extraction/listusers.ts +30 -0
- package/src/parser/rules/block/module/listpages/extraction/query.ts +51 -0
- package/src/parser/rules/block/module/listpages/extraction/result.ts +18 -0
- package/src/parser/rules/block/module/listpages/extraction/template.ts +96 -0
- package/src/parser/rules/block/module/listpages/extraction/variables.ts +58 -0
- package/src/parser/rules/block/module/listpages/index.ts +83 -0
- package/src/parser/rules/block/module/listpages/normalization/date-selector.ts +53 -0
- package/src/parser/rules/block/module/listpages/normalization/numeric-selector.ts +32 -0
- package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +82 -0
- package/src/parser/rules/block/module/listpages/normalization/selectors.ts +2 -0
- package/src/parser/rules/block/module/listpages/normalization/tags-category.ts +86 -0
- package/src/parser/rules/block/module/listpages/normalize.ts +74 -0
- package/src/parser/rules/block/module/listpages/parser.ts +106 -0
- package/src/parser/rules/block/module/listpages/resolution/items.ts +43 -0
- package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +42 -0
- package/src/parser/rules/block/module/listpages/resolve.ts +60 -0
- package/src/parser/rules/block/module/listpages/template/format/content.ts +41 -0
- package/src/parser/rules/block/module/listpages/template/format/date.ts +116 -0
- package/src/parser/rules/block/module/listpages/template/format/index.ts +4 -0
- package/src/parser/rules/block/module/listpages/template/format/tags.ts +7 -0
- package/src/parser/rules/block/module/listpages/template/format/user.ts +9 -0
- package/src/parser/rules/block/module/listpages/template/getters/index.ts +36 -0
- package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +60 -0
- package/src/parser/rules/block/module/listpages/template/getters/simple.ts +65 -0
- package/src/parser/rules/block/module/listpages/template/getters/types.ts +3 -0
- package/src/parser/rules/block/module/listpages/template/syntax.ts +97 -0
- package/src/parser/rules/block/module/listpages/types/data-fetcher.ts +15 -0
- package/src/parser/rules/block/module/listpages/types/data-requirements.ts +52 -0
- package/src/parser/rules/block/module/listpages/types/external-data.ts +77 -0
- package/src/parser/rules/block/module/listpages/types/index.ts +17 -0
- package/src/parser/rules/block/module/listpages/types/normalized-query.ts +120 -0
- package/src/parser/rules/block/module/listpages/types/query.ts +67 -0
- package/src/parser/rules/block/module/listpages/types/template.ts +17 -0
- package/src/parser/rules/block/module/listpages/types/variables.ts +69 -0
- package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +48 -0
- package/src/parser/rules/block/module/listpages/url-resolution/params.ts +19 -0
- package/src/parser/rules/block/module/listpages/url-resolution/query.ts +24 -0
- package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +53 -0
- package/src/parser/rules/block/module/listpages/url-resolution/value.ts +25 -0
- package/src/parser/rules/block/module/listpages/url-resolver.ts +29 -0
- package/src/parser/rules/block/module/listusers/compiler.ts +56 -0
- package/src/parser/rules/block/module/listusers/extract.ts +40 -0
- package/src/parser/rules/block/module/listusers/getters.ts +21 -0
- package/src/parser/rules/block/module/listusers/index.ts +36 -0
- package/src/parser/rules/block/module/listusers/parser.ts +54 -0
- package/src/parser/rules/block/module/listusers/resolve.ts +58 -0
- package/src/parser/rules/block/module/listusers/types.ts +93 -0
- package/src/parser/rules/block/module/listusers/variables.ts +15 -0
- package/src/parser/rules/block/module/mapping.ts +61 -0
- package/src/parser/rules/block/module/open.ts +57 -0
- package/src/parser/rules/block/module/page-tree/index.ts +38 -0
- package/src/parser/rules/block/module/page-tree/types.ts +29 -0
- package/src/parser/rules/block/module/rate/index.ts +28 -0
- package/src/parser/rules/block/module/rate/types.ts +19 -0
- package/src/parser/rules/block/module/resolution/contexts.ts +78 -0
- package/src/parser/rules/block/module/resolution/data-maps.ts +39 -0
- package/src/parser/rules/block/module/resolution/dynamic-modules.ts +93 -0
- package/src/parser/rules/block/module/resolution/styles.ts +53 -0
- package/src/parser/rules/block/module/resolution/walk-resolve.ts +107 -0
- package/src/parser/rules/block/module/resolve.ts +198 -0
- package/src/parser/rules/block/module/rule.ts +56 -0
- package/src/parser/rules/block/module/types-common.ts +70 -0
- package/src/parser/rules/block/module/types.ts +61 -0
- package/src/parser/rules/block/module/utils.ts +43 -0
- package/src/parser/rules/block/module/walk/children.ts +35 -0
- package/src/parser/rules/block/module/walk/index.ts +9 -0
- package/src/parser/rules/block/module/walk/map/index.ts +2 -0
- package/src/parser/rules/block/module/walk/map/stateful-definition-list.ts +25 -0
- package/src/parser/rules/block/module/walk/map/stateful-list.ts +40 -0
- package/src/parser/rules/block/module/walk/map/stateful-table.ts +23 -0
- package/src/parser/rules/block/module/walk/map/stateful-tabs.ts +19 -0
- package/src/parser/rules/block/module/walk/map/stateful.ts +71 -0
- package/src/parser/rules/block/module/walk/map/stateless-definition-list.ts +12 -0
- package/src/parser/rules/block/module/walk/map/stateless-list.ts +29 -0
- package/src/parser/rules/block/module/walk/map/stateless-table.ts +11 -0
- package/src/parser/rules/block/module/walk/map/stateless-tabs.ts +5 -0
- package/src/parser/rules/block/module/walk/map/stateless.ts +51 -0
- package/src/parser/rules/block/module/walk/map/types.ts +6 -0
- package/src/parser/rules/block/module/walk/traverse.ts +65 -0
- package/src/parser/rules/block/orphan-li/content.ts +60 -0
- package/src/parser/rules/block/orphan-li/index.ts +75 -0
- package/src/parser/rules/block/orphan-li/open.ts +25 -0
- package/src/parser/rules/block/orphan-li/tags.ts +40 -0
- package/src/parser/rules/block/paragraph/content.ts +12 -0
- package/src/parser/rules/block/paragraph/index.ts +60 -0
- package/src/parser/rules/block/paragraph/normalize.ts +52 -0
- package/src/parser/rules/block/paragraph/span-markers.ts +52 -0
- package/src/parser/rules/block/parsing/attributes/index.ts +32 -0
- package/src/parser/rules/block/parsing/attributes/names.ts +93 -0
- package/src/parser/rules/block/parsing/attributes/scanner.ts +75 -0
- package/src/parser/rules/block/parsing/attributes/values.ts +26 -0
- package/src/parser/rules/block/parsing/block-item.ts +29 -0
- package/src/parser/rules/block/parsing/content.ts +127 -0
- package/src/parser/rules/block/parsing/end-condition.ts +51 -0
- package/src/parser/rules/block/parsing/inline-content.ts +105 -0
- package/src/parser/rules/block/parsing/inline-newline.ts +41 -0
- package/src/parser/rules/block/parsing/non-boundary.ts +24 -0
- package/src/parser/rules/block/parsing/rule-dispatch.ts +44 -0
- package/src/parser/rules/block/table/index.ts +80 -0
- package/src/parser/rules/block/table/pipe/cell-start.ts +69 -0
- package/src/parser/rules/block/table/pipe/cell.ts +106 -0
- package/src/parser/rules/block/table/pipe/index.ts +2 -0
- package/src/parser/rules/block/table/pipe/row.ts +88 -0
- package/src/parser/rules/block/table/pipe/tokens.ts +14 -0
- package/src/parser/rules/block/table/pipe/trim.ts +50 -0
- package/src/parser/rules/block/table-block/body.ts +79 -0
- package/src/parser/rules/block/table-block/cell-attributes.ts +33 -0
- package/src/parser/rules/block/table-block/cell-boundary.ts +99 -0
- package/src/parser/rules/block/table-block/cell-content/index.ts +88 -0
- package/src/parser/rules/block/table-block/cell-content/segments.ts +134 -0
- package/src/parser/rules/block/table-block/cell-newline.ts +47 -0
- package/src/parser/rules/block/table-block/cell.ts +64 -0
- package/src/parser/rules/block/table-block/index.ts +113 -0
- package/src/parser/rules/block/table-block/row-boundary.ts +75 -0
- package/src/parser/rules/block/table-block/structure.ts +80 -0
- package/src/parser/rules/block/tabview/body.ts +64 -0
- package/src/parser/rules/block/tabview/index.ts +90 -0
- package/src/parser/rules/block/tabview/open.ts +50 -0
- package/src/parser/rules/block/tabview/tab.ts +92 -0
- package/src/parser/rules/block/tabview/tags.ts +30 -0
- package/src/parser/rules/block/toc/element.ts +11 -0
- package/src/parser/rules/block/toc/index.ts +44 -0
- package/src/parser/rules/block/toc/open.ts +84 -0
- package/src/parser/rules/block/utils.ts +15 -0
- package/src/parser/rules/common/attribute-safety.ts +109 -0
- package/src/parser/rules/common/block-name.ts +33 -0
- package/src/parser/rules/common/index.ts +2 -0
- package/src/parser/rules/contracts/index.ts +3 -0
- package/src/parser/rules/contracts/parse-context.ts +38 -0
- package/src/parser/rules/contracts/rule.ts +43 -0
- package/src/parser/rules/contracts/scope.ts +31 -0
- package/src/parser/rules/index.ts +49 -0
- package/src/parser/rules/inline/anchor/attributes.ts +54 -0
- package/src/parser/rules/inline/anchor/child.ts +26 -0
- package/src/parser/rules/inline/anchor/close.ts +34 -0
- package/src/parser/rules/inline/anchor/content.ts +59 -0
- package/src/parser/rules/inline/anchor/index.ts +103 -0
- package/src/parser/rules/inline/anchor/newline.ts +26 -0
- package/src/parser/rules/inline/anchor/open.ts +47 -0
- package/src/parser/rules/inline/anchor/paragraph-strip.ts +14 -0
- package/src/parser/rules/inline/anchor/syntax.ts +40 -0
- package/src/parser/rules/inline/anchor-name/index.ts +38 -0
- package/src/parser/rules/inline/anchor-name/name.ts +39 -0
- package/src/parser/rules/inline/anchor-name/syntax.ts +46 -0
- package/src/parser/rules/inline/bibcite/element.ts +14 -0
- package/src/parser/rules/inline/bibcite/index.ts +34 -0
- package/src/parser/rules/inline/bibcite/syntax.ts +64 -0
- package/src/parser/rules/inline/bold.ts +49 -0
- package/src/parser/rules/inline/color/index.ts +35 -0
- package/src/parser/rules/inline/color/syntax.ts +69 -0
- package/src/parser/rules/inline/comment/consume.ts +31 -0
- package/src/parser/rules/inline/comment/index.ts +64 -0
- package/src/parser/rules/inline/equation-ref/element.ts +8 -0
- package/src/parser/rules/inline/equation-ref/index.ts +34 -0
- package/src/parser/rules/inline/equation-ref/syntax.ts +45 -0
- package/src/parser/rules/inline/expr/branch.ts +104 -0
- package/src/parser/rules/inline/expr/conditional-branch.ts +27 -0
- package/src/parser/rules/inline/expr/conditional.ts +80 -0
- package/src/parser/rules/inline/expr/depth.ts +25 -0
- package/src/parser/rules/inline/expr/elements.ts +39 -0
- package/src/parser/rules/inline/expr/index.ts +84 -0
- package/src/parser/rules/inline/expr/syntax.ts +45 -0
- package/src/parser/rules/inline/footnote/child.ts +22 -0
- package/src/parser/rules/inline/footnote/close.ts +33 -0
- package/src/parser/rules/inline/footnote/content.ts +54 -0
- package/src/parser/rules/inline/footnote/elements.ts +38 -0
- package/src/parser/rules/inline/footnote/index.ts +54 -0
- package/src/parser/rules/inline/footnote/newline.ts +27 -0
- package/src/parser/rules/inline/footnote/open.ts +38 -0
- package/src/parser/rules/inline/formatting/container.ts +50 -0
- package/src/parser/rules/inline/guillemet/index.ts +56 -0
- package/src/parser/rules/inline/guillemet/text.ts +11 -0
- package/src/parser/rules/inline/html/gate.ts +64 -0
- package/src/parser/rules/inline/html/index.ts +81 -0
- package/src/parser/rules/inline/html/open.ts +37 -0
- package/src/parser/rules/inline/image/attributes.ts +22 -0
- package/src/parser/rules/inline/image/body.ts +36 -0
- package/src/parser/rules/inline/image/index.ts +89 -0
- package/src/parser/rules/inline/image/open.ts +56 -0
- package/src/parser/rules/inline/image/source.ts +62 -0
- package/src/parser/rules/inline/image/syntax.ts +76 -0
- package/src/parser/rules/inline/index.ts +150 -0
- package/src/parser/rules/inline/italic.ts +46 -0
- package/src/parser/rules/inline/line-break/backslash.ts +58 -0
- package/src/parser/rules/inline/line-break/elements.ts +9 -0
- package/src/parser/rules/inline/line-break/index.ts +3 -0
- package/src/parser/rules/inline/line-break/newline.ts +82 -0
- package/src/parser/rules/inline/line-break/underscore.ts +45 -0
- package/src/parser/rules/inline/link-anchor.ts +72 -0
- package/src/parser/rules/inline/link-bracket/anchor.ts +3 -0
- package/src/parser/rules/inline/link-bracket/direct-url.ts +5 -0
- package/src/parser/rules/inline/link-bracket/parsed.ts +81 -0
- package/src/parser/rules/inline/link-bracket/parts.ts +64 -0
- package/src/parser/rules/inline/link-bracket/prefix.ts +15 -0
- package/src/parser/rules/inline/link-single.ts +73 -0
- package/src/parser/rules/inline/link-star.ts +72 -0
- package/src/parser/rules/inline/link-triple/fallback.ts +10 -0
- package/src/parser/rules/inline/link-triple/index.ts +62 -0
- package/src/parser/rules/inline/link-triple/interwiki.ts +11 -0
- package/src/parser/rules/inline/link-triple/label.ts +35 -0
- package/src/parser/rules/inline/link-triple/syntax.ts +72 -0
- package/src/parser/rules/inline/link-triple/target.ts +36 -0
- package/src/parser/rules/inline/math-inline/index.ts +40 -0
- package/src/parser/rules/inline/math-inline/syntax.ts +55 -0
- package/src/parser/rules/inline/monospace.ts +50 -0
- package/src/parser/rules/inline/parsing/block-boundary.ts +42 -0
- package/src/parser/rules/inline/parsing/block-start-predicates.ts +117 -0
- package/src/parser/rules/inline/parsing/collect.ts +23 -0
- package/src/parser/rules/inline/parsing/inline-content.ts +115 -0
- package/src/parser/rules/inline/parsing/paragraph-boundary.ts +47 -0
- package/src/parser/rules/inline/parsing/plain-text.ts +69 -0
- package/src/parser/rules/inline/parsing/preserved-line-break.ts +11 -0
- package/src/parser/rules/inline/parsing/rules.ts +34 -0
- package/src/parser/rules/inline/parsing/simple-token.ts +26 -0
- package/src/parser/rules/inline/raw/angle.ts +40 -0
- package/src/parser/rules/inline/raw/double-at.ts +78 -0
- package/src/parser/rules/inline/raw/index.ts +26 -0
- package/src/parser/rules/inline/raw/result.ts +26 -0
- package/src/parser/rules/inline/size/content.ts +65 -0
- package/src/parser/rules/inline/size/index.ts +55 -0
- package/src/parser/rules/inline/size/open.ts +43 -0
- package/src/parser/rules/inline/size/value.ts +45 -0
- package/src/parser/rules/inline/span/content.ts +97 -0
- package/src/parser/rules/inline/span/elements.ts +108 -0
- package/src/parser/rules/inline/span/index.ts +79 -0
- package/src/parser/rules/inline/span/newline.ts +50 -0
- package/src/parser/rules/inline/span/syntax.ts +70 -0
- package/src/parser/rules/inline/strikethrough/index.ts +60 -0
- package/src/parser/rules/inline/strikethrough/parse.ts +14 -0
- package/src/parser/rules/inline/strikethrough/syntax.ts +24 -0
- package/src/parser/rules/inline/subscript.ts +47 -0
- package/src/parser/rules/inline/superscript.ts +49 -0
- package/src/parser/rules/inline/text/element.ts +5 -0
- package/src/parser/rules/inline/text/index.ts +85 -0
- package/src/parser/rules/inline/underline/child.ts +26 -0
- package/src/parser/rules/inline/underline/content.ts +29 -0
- package/src/parser/rules/inline/underline/index.ts +84 -0
- package/src/parser/rules/inline/user/element.ts +11 -0
- package/src/parser/rules/inline/user/index.ts +34 -0
- package/src/parser/rules/inline/user/syntax.ts +67 -0
- package/src/parser/rules/inline/utils.ts +4 -0
- package/src/parser/rules/tokens.ts +106 -0
- package/src/parser/rules/types.ts +9 -0
- package/src/parser/toc.ts +130 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { PageRef } from "@wdprlib/ast";
|
|
2
|
+
|
|
3
|
+
export interface IncludeAssignment {
|
|
4
|
+
key: string;
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Parse the inner content of an `[[include ...]]` directive into a page reference
|
|
10
|
+
* and variable assignments.
|
|
11
|
+
*/
|
|
12
|
+
export function parseIncludeDirective(inner: string): {
|
|
13
|
+
location: PageRef;
|
|
14
|
+
assignments: IncludeAssignment[];
|
|
15
|
+
} {
|
|
16
|
+
const normalized = inner.includes("\n") ? inner.replaceAll("\n", " ") : inner;
|
|
17
|
+
const parts = normalized.split("|");
|
|
18
|
+
const firstSegment = parts[0]!.trim();
|
|
19
|
+
|
|
20
|
+
const spaceIndex = firstSegment.indexOf(" ");
|
|
21
|
+
let target: string;
|
|
22
|
+
const varSegments: string[] = [];
|
|
23
|
+
|
|
24
|
+
if (spaceIndex !== -1) {
|
|
25
|
+
target = firstSegment.slice(0, spaceIndex);
|
|
26
|
+
const rest = firstSegment.slice(spaceIndex + 1).trim();
|
|
27
|
+
if (rest) {
|
|
28
|
+
varSegments.push(rest);
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
target = firstSegment;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (let i = 1; i < parts.length; i++) {
|
|
35
|
+
const segment = parts[i]!.trim();
|
|
36
|
+
if (segment) {
|
|
37
|
+
varSegments.push(segment);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const assignments = parseIncludeAssignments(varSegments);
|
|
42
|
+
return { location: parseIncludePageRef(target), assignments };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function substituteVariables(
|
|
46
|
+
content: string,
|
|
47
|
+
assignments: readonly IncludeAssignment[],
|
|
48
|
+
): string {
|
|
49
|
+
if (assignments.length === 0) return content;
|
|
50
|
+
if (!content.includes("{$")) return content;
|
|
51
|
+
|
|
52
|
+
let substituted = content;
|
|
53
|
+
for (const { key, value } of assignments) {
|
|
54
|
+
substituted = substituted.replaceAll(`{$${key}}`, value);
|
|
55
|
+
}
|
|
56
|
+
return substituted;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseIncludePageRef(target: string): PageRef {
|
|
60
|
+
if (target.startsWith(":")) {
|
|
61
|
+
const rest = target.slice(1);
|
|
62
|
+
const colonIndex = rest.indexOf(":");
|
|
63
|
+
if (colonIndex !== -1) {
|
|
64
|
+
return { site: rest.slice(0, colonIndex), page: rest.slice(colonIndex + 1) };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { site: null, page: target };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parseIncludeAssignments(varSegments: string[]): IncludeAssignment[] {
|
|
71
|
+
const assignments: IncludeAssignment[] = [];
|
|
72
|
+
|
|
73
|
+
for (const segment of varSegments) {
|
|
74
|
+
const assignment = parseVariableSegment(segment);
|
|
75
|
+
if (assignment) {
|
|
76
|
+
assignments.push(assignment);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return assignments;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseVariableSegment(segment: string): IncludeAssignment | null {
|
|
84
|
+
const eqIndex = segment.indexOf("=");
|
|
85
|
+
if (eqIndex === -1) return null;
|
|
86
|
+
const key = segment.slice(0, eqIndex).trim();
|
|
87
|
+
if (!key) return null;
|
|
88
|
+
const value = segment.slice(eqIndex + 1).trim();
|
|
89
|
+
if (value === "") return null;
|
|
90
|
+
return { key, value };
|
|
91
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Include directive resolution for Wikidot's `[[include page]]` syntax.
|
|
4
|
+
*
|
|
5
|
+
* The include system performs text-level macro expansion before parsing. Each
|
|
6
|
+
* `[[include page | var=value]]` directive is replaced with the fetched page's
|
|
7
|
+
* content (after variable substitution), allowing block structures like `[[div]]`
|
|
8
|
+
* to span across include boundaries.
|
|
9
|
+
*
|
|
10
|
+
* Supports:
|
|
11
|
+
* - Same-site includes: `[[include page-name]]`
|
|
12
|
+
* - Cross-site includes: `[[include :site-name:page-name]]`
|
|
13
|
+
* - Variable substitution: `[[include page | key=value]]` replaces `{$key}` in the included content
|
|
14
|
+
* - Iterative expansion with configurable iteration limit (Wikidot-compatible)
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export { resolveIncludes, resolveIncludesAsync, resolveIncludesWithTrace } from "./resolve";
|
|
20
|
+
export { extractIncludeReferences } from "./references";
|
|
21
|
+
export type {
|
|
22
|
+
IncludeFetcher,
|
|
23
|
+
AsyncIncludeFetcher,
|
|
24
|
+
ResolveIncludesOptions,
|
|
25
|
+
IncludeReference,
|
|
26
|
+
IncludeDependency,
|
|
27
|
+
IncludeIterationTrace,
|
|
28
|
+
ResolveIncludesTraceResult,
|
|
29
|
+
} from "./resolve";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { parseIncludeDirective } from "./directive";
|
|
2
|
+
import { scanIncludeDirectives, type IncludeDirectiveMatch } from "./scanner";
|
|
3
|
+
import type { IncludeReference, ResolveIncludesOptions } from "./resolve/types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Extract include directives from raw source without fetching or expanding them.
|
|
7
|
+
*
|
|
8
|
+
* This uses the same scanner and directive parser as `resolveIncludes`, so it
|
|
9
|
+
* reports only directives that the include expansion pass would recognize.
|
|
10
|
+
*
|
|
11
|
+
* This is a source-phase API. It intentionally does not evaluate later syntax
|
|
12
|
+
* such as comments, expressions, or iftags. Wikidot expands includes before
|
|
13
|
+
* those phases, so an include inside a later comment block is still reported,
|
|
14
|
+
* while a token that only becomes `[[include ...]]` after comment/expression/
|
|
15
|
+
* iftags processing is not reported.
|
|
16
|
+
*
|
|
17
|
+
* The result is not a complete transitive dependency graph. Nested includes
|
|
18
|
+
* only become visible after fetching and expanding the current layer; use
|
|
19
|
+
* `resolveIncludesWithTrace` when the caller needs observed dependency edges
|
|
20
|
+
* across iterative expansion.
|
|
21
|
+
*/
|
|
22
|
+
export function extractIncludeReferences(
|
|
23
|
+
source: string,
|
|
24
|
+
options?: ResolveIncludesOptions,
|
|
25
|
+
): IncludeReference[] {
|
|
26
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return scanIncludeDirectives(source).map(createIncludeReference);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createIncludeReference(match: IncludeDirectiveMatch): IncludeReference {
|
|
34
|
+
const { location, assignments } = parseIncludeDirective(match.inner);
|
|
35
|
+
return {
|
|
36
|
+
location,
|
|
37
|
+
assignments,
|
|
38
|
+
start: match.start,
|
|
39
|
+
end: match.end,
|
|
40
|
+
inner: match.inner,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { PageRef } from "@wdprlib/ast";
|
|
2
|
+
import type { AsyncIncludeFetcher, IncludeFetcher } from "./types";
|
|
3
|
+
|
|
4
|
+
export function createCachedIncludeFetcher(
|
|
5
|
+
fetcher: IncludeFetcher,
|
|
6
|
+
normalizeKey: (pageRef: PageRef) => string,
|
|
7
|
+
): IncludeFetcher {
|
|
8
|
+
const cache = new Map<string, string | null>();
|
|
9
|
+
|
|
10
|
+
return (pageRef: PageRef): string | null => {
|
|
11
|
+
const key = normalizeKey(pageRef);
|
|
12
|
+
if (cache.has(key)) {
|
|
13
|
+
return cache.get(key)!;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let result: string | null;
|
|
17
|
+
try {
|
|
18
|
+
result = fetcher(pageRef);
|
|
19
|
+
} catch {
|
|
20
|
+
result = null;
|
|
21
|
+
}
|
|
22
|
+
cache.set(key, result);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createCachedAsyncIncludeFetcher(
|
|
28
|
+
fetcher: AsyncIncludeFetcher,
|
|
29
|
+
normalizeKey: (pageRef: PageRef) => string,
|
|
30
|
+
): AsyncIncludeFetcher {
|
|
31
|
+
const cache = new Map<string, Promise<string | null>>();
|
|
32
|
+
|
|
33
|
+
return async (pageRef: PageRef): Promise<string | null> => {
|
|
34
|
+
const key = normalizeKey(pageRef);
|
|
35
|
+
const cached = cache.get(key);
|
|
36
|
+
if (cached) {
|
|
37
|
+
return cached;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result = fetcher(pageRef).catch(() => null);
|
|
41
|
+
cache.set(key, result);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Text-level expansion of `[[include]]` directives.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PageRef } from "@wdprlib/ast";
|
|
9
|
+
import { createCachedAsyncIncludeFetcher, createCachedIncludeFetcher } from "./cache";
|
|
10
|
+
import { expandIterative, expandIterativeAsync, expandIterativeWithTrace } from "./iterate";
|
|
11
|
+
import type {
|
|
12
|
+
AsyncIncludeFetcher,
|
|
13
|
+
IncludeFetcher,
|
|
14
|
+
ResolveIncludesOptions,
|
|
15
|
+
ResolveIncludesTraceResult,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
export type {
|
|
19
|
+
IncludeFetcher,
|
|
20
|
+
AsyncIncludeFetcher,
|
|
21
|
+
ResolveIncludesOptions,
|
|
22
|
+
IncludeReference,
|
|
23
|
+
IncludeDependency,
|
|
24
|
+
IncludeIterationTrace,
|
|
25
|
+
ResolveIncludesTraceResult,
|
|
26
|
+
} from "./types";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Expand all [[include]] directives in the source text.
|
|
30
|
+
*
|
|
31
|
+
* Uses Wikidot-compatible iterative expansion: each iteration replaces
|
|
32
|
+
* all include directives in the current source with fetched and
|
|
33
|
+
* variable-substituted content. Iteration continues until no further
|
|
34
|
+
* changes occur or `maxIterations` is reached.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveIncludes(
|
|
37
|
+
source: string,
|
|
38
|
+
fetcher: IncludeFetcher,
|
|
39
|
+
options?: ResolveIncludesOptions,
|
|
40
|
+
): string {
|
|
41
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
42
|
+
return source;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
46
|
+
const cachedFetcher = createCachedIncludeFetcher(fetcher, normalizePageKey);
|
|
47
|
+
return expandIterative(source, cachedFetcher, maxIterations);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Expand all [[include]] directives and return dependency/iteration trace data.
|
|
52
|
+
*
|
|
53
|
+
* This follows the same sync expansion behavior as {@link resolveIncludes};
|
|
54
|
+
* the additional trace data is intended for application-level dependency
|
|
55
|
+
* graphs, cache invalidation, and diagnostics.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveIncludesWithTrace(
|
|
58
|
+
source: string,
|
|
59
|
+
fetcher: IncludeFetcher,
|
|
60
|
+
options?: ResolveIncludesOptions,
|
|
61
|
+
): ResolveIncludesTraceResult {
|
|
62
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
63
|
+
return {
|
|
64
|
+
source,
|
|
65
|
+
dependencies: [],
|
|
66
|
+
iterations: [],
|
|
67
|
+
reachedMaxIterations: false,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
72
|
+
const cachedFetcher = createCachedIncludeFetcher(fetcher, normalizePageKey);
|
|
73
|
+
return expandIterativeWithTrace(source, cachedFetcher, maxIterations);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Async version of {@link resolveIncludes}.
|
|
78
|
+
*
|
|
79
|
+
* Expand all [[include]] directives using an async fetcher, allowing
|
|
80
|
+
* page content to be loaded from async sources such as databases.
|
|
81
|
+
*/
|
|
82
|
+
export async function resolveIncludesAsync(
|
|
83
|
+
source: string,
|
|
84
|
+
fetcher: AsyncIncludeFetcher,
|
|
85
|
+
options?: ResolveIncludesOptions,
|
|
86
|
+
): Promise<string> {
|
|
87
|
+
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
88
|
+
return source;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const maxIterations = options?.maxIterations ?? 10;
|
|
92
|
+
const cachedFetcher = createCachedAsyncIncludeFetcher(fetcher, normalizePageKey);
|
|
93
|
+
return expandIterativeAsync(source, cachedFetcher, maxIterations);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Normalize a PageRef into a consistent string key for cache lookups.
|
|
98
|
+
*
|
|
99
|
+
* Page names are lowercased for case-insensitive matching. Cross-site
|
|
100
|
+
* references include the site name as a prefix.
|
|
101
|
+
*/
|
|
102
|
+
function normalizePageKey(location: PageRef): string {
|
|
103
|
+
const site = location.site ?? "";
|
|
104
|
+
const page = location.page.toLowerCase();
|
|
105
|
+
return site ? `${site}:${page}` : page;
|
|
106
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { scanIncludeDirectives } from "../scanner";
|
|
2
|
+
import { createIncludeReference } from "../references";
|
|
3
|
+
import { replaceOneInclude, replaceOneIncludeAsync } from "./replace";
|
|
4
|
+
import type {
|
|
5
|
+
AsyncIncludeFetcher,
|
|
6
|
+
IncludeDependency,
|
|
7
|
+
IncludeFetcher,
|
|
8
|
+
IncludeReference,
|
|
9
|
+
ResolveIncludesTraceResult,
|
|
10
|
+
} from "./types";
|
|
11
|
+
|
|
12
|
+
const MAYBE_INCLUDE_PATTERN = /\[\[include\s/i;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Iteratively expand all `[[include]]` directives in source text.
|
|
16
|
+
*
|
|
17
|
+
* Each iteration replaces every include directive in the current source
|
|
18
|
+
* with its fetched content after variable substitution. No recursion
|
|
19
|
+
* into individual includes: the next iteration handles nested includes.
|
|
20
|
+
*/
|
|
21
|
+
export function expandIterative(
|
|
22
|
+
source: string,
|
|
23
|
+
fetcher: IncludeFetcher,
|
|
24
|
+
maxIterations: number,
|
|
25
|
+
): string {
|
|
26
|
+
let current = source;
|
|
27
|
+
const replacementCache = new Map<string, string>();
|
|
28
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
29
|
+
const expanded = expandOneIteration(current, fetcher, replacementCache);
|
|
30
|
+
if (expanded === null || expanded === current) break;
|
|
31
|
+
current = expanded;
|
|
32
|
+
}
|
|
33
|
+
return current;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Trace-enabled version of {@link expandIterative}.
|
|
38
|
+
*
|
|
39
|
+
* The expansion behavior is identical to the normal sync path; this function
|
|
40
|
+
* additionally records directives seen at each iteration so callers can build
|
|
41
|
+
* dependency graphs and debug max-iteration leftovers.
|
|
42
|
+
*/
|
|
43
|
+
export function expandIterativeWithTrace(
|
|
44
|
+
source: string,
|
|
45
|
+
fetcher: IncludeFetcher,
|
|
46
|
+
maxIterations: number,
|
|
47
|
+
): ResolveIncludesTraceResult {
|
|
48
|
+
let current = source;
|
|
49
|
+
const replacementCache = new Map<string, string>();
|
|
50
|
+
const dependencies: IncludeDependency[] = [];
|
|
51
|
+
const iterations: ResolveIncludesTraceResult["iterations"] = [];
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
54
|
+
const expanded = expandOneIterationWithTrace(current, fetcher, replacementCache, i);
|
|
55
|
+
if (expanded === null) break;
|
|
56
|
+
|
|
57
|
+
dependencies.push(...expanded.dependencies);
|
|
58
|
+
iterations.push({
|
|
59
|
+
iteration: i,
|
|
60
|
+
directives: expanded.references,
|
|
61
|
+
changed: expanded.source !== current,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Stable self-includes can keep scanning as directives forever; Wikidot-style
|
|
65
|
+
// expansion stops when a whole iteration no longer changes the source.
|
|
66
|
+
if (expanded.source === current) break;
|
|
67
|
+
current = expanded.source;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
source: current,
|
|
72
|
+
dependencies,
|
|
73
|
+
iterations,
|
|
74
|
+
// Hitting the cap only matters when the final source still contains a
|
|
75
|
+
// recognizable include directive. A fully expanded document can use exactly
|
|
76
|
+
// maxIterations passes without leaving work behind.
|
|
77
|
+
reachedMaxIterations:
|
|
78
|
+
iterations.length === maxIterations && scanIncludeDirectives(current).length > 0,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Async iterative expansion of `[[include]]` directives.
|
|
84
|
+
*
|
|
85
|
+
* Each iteration scans the current source for include directives, fetches
|
|
86
|
+
* sibling includes concurrently, and builds the replacement string in source
|
|
87
|
+
* order. Nested includes introduced by replacements are still handled by the
|
|
88
|
+
* next iteration.
|
|
89
|
+
*/
|
|
90
|
+
export async function expandIterativeAsync(
|
|
91
|
+
source: string,
|
|
92
|
+
fetcher: AsyncIncludeFetcher,
|
|
93
|
+
maxIterations: number,
|
|
94
|
+
): Promise<string> {
|
|
95
|
+
let current = source;
|
|
96
|
+
const replacementCache = new Map<string, Promise<string>>();
|
|
97
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
98
|
+
const expanded = await expandOneIterationAsync(current, fetcher, replacementCache);
|
|
99
|
+
if (expanded === null || expanded === current) break;
|
|
100
|
+
current = expanded;
|
|
101
|
+
}
|
|
102
|
+
return current;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function expandOneIteration(
|
|
106
|
+
source: string,
|
|
107
|
+
fetcher: IncludeFetcher,
|
|
108
|
+
replacementCache: Map<string, string>,
|
|
109
|
+
): string | null {
|
|
110
|
+
if (!MAYBE_INCLUDE_PATTERN.test(source)) return null;
|
|
111
|
+
|
|
112
|
+
const directives = scanIncludeDirectives(source);
|
|
113
|
+
if (directives.length === 0) return null;
|
|
114
|
+
|
|
115
|
+
const parts: string[] = [];
|
|
116
|
+
let lastPos = 0;
|
|
117
|
+
for (const { start, end, inner } of directives) {
|
|
118
|
+
parts.push(source.slice(lastPos, start), replaceCached(inner, fetcher, replacementCache));
|
|
119
|
+
lastPos = end;
|
|
120
|
+
}
|
|
121
|
+
parts.push(source.slice(lastPos));
|
|
122
|
+
return parts.join("");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function expandOneIterationWithTrace(
|
|
126
|
+
source: string,
|
|
127
|
+
fetcher: IncludeFetcher,
|
|
128
|
+
replacementCache: Map<string, string>,
|
|
129
|
+
iteration: number,
|
|
130
|
+
): {
|
|
131
|
+
source: string;
|
|
132
|
+
references: IncludeReference[];
|
|
133
|
+
dependencies: IncludeDependency[];
|
|
134
|
+
} | null {
|
|
135
|
+
if (!MAYBE_INCLUDE_PATTERN.test(source)) return null;
|
|
136
|
+
|
|
137
|
+
const directives = scanIncludeDirectives(source);
|
|
138
|
+
if (directives.length === 0) return null;
|
|
139
|
+
|
|
140
|
+
const references = directives.map(createIncludeReference);
|
|
141
|
+
const dependencies = references.map((reference) => ({ ...reference, iteration }));
|
|
142
|
+
const parts: string[] = [];
|
|
143
|
+
let lastPos = 0;
|
|
144
|
+
for (const { start, end, inner } of directives) {
|
|
145
|
+
parts.push(source.slice(lastPos, start), replaceCached(inner, fetcher, replacementCache));
|
|
146
|
+
lastPos = end;
|
|
147
|
+
}
|
|
148
|
+
parts.push(source.slice(lastPos));
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
source: parts.join(""),
|
|
152
|
+
references,
|
|
153
|
+
dependencies,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function expandOneIterationAsync(
|
|
158
|
+
source: string,
|
|
159
|
+
fetcher: AsyncIncludeFetcher,
|
|
160
|
+
replacementCache: Map<string, Promise<string>>,
|
|
161
|
+
): Promise<string | null> {
|
|
162
|
+
if (!MAYBE_INCLUDE_PATTERN.test(source)) return null;
|
|
163
|
+
|
|
164
|
+
const directives = scanIncludeDirectives(source);
|
|
165
|
+
if (directives.length === 0) return null;
|
|
166
|
+
|
|
167
|
+
const replacements = await Promise.all(
|
|
168
|
+
directives.map(({ inner }) => replaceCachedAsync(inner, fetcher, replacementCache)),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const parts: string[] = [];
|
|
172
|
+
let lastPos = 0;
|
|
173
|
+
for (let i = 0; i < directives.length; i++) {
|
|
174
|
+
const { start, end } = directives[i]!;
|
|
175
|
+
parts.push(source.slice(lastPos, start), replacements[i]!);
|
|
176
|
+
lastPos = end;
|
|
177
|
+
}
|
|
178
|
+
parts.push(source.slice(lastPos));
|
|
179
|
+
return parts.join("");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function replaceCached(inner: string, fetcher: IncludeFetcher, cache: Map<string, string>): string {
|
|
183
|
+
const cached = cache.get(inner);
|
|
184
|
+
if (cached !== undefined) return cached;
|
|
185
|
+
|
|
186
|
+
const replacement = replaceOneInclude(inner, fetcher);
|
|
187
|
+
cache.set(inner, replacement);
|
|
188
|
+
return replacement;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function replaceCachedAsync(
|
|
192
|
+
inner: string,
|
|
193
|
+
fetcher: AsyncIncludeFetcher,
|
|
194
|
+
cache: Map<string, Promise<string>>,
|
|
195
|
+
): Promise<string> {
|
|
196
|
+
const cached = cache.get(inner);
|
|
197
|
+
if (cached) return cached;
|
|
198
|
+
|
|
199
|
+
const replacement = replaceOneIncludeAsync(inner, fetcher);
|
|
200
|
+
cache.set(inner, replacement);
|
|
201
|
+
return replacement;
|
|
202
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseIncludeDirective, substituteVariables } from "../directive";
|
|
2
|
+
import type { AsyncIncludeFetcher, IncludeFetcher } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Replace a single include match with its fetched + variable-substituted content.
|
|
6
|
+
* Returns the replacement text for a single directive's `inner` content.
|
|
7
|
+
*/
|
|
8
|
+
export function replaceOneInclude(inner: string, fetcher: IncludeFetcher): string {
|
|
9
|
+
const { location, assignments } = parseIncludeDirective(inner);
|
|
10
|
+
const content = fetcher(location);
|
|
11
|
+
if (content === null) {
|
|
12
|
+
return missingIncludeError(location.page);
|
|
13
|
+
}
|
|
14
|
+
return substituteVariables(content, assignments);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function replaceOneIncludeAsync(
|
|
18
|
+
inner: string,
|
|
19
|
+
fetcher: AsyncIncludeFetcher,
|
|
20
|
+
): Promise<string> {
|
|
21
|
+
const { location, assignments } = parseIncludeDirective(inner);
|
|
22
|
+
const content = await fetcher(location);
|
|
23
|
+
if (content === null) {
|
|
24
|
+
return missingIncludeError(location.page);
|
|
25
|
+
}
|
|
26
|
+
return substituteVariables(content, assignments);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function missingIncludeError(page: string): string {
|
|
30
|
+
return `[[div class="error-block"]]\nPage to be included "${page}" cannot be found!\n[[/div]]`;
|
|
31
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { PageRef, WikitextSettings } from "@wdprlib/ast";
|
|
2
|
+
import type { IncludeAssignment } from "../directive";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Callback to fetch page content for include resolution.
|
|
6
|
+
* Returns the wikitext source of the page, or null if the page does not exist.
|
|
7
|
+
*
|
|
8
|
+
* @security The fetcher is called with user-provided page references.
|
|
9
|
+
* Implementations should validate and sanitize page references before
|
|
10
|
+
* using them in database queries or file system access.
|
|
11
|
+
*/
|
|
12
|
+
export type IncludeFetcher = (pageRef: PageRef) => string | null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Async callback to fetch page content for include resolution.
|
|
16
|
+
* Returns a promise of the wikitext source, or null if the page does not exist.
|
|
17
|
+
*
|
|
18
|
+
* @security The fetcher is called with user-provided page references.
|
|
19
|
+
* Implementations should validate and sanitize page references before
|
|
20
|
+
* using them in database queries or file system access.
|
|
21
|
+
*/
|
|
22
|
+
export type AsyncIncludeFetcher = (pageRef: PageRef) => Promise<string | null>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Options for resolveIncludes / resolveIncludesAsync.
|
|
26
|
+
*/
|
|
27
|
+
export interface ResolveIncludesOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Maximum number of expansion iterations (default: 10).
|
|
30
|
+
*
|
|
31
|
+
* Each iteration replaces all `[[include]]` directives in the current
|
|
32
|
+
* source with fetched content. Iteration stops when the source is
|
|
33
|
+
* unchanged or this limit is reached.
|
|
34
|
+
*/
|
|
35
|
+
maxIterations?: number;
|
|
36
|
+
/** Wikitext settings. If enablePageSyntax is false, includes are not expanded. */
|
|
37
|
+
settings?: WikitextSettings;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A single include directive found in raw source text.
|
|
42
|
+
*
|
|
43
|
+
* This represents the directive as it existed during the include expansion
|
|
44
|
+
* phase. It does not imply that the target exists, and it does not include
|
|
45
|
+
* nested dependencies introduced by the target source.
|
|
46
|
+
*/
|
|
47
|
+
export interface IncludeReference {
|
|
48
|
+
/** Target page reference parsed from the directive. */
|
|
49
|
+
location: PageRef;
|
|
50
|
+
/** Variable assignments parsed from the directive, preserving source order. */
|
|
51
|
+
assignments: IncludeAssignment[];
|
|
52
|
+
/** Index of the opening `[[`. */
|
|
53
|
+
start: number;
|
|
54
|
+
/** Index just past the closing `]]`. */
|
|
55
|
+
end: number;
|
|
56
|
+
/** Text between `[[include ` and the closing `]]`. */
|
|
57
|
+
inner: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Include dependency observed during iterative expansion.
|
|
62
|
+
*
|
|
63
|
+
* Unlike `IncludeReference`, this is collected after a fetchable include layer
|
|
64
|
+
* has actually been expanded. If an included page introduces another include,
|
|
65
|
+
* that nested directive appears as a later `IncludeDependency` with a higher
|
|
66
|
+
* `iteration`.
|
|
67
|
+
*/
|
|
68
|
+
export interface IncludeDependency extends IncludeReference {
|
|
69
|
+
/** Zero-based expansion iteration where this directive was observed. */
|
|
70
|
+
iteration: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Trace data for one include expansion iteration.
|
|
75
|
+
*
|
|
76
|
+
* `directives` is the scan result before replacements for that iteration.
|
|
77
|
+
* `changed` is false for stable self-includes where replacing the directive
|
|
78
|
+
* produces the same source again; the resolver stops at that point.
|
|
79
|
+
*/
|
|
80
|
+
export interface IncludeIterationTrace {
|
|
81
|
+
/** Zero-based expansion iteration. */
|
|
82
|
+
iteration: number;
|
|
83
|
+
/** Include directives found in the source for this iteration. */
|
|
84
|
+
directives: IncludeReference[];
|
|
85
|
+
/** Whether replacing the directives changed the source. */
|
|
86
|
+
changed: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Result returned by trace-enabled include expansion.
|
|
91
|
+
*
|
|
92
|
+
* The `source` field is intended to be byte-for-byte equivalent to
|
|
93
|
+
* `resolveIncludes(source, fetcher, options)` for the same inputs. The rest of
|
|
94
|
+
* the object is diagnostic data for dependency collection and cache planning.
|
|
95
|
+
*/
|
|
96
|
+
export interface ResolveIncludesTraceResult {
|
|
97
|
+
/** Final expanded source. */
|
|
98
|
+
source: string;
|
|
99
|
+
/** Include dependencies observed across all expansion iterations. */
|
|
100
|
+
dependencies: IncludeDependency[];
|
|
101
|
+
/** Per-iteration include scan and change information. */
|
|
102
|
+
iterations: IncludeIterationTrace[];
|
|
103
|
+
/** True when expansion stopped with directives still present after hitting the iteration cap. */
|
|
104
|
+
reachedMaxIterations: boolean;
|
|
105
|
+
}
|