@wdprlib/parser 3.2.0 → 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 +10451 -8402
- package/dist/index.d.cts +313 -337
- package/dist/index.d.ts +313 -337
- package/dist/index.js +10438 -8389
- package/package.json +1 -1
- package/src/index.ts +7 -0
- package/src/lexer/anchor.ts +48 -0
- package/src/lexer/index.ts +3 -2
- package/src/lexer/lexer.ts +73 -559
- 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/parser/constants.ts +2 -0
- package/src/parser/depth/index.ts +111 -0
- package/src/parser/depth/stack.ts +82 -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 +1 -1
- 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/typography.ts +70 -5
- 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.ts → center/index.ts} +7 -22
- package/src/parser/rules/block/center/open.ts +27 -0
- package/src/parser/rules/block/{clear-float.ts → clear-float/index.ts} +6 -30
- 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.ts → comment/index.ts} +12 -38
- package/src/parser/rules/block/{content-separator.ts → content-separator/index.ts} +5 -35
- 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.ts → horizontal-rule/index.ts} +4 -21
- 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.ts → iftags/index.ts} +16 -58
- 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/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/body.ts +92 -0
- package/src/parser/rules/block/module/element.ts +33 -0
- package/src/parser/rules/block/module/include/directive.ts +91 -0
- package/src/parser/rules/block/module/include/index.ts +11 -2
- 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 +14 -2
- package/src/parser/rules/block/module/listpages/compiler.ts +12 -392
- package/src/parser/rules/block/module/listpages/extract.ts +25 -359
- 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/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 +8 -324
- 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 +5 -75
- 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 +3 -160
- package/src/parser/rules/block/module/listusers/compiler.ts +4 -25
- package/src/parser/rules/block/module/listusers/extract.ts +4 -9
- package/src/parser/rules/block/module/listusers/getters.ts +21 -0
- package/src/parser/rules/block/module/listusers/variables.ts +15 -0
- package/src/parser/rules/block/module/open.ts +57 -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 +79 -292
- package/src/parser/rules/block/module/rule.ts +56 -0
- package/src/parser/rules/block/module/types-common.ts +11 -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 +10 -610
- package/src/parser/rules/{utils.ts → common/attribute-safety.ts} +3 -49
- 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/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 +2 -39
- 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.ts → comment/index.ts} +10 -36
- 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.ts → guillemet/index.ts} +5 -13
- 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.ts → html/index.ts} +9 -60
- 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/italic.ts +2 -30
- 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 +6 -81
- 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 +7 -98
- package/src/parser/rules/inline/link-star.ts +7 -69
- 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 +2 -30
- 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.ts → strikethrough/index.ts} +5 -60
- 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 +2 -39
- package/src/parser/rules/inline/superscript.ts +4 -39
- package/src/parser/rules/inline/text/element.ts +5 -0
- package/src/parser/rules/inline/{text.ts → text/index.ts} +5 -4
- 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.ts → underline/index.ts} +6 -49
- 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 -344
- package/src/parser/rules/tokens.ts +106 -0
- package/src/parser/rules/types.ts +9 -252
- package/src/parser/depth.ts +0 -251
- package/src/parser/parse.ts +0 -315
- package/src/parser/postprocess/spanStrip.ts +0 -697
- package/src/parser/preprocess/expr.ts +0 -265
- package/src/parser/preprocess/utils.ts +0 -250
- package/src/parser/preprocess/whitespace.ts +0 -111
- package/src/parser/rules/block/align.ts +0 -282
- package/src/parser/rules/block/bibliography.ts +0 -359
- package/src/parser/rules/block/block-list.ts +0 -689
- package/src/parser/rules/block/blockquote.ts +0 -238
- package/src/parser/rules/block/code.ts +0 -187
- package/src/parser/rules/block/collapsible.ts +0 -337
- package/src/parser/rules/block/definition-list.ts +0 -270
- package/src/parser/rules/block/div.ts +0 -400
- package/src/parser/rules/block/embed-block.ts +0 -153
- package/src/parser/rules/block/footnoteblock.ts +0 -200
- package/src/parser/rules/block/heading.ts +0 -142
- package/src/parser/rules/block/html.ts +0 -222
- package/src/parser/rules/block/iframe.ts +0 -239
- package/src/parser/rules/block/include.ts +0 -179
- package/src/parser/rules/block/list.ts +0 -244
- package/src/parser/rules/block/math.ts +0 -183
- package/src/parser/rules/block/module/include/resolve.ts +0 -556
- package/src/parser/rules/block/module/listpages/types.ts +0 -513
- package/src/parser/rules/block/module/walk.ts +0 -380
- package/src/parser/rules/block/module.ts +0 -164
- package/src/parser/rules/block/orphan-li.ts +0 -177
- package/src/parser/rules/block/paragraph.ts +0 -157
- package/src/parser/rules/block/table-block.ts +0 -726
- package/src/parser/rules/block/table.ts +0 -441
- package/src/parser/rules/block/tabview.ts +0 -331
- package/src/parser/rules/block/toc.ts +0 -129
- package/src/parser/rules/inline/anchor-name.ts +0 -154
- package/src/parser/rules/inline/anchor.ts +0 -327
- package/src/parser/rules/inline/bibcite.ts +0 -153
- package/src/parser/rules/inline/color.ts +0 -140
- package/src/parser/rules/inline/equation-ref.ts +0 -115
- package/src/parser/rules/inline/expr.ts +0 -526
- package/src/parser/rules/inline/footnote.ts +0 -223
- package/src/parser/rules/inline/image.ts +0 -328
- package/src/parser/rules/inline/line-break.ts +0 -326
- package/src/parser/rules/inline/link-triple.ts +0 -267
- package/src/parser/rules/inline/math-inline.ts +0 -126
- package/src/parser/rules/inline/raw.ts +0 -262
- package/src/parser/rules/inline/size.ts +0 -244
- package/src/parser/rules/inline/span.ts +0 -424
- package/src/parser/rules/inline/user.ts +0 -147
|
@@ -1,689 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Block rule for the explicit list syntax: `[[ul]]`/`[[ol]]` with `[[li]]` items.
|
|
4
|
-
*
|
|
5
|
-
* Wikidot supports two kinds of lists: the lightweight "marker" syntax
|
|
6
|
-
* (`* item`, `# item`) handled by `list.ts`, and the block-level syntax
|
|
7
|
-
* handled here:
|
|
8
|
-
*
|
|
9
|
-
* ```
|
|
10
|
-
* [[ul]]
|
|
11
|
-
* [[li]]Item 1[[/li]]
|
|
12
|
-
* [[li]]Item 2[[/li]]
|
|
13
|
-
* [[/ul]]
|
|
14
|
-
* ```
|
|
15
|
-
*
|
|
16
|
-
* Block lists can carry HTML attributes on both the list wrapper and
|
|
17
|
-
* individual items, and support arbitrary nesting. Content inside `[[li]]`
|
|
18
|
-
* may include inline markup, block elements (divs, nested tables, etc.),
|
|
19
|
-
* and even nested `[[ul]]`/`[[ol]]` sub-lists.
|
|
20
|
-
*
|
|
21
|
-
* Key Wikidot-specific behaviors reproduced here:
|
|
22
|
-
* - `[[li_]]` is NOT a valid tag and is treated as plain text.
|
|
23
|
-
* - Bare content inside `[[ul]]`/`[[ol]]` (without `[[li]]`) is wrapped in
|
|
24
|
-
* a `<li style="list-style: none">` equivalent (the `_noMarker` flag).
|
|
25
|
-
* - A `<br />` is appended after the entire block list.
|
|
26
|
-
* - Newline handling inside `[[li]]` follows Wikidot rules: single newlines
|
|
27
|
-
* become `<br />`, including trailing newlines before `[[/li]]`.
|
|
28
|
-
* - Content after `[[/li]]` but before the next `[[li]]` or close tag is
|
|
29
|
-
* included in the same list item.
|
|
30
|
-
*
|
|
31
|
-
* @module
|
|
32
|
-
*/
|
|
33
|
-
import type { Element, ListData, ListItem } from "@wdprlib/ast";
|
|
34
|
-
import type { BlockRule, ParseContext, RuleResult } from "../types";
|
|
35
|
-
import { currentToken } from "../types";
|
|
36
|
-
import { parseBlockName, parseAttributes, canApplyBlockRule } from "./utils";
|
|
37
|
-
|
|
38
|
-
/** Discriminated list type for `[[ul]]` (unordered) vs `[[ol]]` (ordered). */
|
|
39
|
-
type ListBlockType = "ul" | "ol";
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Checks whether the tokens at `pos` form a `[[/ul]]` or `[[/ol]]` closing tag.
|
|
43
|
-
*
|
|
44
|
-
* @param ctx - Parse context.
|
|
45
|
-
* @param pos - Token index to inspect.
|
|
46
|
-
* @param expectedType - When provided, only matches that specific list type.
|
|
47
|
-
* @returns `true` if a matching close tag is found.
|
|
48
|
-
*/
|
|
49
|
-
function isListClose(ctx: ParseContext, pos: number, expectedType?: ListBlockType): boolean {
|
|
50
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") return false;
|
|
51
|
-
const nameResult = parseBlockName(ctx, pos + 1);
|
|
52
|
-
if (!nameResult) return false;
|
|
53
|
-
const name = nameResult.name;
|
|
54
|
-
if (expectedType) {
|
|
55
|
-
return name === expectedType;
|
|
56
|
-
}
|
|
57
|
-
return name === "ul" || name === "ol";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Checks whether the tokens at `pos` form a `[[/li]]` closing tag.
|
|
62
|
-
*
|
|
63
|
-
* @param ctx - Parse context.
|
|
64
|
-
* @param pos - Token index to inspect.
|
|
65
|
-
* @returns `true` if `[[/li]]` is found.
|
|
66
|
-
*/
|
|
67
|
-
function isLiClose(ctx: ParseContext, pos: number): boolean {
|
|
68
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") return false;
|
|
69
|
-
const nameResult = parseBlockName(ctx, pos + 1);
|
|
70
|
-
return nameResult?.name === "li";
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Checks whether the tokens at `pos` form a `[[li]]` opening tag.
|
|
75
|
-
*
|
|
76
|
-
* Only the exact name `"li"` is accepted. Wikidot does NOT recognise
|
|
77
|
-
* `[[li_]]` (paragraph-strip variant) -- it is treated as plain text.
|
|
78
|
-
*
|
|
79
|
-
* @param ctx - Parse context.
|
|
80
|
-
* @param pos - Token index to inspect.
|
|
81
|
-
* @returns The block name and token count consumed, or `null` if not matched.
|
|
82
|
-
*/
|
|
83
|
-
function isLiOpen(ctx: ParseContext, pos: number): { name: string; consumed: number } | null {
|
|
84
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") return null;
|
|
85
|
-
const nameResult = parseBlockName(ctx, pos + 1);
|
|
86
|
-
if (!nameResult) return null;
|
|
87
|
-
// Only "li" is valid, not "li_" (Wikidot doesn't recognize li_)
|
|
88
|
-
if (nameResult.name === "li") {
|
|
89
|
-
return { name: nameResult.name, consumed: 1 + nameResult.consumed };
|
|
90
|
-
}
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Checks whether the tokens at `pos` form a `[[ul]]` or `[[ol]]` opening tag,
|
|
96
|
-
* which indicates a nested list inside the current list or list item.
|
|
97
|
-
*
|
|
98
|
-
* @param ctx - Parse context.
|
|
99
|
-
* @param pos - Token index to inspect.
|
|
100
|
-
* @returns The detected list type and token count, or `null` if not matched.
|
|
101
|
-
*/
|
|
102
|
-
function isNestedListOpen(
|
|
103
|
-
ctx: ParseContext,
|
|
104
|
-
pos: number,
|
|
105
|
-
): { type: ListBlockType; consumed: number } | null {
|
|
106
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") return null;
|
|
107
|
-
const nameResult = parseBlockName(ctx, pos + 1);
|
|
108
|
-
if (!nameResult) return null;
|
|
109
|
-
if (nameResult.name === "ul" || nameResult.name === "ol") {
|
|
110
|
-
return { type: nameResult.name as ListBlockType, consumed: 1 + nameResult.consumed };
|
|
111
|
-
}
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Consumes the tokens of a closing tag `[[/name]]` and an optional trailing
|
|
117
|
-
* NEWLINE, returning the total number of tokens consumed.
|
|
118
|
-
*
|
|
119
|
-
* @param ctx - Parse context.
|
|
120
|
-
* @param pos - Token index at the BLOCK_END_OPEN token.
|
|
121
|
-
* @returns Number of tokens consumed.
|
|
122
|
-
*/
|
|
123
|
-
function consumeCloseTag(ctx: ParseContext, pos: number): number {
|
|
124
|
-
let closeConsumed = 1; // BLOCK_END_OPEN
|
|
125
|
-
const nameResult = parseBlockName(ctx, pos + 1);
|
|
126
|
-
if (nameResult) closeConsumed += nameResult.consumed;
|
|
127
|
-
if (ctx.tokens[pos + closeConsumed]?.type === "BLOCK_CLOSE") closeConsumed++;
|
|
128
|
-
if (ctx.tokens[pos + closeConsumed]?.type === "NEWLINE") closeConsumed++;
|
|
129
|
-
return closeConsumed;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Parses a single `[[li]]...[[/li]]` list item, including its attributes
|
|
134
|
-
* and body content.
|
|
135
|
-
*
|
|
136
|
-
* Body content may include inline markup, block-level elements (except
|
|
137
|
-
* block-list itself, to prevent infinite recursion), and nested
|
|
138
|
-
* `[[ul]]`/`[[ol]]` sub-lists. Newlines inside the item follow Wikidot
|
|
139
|
-
* rules: a single newline produces `<br />`, even right before `[[/li]]`.
|
|
140
|
-
*
|
|
141
|
-
* After the `[[/li]]` tag, any trailing content before the next `[[li]]`,
|
|
142
|
-
* close tag, or nested list open is also captured into the same item,
|
|
143
|
-
* matching Wikidot's behaviour of appending post-close content to the
|
|
144
|
-
* preceding `<li>`.
|
|
145
|
-
*
|
|
146
|
-
* @param ctx - Parse context.
|
|
147
|
-
* @param startPos - Token index at the expected `[[li]]` open.
|
|
148
|
-
* @param listType - The parent list type, used to detect the list-level
|
|
149
|
-
* closing tag (`[[/ul]]` or `[[/ol]]`).
|
|
150
|
-
* @returns The parsed list item and token count, or `null` on failure.
|
|
151
|
-
*/
|
|
152
|
-
function parseLiItem(
|
|
153
|
-
ctx: ParseContext,
|
|
154
|
-
startPos: number,
|
|
155
|
-
listType: ListBlockType,
|
|
156
|
-
): { item: ListItem | Element; consumed: number } | null {
|
|
157
|
-
let pos = startPos;
|
|
158
|
-
let consumed = 0;
|
|
159
|
-
|
|
160
|
-
// Check for [[li]] open
|
|
161
|
-
const liOpen = isLiOpen(ctx, pos);
|
|
162
|
-
if (!liOpen) return null;
|
|
163
|
-
|
|
164
|
-
pos += liOpen.consumed;
|
|
165
|
-
consumed += liOpen.consumed;
|
|
166
|
-
|
|
167
|
-
// Parse attributes
|
|
168
|
-
const attrResult = parseAttributes(ctx, pos);
|
|
169
|
-
pos += attrResult.consumed;
|
|
170
|
-
consumed += attrResult.consumed;
|
|
171
|
-
|
|
172
|
-
// Expect ]]
|
|
173
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
pos++;
|
|
177
|
-
consumed++;
|
|
178
|
-
|
|
179
|
-
// Optional newline after [[li ...]]
|
|
180
|
-
const hasNewlineAfterOpen = ctx.tokens[pos]?.type === "NEWLINE";
|
|
181
|
-
if (hasNewlineAfterOpen) {
|
|
182
|
-
pos++;
|
|
183
|
-
consumed++;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Parse content until [[/li]] or [[ul]]/[[ol]] (nested list)
|
|
187
|
-
const contentElements: Element[] = [];
|
|
188
|
-
|
|
189
|
-
while (pos < ctx.tokens.length) {
|
|
190
|
-
const token = ctx.tokens[pos];
|
|
191
|
-
if (!token || token.type === "EOF") break;
|
|
192
|
-
|
|
193
|
-
// Check for [[/li]] close
|
|
194
|
-
if (isLiClose(ctx, pos)) {
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Check for [[/ul]] or [[/ol]] - unclosed li
|
|
199
|
-
if (isListClose(ctx, pos, listType)) {
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Check for nested [[ul]] or [[ol]]
|
|
204
|
-
const nestedListOpen = isNestedListOpen(ctx, pos);
|
|
205
|
-
if (nestedListOpen) {
|
|
206
|
-
const nestedResult = parseListBlock(ctx, pos, nestedListOpen.type);
|
|
207
|
-
if (nestedResult) {
|
|
208
|
-
// Add nested list directly to contentElements (maintains order)
|
|
209
|
-
contentElements.push(nestedResult.element);
|
|
210
|
-
// Wikidot adds <br /> after nested lists inside li
|
|
211
|
-
contentElements.push({ element: "line-break" });
|
|
212
|
-
consumed += nestedResult.consumed;
|
|
213
|
-
pos += nestedResult.consumed;
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Skip whitespace at beginning of lines
|
|
219
|
-
if (token.type === "WHITESPACE" && token.lineStart) {
|
|
220
|
-
pos++;
|
|
221
|
-
consumed++;
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Handle newlines
|
|
226
|
-
if (token.type === "NEWLINE") {
|
|
227
|
-
pos++;
|
|
228
|
-
consumed++;
|
|
229
|
-
// Check if next line starts with [[/li]] or nested list
|
|
230
|
-
// Count consecutive newlines
|
|
231
|
-
let consecutiveNewlines = 1;
|
|
232
|
-
while (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
233
|
-
pos++;
|
|
234
|
-
consumed++;
|
|
235
|
-
consecutiveNewlines++;
|
|
236
|
-
}
|
|
237
|
-
// Skip leading whitespace
|
|
238
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE" && ctx.tokens[pos]?.lineStart) {
|
|
239
|
-
pos++;
|
|
240
|
-
consumed++;
|
|
241
|
-
}
|
|
242
|
-
// Wikidot behavior:
|
|
243
|
-
// - Single newline followed by content or [[/li]] → <br />
|
|
244
|
-
// - Multiple newlines (paragraph break) → no <br />
|
|
245
|
-
// - Need content before this newline
|
|
246
|
-
const atCloseTag =
|
|
247
|
-
isLiClose(ctx, pos) || isListClose(ctx, pos, listType) || ctx.tokens[pos]?.type === "EOF";
|
|
248
|
-
if (consecutiveNewlines === 1 && contentElements.length > 0) {
|
|
249
|
-
// Single newline with content before - add line-break
|
|
250
|
-
// (Even before [[/li]], Wikidot adds <br /> for the trailing newline)
|
|
251
|
-
contentElements.push({ element: "line-break" });
|
|
252
|
-
}
|
|
253
|
-
if (atCloseTag) {
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Try block rules first (for div, etc. inside li)
|
|
260
|
-
let matched = false;
|
|
261
|
-
const blockCtx: ParseContext = { ...ctx, pos };
|
|
262
|
-
|
|
263
|
-
// Filter out block-list rule to avoid infinite recursion
|
|
264
|
-
const filteredBlockRules = ctx.blockRules.filter((r) => r.name !== "block-list");
|
|
265
|
-
for (const rule of filteredBlockRules) {
|
|
266
|
-
if (canApplyBlockRule(rule, token)) {
|
|
267
|
-
const result = rule.parse(blockCtx);
|
|
268
|
-
if (result.success) {
|
|
269
|
-
contentElements.push(...result.elements);
|
|
270
|
-
consumed += result.consumed;
|
|
271
|
-
pos += result.consumed;
|
|
272
|
-
matched = true;
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (matched) continue;
|
|
279
|
-
|
|
280
|
-
// Try inline rules
|
|
281
|
-
const inlineCtx: ParseContext = { ...ctx, pos };
|
|
282
|
-
for (const rule of ctx.inlineRules) {
|
|
283
|
-
if (rule.startTokens.includes(token.type)) {
|
|
284
|
-
const result = rule.parse(inlineCtx);
|
|
285
|
-
if (result.success) {
|
|
286
|
-
contentElements.push(...result.elements);
|
|
287
|
-
consumed += result.consumed;
|
|
288
|
-
pos += result.consumed;
|
|
289
|
-
matched = true;
|
|
290
|
-
break;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (!matched) {
|
|
296
|
-
// Fallback to text
|
|
297
|
-
contentElements.push({ element: "text", data: token.value });
|
|
298
|
-
consumed++;
|
|
299
|
-
pos++;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Diagnostic for missing [[/li]]
|
|
304
|
-
if (!isLiClose(ctx, pos)) {
|
|
305
|
-
ctx.diagnostics.push({
|
|
306
|
-
severity: "warning",
|
|
307
|
-
code: "unclosed-block",
|
|
308
|
-
message: "Missing closing tag [[/li]] for [[li]]",
|
|
309
|
-
position: ctx.tokens[startPos]?.position ?? {
|
|
310
|
-
start: { line: 0, column: 0, offset: 0 },
|
|
311
|
-
end: { line: 0, column: 0, offset: 0 },
|
|
312
|
-
},
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Consume [[/li]] if present
|
|
317
|
-
if (isLiClose(ctx, pos)) {
|
|
318
|
-
const closeConsumed = consumeCloseTag(ctx, pos);
|
|
319
|
-
consumed += closeConsumed;
|
|
320
|
-
pos += closeConsumed;
|
|
321
|
-
|
|
322
|
-
// Wikidot behavior: content after [[/li]] but before next [[li]] or [[/ul]]/[[/ol]]
|
|
323
|
-
// is included in the same <li> element
|
|
324
|
-
// Skip newlines first
|
|
325
|
-
while (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
326
|
-
pos++;
|
|
327
|
-
consumed++;
|
|
328
|
-
}
|
|
329
|
-
// Skip whitespace
|
|
330
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
331
|
-
pos++;
|
|
332
|
-
consumed++;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Collect trailing content until next [[li]], [[/ul]], [[/ol]], or EOF
|
|
336
|
-
while (pos < ctx.tokens.length) {
|
|
337
|
-
const tok = ctx.tokens[pos];
|
|
338
|
-
if (!tok || tok.type === "EOF") break;
|
|
339
|
-
if (tok.type === "NEWLINE") {
|
|
340
|
-
pos++;
|
|
341
|
-
consumed++;
|
|
342
|
-
// Skip consecutive newlines
|
|
343
|
-
while (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
344
|
-
pos++;
|
|
345
|
-
consumed++;
|
|
346
|
-
}
|
|
347
|
-
// Skip whitespace
|
|
348
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE" && ctx.tokens[pos]?.lineStart) {
|
|
349
|
-
pos++;
|
|
350
|
-
consumed++;
|
|
351
|
-
}
|
|
352
|
-
// Check for end conditions
|
|
353
|
-
if (
|
|
354
|
-
isLiOpen(ctx, pos) ||
|
|
355
|
-
isListClose(ctx, pos, listType) ||
|
|
356
|
-
isNestedListOpen(ctx, pos) ||
|
|
357
|
-
ctx.tokens[pos]?.type === "EOF"
|
|
358
|
-
) {
|
|
359
|
-
break;
|
|
360
|
-
}
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
if (isLiOpen(ctx, pos) || isListClose(ctx, pos, listType) || isNestedListOpen(ctx, pos)) {
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
// Parse inline content for trailing
|
|
367
|
-
let matched = false;
|
|
368
|
-
const inlineCtx: ParseContext = { ...ctx, pos };
|
|
369
|
-
for (const rule of ctx.inlineRules) {
|
|
370
|
-
if (rule.startTokens.includes(tok.type)) {
|
|
371
|
-
const result = rule.parse(inlineCtx);
|
|
372
|
-
if (result.success) {
|
|
373
|
-
contentElements.push(...result.elements);
|
|
374
|
-
consumed += result.consumed;
|
|
375
|
-
pos += result.consumed;
|
|
376
|
-
matched = true;
|
|
377
|
-
break;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
if (!matched) {
|
|
382
|
-
contentElements.push({ element: "text", data: tok.value });
|
|
383
|
-
consumed++;
|
|
384
|
-
pos++;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Regular list item with content (may include nested list as element)
|
|
390
|
-
return {
|
|
391
|
-
item: {
|
|
392
|
-
"item-type": "elements",
|
|
393
|
-
attributes: attrResult.attrs,
|
|
394
|
-
elements: contentElements,
|
|
395
|
-
} as ListItem,
|
|
396
|
-
consumed,
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Parses a complete `[[ul]]...[[/ul]]` or `[[ol]]...[[/ol]]` block,
|
|
402
|
-
* including its attributes, child `[[li]]` items, bare content, and
|
|
403
|
-
* nested sub-lists.
|
|
404
|
-
*
|
|
405
|
-
* Bare content (text without an enclosing `[[li]]`) is wrapped in an
|
|
406
|
-
* item with the `_noMarker` attribute, which the renderer translates
|
|
407
|
-
* to `<li style="list-style: none">`. When there is only a single
|
|
408
|
-
* paragraph of bare content, the paragraph wrapper is removed to match
|
|
409
|
-
* Wikidot's output.
|
|
410
|
-
*
|
|
411
|
-
* @param ctx - Parse context.
|
|
412
|
-
* @param startPos - Token index at the BLOCK_OPEN for `[[ul]]`/`[[ol]]`.
|
|
413
|
-
* @param listType - Whether this is an unordered or ordered list.
|
|
414
|
-
* @returns The list element and consumed token count, or `null` on failure.
|
|
415
|
-
*/
|
|
416
|
-
function parseListBlock(
|
|
417
|
-
ctx: ParseContext,
|
|
418
|
-
startPos: number,
|
|
419
|
-
listType: ListBlockType,
|
|
420
|
-
): { element: Element; consumed: number } | null {
|
|
421
|
-
let pos = startPos;
|
|
422
|
-
let consumed = 0;
|
|
423
|
-
|
|
424
|
-
// Skip [[ul or [[ol
|
|
425
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") return null;
|
|
426
|
-
pos++;
|
|
427
|
-
consumed++;
|
|
428
|
-
|
|
429
|
-
// Parse block name
|
|
430
|
-
const nameResult = parseBlockName(ctx, pos);
|
|
431
|
-
if (!nameResult || (nameResult.name !== "ul" && nameResult.name !== "ol")) {
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
pos += nameResult.consumed;
|
|
435
|
-
consumed += nameResult.consumed;
|
|
436
|
-
|
|
437
|
-
// Parse attributes
|
|
438
|
-
const attrResult = parseAttributes(ctx, pos);
|
|
439
|
-
pos += attrResult.consumed;
|
|
440
|
-
consumed += attrResult.consumed;
|
|
441
|
-
|
|
442
|
-
// Expect ]]
|
|
443
|
-
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
444
|
-
return null;
|
|
445
|
-
}
|
|
446
|
-
pos++;
|
|
447
|
-
consumed++;
|
|
448
|
-
|
|
449
|
-
// Wikidot: [[ul]] must be followed by newline to be recognized
|
|
450
|
-
// Exception: inline form [[ul]][[li]]...[[/li]][[/ul]] on same line is valid
|
|
451
|
-
const hasNewlineAfterOpen = ctx.tokens[pos]?.type === "NEWLINE";
|
|
452
|
-
if (hasNewlineAfterOpen) {
|
|
453
|
-
pos++;
|
|
454
|
-
consumed++;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Parse list items
|
|
458
|
-
const items: ListItem[] = [];
|
|
459
|
-
let foundListClose = false;
|
|
460
|
-
|
|
461
|
-
while (pos < ctx.tokens.length) {
|
|
462
|
-
const token = ctx.tokens[pos];
|
|
463
|
-
if (!token || token.type === "EOF") break;
|
|
464
|
-
|
|
465
|
-
// Check for [[/ul]] or [[/ol]] close
|
|
466
|
-
if (isListClose(ctx, pos, listType)) {
|
|
467
|
-
foundListClose = true;
|
|
468
|
-
const closeConsumed = consumeCloseTag(ctx, pos);
|
|
469
|
-
consumed += closeConsumed;
|
|
470
|
-
break;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Skip whitespace
|
|
474
|
-
if (token.type === "WHITESPACE") {
|
|
475
|
-
pos++;
|
|
476
|
-
consumed++;
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// Skip newlines
|
|
481
|
-
if (token.type === "NEWLINE") {
|
|
482
|
-
pos++;
|
|
483
|
-
consumed++;
|
|
484
|
-
continue;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Check for nested [[ul]] or [[ol]] without [[li]] wrapper
|
|
488
|
-
const nestedListOpen = isNestedListOpen(ctx, pos);
|
|
489
|
-
if (nestedListOpen) {
|
|
490
|
-
const nestedResult = parseListBlock(ctx, pos, nestedListOpen.type);
|
|
491
|
-
if (nestedResult && nestedResult.element.element === "list") {
|
|
492
|
-
const listData = nestedResult.element.data as ListData;
|
|
493
|
-
items.push({
|
|
494
|
-
"item-type": "sub-list",
|
|
495
|
-
element: "list",
|
|
496
|
-
data: listData,
|
|
497
|
-
});
|
|
498
|
-
consumed += nestedResult.consumed;
|
|
499
|
-
pos += nestedResult.consumed;
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// Try to parse [[li]] item
|
|
505
|
-
const liResult = parseLiItem(ctx, pos, listType);
|
|
506
|
-
if (liResult) {
|
|
507
|
-
if ("item-type" in liResult.item) {
|
|
508
|
-
items.push(liResult.item as ListItem);
|
|
509
|
-
}
|
|
510
|
-
consumed += liResult.consumed;
|
|
511
|
-
pos += liResult.consumed;
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
// Wikidot behavior: bare content inside [[ul]]/[[ol]] (without [[li]])
|
|
516
|
-
// is wrapped in <li style="list-style: none">
|
|
517
|
-
// Empty lines create paragraph breaks within the bare content
|
|
518
|
-
// Collect content until [[/ul]], [[/ol]], [[li]], or [[ul]]/[[ol]]
|
|
519
|
-
const bareContent: Element[] = [];
|
|
520
|
-
let currentParagraph: Element[] = [];
|
|
521
|
-
|
|
522
|
-
const flushParagraph = () => {
|
|
523
|
-
if (currentParagraph.length > 0) {
|
|
524
|
-
// Trim trailing line-breaks from paragraph
|
|
525
|
-
while (
|
|
526
|
-
currentParagraph.length > 0 &&
|
|
527
|
-
currentParagraph[currentParagraph.length - 1]?.element === "line-break"
|
|
528
|
-
) {
|
|
529
|
-
currentParagraph.pop();
|
|
530
|
-
}
|
|
531
|
-
if (currentParagraph.length > 0) {
|
|
532
|
-
bareContent.push({
|
|
533
|
-
element: "container",
|
|
534
|
-
data: {
|
|
535
|
-
type: "paragraph",
|
|
536
|
-
attributes: {},
|
|
537
|
-
elements: currentParagraph,
|
|
538
|
-
},
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
currentParagraph = [];
|
|
542
|
-
}
|
|
543
|
-
};
|
|
544
|
-
|
|
545
|
-
while (pos < ctx.tokens.length) {
|
|
546
|
-
const tok = ctx.tokens[pos];
|
|
547
|
-
if (!tok || tok.type === "EOF") break;
|
|
548
|
-
if (tok.type === "NEWLINE") {
|
|
549
|
-
pos++;
|
|
550
|
-
consumed++;
|
|
551
|
-
// Count consecutive newlines
|
|
552
|
-
let consecutiveNewlines = 1;
|
|
553
|
-
while (ctx.tokens[pos]?.type === "NEWLINE") {
|
|
554
|
-
pos++;
|
|
555
|
-
consumed++;
|
|
556
|
-
consecutiveNewlines++;
|
|
557
|
-
}
|
|
558
|
-
// Skip leading whitespace
|
|
559
|
-
while (ctx.tokens[pos]?.type === "WHITESPACE" && ctx.tokens[pos]?.lineStart) {
|
|
560
|
-
pos++;
|
|
561
|
-
consumed++;
|
|
562
|
-
}
|
|
563
|
-
// Check if next meaningful token is a close tag or li open
|
|
564
|
-
if (isListClose(ctx, pos, listType) || isLiOpen(ctx, pos) || isNestedListOpen(ctx, pos)) {
|
|
565
|
-
break;
|
|
566
|
-
}
|
|
567
|
-
// Multiple newlines = paragraph break
|
|
568
|
-
if (consecutiveNewlines >= 2) {
|
|
569
|
-
flushParagraph();
|
|
570
|
-
} else if (currentParagraph.length > 0) {
|
|
571
|
-
// Single newline = line break
|
|
572
|
-
currentParagraph.push({ element: "line-break" });
|
|
573
|
-
}
|
|
574
|
-
continue;
|
|
575
|
-
}
|
|
576
|
-
if (isListClose(ctx, pos, listType) || isLiOpen(ctx, pos) || isNestedListOpen(ctx, pos)) {
|
|
577
|
-
break;
|
|
578
|
-
}
|
|
579
|
-
// Parse inline content
|
|
580
|
-
let matched = false;
|
|
581
|
-
const inlineCtx: ParseContext = { ...ctx, pos };
|
|
582
|
-
for (const rule of ctx.inlineRules) {
|
|
583
|
-
if (rule.startTokens.includes(tok.type)) {
|
|
584
|
-
const result = rule.parse(inlineCtx);
|
|
585
|
-
if (result.success) {
|
|
586
|
-
currentParagraph.push(...result.elements);
|
|
587
|
-
consumed += result.consumed;
|
|
588
|
-
pos += result.consumed;
|
|
589
|
-
matched = true;
|
|
590
|
-
break;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
if (!matched) {
|
|
595
|
-
currentParagraph.push({ element: "text", data: tok.value });
|
|
596
|
-
consumed++;
|
|
597
|
-
pos++;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
// Flush remaining content
|
|
601
|
-
flushParagraph();
|
|
602
|
-
if (bareContent.length > 0) {
|
|
603
|
-
// Wikidot behavior: if there's only one paragraph, unwrap it
|
|
604
|
-
// Only use <p> tags when there are multiple paragraphs
|
|
605
|
-
let finalElements: Element[];
|
|
606
|
-
if (
|
|
607
|
-
bareContent.length === 1 &&
|
|
608
|
-
bareContent[0]?.element === "container" &&
|
|
609
|
-
(bareContent[0] as { data?: { type?: string } }).data?.type === "paragraph"
|
|
610
|
-
) {
|
|
611
|
-
// Single paragraph - unwrap
|
|
612
|
-
finalElements = (bareContent[0] as { data: { elements: Element[] } }).data.elements;
|
|
613
|
-
} else {
|
|
614
|
-
finalElements = bareContent;
|
|
615
|
-
}
|
|
616
|
-
items.push({
|
|
617
|
-
"item-type": "elements",
|
|
618
|
-
attributes: { _noMarker: "true" }, // Flag for list-style: none
|
|
619
|
-
elements: finalElements,
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
if (!foundListClose) {
|
|
625
|
-
ctx.diagnostics.push({
|
|
626
|
-
severity: "warning",
|
|
627
|
-
code: "unclosed-block",
|
|
628
|
-
message: `Missing closing tag [[/${listType}]] for [[${listType}]]`,
|
|
629
|
-
position: ctx.tokens[startPos]?.position ?? {
|
|
630
|
-
start: { line: 0, column: 0, offset: 0 },
|
|
631
|
-
end: { line: 0, column: 0, offset: 0 },
|
|
632
|
-
},
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const listData: ListData = {
|
|
637
|
-
type: listType === "ol" ? "numbered" : "bullet",
|
|
638
|
-
attributes: attrResult.attrs,
|
|
639
|
-
items,
|
|
640
|
-
};
|
|
641
|
-
|
|
642
|
-
return {
|
|
643
|
-
element: {
|
|
644
|
-
element: "list",
|
|
645
|
-
data: listData,
|
|
646
|
-
},
|
|
647
|
-
consumed,
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* Block rule for Wikidot explicit list syntax (`[[ul]]`/`[[ol]]`).
|
|
653
|
-
*
|
|
654
|
-
* The entry point verifies that the BLOCK_OPEN is followed by the name
|
|
655
|
-
* `"ul"` or `"ol"`, then delegates to `parseListBlock()`. On success
|
|
656
|
-
* a trailing `<br />` element is appended, matching Wikidot's rendering.
|
|
657
|
-
*/
|
|
658
|
-
export const blockListRule: BlockRule = {
|
|
659
|
-
name: "block-list",
|
|
660
|
-
startTokens: ["BLOCK_OPEN"],
|
|
661
|
-
requiresLineStart: false,
|
|
662
|
-
|
|
663
|
-
parse(ctx: ParseContext): RuleResult<Element> {
|
|
664
|
-
const openToken = currentToken(ctx);
|
|
665
|
-
if (openToken.type !== "BLOCK_OPEN") {
|
|
666
|
-
return { success: false };
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// Check for [[ul or [[ol
|
|
670
|
-
const nameResult = parseBlockName(ctx, ctx.pos + 1);
|
|
671
|
-
if (!nameResult || (nameResult.name !== "ul" && nameResult.name !== "ol")) {
|
|
672
|
-
return { success: false };
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
const listType = nameResult.name as ListBlockType;
|
|
676
|
-
const result = parseListBlock(ctx, ctx.pos, listType);
|
|
677
|
-
|
|
678
|
-
if (!result) {
|
|
679
|
-
return { success: false };
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// Wikidot adds <br /> after block lists
|
|
683
|
-
return {
|
|
684
|
-
success: true,
|
|
685
|
-
elements: [result.element, { element: "line-break" }],
|
|
686
|
-
consumed: result.consumed,
|
|
687
|
-
};
|
|
688
|
-
},
|
|
689
|
-
};
|