@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,93 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import { isListPagesModule, resolveListPages } from "../listpages/resolve";
|
|
3
|
+
import { isListUsersModule, resolveListUsers } from "../listusers/resolve";
|
|
4
|
+
import { walkElements } from "../walk";
|
|
5
|
+
import type { ListPagesContext, ListUsersContext } from "./contexts";
|
|
6
|
+
|
|
7
|
+
export interface DynamicModuleContext {
|
|
8
|
+
listPages: ListPagesContext | null;
|
|
9
|
+
listUsers: ListUsersContext | null;
|
|
10
|
+
fetchListPagesProvided: boolean;
|
|
11
|
+
fetchListUsersProvided: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DynamicModuleIds {
|
|
15
|
+
listPagesId: number;
|
|
16
|
+
listUsersId: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DynamicModuleResolution {
|
|
20
|
+
handled: boolean;
|
|
21
|
+
elements: Element[];
|
|
22
|
+
ids: DynamicModuleIds;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function resolveDynamicModuleElement(
|
|
26
|
+
element: Element,
|
|
27
|
+
ctx: DynamicModuleContext,
|
|
28
|
+
ids: DynamicModuleIds,
|
|
29
|
+
): DynamicModuleResolution {
|
|
30
|
+
if (element.element !== "module") {
|
|
31
|
+
return { handled: false, elements: [element], ids };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isListPagesModule(element.data)) {
|
|
35
|
+
const elements: Element[] = [];
|
|
36
|
+
const listPagesId = ids.listPagesId;
|
|
37
|
+
|
|
38
|
+
if (ctx.listPages) {
|
|
39
|
+
const moduleData = ctx.listPages.dataMap.get(listPagesId);
|
|
40
|
+
const template = ctx.listPages.compiledTemplates.get(listPagesId);
|
|
41
|
+
|
|
42
|
+
if (moduleData && template) {
|
|
43
|
+
elements.push(...resolveListPages(element.data, moduleData, template, ctx.listPages.parse));
|
|
44
|
+
}
|
|
45
|
+
} else if (!ctx.fetchListPagesProvided) {
|
|
46
|
+
elements.push(element);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
handled: true,
|
|
51
|
+
elements,
|
|
52
|
+
ids: { ...ids, listPagesId: listPagesId + 1 },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (isListUsersModule(element.data)) {
|
|
57
|
+
const elements: Element[] = [];
|
|
58
|
+
const listUsersId = ids.listUsersId;
|
|
59
|
+
|
|
60
|
+
if (ctx.listUsers) {
|
|
61
|
+
const moduleData = ctx.listUsers.dataMap.get(listUsersId);
|
|
62
|
+
const template = ctx.listUsers.compiledTemplates.get(listUsersId);
|
|
63
|
+
|
|
64
|
+
if (moduleData && template) {
|
|
65
|
+
elements.push(...resolveListUsers(element.data, moduleData, template, ctx.listUsers.parse));
|
|
66
|
+
}
|
|
67
|
+
} else if (!ctx.fetchListUsersProvided) {
|
|
68
|
+
elements.push(element);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
handled: true,
|
|
73
|
+
elements,
|
|
74
|
+
ids: { ...ids, listUsersId: listUsersId + 1 },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { handled: false, elements: [element], ids };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function countDynamicModules(elements: Element[]): DynamicModuleIds {
|
|
82
|
+
const counts: DynamicModuleIds = { listPagesId: 0, listUsersId: 0 };
|
|
83
|
+
walkElements(elements, (element) => {
|
|
84
|
+
if (element.element !== "module") return;
|
|
85
|
+
|
|
86
|
+
if (isListPagesModule(element.data)) {
|
|
87
|
+
counts.listPagesId++;
|
|
88
|
+
} else if (isListUsersModule(element.data)) {
|
|
89
|
+
counts.listUsersId++;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return counts;
|
|
93
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import { STYLE_SLOT_PREFIX } from "@wdprlib/ast";
|
|
3
|
+
import { mapElementChildren } from "../walk";
|
|
4
|
+
import type { IfTagsData } from "../iftags/resolve";
|
|
5
|
+
|
|
6
|
+
type IfTagsDataWithStyleSlot = IfTagsData & {
|
|
7
|
+
_styleSlot: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Collect and remove style elements from the AST.
|
|
12
|
+
*
|
|
13
|
+
* Unresolved `if-tags` elements receive style-slot placeholders so render-time
|
|
14
|
+
* iftags evaluation can preserve style order relative to already collected CSS.
|
|
15
|
+
*/
|
|
16
|
+
export function collectStyles(elements: Element[]): { elements: Element[]; styles: string[] } {
|
|
17
|
+
const styles: string[] = [];
|
|
18
|
+
const ctx = { nextSlotId: 0 };
|
|
19
|
+
const filtered = collectStylesFromElements(elements, styles, ctx);
|
|
20
|
+
return { elements: filtered, styles };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function collectStylesFromElements(
|
|
24
|
+
elements: Element[],
|
|
25
|
+
styles: string[],
|
|
26
|
+
ctx: { nextSlotId: number },
|
|
27
|
+
): Element[] {
|
|
28
|
+
const result: Element[] = [];
|
|
29
|
+
|
|
30
|
+
for (const element of elements) {
|
|
31
|
+
if (element.element === "style") {
|
|
32
|
+
styles.push(element.data as string);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (element.element === "if-tags") {
|
|
37
|
+
const slotId = ctx.nextSlotId++;
|
|
38
|
+
styles.push(`${STYLE_SLOT_PREFIX}${slotId}`);
|
|
39
|
+
const data: IfTagsDataWithStyleSlot = { ...(element.data as IfTagsData), _styleSlot: slotId };
|
|
40
|
+
result.push({
|
|
41
|
+
element: "if-tags",
|
|
42
|
+
data,
|
|
43
|
+
});
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
result.push(
|
|
48
|
+
mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx)),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import { mapElementChildrenWithState } from "../walk";
|
|
3
|
+
import { isIfTagsElement, resolveIfTags, type IfTagsData } from "../iftags/resolve";
|
|
4
|
+
import type { ListPagesContext, ListUsersContext } from "./contexts";
|
|
5
|
+
import { countDynamicModules, resolveDynamicModuleElement } from "./dynamic-modules";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolution context passed through AST traversal.
|
|
9
|
+
*/
|
|
10
|
+
export interface WalkContext {
|
|
11
|
+
listPages: ListPagesContext | null;
|
|
12
|
+
listUsers: ListUsersContext | null;
|
|
13
|
+
/** Whether fetchListPages callback was provided, even if no data returned. */
|
|
14
|
+
fetchListPagesProvided: boolean;
|
|
15
|
+
/** Whether fetchListUsers callback was provided, even if no data returned. */
|
|
16
|
+
fetchListUsersProvided: boolean;
|
|
17
|
+
pageTags: string[] | null;
|
|
18
|
+
listPagesIdCounter: number;
|
|
19
|
+
listUsersIdCounter: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WalkResult {
|
|
23
|
+
elements: Element[];
|
|
24
|
+
nextListPagesId: number;
|
|
25
|
+
nextListUsersId: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Walk AST and resolve modules/iftags.
|
|
30
|
+
*/
|
|
31
|
+
export function walkAndResolve(elements: Element[], ctx: WalkContext): WalkResult {
|
|
32
|
+
const result: Element[] = [];
|
|
33
|
+
let listPagesId = ctx.listPagesIdCounter;
|
|
34
|
+
let listUsersId = ctx.listUsersIdCounter;
|
|
35
|
+
|
|
36
|
+
for (const element of elements) {
|
|
37
|
+
const dynamicModule = resolveDynamicModuleElement(element, ctx, { listPagesId, listUsersId });
|
|
38
|
+
if (dynamicModule.handled) {
|
|
39
|
+
result.push(...dynamicModule.elements);
|
|
40
|
+
listPagesId = dynamicModule.ids.listPagesId;
|
|
41
|
+
listUsersId = dynamicModule.ids.listUsersId;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isIfTagsElement(element)) {
|
|
46
|
+
const ifTagsData = element.data as IfTagsData;
|
|
47
|
+
const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
|
|
48
|
+
|
|
49
|
+
if (resolveResult.evaluated) {
|
|
50
|
+
if (resolveResult.matched) {
|
|
51
|
+
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
52
|
+
...ctx,
|
|
53
|
+
listPagesIdCounter: listPagesId,
|
|
54
|
+
listUsersIdCounter: listUsersId,
|
|
55
|
+
});
|
|
56
|
+
result.push(...childResult.elements);
|
|
57
|
+
listPagesId = childResult.nextListPagesId;
|
|
58
|
+
listUsersId = childResult.nextListUsersId;
|
|
59
|
+
} else {
|
|
60
|
+
const counts = countDynamicModules(ifTagsData.elements);
|
|
61
|
+
listPagesId += counts.listPagesId;
|
|
62
|
+
listUsersId += counts.listUsersId;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
66
|
+
...ctx,
|
|
67
|
+
listPagesIdCounter: listPagesId,
|
|
68
|
+
listUsersIdCounter: listUsersId,
|
|
69
|
+
});
|
|
70
|
+
result.push({
|
|
71
|
+
element: "if-tags",
|
|
72
|
+
data: {
|
|
73
|
+
...ifTagsData,
|
|
74
|
+
elements: childResult.elements,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
listPagesId = childResult.nextListPagesId;
|
|
78
|
+
listUsersId = childResult.nextListUsersId;
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const mapped = mapElementChildrenWithState(
|
|
84
|
+
element,
|
|
85
|
+
{ listPagesId, listUsersId },
|
|
86
|
+
(children, state) => {
|
|
87
|
+
const childResult = walkAndResolve(children, {
|
|
88
|
+
...ctx,
|
|
89
|
+
listPagesIdCounter: state.listPagesId,
|
|
90
|
+
listUsersIdCounter: state.listUsersId,
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
elements: childResult.elements,
|
|
94
|
+
state: {
|
|
95
|
+
listPagesId: childResult.nextListPagesId,
|
|
96
|
+
listUsersId: childResult.nextListUsersId,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
result.push(mapped.element);
|
|
102
|
+
listPagesId = mapped.state.listPagesId;
|
|
103
|
+
listUsersId = mapped.state.listUsersId;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { elements: result, nextListPagesId: listPagesId, nextListUsersId: listUsersId };
|
|
107
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified resolver that walks a parsed AST and expands dynamic modules.
|
|
3
|
+
*
|
|
4
|
+
* Handles three module families in a single traversal:
|
|
5
|
+
*
|
|
6
|
+
* - **ListPages** — fetches page data via {@link DataProvider.fetchListPages},
|
|
7
|
+
* resolves `@URL` parameters from the page path (HPC support), and
|
|
8
|
+
* expands `%%variable%%` templates.
|
|
9
|
+
* - **ListUsers** — fetches user data via {@link DataProvider.fetchListUsers}
|
|
10
|
+
* and expands `%%variable%%` templates.
|
|
11
|
+
* - **IfTags** — evaluates tag conditions against the current page's tags
|
|
12
|
+
* (from {@link DataProvider.getPageTags}) and keeps or discards content.
|
|
13
|
+
*
|
|
14
|
+
* The main entry point is {@link resolveModules}.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { SyntaxTree } from "@wdprlib/ast";
|
|
20
|
+
import type { DataProvider } from "./types-common";
|
|
21
|
+
import { resolveIncludes } from "./include";
|
|
22
|
+
import type { ListPagesDataRequirement, CompiledTemplate } from "./listpages/types";
|
|
23
|
+
import type { ListUsersDataRequirement, ListUsersCompiledTemplate } from "./listusers/types";
|
|
24
|
+
import type { ParseFunction } from "./listpages/resolve";
|
|
25
|
+
import { buildListPagesContext, buildListUsersContext } from "./resolution/contexts";
|
|
26
|
+
import { walkAndResolve } from "./resolution/walk-resolve";
|
|
27
|
+
import { collectStyles } from "./resolution/styles";
|
|
28
|
+
|
|
29
|
+
const MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
|
|
30
|
+
|
|
31
|
+
// Re-export from listpages/resolve for external use
|
|
32
|
+
export type { ParseFunction } from "./listpages/resolve";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Transform module-generated wikitext before it is parsed back into AST nodes.
|
|
36
|
+
*
|
|
37
|
+
* Applications can use this hook to inject include resolution, parse caches, or
|
|
38
|
+
* diagnostics for ListPages/ListUsers secondary transformations.
|
|
39
|
+
*
|
|
40
|
+
* This hook receives the string after module variables such as `%%title%%` have
|
|
41
|
+
* already been substituted. Returning a different string changes what is parsed
|
|
42
|
+
* for that module item. When this hook is supplied it replaces the built-in
|
|
43
|
+
* secondary include pass, so callers that still need Wikidot-style secondary
|
|
44
|
+
* includes must call `resolveIncludes()` or equivalent logic from the hook.
|
|
45
|
+
*/
|
|
46
|
+
export type ModuleSourceTransform = (source: string) => string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Configuration for {@link resolveModules}.
|
|
50
|
+
*
|
|
51
|
+
* Callers must supply pre-extracted requirements and pre-compiled
|
|
52
|
+
* templates (obtained from `extractDataRequirements()` and
|
|
53
|
+
* `compileTemplate()` / `compileListUsersTemplate()`).
|
|
54
|
+
*
|
|
55
|
+
* @group Module Resolution
|
|
56
|
+
*/
|
|
57
|
+
export interface ResolveOptions {
|
|
58
|
+
/** Parser function used to re-parse expanded template markup into AST nodes */
|
|
59
|
+
parse: ParseFunction;
|
|
60
|
+
|
|
61
|
+
/** Pre-compiled ListPages body templates, keyed by requirement ID */
|
|
62
|
+
compiledListPagesTemplates: Map<number, CompiledTemplate>;
|
|
63
|
+
|
|
64
|
+
/** Pre-compiled ListUsers body templates, keyed by requirement ID */
|
|
65
|
+
compiledListUsersTemplates?: Map<number, ListUsersCompiledTemplate>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Data requirements grouped by module type.
|
|
69
|
+
* Obtained from `extractDataRequirements()`.
|
|
70
|
+
*/
|
|
71
|
+
requirements: {
|
|
72
|
+
listPages?: ListPagesDataRequirement[];
|
|
73
|
+
listUsers?: ListUsersDataRequirement[];
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* URL path for `@URL` parameter resolution (HPC / pagination support).
|
|
78
|
+
*
|
|
79
|
+
* Wikidot encodes pagination state in the URL path as key/value pairs
|
|
80
|
+
* after the page name, e.g. `"/scp-001/offset/10/page2_limit/5"`.
|
|
81
|
+
* When provided, `@URL` references in ListPages queries are replaced
|
|
82
|
+
* with the corresponding values from this path.
|
|
83
|
+
*/
|
|
84
|
+
urlPath?: string;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Maximum include expansion iterations for secondary transformations inside
|
|
88
|
+
* modules such as ListPages/ListUsers. Defaults to Wikidot's observed
|
|
89
|
+
* secondary transformation limit.
|
|
90
|
+
*/
|
|
91
|
+
includeMaxIterations?: number;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Transform module-generated wikitext before re-parsing it.
|
|
95
|
+
*
|
|
96
|
+
* When omitted, `resolveModules()` preserves the existing default: if
|
|
97
|
+
* `dataProvider.fetchInclude` is present, secondary `[[include]]` expansion
|
|
98
|
+
* is performed with `includeMaxIterations`; otherwise the source is parsed
|
|
99
|
+
* unchanged. When supplied, this hook owns the whole transformation.
|
|
100
|
+
*
|
|
101
|
+
* This is the extension point for application-level parse/include caches. The
|
|
102
|
+
* parser package does not persist cache entries itself because cache keys and
|
|
103
|
+
* invalidation depend on site/page revisions, tags, URL parameters, and user
|
|
104
|
+
* state outside wdpr.
|
|
105
|
+
*/
|
|
106
|
+
transformModuleSource?: ModuleSourceTransform;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve all modules in the AST
|
|
111
|
+
*
|
|
112
|
+
* Fetches data for each module using the provided callback,
|
|
113
|
+
* then expands the modules with the fetched data.
|
|
114
|
+
*
|
|
115
|
+
* Handles:
|
|
116
|
+
* - ListPages: fetches page data and expands templates
|
|
117
|
+
* - IfTags: evaluates tag conditions and includes/excludes content
|
|
118
|
+
*
|
|
119
|
+
* @param ast - Parsed AST
|
|
120
|
+
* @param dataProvider - Callback provider to fetch data for each module
|
|
121
|
+
* @param options - Resolution options including requirements
|
|
122
|
+
*/
|
|
123
|
+
export async function resolveModules(
|
|
124
|
+
ast: SyntaxTree,
|
|
125
|
+
dataProvider: DataProvider,
|
|
126
|
+
options: ResolveOptions,
|
|
127
|
+
): Promise<SyntaxTree> {
|
|
128
|
+
const parse = createModuleParseFunction(options, dataProvider);
|
|
129
|
+
const listPagesCtx = await buildListPagesContext(
|
|
130
|
+
dataProvider,
|
|
131
|
+
options.requirements.listPages ?? [],
|
|
132
|
+
options.compiledListPagesTemplates,
|
|
133
|
+
parse,
|
|
134
|
+
options.urlPath,
|
|
135
|
+
);
|
|
136
|
+
const listUsersCtx = await buildListUsersContext(
|
|
137
|
+
dataProvider,
|
|
138
|
+
options.requirements.listUsers ?? [],
|
|
139
|
+
options.compiledListUsersTemplates,
|
|
140
|
+
parse,
|
|
141
|
+
);
|
|
142
|
+
const pageTags = dataProvider.getPageTags?.() ?? null;
|
|
143
|
+
|
|
144
|
+
// Resolve AST
|
|
145
|
+
const resolvedElements = walkAndResolve(ast.elements, {
|
|
146
|
+
listPages: listPagesCtx,
|
|
147
|
+
listUsers: listUsersCtx,
|
|
148
|
+
fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
|
|
149
|
+
fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
|
|
150
|
+
pageTags,
|
|
151
|
+
listPagesIdCounter: 0,
|
|
152
|
+
listUsersIdCounter: 0,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Collect style elements from resolved AST
|
|
156
|
+
const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
|
|
157
|
+
|
|
158
|
+
const result: SyntaxTree = {
|
|
159
|
+
...ast,
|
|
160
|
+
elements: finalElements,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
if (styles.length > 0) {
|
|
164
|
+
result.styles = styles;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function createModuleParseFunction(
|
|
171
|
+
options: ResolveOptions,
|
|
172
|
+
dataProvider: DataProvider,
|
|
173
|
+
): ParseFunction {
|
|
174
|
+
const transform = createModuleSourceTransform(options, dataProvider);
|
|
175
|
+
if (!transform) {
|
|
176
|
+
return options.parse;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return (source: string) => options.parse(transform(source));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function createModuleSourceTransform(
|
|
183
|
+
options: ResolveOptions,
|
|
184
|
+
dataProvider: DataProvider,
|
|
185
|
+
): ModuleSourceTransform | null {
|
|
186
|
+
if (options.transformModuleSource) {
|
|
187
|
+
return options.transformModuleSource;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!dataProvider.fetchInclude) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return (source: string) =>
|
|
195
|
+
resolveIncludes(source, dataProvider.fetchInclude!, {
|
|
196
|
+
maxIterations: options.includeMaxIterations ?? MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import type { BlockRule, ParseContext, RuleResult } from "../../types";
|
|
3
|
+
import { currentToken } from "../../types";
|
|
4
|
+
import { parseModuleBody } from "./body";
|
|
5
|
+
import { createUnknownModuleElement, moduleParseResultToElement } from "./element";
|
|
6
|
+
import { getModuleRuleByName } from "./mapping";
|
|
7
|
+
import { parseModuleOpen } from "./open";
|
|
8
|
+
|
|
9
|
+
export const moduleRule: BlockRule = {
|
|
10
|
+
name: "module",
|
|
11
|
+
startTokens: ["BLOCK_OPEN"],
|
|
12
|
+
requiresLineStart: false,
|
|
13
|
+
|
|
14
|
+
parse(ctx: ParseContext): RuleResult<Element> {
|
|
15
|
+
const openToken = currentToken(ctx);
|
|
16
|
+
if (openToken.type !== "BLOCK_OPEN") {
|
|
17
|
+
return { success: false };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const openResult = parseModuleOpen(ctx);
|
|
21
|
+
if (!openResult) {
|
|
22
|
+
return { success: false };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Page syntax disabled (e.g., forum-post mode)
|
|
26
|
+
if (!ctx.settings.enablePageSyntax) {
|
|
27
|
+
return { success: false };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Dispatch to specific module parser
|
|
31
|
+
const moduleParseRule = getModuleRuleByName(openResult.moduleName);
|
|
32
|
+
|
|
33
|
+
// Check for body based on module rule's hasBody flag
|
|
34
|
+
// For unknown modules, default to no body (they will be parsed as bodyless)
|
|
35
|
+
const bodyResult = parseModuleBody(ctx, openResult.pos, moduleParseRule?.hasBody ?? false);
|
|
36
|
+
const consumed = openResult.consumed + bodyResult.consumed;
|
|
37
|
+
|
|
38
|
+
if (moduleParseRule) {
|
|
39
|
+
const result = moduleParseRule.parse(ctx, bodyResult.pos, openResult.attrs, bodyResult.body);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
elements: [moduleParseResultToElement(result)],
|
|
44
|
+
consumed,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
elements: [
|
|
51
|
+
createUnknownModuleElement(openResult.moduleName, openResult.attrs, bodyResult.body),
|
|
52
|
+
],
|
|
53
|
+
consumed,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared callback interface for module resolution.
|
|
3
|
+
*
|
|
4
|
+
* `DataProvider` is the single object that callers pass to
|
|
5
|
+
* `resolveModules()` to supply external data. Each property is an
|
|
6
|
+
* optional async callback; if omitted the corresponding module type is
|
|
7
|
+
* left unresolved in the AST.
|
|
8
|
+
*
|
|
9
|
+
* Include resolution uses a separate API (`resolveIncludes()`)
|
|
10
|
+
* because it operates on raw wikitext before parsing, not on AST nodes.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { ListPagesDataFetcher } from "./listpages/types";
|
|
16
|
+
import type { ListUsersDataFetcher } from "./listusers/types";
|
|
17
|
+
import type { IfTagsResolver } from "./iftags/types";
|
|
18
|
+
import type { IncludeFetcher } from "./include/resolve/types";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Callback bag for supplying external data during module resolution.
|
|
22
|
+
*
|
|
23
|
+
* Pass an instance to `resolveModules()`. Every callback is optional:
|
|
24
|
+
* when a callback is missing the corresponding module node is kept as-is
|
|
25
|
+
* in the output AST — useful when you only need to resolve a subset of
|
|
26
|
+
* modules (e.g. only `[[iftags]]` on the client side).
|
|
27
|
+
*
|
|
28
|
+
* @group Module Resolution
|
|
29
|
+
*/
|
|
30
|
+
export interface DataProvider {
|
|
31
|
+
/**
|
|
32
|
+
* Fetch page data for `[[module ListPages]]` expansion.
|
|
33
|
+
*
|
|
34
|
+
* Called once per ListPages instance in the AST with the normalised
|
|
35
|
+
* query parameters extracted from the module's wikitext attributes.
|
|
36
|
+
*
|
|
37
|
+
* @security The query fields originate from **untrusted user input**.
|
|
38
|
+
* When building database queries from the returned requirement:
|
|
39
|
+
* - **Never** interpolate `req.query` / `req.rawAttributes` into SQL
|
|
40
|
+
* - **Always** use parameterised queries or prepared statements
|
|
41
|
+
* - For `order` (ORDER BY), validate against a whitelist of column names
|
|
42
|
+
*/
|
|
43
|
+
fetchListPages?: ListPagesDataFetcher;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Fetch user data for `[[module ListUsers]]` expansion.
|
|
47
|
+
*
|
|
48
|
+
* Called once per ListUsers instance with the parsed query parameters.
|
|
49
|
+
*/
|
|
50
|
+
fetchListUsers?: ListUsersDataFetcher;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Fetch raw wikitext for `[[include]]` directives that are created during
|
|
54
|
+
* module secondary transformations such as ListPages/ListUsers item rendering.
|
|
55
|
+
*
|
|
56
|
+
* Top-level include expansion still uses `resolveIncludes()` directly before
|
|
57
|
+
* parsing. This callback is only for module-rendered wikitext that needs its
|
|
58
|
+
* own include pass before being parsed again.
|
|
59
|
+
*/
|
|
60
|
+
fetchInclude?: IncludeFetcher;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Return the current page's tags for `[[iftags]]` evaluation.
|
|
64
|
+
*
|
|
65
|
+
* If provided, `[[iftags]]` blocks are evaluated and either kept or
|
|
66
|
+
* discarded based on whether the page's tags satisfy the condition.
|
|
67
|
+
* If omitted, `[[iftags]]` blocks pass through unresolved.
|
|
68
|
+
*/
|
|
69
|
+
getPageTags?: IfTagsResolver;
|
|
70
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Core type definitions for the Wikidot module system.
|
|
4
|
+
*
|
|
5
|
+
* Wikidot modules are block-level constructs invoked with `[[module Name ...]]`
|
|
6
|
+
* syntax. Each module type (ListPages, CSS, Rate, etc.) is implemented as a
|
|
7
|
+
* `ModuleRule` that defines how to parse the module's attributes and body into
|
|
8
|
+
* an AST node.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Element, Module } from "@wdprlib/ast";
|
|
14
|
+
import type { ParseContext } from "../../types";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parser function type for re-parsing substituted template output as wikitext.
|
|
18
|
+
*
|
|
19
|
+
* Used by ListPages and ListUsers modules during the resolution phase. After
|
|
20
|
+
* template variables are substituted with actual data, the resulting string
|
|
21
|
+
* needs to be parsed as wikitext to produce AST elements.
|
|
22
|
+
*
|
|
23
|
+
* @param input - Wikitext string to parse
|
|
24
|
+
* @returns Object containing the parsed elements
|
|
25
|
+
*/
|
|
26
|
+
export type ParseFunction = (input: string) => { elements: Element[] };
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Definition of a module rule that handles a specific Wikidot module type.
|
|
30
|
+
*
|
|
31
|
+
* Each module rule declares which module names it handles (e.g., "listpages",
|
|
32
|
+
* "css"), whether the module accepts a body (content between `[[module Name]]`
|
|
33
|
+
* and `[[/module]]`), and a parse function that produces the AST representation.
|
|
34
|
+
*
|
|
35
|
+
* The parse function's return type determines how the result is handled:
|
|
36
|
+
* - `Module`: Wrapped as `{ element: "module", data: Module }` in the AST
|
|
37
|
+
* - `Element`: Used directly as an AST element (e.g., CSS module returns a `style` element)
|
|
38
|
+
*/
|
|
39
|
+
export interface ModuleRule {
|
|
40
|
+
/** Internal identifier for the rule (e.g., "module-listpages") */
|
|
41
|
+
name: string;
|
|
42
|
+
/** Module names this rule handles, matched case-insensitively (e.g., ["listpages"]) */
|
|
43
|
+
acceptsNames: string[];
|
|
44
|
+
/** Whether this module accepts a body (content between `[[module]]` and `[[/module]]`) */
|
|
45
|
+
hasBody: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Parse the module's attributes and optional body into an AST node.
|
|
48
|
+
*
|
|
49
|
+
* @param ctx - Current parse context (token stream, settings, etc.)
|
|
50
|
+
* @param pos - Current token position
|
|
51
|
+
* @param args - Key-value attributes from the module's opening tag
|
|
52
|
+
* @param body - Raw text content between opening and closing tags (only if `hasBody` is true)
|
|
53
|
+
* @returns A Module data object or a direct Element
|
|
54
|
+
*/
|
|
55
|
+
parse: (
|
|
56
|
+
ctx: ParseContext,
|
|
57
|
+
pos: number,
|
|
58
|
+
args: Record<string, string>,
|
|
59
|
+
body?: string,
|
|
60
|
+
) => Module | Element;
|
|
61
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Utility functions for parsing Wikidot module attribute values.
|
|
4
|
+
*
|
|
5
|
+
* Wikidot modules accept attributes as string key-value pairs. These utilities
|
|
6
|
+
* convert common attribute types (booleans, integers) from their string
|
|
7
|
+
* representation to proper TypeScript types, following Wikidot's conventions
|
|
8
|
+
* for truthy/falsy values.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parse a boolean value from a Wikidot attribute string.
|
|
15
|
+
*
|
|
16
|
+
* Wikidot accepts both "yes"/"no" and "true"/"false" as boolean attribute values.
|
|
17
|
+
* If the value does not match any recognized boolean string, the default is returned.
|
|
18
|
+
*
|
|
19
|
+
* @param value - The attribute string value, or undefined if the attribute was not specified
|
|
20
|
+
* @param defaultValue - Value to return when the attribute is undefined or unrecognized
|
|
21
|
+
* @returns The parsed boolean value
|
|
22
|
+
*/
|
|
23
|
+
export function parseBool(value: string | undefined, defaultValue: boolean): boolean {
|
|
24
|
+
if (value === undefined) return defaultValue;
|
|
25
|
+
if (value === "yes" || value === "true") return true;
|
|
26
|
+
if (value === "no" || value === "false") return false;
|
|
27
|
+
return defaultValue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Parse a 32-bit integer value from a Wikidot attribute string.
|
|
32
|
+
*
|
|
33
|
+
* Uses base-10 parsing. Returns undefined for non-numeric strings or
|
|
34
|
+
* when the attribute is not specified.
|
|
35
|
+
*
|
|
36
|
+
* @param value - The attribute string value, or undefined if not specified
|
|
37
|
+
* @returns The parsed integer, or undefined if parsing fails
|
|
38
|
+
*/
|
|
39
|
+
export function parseInt32(value: string | undefined): number | undefined {
|
|
40
|
+
if (value === undefined) return undefined;
|
|
41
|
+
const num = Number.parseInt(value, 10);
|
|
42
|
+
return Number.isNaN(num) ? undefined : num;
|
|
43
|
+
}
|