@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,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paragraph rule
|
|
3
|
+
*
|
|
4
|
+
* Collects inline content until paragraph break (double newline) or end of input.
|
|
5
|
+
* Line breaks within paragraphs are handled by the newlineLineBreakRule.
|
|
6
|
+
*/
|
|
7
|
+
import type { Element } from "@wdprlib/ast";
|
|
8
|
+
import type { BlockRule, ParseContext, RuleResult } from "../../types";
|
|
9
|
+
import { parseInlineContent } from "./content";
|
|
10
|
+
import { normalizeParagraphElements } from "./normalize";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Paragraph is the fallback block rule.
|
|
14
|
+
*
|
|
15
|
+
* Wikidot behavior:
|
|
16
|
+
* - Single newline -> <br> (handled by newlineLineBreakRule)
|
|
17
|
+
* - Blank line (double newline) -> new paragraph
|
|
18
|
+
*/
|
|
19
|
+
export const paragraphRule: BlockRule = {
|
|
20
|
+
name: "paragraph",
|
|
21
|
+
startTokens: [],
|
|
22
|
+
requiresLineStart: false,
|
|
23
|
+
|
|
24
|
+
parse(ctx: ParseContext): RuleResult<Element> {
|
|
25
|
+
const result = parseInlineContent(ctx);
|
|
26
|
+
if (result.elements.length === 0) {
|
|
27
|
+
return { success: false };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const elements = normalizeParagraphElements(result.elements);
|
|
31
|
+
if (elements.length === 0) {
|
|
32
|
+
return { success: false };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const nextPos = ctx.pos + result.consumed;
|
|
36
|
+
const nextToken = ctx.tokens[nextPos];
|
|
37
|
+
if (nextToken?.type === "COLON" && nextToken.lineStart) {
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
elements: [...elements, { element: "line-break" }],
|
|
41
|
+
consumed: result.consumed,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
elements: [
|
|
48
|
+
{
|
|
49
|
+
element: "container",
|
|
50
|
+
data: {
|
|
51
|
+
type: "paragraph",
|
|
52
|
+
attributes: {},
|
|
53
|
+
elements,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
consumed: result.consumed,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import { processCloseSpanMarkers } from "./span-markers";
|
|
3
|
+
|
|
4
|
+
type PreservedLineBreak = Extract<Element, { element: "line-break" }> & {
|
|
5
|
+
_preservedTrailingBreak?: boolean;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function normalizeParagraphElements(source: Element[]): Element[] {
|
|
9
|
+
let elements = processCloseSpanMarkers(source);
|
|
10
|
+
|
|
11
|
+
removeTrailingLineBreaks(elements);
|
|
12
|
+
removeTrailingWhitespaceText(elements);
|
|
13
|
+
elements = removeLeadingLineBreaks(elements);
|
|
14
|
+
|
|
15
|
+
return elements;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function removeTrailingLineBreaks(elements: Element[]): void {
|
|
19
|
+
while (elements.length > 0 && elements[elements.length - 1]?.element === "line-break") {
|
|
20
|
+
const lastEl = elements[elements.length - 1] as PreservedLineBreak;
|
|
21
|
+
if (lastEl._preservedTrailingBreak) {
|
|
22
|
+
delete lastEl._preservedTrailingBreak;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
elements.pop();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function removeTrailingWhitespaceText(elements: Element[]): void {
|
|
30
|
+
while (elements.length > 0) {
|
|
31
|
+
const last = elements[elements.length - 1];
|
|
32
|
+
if (
|
|
33
|
+
last?.element === "text" &&
|
|
34
|
+
"data" in last &&
|
|
35
|
+
typeof last.data === "string" &&
|
|
36
|
+
last.data.trim() === ""
|
|
37
|
+
) {
|
|
38
|
+
elements.pop();
|
|
39
|
+
} else {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function removeLeadingLineBreaks(elements: Element[]): Element[] {
|
|
46
|
+
let first = 0;
|
|
47
|
+
while (first < elements.length && elements[first]?.element === "line-break") {
|
|
48
|
+
first++;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return first > 0 ? elements.slice(first) : elements;
|
|
52
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Process closeSpan markers in inline content.
|
|
5
|
+
*
|
|
6
|
+
* When a `_closeSpan` marker is found, all preceding content is wrapped
|
|
7
|
+
* in a span and the marker itself is omitted.
|
|
8
|
+
*/
|
|
9
|
+
export function processCloseSpanMarkers(elements: Element[]): Element[] {
|
|
10
|
+
let result: Element[] | null = null;
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < elements.length; i++) {
|
|
13
|
+
const elem = elements[i];
|
|
14
|
+
if (!elem) continue;
|
|
15
|
+
|
|
16
|
+
if (isCloseSpanMarker(elem)) {
|
|
17
|
+
if (result === null) {
|
|
18
|
+
result = elements.slice(0, i);
|
|
19
|
+
}
|
|
20
|
+
if (result.length > 0) {
|
|
21
|
+
const spanContent = [...result];
|
|
22
|
+
result.length = 0;
|
|
23
|
+
result.push({
|
|
24
|
+
element: "container",
|
|
25
|
+
data: {
|
|
26
|
+
type: "span",
|
|
27
|
+
attributes: {},
|
|
28
|
+
elements: spanContent,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
result?.push(elem);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return result ?? elements;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isCloseSpanMarker(elem: Element): boolean {
|
|
41
|
+
return (
|
|
42
|
+
elem.element === "container" &&
|
|
43
|
+
elem.data &&
|
|
44
|
+
typeof elem.data === "object" &&
|
|
45
|
+
"type" in elem.data &&
|
|
46
|
+
elem.data.type === "span" &&
|
|
47
|
+
"attributes" in elem.data &&
|
|
48
|
+
typeof elem.data.attributes === "object" &&
|
|
49
|
+
elem.data.attributes !== null &&
|
|
50
|
+
"_closeSpan" in elem.data.attributes
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ParseContext } from "../../../types";
|
|
2
|
+
import { filterUnsafeAttributes } from "../../../common";
|
|
3
|
+
import { scanAttributes, type AttributeParseResult } from "./scanner";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses HTML-style attributes from block opening tags.
|
|
7
|
+
*
|
|
8
|
+
* Supports quoted values, single-token unquoted values, boolean attributes,
|
|
9
|
+
* and hyphenated names like `data-paragraph` or `aria-label`.
|
|
10
|
+
*
|
|
11
|
+
* Attribute names are lowercased. The result is filtered through
|
|
12
|
+
* `filterUnsafeAttributes` to strip potentially dangerous HTML attributes.
|
|
13
|
+
*/
|
|
14
|
+
export function parseAttributes(ctx: ParseContext, startPos: number): AttributeParseResult {
|
|
15
|
+
const result = scanAttributes(ctx, startPos, { hyphenatedNames: true, strikeHyphens: false });
|
|
16
|
+
return { attrs: filterUnsafeAttributes(result.attrs), consumed: result.consumed };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parses attributes from block opening tags without safety filtering.
|
|
21
|
+
*
|
|
22
|
+
* Use this for block-specific parameters that are not emitted as HTML
|
|
23
|
+
* attributes. Hyphenated name handling is configurable for legacy parser
|
|
24
|
+
* contexts that need the first segment only.
|
|
25
|
+
*/
|
|
26
|
+
export function parseAttributesRaw(
|
|
27
|
+
ctx: ParseContext,
|
|
28
|
+
startPos: number,
|
|
29
|
+
hyphenatedNames = true,
|
|
30
|
+
): AttributeParseResult {
|
|
31
|
+
return scanAttributes(ctx, startPos, { hyphenatedNames, strikeHyphens: true });
|
|
32
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Token } from "../../../../../lexer";
|
|
2
|
+
import type { ParseContext } from "../../../types";
|
|
3
|
+
|
|
4
|
+
export interface AttributeNameOptions {
|
|
5
|
+
hyphenatedNames: boolean;
|
|
6
|
+
strikeHyphens: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface AttributeNameResult {
|
|
10
|
+
name: string;
|
|
11
|
+
pos: number;
|
|
12
|
+
consumed: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function consumeAttributeName(
|
|
16
|
+
ctx: ParseContext,
|
|
17
|
+
startPos: number,
|
|
18
|
+
startConsumed: number,
|
|
19
|
+
startName: string,
|
|
20
|
+
options: AttributeNameOptions,
|
|
21
|
+
): AttributeNameResult {
|
|
22
|
+
return options.strikeHyphens
|
|
23
|
+
? consumeRawNameSuffix(ctx, startPos, startConsumed, startName, options.hyphenatedNames)
|
|
24
|
+
: consumeSafeNameSuffix(ctx, startPos, startConsumed, startName);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isAttributeNameToken(token: Token | undefined): token is Token {
|
|
28
|
+
return token?.type === "TEXT" || token?.type === "IDENTIFIER";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function consumeSafeNameSuffix(
|
|
32
|
+
ctx: ParseContext,
|
|
33
|
+
startPos: number,
|
|
34
|
+
startConsumed: number,
|
|
35
|
+
startName: string,
|
|
36
|
+
): AttributeNameResult {
|
|
37
|
+
let name = startName;
|
|
38
|
+
let pos = startPos;
|
|
39
|
+
let consumed = startConsumed;
|
|
40
|
+
|
|
41
|
+
while (
|
|
42
|
+
ctx.tokens[pos]?.type === "TEXT" &&
|
|
43
|
+
ctx.tokens[pos]?.value === "-" &&
|
|
44
|
+
isAttributeNameToken(ctx.tokens[pos + 1])
|
|
45
|
+
) {
|
|
46
|
+
name += "-";
|
|
47
|
+
pos++;
|
|
48
|
+
consumed++;
|
|
49
|
+
name += ctx.tokens[pos]?.value ?? "";
|
|
50
|
+
pos++;
|
|
51
|
+
consumed++;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return { name, pos, consumed };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function consumeRawNameSuffix(
|
|
58
|
+
ctx: ParseContext,
|
|
59
|
+
startPos: number,
|
|
60
|
+
startConsumed: number,
|
|
61
|
+
startName: string,
|
|
62
|
+
hyphenatedNames: boolean,
|
|
63
|
+
): AttributeNameResult {
|
|
64
|
+
let name = startName;
|
|
65
|
+
let pos = startPos;
|
|
66
|
+
let consumed = startConsumed;
|
|
67
|
+
|
|
68
|
+
while (isHyphenToken(ctx.tokens[pos])) {
|
|
69
|
+
while (isHyphenToken(ctx.tokens[pos])) {
|
|
70
|
+
if (hyphenatedNames) {
|
|
71
|
+
name += ctx.tokens[pos]?.value ?? "-";
|
|
72
|
+
}
|
|
73
|
+
pos++;
|
|
74
|
+
consumed++;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!isAttributeNameToken(ctx.tokens[pos])) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (hyphenatedNames) {
|
|
82
|
+
name += ctx.tokens[pos]?.value ?? "";
|
|
83
|
+
}
|
|
84
|
+
pos++;
|
|
85
|
+
consumed++;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { name, pos, consumed };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isHyphenToken(token: Token | undefined): boolean {
|
|
92
|
+
return (token?.type === "TEXT" && token.value === "-") || token?.type === "STRIKE_MARKER";
|
|
93
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Token } from "../../../../../lexer";
|
|
2
|
+
import type { ParseContext } from "../../../types";
|
|
3
|
+
import { consumeAttributeName, isAttributeNameToken } from "./names";
|
|
4
|
+
import { consumeAttributeValue } from "./values";
|
|
5
|
+
|
|
6
|
+
export interface AttributeParseResult {
|
|
7
|
+
attrs: Record<string, string>;
|
|
8
|
+
consumed: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface AttributeScanOptions {
|
|
12
|
+
hyphenatedNames: boolean;
|
|
13
|
+
strikeHyphens: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function scanAttributes(
|
|
17
|
+
ctx: ParseContext,
|
|
18
|
+
startPos: number,
|
|
19
|
+
options: AttributeScanOptions,
|
|
20
|
+
): AttributeParseResult {
|
|
21
|
+
const attrs: Record<string, string> = {};
|
|
22
|
+
let pos = startPos;
|
|
23
|
+
let consumed = 0;
|
|
24
|
+
|
|
25
|
+
while (pos < ctx.tokens.length) {
|
|
26
|
+
const token = ctx.tokens[pos];
|
|
27
|
+
if (!token || isAttributeTerminator(token)) {
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (token.type === "WHITESPACE") {
|
|
32
|
+
pos++;
|
|
33
|
+
consumed++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!isAttributeNameToken(token)) {
|
|
38
|
+
pos++;
|
|
39
|
+
consumed++;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let name = token.value;
|
|
44
|
+
pos++;
|
|
45
|
+
consumed++;
|
|
46
|
+
|
|
47
|
+
const nameResult = consumeAttributeName(ctx, pos, consumed, name, options);
|
|
48
|
+
pos = nameResult.pos;
|
|
49
|
+
consumed = nameResult.consumed;
|
|
50
|
+
name = nameResult.name.toLowerCase();
|
|
51
|
+
|
|
52
|
+
if (ctx.tokens[pos]?.type !== "EQUALS") {
|
|
53
|
+
attrs[name] = "true";
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pos++;
|
|
58
|
+
consumed++;
|
|
59
|
+
|
|
60
|
+
const valueResult = consumeAttributeValue(ctx.tokens[pos]);
|
|
61
|
+
if (!valueResult) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
attrs[name] = valueResult.value;
|
|
66
|
+
pos++;
|
|
67
|
+
consumed++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { attrs, consumed };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isAttributeTerminator(token: Token): boolean {
|
|
74
|
+
return token.type === "BLOCK_CLOSE" || token.type === "NEWLINE" || token.type === "EOF";
|
|
75
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Token } from "../../../../../lexer";
|
|
2
|
+
import { isAttributeNameToken } from "./names";
|
|
3
|
+
|
|
4
|
+
export interface AttributeValueResult {
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function consumeAttributeValue(token: Token | undefined): AttributeValueResult | null {
|
|
9
|
+
if (!token) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (token.type === "QUOTED_STRING") {
|
|
14
|
+
return { value: stripQuotes(token.value) };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (isAttributeNameToken(token)) {
|
|
18
|
+
return { value: token.value };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function stripQuotes(value: string): string {
|
|
25
|
+
return value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
|
|
26
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import type { ParseContext } from "../../types";
|
|
3
|
+
import { getCandidateBlockRules } from "./rule-dispatch";
|
|
4
|
+
|
|
5
|
+
export interface BlockItemResult {
|
|
6
|
+
elements: Element[];
|
|
7
|
+
consumed: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function parseBlockItem(ctx: ParseContext): BlockItemResult {
|
|
11
|
+
const token = ctx.tokens[ctx.pos];
|
|
12
|
+
if (!token) {
|
|
13
|
+
return { elements: [], consumed: 0 };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const rule of getCandidateBlockRules(ctx.blockRules, token)) {
|
|
17
|
+
const result = rule.parse(ctx);
|
|
18
|
+
if (result.success) {
|
|
19
|
+
return { elements: result.elements, consumed: result.consumed };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const fallback = ctx.blockFallbackRule.parse(ctx);
|
|
24
|
+
if (fallback.success && fallback.elements.length > 0) {
|
|
25
|
+
return { elements: fallback.elements, consumed: fallback.consumed };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { elements: [], consumed: 1 };
|
|
29
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { Element } from "@wdprlib/ast";
|
|
2
|
+
import type { ParseContext } from "../../types";
|
|
3
|
+
import { parseBlockItem } from "./block-item";
|
|
4
|
+
|
|
5
|
+
export interface BlockParseResult {
|
|
6
|
+
/** The parsed AST elements. */
|
|
7
|
+
elements: Element[];
|
|
8
|
+
/** Total number of tokens consumed from the stream. */
|
|
9
|
+
consumed: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const excludedBlockRulesCache = new WeakMap<
|
|
13
|
+
ParseContext["blockRules"],
|
|
14
|
+
WeakMap<ReadonlySet<string>, ParseContext["blockRules"]>
|
|
15
|
+
>();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parses block-level elements from the token stream until a close
|
|
19
|
+
* condition is satisfied.
|
|
20
|
+
*
|
|
21
|
+
* This is the workhorse parser used by container blocks (div, collapsible,
|
|
22
|
+
* tabview, iftags, align, etc.) to parse their body content. It loops
|
|
23
|
+
* through tokens, trying each block rule in priority order, and falls back
|
|
24
|
+
* to the paragraph rule when nothing else matches.
|
|
25
|
+
*
|
|
26
|
+
* Whitespace and newline tokens between blocks are silently consumed.
|
|
27
|
+
* The close condition receives a ParseContext snapshot at the current
|
|
28
|
+
* position and should return `true` to stop parsing (the close tag
|
|
29
|
+
* itself is NOT consumed here -- the caller handles that).
|
|
30
|
+
*
|
|
31
|
+
* The close condition is also injected into `blockCloseCondition` on
|
|
32
|
+
* the context so that the paragraph parser can respect the enclosing
|
|
33
|
+
* block's boundary.
|
|
34
|
+
*
|
|
35
|
+
* @param ctx - Parse context positioned at the start of the body.
|
|
36
|
+
* @param closeCondition - Predicate that signals the end of the block body.
|
|
37
|
+
* @param options - Optional settings.
|
|
38
|
+
* @param options.excludedBlockNames - Block names that should be excluded
|
|
39
|
+
* from both rule dispatch and paragraph-boundary detection. The named
|
|
40
|
+
* rules are filtered out of `blockRules`, and the set is propagated to
|
|
41
|
+
* the inline parser via `ParseContext.excludedBlockNames` so that
|
|
42
|
+
* `BLOCK_OPEN` / `BLOCK_END_OPEN` tokens for these names do not trigger
|
|
43
|
+
* paragraph breaks.
|
|
44
|
+
* @returns Parsed elements and total tokens consumed.
|
|
45
|
+
*/
|
|
46
|
+
export function parseBlocksUntil(
|
|
47
|
+
ctx: ParseContext,
|
|
48
|
+
closeCondition: (ctx: ParseContext) => boolean,
|
|
49
|
+
options?: { excludedBlockNames?: ReadonlySet<string> },
|
|
50
|
+
): BlockParseResult {
|
|
51
|
+
const elements: Element[] = [];
|
|
52
|
+
let consumed = 0;
|
|
53
|
+
let pos = ctx.pos;
|
|
54
|
+
|
|
55
|
+
const excluded = options?.excludedBlockNames;
|
|
56
|
+
const blockRules = excluded ? getExcludedBlockRules(ctx.blockRules, excluded) : ctx.blockRules;
|
|
57
|
+
const blockScope = {
|
|
58
|
+
...ctx.scope,
|
|
59
|
+
blockCloseCondition: closeCondition,
|
|
60
|
+
excludedBlockNames: excluded,
|
|
61
|
+
};
|
|
62
|
+
const checkCtx: ParseContext = { ...ctx, pos };
|
|
63
|
+
const blockCtx: ParseContext = {
|
|
64
|
+
...ctx,
|
|
65
|
+
pos,
|
|
66
|
+
blockRules,
|
|
67
|
+
scope: blockScope,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
while (pos < ctx.tokens.length) {
|
|
71
|
+
const token = ctx.tokens[pos];
|
|
72
|
+
if (!token || token.type === "EOF") {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check close condition
|
|
77
|
+
checkCtx.pos = pos;
|
|
78
|
+
if (closeCondition(checkCtx)) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Skip whitespace
|
|
83
|
+
if (token.type === "WHITESPACE") {
|
|
84
|
+
pos++;
|
|
85
|
+
consumed++;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Skip newlines
|
|
90
|
+
if (token.type === "NEWLINE") {
|
|
91
|
+
pos++;
|
|
92
|
+
consumed++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Pass close condition and excluded names to context
|
|
97
|
+
blockCtx.pos = pos;
|
|
98
|
+
blockCtx.scope = blockScope;
|
|
99
|
+
|
|
100
|
+
const result = parseBlockItem(blockCtx);
|
|
101
|
+
elements.push(...result.elements);
|
|
102
|
+
consumed += result.consumed;
|
|
103
|
+
pos += result.consumed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { elements, consumed };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getExcludedBlockRules(
|
|
110
|
+
blockRules: ParseContext["blockRules"],
|
|
111
|
+
excluded: ReadonlySet<string>,
|
|
112
|
+
): ParseContext["blockRules"] {
|
|
113
|
+
let byExcluded = excludedBlockRulesCache.get(blockRules);
|
|
114
|
+
if (!byExcluded) {
|
|
115
|
+
byExcluded = new WeakMap();
|
|
116
|
+
excludedBlockRulesCache.set(blockRules, byExcluded);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const cached = byExcluded.get(excluded);
|
|
120
|
+
if (cached) {
|
|
121
|
+
return cached;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const filtered = blockRules.filter((rule) => !excluded.has(rule.name));
|
|
125
|
+
byExcluded.set(excluded, filtered);
|
|
126
|
+
return filtered;
|
|
127
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
import { parseBlockName } from "../utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a reusable close-condition function that matches block end tags
|
|
6
|
+
* (`[[/name]]`) for one or more block names.
|
|
7
|
+
*
|
|
8
|
+
* The returned function inspects the tokens at `ctx.pos` and returns both
|
|
9
|
+
* whether a match was found and how many tokens the closing tag occupies
|
|
10
|
+
* (including the optional trailing NEWLINE).
|
|
11
|
+
*
|
|
12
|
+
* @param blockNames - Array of block names to match (e.g. `["div"]`).
|
|
13
|
+
* @returns A function suitable for use as a `closeCondition` argument,
|
|
14
|
+
* returning `{ matched, consumed }`.
|
|
15
|
+
*/
|
|
16
|
+
export function createBlockEndCondition(
|
|
17
|
+
blockNames: string[],
|
|
18
|
+
): (ctx: ParseContext) => { matched: boolean; consumed: number } {
|
|
19
|
+
return (ctx: ParseContext) => {
|
|
20
|
+
const token = ctx.tokens[ctx.pos];
|
|
21
|
+
if (token?.type !== "BLOCK_END_OPEN") {
|
|
22
|
+
return { matched: false, consumed: 0 };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const nameResult = parseBlockName(ctx, ctx.pos + 1);
|
|
26
|
+
if (!nameResult) {
|
|
27
|
+
return { matched: false, consumed: 0 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!blockNames.includes(nameResult.name)) {
|
|
31
|
+
return { matched: false, consumed: 0 };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Calculate consumed: [[/ + name + ]]
|
|
35
|
+
let consumed = 1 + nameResult.consumed;
|
|
36
|
+
|
|
37
|
+
// Check for closing ]]
|
|
38
|
+
const closePos = ctx.pos + 1 + nameResult.consumed;
|
|
39
|
+
if (ctx.tokens[closePos]?.type === "BLOCK_CLOSE") {
|
|
40
|
+
consumed++;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check for trailing newline
|
|
44
|
+
const newlinePos = closePos + 1;
|
|
45
|
+
if (ctx.tokens[newlinePos]?.type === "NEWLINE") {
|
|
46
|
+
consumed++;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { matched: true, consumed };
|
|
50
|
+
};
|
|
51
|
+
}
|