@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,50 @@
|
|
|
1
|
+
import type { Element, StringContainerType } from "@wdprlib/ast";
|
|
2
|
+
import type { TokenType } from "../../../../lexer";
|
|
3
|
+
import type { ParseContext, RuleResult } from "../../types";
|
|
4
|
+
import { currentToken, hasClosingMarkerBeforeNewline } from "../../types";
|
|
5
|
+
import { parseInlineUntil } from "../utils";
|
|
6
|
+
|
|
7
|
+
export function createInlineContainer(type: StringContainerType, elements: Element[]): Element {
|
|
8
|
+
return {
|
|
9
|
+
element: "container",
|
|
10
|
+
data: {
|
|
11
|
+
type,
|
|
12
|
+
attributes: {},
|
|
13
|
+
elements,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function parseSameLineDelimitedContainer(
|
|
19
|
+
ctx: ParseContext,
|
|
20
|
+
closeToken: TokenType,
|
|
21
|
+
type: StringContainerType,
|
|
22
|
+
options: { discardEmpty?: boolean } = {},
|
|
23
|
+
): RuleResult<Element> {
|
|
24
|
+
const startToken = currentToken(ctx);
|
|
25
|
+
|
|
26
|
+
if (!hasClosingMarkerBeforeNewline({ ...ctx, pos: ctx.pos + 1 }, closeToken)) {
|
|
27
|
+
return {
|
|
28
|
+
success: true,
|
|
29
|
+
elements: [{ element: "text", data: startToken.value }],
|
|
30
|
+
consumed: 1,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = parseInlineUntil({ ...ctx, pos: ctx.pos + 1 }, closeToken);
|
|
35
|
+
const consumed = 1 + result.consumed + 1;
|
|
36
|
+
|
|
37
|
+
if (options.discardEmpty === true && result.elements.length === 0) {
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
elements: [],
|
|
41
|
+
consumed,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
elements: [createInlineContainer(type, result.elements)],
|
|
48
|
+
consumed,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Parses Wikidot's guillemet (angle quotation mark) syntax.
|
|
4
|
+
*
|
|
5
|
+
* Converts ASCII double-angle-bracket sequences into their Unicode
|
|
6
|
+
* typographic equivalents:
|
|
7
|
+
* - `<<` becomes `\u00AB` (LEFT-POINTING DOUBLE ANGLE QUOTATION MARK)
|
|
8
|
+
* - `>>` becomes `\u00BB` (RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK)
|
|
9
|
+
*
|
|
10
|
+
* These typographic characters are commonly used in European languages
|
|
11
|
+
* (particularly French and Russian) as quotation marks. Wikidot provides
|
|
12
|
+
* this shorthand so authors do not need to type the Unicode characters
|
|
13
|
+
* directly.
|
|
14
|
+
*
|
|
15
|
+
* Produces a `"text"` AST element containing the Unicode character.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
import type { Element } from "@wdprlib/ast";
|
|
20
|
+
import type { InlineRule, ParseContext, RuleResult } from "../../types";
|
|
21
|
+
import { guillemetText } from "./text";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Inline rule for converting `<<` and `>>` to typographic guillemets.
|
|
25
|
+
*
|
|
26
|
+
* Triggered by `LEFT_DOUBLE_ANGLE` or `RIGHT_DOUBLE_ANGLE` tokens.
|
|
27
|
+
* This is a simple one-to-one token replacement with no content
|
|
28
|
+
* parsing or nesting.
|
|
29
|
+
*/
|
|
30
|
+
export const guillemetRule: InlineRule = {
|
|
31
|
+
name: "guillemet",
|
|
32
|
+
startTokens: ["LEFT_DOUBLE_ANGLE", "RIGHT_DOUBLE_ANGLE"],
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Converts a double-angle-bracket token to its Unicode guillemet equivalent.
|
|
36
|
+
*
|
|
37
|
+
* @param ctx - Parse context with token stream and current position
|
|
38
|
+
* @returns A successful result with a `"text"` element containing the
|
|
39
|
+
* Unicode guillemet character, or `{ success: false }` if the
|
|
40
|
+
* token is neither `<<` nor `>>`
|
|
41
|
+
*/
|
|
42
|
+
parse(ctx: ParseContext): RuleResult<Element> {
|
|
43
|
+
const token = ctx.tokens[ctx.pos];
|
|
44
|
+
const text = guillemetText(token?.type);
|
|
45
|
+
|
|
46
|
+
if (text) {
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
elements: [{ element: "text", data: text }],
|
|
50
|
+
consumed: 1,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return { success: false };
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TokenType } from "../../../../lexer";
|
|
2
|
+
|
|
3
|
+
export function guillemetText(tokenType: TokenType | undefined): string | null {
|
|
4
|
+
if (tokenType === "LEFT_DOUBLE_ANGLE") {
|
|
5
|
+
return "\u00AB";
|
|
6
|
+
}
|
|
7
|
+
if (tokenType === "RIGHT_DOUBLE_ANGLE") {
|
|
8
|
+
return "\u00BB";
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
import { parseBlockName } from "../../common";
|
|
3
|
+
import { lookaheadHasHtmlClose } from "../../block/html";
|
|
4
|
+
|
|
5
|
+
export interface DisabledHtmlBody {
|
|
6
|
+
consumed: number;
|
|
7
|
+
foundClose: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function consumeDisabledHtmlBody(ctx: ParseContext, startPos: number): DisabledHtmlBody {
|
|
11
|
+
const hasCloseAhead = lookaheadHasHtmlClose(ctx, startPos);
|
|
12
|
+
let pos = startPos;
|
|
13
|
+
let consumed = 0;
|
|
14
|
+
|
|
15
|
+
while (pos < ctx.tokens.length) {
|
|
16
|
+
const token = ctx.tokens[pos];
|
|
17
|
+
if (!token || token.type === "EOF") {
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!hasCloseAhead && token.type === "NEWLINE" && ctx.tokens[pos + 1]?.type === "NEWLINE") {
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const closeResult = tryConsumeHtmlClose(ctx, pos);
|
|
26
|
+
if (closeResult) {
|
|
27
|
+
return {
|
|
28
|
+
consumed: consumed + closeResult.consumed,
|
|
29
|
+
foundClose: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pos++;
|
|
34
|
+
consumed++;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { consumed, foundClose: false };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function tryConsumeHtmlClose(ctx: ParseContext, pos: number): { consumed: number } | null {
|
|
41
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const closeNameResult = parseBlockName(ctx, pos + 1);
|
|
46
|
+
if (closeNameResult?.name.toLowerCase() !== "html") {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let checkPos = pos + 1 + closeNameResult.consumed;
|
|
51
|
+
while (ctx.tokens[checkPos]?.type === "WHITESPACE") {
|
|
52
|
+
checkPos++;
|
|
53
|
+
}
|
|
54
|
+
if (ctx.tokens[checkPos]?.type !== "BLOCK_CLOSE") {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let consumed = checkPos - pos + 1;
|
|
59
|
+
if (ctx.tokens[checkPos + 1]?.type === "NEWLINE") {
|
|
60
|
+
consumed++;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { consumed };
|
|
64
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Inline-position gate for `[[html]]...[[/html]]` when the parser is
|
|
4
|
+
* configured with `allowHtmlBlocks: false`.
|
|
5
|
+
*
|
|
6
|
+
* The block-level {@link htmlBlockRule} already removes `[[html]]` blocks
|
|
7
|
+
* that sit at the start of a line, but the block dispatcher never
|
|
8
|
+
* reaches a `[[html]]` that appears mid-paragraph. Without this inline
|
|
9
|
+
* rule, the body of a disabled-but-inline-positioned `[[html]]` would
|
|
10
|
+
* end up parsed as paragraph text and leak into the output as escaped
|
|
11
|
+
* HTML.
|
|
12
|
+
*
|
|
13
|
+
* When enabled (`allowHtmlBlocks !== false`), the rule does nothing
|
|
14
|
+
* (returns `success: false`) so the existing paragraph behaviour is
|
|
15
|
+
* preserved: a stray inline `[[html]]` renders as text. The block-level
|
|
16
|
+
* rule handles the proper case where `[[html]]` is on its own line.
|
|
17
|
+
*
|
|
18
|
+
* When disabled (`allowHtmlBlocks === false`):
|
|
19
|
+
* - A well-formed `[[html ...]]...[[/html]]` is fully consumed and
|
|
20
|
+
* produces no AST element, emitting an `html-block-disabled` info
|
|
21
|
+
* diagnostic.
|
|
22
|
+
* - An unclosed `[[html ...]]` is consumed to the end of the token
|
|
23
|
+
* stream so the body cannot leak as inline text, emitting both
|
|
24
|
+
* `unclosed-block` (warning) and `html-block-disabled` (info).
|
|
25
|
+
*
|
|
26
|
+
* @module
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { Element } from "@wdprlib/ast";
|
|
30
|
+
import type { InlineRule, ParseContext, RuleResult } from "../../types";
|
|
31
|
+
import { currentToken } from "../../types";
|
|
32
|
+
import { consumeDisabledHtmlBody } from "./gate";
|
|
33
|
+
import { parseHtmlInlineOpen } from "./open";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Inline rule that gates `[[html]]` when the setting disallows it.
|
|
37
|
+
*/
|
|
38
|
+
export const htmlInlineRule: InlineRule = {
|
|
39
|
+
name: "html",
|
|
40
|
+
startTokens: ["BLOCK_OPEN"],
|
|
41
|
+
|
|
42
|
+
parse(ctx: ParseContext): RuleResult<Element> {
|
|
43
|
+
const openToken = currentToken(ctx);
|
|
44
|
+
if (openToken.type !== "BLOCK_OPEN") {
|
|
45
|
+
return { success: false };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const openResult = parseHtmlInlineOpen(ctx);
|
|
49
|
+
if (!openResult) {
|
|
50
|
+
return { success: false };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Enabled: leave inline `[[html]]` alone — it falls through to text
|
|
54
|
+
// rendering, matching the historical behaviour for stray block-named
|
|
55
|
+
// openers used inline.
|
|
56
|
+
if (ctx.settings.allowHtmlBlocks !== false) {
|
|
57
|
+
return { success: false };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const bodyResult = consumeDisabledHtmlBody(ctx, openResult.bodyStart);
|
|
61
|
+
const consumed = openResult.consumed + bodyResult.consumed;
|
|
62
|
+
|
|
63
|
+
if (!bodyResult.foundClose) {
|
|
64
|
+
ctx.diagnostics.push({
|
|
65
|
+
severity: "warning",
|
|
66
|
+
code: "unclosed-block",
|
|
67
|
+
message: "Missing closing tag [[/html]] for [[html]]",
|
|
68
|
+
position: openToken.position,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ctx.diagnostics.push({
|
|
73
|
+
severity: "info",
|
|
74
|
+
code: "html-block-disabled",
|
|
75
|
+
message: "[[html]] block ignored: disabled by settings",
|
|
76
|
+
position: openToken.position,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return { success: true, elements: [], consumed };
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
import { parseAttributesRaw, parseBlockName } from "../../block/utils";
|
|
3
|
+
|
|
4
|
+
export interface HtmlInlineOpenResult {
|
|
5
|
+
bodyStart: number;
|
|
6
|
+
consumed: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function parseHtmlInlineOpen(ctx: ParseContext): HtmlInlineOpenResult | null {
|
|
10
|
+
if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let pos = ctx.pos + 1;
|
|
15
|
+
let consumed = 1;
|
|
16
|
+
|
|
17
|
+
const nameResult = parseBlockName(ctx, pos);
|
|
18
|
+
if (!nameResult || nameResult.name.toLowerCase() !== "html") {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pos += nameResult.consumed;
|
|
23
|
+
consumed += nameResult.consumed;
|
|
24
|
+
|
|
25
|
+
const attrResult = parseAttributesRaw(ctx, pos);
|
|
26
|
+
pos += attrResult.consumed;
|
|
27
|
+
consumed += attrResult.consumed;
|
|
28
|
+
|
|
29
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pos++;
|
|
34
|
+
consumed++;
|
|
35
|
+
|
|
36
|
+
return { bodyStart: pos, consumed };
|
|
37
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AttributeMap } from "@wdprlib/ast";
|
|
2
|
+
import type { ParseContext } from "../../types";
|
|
3
|
+
import { parseAttributesRaw } from "../../block/utils";
|
|
4
|
+
import { filterUnsafeAttributes } from "../../common";
|
|
5
|
+
|
|
6
|
+
export interface ImageAttributes {
|
|
7
|
+
attributes: AttributeMap;
|
|
8
|
+
link: string | null;
|
|
9
|
+
consumed: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function parseImageAttributes(ctx: ParseContext, startPos: number): ImageAttributes {
|
|
13
|
+
const result = parseAttributesRaw(ctx, startPos, false);
|
|
14
|
+
const link = result.attrs.link ?? null;
|
|
15
|
+
const { link: _link, ...htmlAttributes } = result.attrs;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
attributes: filterUnsafeAttributes(htmlAttributes),
|
|
19
|
+
link,
|
|
20
|
+
consumed: result.consumed,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
|
|
3
|
+
export interface ImageSourceText {
|
|
4
|
+
sourceText: string;
|
|
5
|
+
consumed: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function parseImageSourceText(ctx: ParseContext, startPos: number): ImageSourceText {
|
|
9
|
+
let pos = startPos;
|
|
10
|
+
let consumed = 0;
|
|
11
|
+
|
|
12
|
+
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
13
|
+
pos++;
|
|
14
|
+
consumed++;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let sourceText = "";
|
|
18
|
+
while (pos < ctx.tokens.length) {
|
|
19
|
+
const token = ctx.tokens[pos];
|
|
20
|
+
if (
|
|
21
|
+
!token ||
|
|
22
|
+
token.type === "WHITESPACE" ||
|
|
23
|
+
token.type === "BLOCK_CLOSE" ||
|
|
24
|
+
token.type === "NEWLINE" ||
|
|
25
|
+
token.type === "EOF"
|
|
26
|
+
) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
sourceText += token.value;
|
|
31
|
+
pos++;
|
|
32
|
+
consumed++;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { sourceText, consumed };
|
|
36
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Parses the Wikidot image block syntax: `[[image source attributes]]`.
|
|
4
|
+
*
|
|
5
|
+
* Images support several alignment/float prefixes that modify how the
|
|
6
|
+
* image is positioned on the page:
|
|
7
|
+
* - `[[image src]]` -- default (no alignment)
|
|
8
|
+
* - `[[=image src]]` -- centered
|
|
9
|
+
* - `[[<image src]]` -- left-aligned
|
|
10
|
+
* - `[[>image src]]` -- right-aligned
|
|
11
|
+
* - `[[f<image src]]` -- float left
|
|
12
|
+
* - `[[f>image src]]` -- float right
|
|
13
|
+
* - `[[f=image src]]` -- float center
|
|
14
|
+
*
|
|
15
|
+
* Image sources can be:
|
|
16
|
+
* - Full URLs (`http://...`, `https://...`, `/path`)
|
|
17
|
+
* - Local file references in three formats:
|
|
18
|
+
* - `file.ext` (file on current page, type `file1`)
|
|
19
|
+
* - `page/file.ext` (file on another page, type `file2`)
|
|
20
|
+
* - `site:page/file.ext` or `site/page/file.ext` (cross-site file, type `file3`)
|
|
21
|
+
*
|
|
22
|
+
* Optional attributes follow the source (e.g. `alt`, `title`, `width`,
|
|
23
|
+
* `height`, `style`, `class`, `link`). The `link` attribute is treated
|
|
24
|
+
* specially: it wraps the image in a hyperlink rather than being applied
|
|
25
|
+
* as an HTML attribute. Unsafe attributes are filtered out.
|
|
26
|
+
*
|
|
27
|
+
* Produces an `"image"` AST element with source, alignment, link, and
|
|
28
|
+
* attribute data.
|
|
29
|
+
*
|
|
30
|
+
* @module
|
|
31
|
+
*/
|
|
32
|
+
import type { Element } from "@wdprlib/ast";
|
|
33
|
+
import type { InlineRule, ParseContext, RuleResult } from "../../types";
|
|
34
|
+
import { currentToken } from "../../types";
|
|
35
|
+
import { parseImageOpen } from "./open";
|
|
36
|
+
import { parseAlignment, parseImageSource } from "./source";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Inline rule for parsing `[[image source attributes]]` and its alignment variants.
|
|
40
|
+
*
|
|
41
|
+
* Triggered by a `BLOCK_OPEN` (`[[`) token. The rule identifies the image
|
|
42
|
+
* block name (with optional alignment prefix), extracts the image source,
|
|
43
|
+
* parses remaining attributes, filters unsafe attributes, and extracts the
|
|
44
|
+
* `link` attribute for special handling.
|
|
45
|
+
*
|
|
46
|
+
* Fails if the block name is not an image variant, if no source is provided,
|
|
47
|
+
* or if `]]` is not found.
|
|
48
|
+
*/
|
|
49
|
+
export const imageRule: InlineRule = {
|
|
50
|
+
name: "image",
|
|
51
|
+
startTokens: ["BLOCK_OPEN"],
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Attempts to parse an image block at the current position.
|
|
55
|
+
*
|
|
56
|
+
* @param ctx - Parse context with token stream and current position
|
|
57
|
+
* @returns A successful result with an `"image"` element, or `{ success: false }`
|
|
58
|
+
*/
|
|
59
|
+
parse(ctx: ParseContext): RuleResult<Element> {
|
|
60
|
+
const openToken = currentToken(ctx);
|
|
61
|
+
if (openToken.type !== "BLOCK_OPEN") {
|
|
62
|
+
return { success: false };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const openResult = parseImageOpen(ctx);
|
|
66
|
+
if (!openResult) {
|
|
67
|
+
return { success: false };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const source = parseImageSource(openResult.sourceText);
|
|
71
|
+
const alignment = parseAlignment(openResult.blockName);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
elements: [
|
|
76
|
+
{
|
|
77
|
+
element: "image",
|
|
78
|
+
data: {
|
|
79
|
+
source,
|
|
80
|
+
link: openResult.link,
|
|
81
|
+
alignment,
|
|
82
|
+
attributes: openResult.attributes,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
consumed: openResult.consumed,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
import { parseImageAttributes } from "./attributes";
|
|
3
|
+
import { parseImageSourceText } from "./body";
|
|
4
|
+
import { isImageBlockName, parseImageBlockName } from "./syntax";
|
|
5
|
+
|
|
6
|
+
export interface ImageOpenResult {
|
|
7
|
+
blockName: string;
|
|
8
|
+
sourceText: string;
|
|
9
|
+
link: string | null;
|
|
10
|
+
attributes: Record<string, string>;
|
|
11
|
+
consumed: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function parseImageOpen(ctx: ParseContext): ImageOpenResult | null {
|
|
15
|
+
if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let pos = ctx.pos + 1;
|
|
20
|
+
let consumed = 1;
|
|
21
|
+
|
|
22
|
+
const nameResult = parseImageBlockName(ctx, pos);
|
|
23
|
+
if (!nameResult || !isImageBlockName(nameResult.name)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pos += nameResult.consumed;
|
|
28
|
+
consumed += nameResult.consumed;
|
|
29
|
+
|
|
30
|
+
const sourceText = parseImageSourceText(ctx, pos);
|
|
31
|
+
pos += sourceText.consumed;
|
|
32
|
+
consumed += sourceText.consumed;
|
|
33
|
+
|
|
34
|
+
const attrs = parseImageAttributes(ctx, pos);
|
|
35
|
+
pos += attrs.consumed;
|
|
36
|
+
consumed += attrs.consumed;
|
|
37
|
+
|
|
38
|
+
if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pos++;
|
|
43
|
+
consumed++;
|
|
44
|
+
|
|
45
|
+
if (!sourceText.sourceText) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
blockName: nameResult.name,
|
|
51
|
+
sourceText: sourceText.sourceText,
|
|
52
|
+
link: attrs.link,
|
|
53
|
+
attributes: attrs.attributes,
|
|
54
|
+
consumed,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Alignment, FloatAlignment, ImageSource } from "@wdprlib/ast";
|
|
2
|
+
|
|
3
|
+
export function parseImageSource(src: string): ImageSource {
|
|
4
|
+
if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("/")) {
|
|
5
|
+
return { type: "url", data: src };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const colonIdx = src.indexOf(":");
|
|
9
|
+
const slashIdx = src.indexOf("/");
|
|
10
|
+
|
|
11
|
+
if (colonIdx > 0 && slashIdx > colonIdx) {
|
|
12
|
+
const site = src.substring(0, colonIdx);
|
|
13
|
+
const rest = src.substring(colonIdx + 1);
|
|
14
|
+
const lastSlash = rest.lastIndexOf("/");
|
|
15
|
+
const page = rest.substring(0, lastSlash);
|
|
16
|
+
const file = rest.substring(lastSlash + 1);
|
|
17
|
+
return { type: "file3", data: { site, page, file } };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const slashes = src.split("/").length - 1;
|
|
21
|
+
if (slashes >= 2) {
|
|
22
|
+
const firstSlash = src.indexOf("/");
|
|
23
|
+
const lastSlash = src.lastIndexOf("/");
|
|
24
|
+
const site = src.substring(0, firstSlash);
|
|
25
|
+
const page = src.substring(firstSlash + 1, lastSlash);
|
|
26
|
+
const file = src.substring(lastSlash + 1);
|
|
27
|
+
return { type: "file3", data: { site, page, file } };
|
|
28
|
+
}
|
|
29
|
+
if (slashIdx > 0) {
|
|
30
|
+
const page = src.substring(0, slashIdx);
|
|
31
|
+
const file = src.substring(slashIdx + 1);
|
|
32
|
+
return { type: "file2", data: { page, file } };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { type: "file1", data: { file: src } };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function parseAlignment(blockName: string): FloatAlignment | null {
|
|
39
|
+
let align: Alignment = "left";
|
|
40
|
+
let float = false;
|
|
41
|
+
|
|
42
|
+
if (blockName === "=image") {
|
|
43
|
+
align = "center";
|
|
44
|
+
} else if (blockName === "<image") {
|
|
45
|
+
align = "left";
|
|
46
|
+
} else if (blockName === ">image") {
|
|
47
|
+
align = "right";
|
|
48
|
+
} else if (blockName === "f<image") {
|
|
49
|
+
align = "left";
|
|
50
|
+
float = true;
|
|
51
|
+
} else if (blockName === "f>image") {
|
|
52
|
+
align = "right";
|
|
53
|
+
float = true;
|
|
54
|
+
} else if (blockName === "f=image") {
|
|
55
|
+
align = "center";
|
|
56
|
+
float = true;
|
|
57
|
+
} else if (blockName === "image") {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { align, float };
|
|
62
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ParseContext } from "../../types";
|
|
2
|
+
|
|
3
|
+
const IMAGE_BLOCK_NAMES = new Set([
|
|
4
|
+
"image",
|
|
5
|
+
"=image",
|
|
6
|
+
"<image",
|
|
7
|
+
">image",
|
|
8
|
+
"f<image",
|
|
9
|
+
"f>image",
|
|
10
|
+
"f=image",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
export interface ImageBlockName {
|
|
14
|
+
name: string;
|
|
15
|
+
consumed: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function parseImageBlockName(ctx: ParseContext, startPos: number): ImageBlockName | null {
|
|
19
|
+
let pos = startPos;
|
|
20
|
+
let consumed = 0;
|
|
21
|
+
|
|
22
|
+
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
23
|
+
pos++;
|
|
24
|
+
consumed++;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const prefixResult = parseImagePrefix(ctx, pos);
|
|
28
|
+
const prefix = prefixResult.prefix;
|
|
29
|
+
pos += prefixResult.consumed;
|
|
30
|
+
consumed += prefixResult.consumed;
|
|
31
|
+
|
|
32
|
+
const nameToken = ctx.tokens[pos];
|
|
33
|
+
if (!nameToken || (nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER")) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { name: prefix + nameToken.value.toLowerCase(), consumed: consumed + 1 };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isImageBlockName(blockName: string): boolean {
|
|
41
|
+
return IMAGE_BLOCK_NAMES.has(blockName);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function parseImagePrefix(ctx: ParseContext, pos: number): { prefix: string; consumed: number } {
|
|
45
|
+
const token = ctx.tokens[pos];
|
|
46
|
+
|
|
47
|
+
if (token?.type === "EQUALS") {
|
|
48
|
+
return { prefix: "=", consumed: 1 };
|
|
49
|
+
}
|
|
50
|
+
if (token?.type === "TEXT" && token.value === "<") {
|
|
51
|
+
return { prefix: "<", consumed: 1 };
|
|
52
|
+
}
|
|
53
|
+
if ((token?.type === "TEXT" || token?.type === "BLOCKQUOTE_MARKER") && token.value === ">") {
|
|
54
|
+
return { prefix: ">", consumed: 1 };
|
|
55
|
+
}
|
|
56
|
+
if (token?.type === "IDENTIFIER" && token.value.toLowerCase() === "f") {
|
|
57
|
+
return parseFloatPrefix(ctx, pos + 1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { prefix: "", consumed: 0 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseFloatPrefix(ctx: ParseContext, pos: number): { prefix: string; consumed: number } {
|
|
64
|
+
const token = ctx.tokens[pos];
|
|
65
|
+
if (token?.type === "TEXT" && token.value === "<") {
|
|
66
|
+
return { prefix: "f<", consumed: 2 };
|
|
67
|
+
}
|
|
68
|
+
if ((token?.type === "TEXT" || token?.type === "BLOCKQUOTE_MARKER") && token.value === ">") {
|
|
69
|
+
return { prefix: "f>", consumed: 2 };
|
|
70
|
+
}
|
|
71
|
+
if (token?.type === "EQUALS") {
|
|
72
|
+
return { prefix: "f=", consumed: 2 };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { prefix: "", consumed: 0 };
|
|
76
|
+
}
|