@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.
Files changed (433) hide show
  1. package/dist/index.cjs +10451 -8402
  2. package/dist/index.d.cts +313 -337
  3. package/dist/index.d.ts +313 -337
  4. package/dist/index.js +10438 -8389
  5. package/package.json +1 -1
  6. package/src/index.ts +7 -0
  7. package/src/lexer/anchor.ts +48 -0
  8. package/src/lexer/index.ts +3 -2
  9. package/src/lexer/lexer.ts +73 -559
  10. package/src/lexer/options.ts +19 -0
  11. package/src/lexer/punctuation.ts +70 -0
  12. package/src/lexer/quoted-string.ts +16 -0
  13. package/src/lexer/runs.ts +85 -0
  14. package/src/lexer/spacing-actions.ts +24 -0
  15. package/src/lexer/state.ts +103 -0
  16. package/src/lexer/syntax-actions.ts +80 -0
  17. package/src/lexer/text-actions.ts +41 -0
  18. package/src/lexer/token-actions.ts +136 -0
  19. package/src/lexer/token-factory.ts +62 -0
  20. package/src/lexer/tokenize.ts +18 -0
  21. package/src/parser/constants.ts +2 -0
  22. package/src/parser/depth/index.ts +111 -0
  23. package/src/parser/depth/stack.ts +82 -0
  24. package/src/parser/parse/block.ts +42 -0
  25. package/src/parser/parse/context.ts +26 -0
  26. package/src/parser/parse/footnotes.ts +25 -0
  27. package/src/parser/parse/index.ts +42 -0
  28. package/src/parser/parse/options.ts +34 -0
  29. package/src/parser/parse/parser.ts +79 -0
  30. package/src/parser/parse/plain-non-ascii.ts +129 -0
  31. package/src/parser/parse/result.ts +57 -0
  32. package/src/parser/parse/source.ts +11 -0
  33. package/src/parser/postprocess/divAdjacentParagraph.ts +1 -1
  34. package/src/parser/postprocess/spanStrip/clean-element.ts +168 -0
  35. package/src/parser/postprocess/spanStrip/cleanup.ts +25 -0
  36. package/src/parser/postprocess/spanStrip/empty-spans.ts +36 -0
  37. package/src/parser/postprocess/spanStrip/escaped.ts +78 -0
  38. package/src/parser/postprocess/spanStrip/factory.ts +23 -0
  39. package/src/parser/postprocess/spanStrip/index.ts +8 -0
  40. package/src/parser/postprocess/spanStrip/merge.ts +117 -0
  41. package/src/parser/postprocess/spanStrip/predicates.ts +59 -0
  42. package/src/parser/postprocess/spanStrip/split.ts +67 -0
  43. package/src/parser/preprocess/expr/chars.ts +15 -0
  44. package/src/parser/preprocess/expr/evaluate.ts +22 -0
  45. package/src/parser/preprocess/expr/index.ts +45 -0
  46. package/src/parser/preprocess/expr/kind.ts +19 -0
  47. package/src/parser/preprocess/expr/parse.ts +103 -0
  48. package/src/parser/preprocess/expr/scan.ts +34 -0
  49. package/src/parser/preprocess/expr/types.ts +14 -0
  50. package/src/parser/preprocess/typography.ts +70 -5
  51. package/src/parser/preprocess/utils/bracket-depths.ts +98 -0
  52. package/src/parser/preprocess/utils/index.ts +13 -0
  53. package/src/parser/preprocess/utils/raw-regions.ts +153 -0
  54. package/src/parser/preprocess/whitespace/detection.ts +39 -0
  55. package/src/parser/preprocess/whitespace/index.ts +79 -0
  56. package/src/parser/preprocess/whitespace/leading-spaces.ts +11 -0
  57. package/src/parser/preprocess/whitespace/patterns.ts +23 -0
  58. package/src/parser/rules/block/align/body.ts +46 -0
  59. package/src/parser/rules/block/align/element.ts +13 -0
  60. package/src/parser/rules/block/align/index.ts +90 -0
  61. package/src/parser/rules/block/align/syntax.ts +113 -0
  62. package/src/parser/rules/block/bibliography/body.ts +81 -0
  63. package/src/parser/rules/block/bibliography/entries.ts +49 -0
  64. package/src/parser/rules/block/bibliography/entry-content.ts +73 -0
  65. package/src/parser/rules/block/bibliography/entry-key.ts +83 -0
  66. package/src/parser/rules/block/bibliography/index.ts +90 -0
  67. package/src/parser/rules/block/bibliography/open.ts +53 -0
  68. package/src/parser/rules/block/block-list/bare-content.ts +105 -0
  69. package/src/parser/rules/block/block-list/bare-paragraph.ts +60 -0
  70. package/src/parser/rules/block/block-list/index.ts +51 -0
  71. package/src/parser/rules/block/block-list/item-content.ts +132 -0
  72. package/src/parser/rules/block/block-list/li-content.ts +107 -0
  73. package/src/parser/rules/block/block-list/li-item.ts +77 -0
  74. package/src/parser/rules/block/block-list/list-block.ts +100 -0
  75. package/src/parser/rules/block/block-list/open.ts +51 -0
  76. package/src/parser/rules/block/block-list/tags.ts +50 -0
  77. package/src/parser/rules/block/blockquote/build.ts +62 -0
  78. package/src/parser/rules/block/blockquote/index.ts +80 -0
  79. package/src/parser/rules/block/blockquote/line.ts +79 -0
  80. package/src/parser/rules/block/blockquote/lines.ts +39 -0
  81. package/src/parser/rules/block/{center.ts → center/index.ts} +7 -22
  82. package/src/parser/rules/block/center/open.ts +27 -0
  83. package/src/parser/rules/block/{clear-float.ts → clear-float/index.ts} +6 -30
  84. package/src/parser/rules/block/clear-float/syntax.ts +43 -0
  85. package/src/parser/rules/block/code/attributes.ts +30 -0
  86. package/src/parser/rules/block/code/content.ts +57 -0
  87. package/src/parser/rules/block/code/index.ts +100 -0
  88. package/src/parser/rules/block/collapsible/attributes.ts +95 -0
  89. package/src/parser/rules/block/collapsible/body.ts +69 -0
  90. package/src/parser/rules/block/collapsible/index.ts +117 -0
  91. package/src/parser/rules/block/collapsible/open.ts +51 -0
  92. package/src/parser/rules/block/collapsible/orphans.ts +31 -0
  93. package/src/parser/rules/block/collapsible/tags.ts +17 -0
  94. package/src/parser/rules/block/comment/consume.ts +37 -0
  95. package/src/parser/rules/block/{comment.ts → comment/index.ts} +12 -38
  96. package/src/parser/rules/block/{content-separator.ts → content-separator/index.ts} +5 -35
  97. package/src/parser/rules/block/content-separator/syntax.ts +33 -0
  98. package/src/parser/rules/block/definition-list/collect.ts +40 -0
  99. package/src/parser/rules/block/definition-list/index.ts +63 -0
  100. package/src/parser/rules/block/definition-list/item-key.ts +95 -0
  101. package/src/parser/rules/block/definition-list/item-value.ts +56 -0
  102. package/src/parser/rules/block/definition-list/items.ts +54 -0
  103. package/src/parser/rules/block/div/body.ts +41 -0
  104. package/src/parser/rules/block/div/close.ts +41 -0
  105. package/src/parser/rules/block/div/failed.ts +117 -0
  106. package/src/parser/rules/block/div/index.ts +112 -0
  107. package/src/parser/rules/block/div/nesting.ts +37 -0
  108. package/src/parser/rules/block/div/open.ts +59 -0
  109. package/src/parser/rules/block/div/paragraph-strip.ts +44 -0
  110. package/src/parser/rules/block/embed-block/content.ts +53 -0
  111. package/src/parser/rules/block/embed-block/index.ts +91 -0
  112. package/src/parser/rules/block/embed-block/open.ts +52 -0
  113. package/src/parser/rules/block/embed-block/tags.ts +5 -0
  114. package/src/parser/rules/block/footnoteblock/attributes.ts +73 -0
  115. package/src/parser/rules/block/footnoteblock/index.ts +82 -0
  116. package/src/parser/rules/block/footnoteblock/open.ts +53 -0
  117. package/src/parser/rules/block/heading/index.ts +87 -0
  118. package/src/parser/rules/block/heading/open.ts +50 -0
  119. package/src/parser/rules/block/heading/toc-text.ts +26 -0
  120. package/src/parser/rules/block/{horizontal-rule.ts → horizontal-rule/index.ts} +4 -21
  121. package/src/parser/rules/block/horizontal-rule/syntax.ts +21 -0
  122. package/src/parser/rules/block/html/body.ts +114 -0
  123. package/src/parser/rules/block/html/diagnostics.ts +11 -0
  124. package/src/parser/rules/block/html/index.ts +95 -0
  125. package/src/parser/rules/block/html/open.ts +36 -0
  126. package/src/parser/rules/block/iframe/attributes.ts +106 -0
  127. package/src/parser/rules/block/iframe/index.ts +73 -0
  128. package/src/parser/rules/block/iframe/open.ts +58 -0
  129. package/src/parser/rules/block/iframe/source.ts +24 -0
  130. package/src/parser/rules/block/iframe/url.ts +38 -0
  131. package/src/parser/rules/block/iftags/body.ts +48 -0
  132. package/src/parser/rules/block/iftags/condition.ts +24 -0
  133. package/src/parser/rules/block/{iftags.ts → iftags/index.ts} +16 -58
  134. package/src/parser/rules/block/include/arguments.ts +48 -0
  135. package/src/parser/rules/block/include/index.ts +75 -0
  136. package/src/parser/rules/block/include/location.ts +24 -0
  137. package/src/parser/rules/block/include/variables.ts +37 -0
  138. package/src/parser/rules/block/list/index.ts +73 -0
  139. package/src/parser/rules/block/list/line.ts +77 -0
  140. package/src/parser/rules/block/list/native.ts +89 -0
  141. package/src/parser/rules/block/math/content.ts +54 -0
  142. package/src/parser/rules/block/math/index.ts +106 -0
  143. package/src/parser/rules/block/math/name.ts +35 -0
  144. package/src/parser/rules/block/module/body.ts +92 -0
  145. package/src/parser/rules/block/module/element.ts +33 -0
  146. package/src/parser/rules/block/module/include/directive.ts +91 -0
  147. package/src/parser/rules/block/module/include/index.ts +11 -2
  148. package/src/parser/rules/block/module/include/references.ts +42 -0
  149. package/src/parser/rules/block/module/include/resolve/cache.ts +44 -0
  150. package/src/parser/rules/block/module/include/resolve/index.ts +106 -0
  151. package/src/parser/rules/block/module/include/resolve/iterate.ts +202 -0
  152. package/src/parser/rules/block/module/include/resolve/replace.ts +31 -0
  153. package/src/parser/rules/block/module/include/resolve/types.ts +105 -0
  154. package/src/parser/rules/block/module/include/scanner.ts +121 -0
  155. package/src/parser/rules/block/module/index.ts +14 -2
  156. package/src/parser/rules/block/module/listpages/compiler.ts +12 -392
  157. package/src/parser/rules/block/module/listpages/extract.ts +25 -359
  158. package/src/parser/rules/block/module/listpages/extraction/listpages.ts +42 -0
  159. package/src/parser/rules/block/module/listpages/extraction/listusers.ts +30 -0
  160. package/src/parser/rules/block/module/listpages/extraction/query.ts +51 -0
  161. package/src/parser/rules/block/module/listpages/extraction/result.ts +18 -0
  162. package/src/parser/rules/block/module/listpages/extraction/template.ts +96 -0
  163. package/src/parser/rules/block/module/listpages/extraction/variables.ts +58 -0
  164. package/src/parser/rules/block/module/listpages/normalization/date-selector.ts +53 -0
  165. package/src/parser/rules/block/module/listpages/normalization/numeric-selector.ts +32 -0
  166. package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +82 -0
  167. package/src/parser/rules/block/module/listpages/normalization/selectors.ts +2 -0
  168. package/src/parser/rules/block/module/listpages/normalization/tags-category.ts +86 -0
  169. package/src/parser/rules/block/module/listpages/normalize.ts +8 -324
  170. package/src/parser/rules/block/module/listpages/resolution/items.ts +43 -0
  171. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +42 -0
  172. package/src/parser/rules/block/module/listpages/resolve.ts +5 -75
  173. package/src/parser/rules/block/module/listpages/template/format/content.ts +41 -0
  174. package/src/parser/rules/block/module/listpages/template/format/date.ts +116 -0
  175. package/src/parser/rules/block/module/listpages/template/format/index.ts +4 -0
  176. package/src/parser/rules/block/module/listpages/template/format/tags.ts +7 -0
  177. package/src/parser/rules/block/module/listpages/template/format/user.ts +9 -0
  178. package/src/parser/rules/block/module/listpages/template/getters/index.ts +36 -0
  179. package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +60 -0
  180. package/src/parser/rules/block/module/listpages/template/getters/simple.ts +65 -0
  181. package/src/parser/rules/block/module/listpages/template/getters/types.ts +3 -0
  182. package/src/parser/rules/block/module/listpages/template/syntax.ts +97 -0
  183. package/src/parser/rules/block/module/listpages/types/data-fetcher.ts +15 -0
  184. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +52 -0
  185. package/src/parser/rules/block/module/listpages/types/external-data.ts +77 -0
  186. package/src/parser/rules/block/module/listpages/types/index.ts +17 -0
  187. package/src/parser/rules/block/module/listpages/types/normalized-query.ts +120 -0
  188. package/src/parser/rules/block/module/listpages/types/query.ts +67 -0
  189. package/src/parser/rules/block/module/listpages/types/template.ts +17 -0
  190. package/src/parser/rules/block/module/listpages/types/variables.ts +69 -0
  191. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +48 -0
  192. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +19 -0
  193. package/src/parser/rules/block/module/listpages/url-resolution/query.ts +24 -0
  194. package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +53 -0
  195. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +25 -0
  196. package/src/parser/rules/block/module/listpages/url-resolver.ts +3 -160
  197. package/src/parser/rules/block/module/listusers/compiler.ts +4 -25
  198. package/src/parser/rules/block/module/listusers/extract.ts +4 -9
  199. package/src/parser/rules/block/module/listusers/getters.ts +21 -0
  200. package/src/parser/rules/block/module/listusers/variables.ts +15 -0
  201. package/src/parser/rules/block/module/open.ts +57 -0
  202. package/src/parser/rules/block/module/resolution/contexts.ts +78 -0
  203. package/src/parser/rules/block/module/resolution/data-maps.ts +39 -0
  204. package/src/parser/rules/block/module/resolution/dynamic-modules.ts +93 -0
  205. package/src/parser/rules/block/module/resolution/styles.ts +53 -0
  206. package/src/parser/rules/block/module/resolution/walk-resolve.ts +107 -0
  207. package/src/parser/rules/block/module/resolve.ts +79 -292
  208. package/src/parser/rules/block/module/rule.ts +56 -0
  209. package/src/parser/rules/block/module/types-common.ts +11 -0
  210. package/src/parser/rules/block/module/walk/children.ts +35 -0
  211. package/src/parser/rules/block/module/walk/index.ts +9 -0
  212. package/src/parser/rules/block/module/walk/map/index.ts +2 -0
  213. package/src/parser/rules/block/module/walk/map/stateful-definition-list.ts +25 -0
  214. package/src/parser/rules/block/module/walk/map/stateful-list.ts +40 -0
  215. package/src/parser/rules/block/module/walk/map/stateful-table.ts +23 -0
  216. package/src/parser/rules/block/module/walk/map/stateful-tabs.ts +19 -0
  217. package/src/parser/rules/block/module/walk/map/stateful.ts +71 -0
  218. package/src/parser/rules/block/module/walk/map/stateless-definition-list.ts +12 -0
  219. package/src/parser/rules/block/module/walk/map/stateless-list.ts +29 -0
  220. package/src/parser/rules/block/module/walk/map/stateless-table.ts +11 -0
  221. package/src/parser/rules/block/module/walk/map/stateless-tabs.ts +5 -0
  222. package/src/parser/rules/block/module/walk/map/stateless.ts +51 -0
  223. package/src/parser/rules/block/module/walk/map/types.ts +6 -0
  224. package/src/parser/rules/block/module/walk/traverse.ts +65 -0
  225. package/src/parser/rules/block/orphan-li/content.ts +60 -0
  226. package/src/parser/rules/block/orphan-li/index.ts +75 -0
  227. package/src/parser/rules/block/orphan-li/open.ts +25 -0
  228. package/src/parser/rules/block/orphan-li/tags.ts +40 -0
  229. package/src/parser/rules/block/paragraph/content.ts +12 -0
  230. package/src/parser/rules/block/paragraph/index.ts +60 -0
  231. package/src/parser/rules/block/paragraph/normalize.ts +52 -0
  232. package/src/parser/rules/block/paragraph/span-markers.ts +52 -0
  233. package/src/parser/rules/block/parsing/attributes/index.ts +32 -0
  234. package/src/parser/rules/block/parsing/attributes/names.ts +93 -0
  235. package/src/parser/rules/block/parsing/attributes/scanner.ts +75 -0
  236. package/src/parser/rules/block/parsing/attributes/values.ts +26 -0
  237. package/src/parser/rules/block/parsing/block-item.ts +29 -0
  238. package/src/parser/rules/block/parsing/content.ts +127 -0
  239. package/src/parser/rules/block/parsing/end-condition.ts +51 -0
  240. package/src/parser/rules/block/parsing/inline-content.ts +105 -0
  241. package/src/parser/rules/block/parsing/inline-newline.ts +41 -0
  242. package/src/parser/rules/block/parsing/non-boundary.ts +24 -0
  243. package/src/parser/rules/block/parsing/rule-dispatch.ts +44 -0
  244. package/src/parser/rules/block/table/index.ts +80 -0
  245. package/src/parser/rules/block/table/pipe/cell-start.ts +69 -0
  246. package/src/parser/rules/block/table/pipe/cell.ts +106 -0
  247. package/src/parser/rules/block/table/pipe/index.ts +2 -0
  248. package/src/parser/rules/block/table/pipe/row.ts +88 -0
  249. package/src/parser/rules/block/table/pipe/tokens.ts +14 -0
  250. package/src/parser/rules/block/table/pipe/trim.ts +50 -0
  251. package/src/parser/rules/block/table-block/body.ts +79 -0
  252. package/src/parser/rules/block/table-block/cell-attributes.ts +33 -0
  253. package/src/parser/rules/block/table-block/cell-boundary.ts +99 -0
  254. package/src/parser/rules/block/table-block/cell-content/index.ts +88 -0
  255. package/src/parser/rules/block/table-block/cell-content/segments.ts +134 -0
  256. package/src/parser/rules/block/table-block/cell-newline.ts +47 -0
  257. package/src/parser/rules/block/table-block/cell.ts +64 -0
  258. package/src/parser/rules/block/table-block/index.ts +113 -0
  259. package/src/parser/rules/block/table-block/row-boundary.ts +75 -0
  260. package/src/parser/rules/block/table-block/structure.ts +80 -0
  261. package/src/parser/rules/block/tabview/body.ts +64 -0
  262. package/src/parser/rules/block/tabview/index.ts +90 -0
  263. package/src/parser/rules/block/tabview/open.ts +50 -0
  264. package/src/parser/rules/block/tabview/tab.ts +92 -0
  265. package/src/parser/rules/block/tabview/tags.ts +30 -0
  266. package/src/parser/rules/block/toc/element.ts +11 -0
  267. package/src/parser/rules/block/toc/index.ts +44 -0
  268. package/src/parser/rules/block/toc/open.ts +84 -0
  269. package/src/parser/rules/block/utils.ts +10 -610
  270. package/src/parser/rules/{utils.ts → common/attribute-safety.ts} +3 -49
  271. package/src/parser/rules/common/block-name.ts +33 -0
  272. package/src/parser/rules/common/index.ts +2 -0
  273. package/src/parser/rules/contracts/index.ts +3 -0
  274. package/src/parser/rules/contracts/parse-context.ts +38 -0
  275. package/src/parser/rules/contracts/rule.ts +43 -0
  276. package/src/parser/rules/contracts/scope.ts +31 -0
  277. package/src/parser/rules/inline/anchor/attributes.ts +54 -0
  278. package/src/parser/rules/inline/anchor/child.ts +26 -0
  279. package/src/parser/rules/inline/anchor/close.ts +34 -0
  280. package/src/parser/rules/inline/anchor/content.ts +59 -0
  281. package/src/parser/rules/inline/anchor/index.ts +103 -0
  282. package/src/parser/rules/inline/anchor/newline.ts +26 -0
  283. package/src/parser/rules/inline/anchor/open.ts +47 -0
  284. package/src/parser/rules/inline/anchor/paragraph-strip.ts +14 -0
  285. package/src/parser/rules/inline/anchor/syntax.ts +40 -0
  286. package/src/parser/rules/inline/anchor-name/index.ts +38 -0
  287. package/src/parser/rules/inline/anchor-name/name.ts +39 -0
  288. package/src/parser/rules/inline/anchor-name/syntax.ts +46 -0
  289. package/src/parser/rules/inline/bibcite/element.ts +14 -0
  290. package/src/parser/rules/inline/bibcite/index.ts +34 -0
  291. package/src/parser/rules/inline/bibcite/syntax.ts +64 -0
  292. package/src/parser/rules/inline/bold.ts +2 -39
  293. package/src/parser/rules/inline/color/index.ts +35 -0
  294. package/src/parser/rules/inline/color/syntax.ts +69 -0
  295. package/src/parser/rules/inline/comment/consume.ts +31 -0
  296. package/src/parser/rules/inline/{comment.ts → comment/index.ts} +10 -36
  297. package/src/parser/rules/inline/equation-ref/element.ts +8 -0
  298. package/src/parser/rules/inline/equation-ref/index.ts +34 -0
  299. package/src/parser/rules/inline/equation-ref/syntax.ts +45 -0
  300. package/src/parser/rules/inline/expr/branch.ts +104 -0
  301. package/src/parser/rules/inline/expr/conditional-branch.ts +27 -0
  302. package/src/parser/rules/inline/expr/conditional.ts +80 -0
  303. package/src/parser/rules/inline/expr/depth.ts +25 -0
  304. package/src/parser/rules/inline/expr/elements.ts +39 -0
  305. package/src/parser/rules/inline/expr/index.ts +84 -0
  306. package/src/parser/rules/inline/expr/syntax.ts +45 -0
  307. package/src/parser/rules/inline/footnote/child.ts +22 -0
  308. package/src/parser/rules/inline/footnote/close.ts +33 -0
  309. package/src/parser/rules/inline/footnote/content.ts +54 -0
  310. package/src/parser/rules/inline/footnote/elements.ts +38 -0
  311. package/src/parser/rules/inline/footnote/index.ts +54 -0
  312. package/src/parser/rules/inline/footnote/newline.ts +27 -0
  313. package/src/parser/rules/inline/footnote/open.ts +38 -0
  314. package/src/parser/rules/inline/formatting/container.ts +50 -0
  315. package/src/parser/rules/inline/{guillemet.ts → guillemet/index.ts} +5 -13
  316. package/src/parser/rules/inline/guillemet/text.ts +11 -0
  317. package/src/parser/rules/inline/html/gate.ts +64 -0
  318. package/src/parser/rules/inline/{html.ts → html/index.ts} +9 -60
  319. package/src/parser/rules/inline/html/open.ts +37 -0
  320. package/src/parser/rules/inline/image/attributes.ts +22 -0
  321. package/src/parser/rules/inline/image/body.ts +36 -0
  322. package/src/parser/rules/inline/image/index.ts +89 -0
  323. package/src/parser/rules/inline/image/open.ts +56 -0
  324. package/src/parser/rules/inline/image/source.ts +62 -0
  325. package/src/parser/rules/inline/image/syntax.ts +76 -0
  326. package/src/parser/rules/inline/italic.ts +2 -30
  327. package/src/parser/rules/inline/line-break/backslash.ts +58 -0
  328. package/src/parser/rules/inline/line-break/elements.ts +9 -0
  329. package/src/parser/rules/inline/line-break/index.ts +3 -0
  330. package/src/parser/rules/inline/line-break/newline.ts +82 -0
  331. package/src/parser/rules/inline/line-break/underscore.ts +45 -0
  332. package/src/parser/rules/inline/link-anchor.ts +6 -81
  333. package/src/parser/rules/inline/link-bracket/anchor.ts +3 -0
  334. package/src/parser/rules/inline/link-bracket/direct-url.ts +5 -0
  335. package/src/parser/rules/inline/link-bracket/parsed.ts +81 -0
  336. package/src/parser/rules/inline/link-bracket/parts.ts +64 -0
  337. package/src/parser/rules/inline/link-bracket/prefix.ts +15 -0
  338. package/src/parser/rules/inline/link-single.ts +7 -98
  339. package/src/parser/rules/inline/link-star.ts +7 -69
  340. package/src/parser/rules/inline/link-triple/fallback.ts +10 -0
  341. package/src/parser/rules/inline/link-triple/index.ts +62 -0
  342. package/src/parser/rules/inline/link-triple/interwiki.ts +11 -0
  343. package/src/parser/rules/inline/link-triple/label.ts +35 -0
  344. package/src/parser/rules/inline/link-triple/syntax.ts +72 -0
  345. package/src/parser/rules/inline/link-triple/target.ts +36 -0
  346. package/src/parser/rules/inline/math-inline/index.ts +40 -0
  347. package/src/parser/rules/inline/math-inline/syntax.ts +55 -0
  348. package/src/parser/rules/inline/monospace.ts +2 -30
  349. package/src/parser/rules/inline/parsing/block-boundary.ts +42 -0
  350. package/src/parser/rules/inline/parsing/block-start-predicates.ts +117 -0
  351. package/src/parser/rules/inline/parsing/collect.ts +23 -0
  352. package/src/parser/rules/inline/parsing/inline-content.ts +115 -0
  353. package/src/parser/rules/inline/parsing/paragraph-boundary.ts +47 -0
  354. package/src/parser/rules/inline/parsing/plain-text.ts +69 -0
  355. package/src/parser/rules/inline/parsing/preserved-line-break.ts +11 -0
  356. package/src/parser/rules/inline/parsing/rules.ts +34 -0
  357. package/src/parser/rules/inline/parsing/simple-token.ts +26 -0
  358. package/src/parser/rules/inline/raw/angle.ts +40 -0
  359. package/src/parser/rules/inline/raw/double-at.ts +78 -0
  360. package/src/parser/rules/inline/raw/index.ts +26 -0
  361. package/src/parser/rules/inline/raw/result.ts +26 -0
  362. package/src/parser/rules/inline/size/content.ts +65 -0
  363. package/src/parser/rules/inline/size/index.ts +55 -0
  364. package/src/parser/rules/inline/size/open.ts +43 -0
  365. package/src/parser/rules/inline/size/value.ts +45 -0
  366. package/src/parser/rules/inline/span/content.ts +97 -0
  367. package/src/parser/rules/inline/span/elements.ts +108 -0
  368. package/src/parser/rules/inline/span/index.ts +79 -0
  369. package/src/parser/rules/inline/span/newline.ts +50 -0
  370. package/src/parser/rules/inline/span/syntax.ts +70 -0
  371. package/src/parser/rules/inline/{strikethrough.ts → strikethrough/index.ts} +5 -60
  372. package/src/parser/rules/inline/strikethrough/parse.ts +14 -0
  373. package/src/parser/rules/inline/strikethrough/syntax.ts +24 -0
  374. package/src/parser/rules/inline/subscript.ts +2 -39
  375. package/src/parser/rules/inline/superscript.ts +4 -39
  376. package/src/parser/rules/inline/text/element.ts +5 -0
  377. package/src/parser/rules/inline/{text.ts → text/index.ts} +5 -4
  378. package/src/parser/rules/inline/underline/child.ts +26 -0
  379. package/src/parser/rules/inline/underline/content.ts +29 -0
  380. package/src/parser/rules/inline/{underline.ts → underline/index.ts} +6 -49
  381. package/src/parser/rules/inline/user/element.ts +11 -0
  382. package/src/parser/rules/inline/user/index.ts +34 -0
  383. package/src/parser/rules/inline/user/syntax.ts +67 -0
  384. package/src/parser/rules/inline/utils.ts +4 -344
  385. package/src/parser/rules/tokens.ts +106 -0
  386. package/src/parser/rules/types.ts +9 -252
  387. package/src/parser/depth.ts +0 -251
  388. package/src/parser/parse.ts +0 -315
  389. package/src/parser/postprocess/spanStrip.ts +0 -697
  390. package/src/parser/preprocess/expr.ts +0 -265
  391. package/src/parser/preprocess/utils.ts +0 -250
  392. package/src/parser/preprocess/whitespace.ts +0 -111
  393. package/src/parser/rules/block/align.ts +0 -282
  394. package/src/parser/rules/block/bibliography.ts +0 -359
  395. package/src/parser/rules/block/block-list.ts +0 -689
  396. package/src/parser/rules/block/blockquote.ts +0 -238
  397. package/src/parser/rules/block/code.ts +0 -187
  398. package/src/parser/rules/block/collapsible.ts +0 -337
  399. package/src/parser/rules/block/definition-list.ts +0 -270
  400. package/src/parser/rules/block/div.ts +0 -400
  401. package/src/parser/rules/block/embed-block.ts +0 -153
  402. package/src/parser/rules/block/footnoteblock.ts +0 -200
  403. package/src/parser/rules/block/heading.ts +0 -142
  404. package/src/parser/rules/block/html.ts +0 -222
  405. package/src/parser/rules/block/iframe.ts +0 -239
  406. package/src/parser/rules/block/include.ts +0 -179
  407. package/src/parser/rules/block/list.ts +0 -244
  408. package/src/parser/rules/block/math.ts +0 -183
  409. package/src/parser/rules/block/module/include/resolve.ts +0 -556
  410. package/src/parser/rules/block/module/listpages/types.ts +0 -513
  411. package/src/parser/rules/block/module/walk.ts +0 -380
  412. package/src/parser/rules/block/module.ts +0 -164
  413. package/src/parser/rules/block/orphan-li.ts +0 -177
  414. package/src/parser/rules/block/paragraph.ts +0 -157
  415. package/src/parser/rules/block/table-block.ts +0 -726
  416. package/src/parser/rules/block/table.ts +0 -441
  417. package/src/parser/rules/block/tabview.ts +0 -331
  418. package/src/parser/rules/block/toc.ts +0 -129
  419. package/src/parser/rules/inline/anchor-name.ts +0 -154
  420. package/src/parser/rules/inline/anchor.ts +0 -327
  421. package/src/parser/rules/inline/bibcite.ts +0 -153
  422. package/src/parser/rules/inline/color.ts +0 -140
  423. package/src/parser/rules/inline/equation-ref.ts +0 -115
  424. package/src/parser/rules/inline/expr.ts +0 -526
  425. package/src/parser/rules/inline/footnote.ts +0 -223
  426. package/src/parser/rules/inline/image.ts +0 -328
  427. package/src/parser/rules/inline/line-break.ts +0 -326
  428. package/src/parser/rules/inline/link-triple.ts +0 -267
  429. package/src/parser/rules/inline/math-inline.ts +0 -126
  430. package/src/parser/rules/inline/raw.ts +0 -262
  431. package/src/parser/rules/inline/size.ts +0 -244
  432. package/src/parser/rules/inline/span.ts +0 -424
  433. package/src/parser/rules/inline/user.ts +0 -147
@@ -0,0 +1,168 @@
1
+ import type { DefinitionListItem, Element, ListItem } from "@wdprlib/ast";
2
+ import type { InternalContainerData } from "./predicates";
3
+
4
+ type CleanElements = (elements: Element[]) => Element[];
5
+
6
+ export function cleanElement(el: Element, cleanElements: CleanElements): Element {
7
+ if (el.element === "line-break") {
8
+ return cleanLineBreak(el);
9
+ }
10
+
11
+ if (el.element === "container") {
12
+ return cleanContainer(el, cleanElements);
13
+ }
14
+
15
+ if (el.element === "collapsible") {
16
+ const elements = cleanElements(el.data.elements);
17
+ if (elements === el.data.elements) {
18
+ return el;
19
+ }
20
+ return {
21
+ element: "collapsible",
22
+ data: {
23
+ ...el.data,
24
+ elements,
25
+ },
26
+ };
27
+ }
28
+
29
+ if (el.element === "color") {
30
+ const elements = cleanElements(el.data.elements);
31
+ if (elements === el.data.elements) {
32
+ return el;
33
+ }
34
+ return {
35
+ element: "color",
36
+ data: {
37
+ ...el.data,
38
+ elements,
39
+ },
40
+ };
41
+ }
42
+
43
+ if (el.element === "list") {
44
+ let items: typeof el.data.items | null = null;
45
+ for (let i = 0; i < el.data.items.length; i++) {
46
+ const item = el.data.items[i]!;
47
+ const cleaned = cleanListItem(item, cleanElements);
48
+ if (items !== null) {
49
+ items.push(cleaned);
50
+ } else if (cleaned !== item) {
51
+ items = el.data.items.slice(0, i);
52
+ items.push(cleaned);
53
+ }
54
+ }
55
+
56
+ if (items === null) {
57
+ return el;
58
+ }
59
+
60
+ return {
61
+ element: "list",
62
+ data: {
63
+ ...el.data,
64
+ items,
65
+ },
66
+ };
67
+ }
68
+
69
+ if (el.element === "definition-list") {
70
+ let items: typeof el.data | null = null;
71
+ for (let i = 0; i < el.data.length; i++) {
72
+ const item = el.data[i]!;
73
+ const cleaned = cleanDefinitionListItem(item, cleanElements);
74
+ if (items !== null) {
75
+ items.push(cleaned);
76
+ } else if (cleaned !== item) {
77
+ items = el.data.slice(0, i);
78
+ items.push(cleaned);
79
+ }
80
+ }
81
+
82
+ if (items === null) {
83
+ return el;
84
+ }
85
+
86
+ return {
87
+ element: "definition-list",
88
+ data: items,
89
+ };
90
+ }
91
+
92
+ return el;
93
+ }
94
+
95
+ function cleanLineBreak(el: Element): Element {
96
+ for (const key in el) {
97
+ if (key !== "element") {
98
+ return { element: "line-break" };
99
+ }
100
+ }
101
+ return el;
102
+ }
103
+
104
+ function cleanContainer(
105
+ el: Extract<Element, { element: "container" }>,
106
+ cleanElements: CleanElements,
107
+ ): Element {
108
+ const data = el.data as InternalContainerData;
109
+ const elements = cleanElements(data.elements);
110
+ const hasInternalFlags =
111
+ data._paragraphStrip !== undefined ||
112
+ data._emptyParagraphStrip !== undefined ||
113
+ data._escapedFromParagraph !== undefined ||
114
+ data._splitByBlankLine !== undefined;
115
+
116
+ if (!hasInternalFlags && elements === data.elements) {
117
+ return el;
118
+ }
119
+
120
+ return {
121
+ element: "container",
122
+ data: {
123
+ type: data.type,
124
+ attributes: data.attributes,
125
+ elements,
126
+ },
127
+ };
128
+ }
129
+
130
+ function cleanListItem(item: ListItem, cleanElements: CleanElements): ListItem {
131
+ if (item["item-type"] === "elements") {
132
+ const elements = cleanElements(item.elements);
133
+ return elements === item.elements
134
+ ? item
135
+ : {
136
+ ...item,
137
+ elements,
138
+ };
139
+ }
140
+
141
+ if (item["item-type"] === "sub-list") {
142
+ const cleanedList = cleanElement({ element: "list", data: item.data }, cleanElements);
143
+ return cleanedList.element === "list" && cleanedList.data !== item.data
144
+ ? {
145
+ "item-type": "sub-list",
146
+ element: "list",
147
+ data: cleanedList.data,
148
+ }
149
+ : item;
150
+ }
151
+
152
+ return item;
153
+ }
154
+
155
+ function cleanDefinitionListItem(
156
+ item: DefinitionListItem,
157
+ cleanElements: CleanElements,
158
+ ): DefinitionListItem {
159
+ const key = cleanElements(item.key);
160
+ const value = cleanElements(item.value);
161
+ return key === item.key && value === item.value
162
+ ? item
163
+ : {
164
+ ...item,
165
+ key,
166
+ value,
167
+ };
168
+ }
@@ -0,0 +1,25 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { cleanElement } from "./clean-element";
3
+ import { removeEmptySpansAndAdjacentWhitespace } from "./empty-spans";
4
+
5
+ /**
6
+ * Recursively remove internal flags from AST elements and clean up empty spans.
7
+ */
8
+ export function cleanInternalFlags(elements: Element[]): Element[] {
9
+ let cleaned: Element[] | null = null;
10
+
11
+ for (let i = 0; i < elements.length; i++) {
12
+ const el = elements[i];
13
+ if (!el) continue;
14
+
15
+ const next = cleanElement(el, cleanInternalFlags);
16
+ if (cleaned !== null) {
17
+ cleaned.push(next);
18
+ } else if (next !== el) {
19
+ cleaned = elements.slice(0, i);
20
+ cleaned.push(next);
21
+ }
22
+ }
23
+
24
+ return removeEmptySpansAndAdjacentWhitespace(cleaned ?? elements);
25
+ }
@@ -0,0 +1,36 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { isEmptySpan, isWhitespaceText } from "./predicates";
3
+
4
+ export function removeEmptySpansAndAdjacentWhitespace(elements: Element[]): Element[] {
5
+ let hasEmptySpan = false;
6
+ for (const el of elements) {
7
+ if (el && isEmptySpan(el)) {
8
+ hasEmptySpan = true;
9
+ break;
10
+ }
11
+ }
12
+ if (!hasEmptySpan) {
13
+ return elements;
14
+ }
15
+
16
+ const result: Element[] = [];
17
+
18
+ for (let i = 0; i < elements.length; i++) {
19
+ const el = elements[i];
20
+ if (!el) continue;
21
+
22
+ if (isEmptySpan(el)) {
23
+ if (result.length > 0 && isWhitespaceText(result[result.length - 1]!)) {
24
+ result.pop();
25
+ }
26
+ while (i + 1 < elements.length && elements[i + 1] && isWhitespaceText(elements[i + 1]!)) {
27
+ i++;
28
+ }
29
+ continue;
30
+ }
31
+
32
+ result.push(el);
33
+ }
34
+
35
+ return result;
36
+ }
@@ -0,0 +1,78 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { spanElement } from "./factory";
3
+ import {
4
+ getContainerData,
5
+ isEscapedSpan,
6
+ isSpanStripMarker,
7
+ type InternalContainerData,
8
+ } from "./predicates";
9
+
10
+ export function extractEscapedSpans(children: Element[]): Element[] {
11
+ const escaped: Element[] = [];
12
+
13
+ let firstEscapedIndex = -1;
14
+ for (let i = 0; i < children.length; i++) {
15
+ const child = children[i];
16
+ if (child && isEscapedSpan(child)) {
17
+ firstEscapedIndex = i;
18
+ break;
19
+ }
20
+ }
21
+
22
+ if (firstEscapedIndex === -1) {
23
+ return escaped;
24
+ }
25
+
26
+ let currentSpanChildren: Element[] = [];
27
+
28
+ for (let i = firstEscapedIndex; i < children.length; i++) {
29
+ const child = children[i];
30
+ if (!child) continue;
31
+
32
+ if (isEscapedSpan(child)) {
33
+ if (currentSpanChildren.length > 0) {
34
+ escaped.push(spanElement(currentSpanChildren));
35
+ currentSpanChildren = [];
36
+ }
37
+ escaped.push(child);
38
+ } else if (isSpanStripMarker(child)) {
39
+ const childData = getContainerData(child);
40
+ if (childData) {
41
+ escaped.push(spanElement(childData.elements, childData.attributes));
42
+ }
43
+ } else {
44
+ currentSpanChildren.push(child);
45
+ }
46
+ }
47
+
48
+ if (currentSpanChildren.length > 0) {
49
+ escaped.push(spanElement(currentSpanChildren));
50
+ }
51
+
52
+ children.splice(firstEscapedIndex);
53
+
54
+ return escaped;
55
+ }
56
+
57
+ export function removeLineBreaksAroundSpanStrip(children: Element[]): void {
58
+ for (let i = children.length - 1; i >= 0; i--) {
59
+ const child = children[i];
60
+ if (!child) continue;
61
+
62
+ if (child.element === "line-break") {
63
+ const prev = children[i - 1];
64
+ const next = children[i + 1];
65
+ if (isSpanStripMarker(prev) || isSpanStripMarker(next)) {
66
+ children.splice(i, 1);
67
+ continue;
68
+ }
69
+ }
70
+
71
+ if (child.element === "container") {
72
+ const data = child.data as InternalContainerData;
73
+ if (data.type === "span" && data._emptyParagraphStrip) {
74
+ children.splice(i, 1);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,23 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+
3
+ export function paragraphElement(elements: Element[]): Element {
4
+ return {
5
+ element: "container",
6
+ data: {
7
+ type: "paragraph",
8
+ attributes: {},
9
+ elements,
10
+ },
11
+ };
12
+ }
13
+
14
+ export function spanElement(elements: Element[], attributes: Record<string, string> = {}): Element {
15
+ return {
16
+ element: "container",
17
+ data: {
18
+ type: "span",
19
+ attributes,
20
+ elements,
21
+ },
22
+ };
23
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public facade for span-strip post-processing.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ export { mergeSpanStripParagraphs } from "./merge";
8
+ export { cleanInternalFlags } from "./cleanup";
@@ -0,0 +1,117 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { extractEscapedSpans, removeLineBreaksAroundSpanStrip } from "./escaped";
3
+ import { paragraphElement } from "./factory";
4
+ import {
5
+ getContainerData,
6
+ hasParagraphStripSpan,
7
+ isContainer,
8
+ isEmptyExpr,
9
+ isSplitSpan,
10
+ } from "./predicates";
11
+ import { splitParagraphAtBlankLineSpans, splitParagraphAtEmptyExpr } from "./split";
12
+
13
+ /**
14
+ * Merge and split paragraphs according to Wikidot's `span_` and expr behaviors.
15
+ */
16
+ export function mergeSpanStripParagraphs(children: Element[]): Element[] {
17
+ const expandedChildren = expandSplitParagraphs(children);
18
+ const result: Element[] = [];
19
+ let i = 0;
20
+
21
+ while (i < expandedChildren.length) {
22
+ const node = expandedChildren[i];
23
+
24
+ if (!node || !isContainer(node, "paragraph")) {
25
+ if (node) result.push(node);
26
+ i++;
27
+ continue;
28
+ }
29
+
30
+ if (!hasParagraphStripSpan(node)) {
31
+ result.push(node);
32
+ i++;
33
+ continue;
34
+ }
35
+
36
+ const paraData = getContainerData(node);
37
+ if (!paraData) {
38
+ result.push(node);
39
+ i++;
40
+ continue;
41
+ }
42
+
43
+ const mergedChildren: Element[] = [...paraData.elements];
44
+ i++;
45
+
46
+ while (i < expandedChildren.length) {
47
+ const nextPara = expandedChildren[i];
48
+ if (!nextPara || !isContainer(nextPara, "paragraph")) {
49
+ break;
50
+ }
51
+
52
+ const nextParaData = getContainerData(nextPara);
53
+ if (!nextParaData) {
54
+ break;
55
+ }
56
+
57
+ const hasSpanStrip = hasParagraphStripSpan(nextPara);
58
+ mergedChildren.push(...nextParaData.elements);
59
+ i++;
60
+
61
+ if (!hasSpanStrip) {
62
+ const peekNext = expandedChildren[i];
63
+ if (!peekNext || !isContainer(peekNext, "paragraph") || !hasParagraphStripSpan(peekNext)) {
64
+ break;
65
+ }
66
+ }
67
+ }
68
+
69
+ const escapedSpans = extractEscapedSpans(mergedChildren);
70
+ removeLineBreaksAroundSpanStrip(mergedChildren);
71
+
72
+ if (escapedSpans.length > 0) {
73
+ if (mergedChildren.length > 0) {
74
+ result.push(paragraphElement(mergedChildren));
75
+ }
76
+ } else {
77
+ result.push(...mergedChildren);
78
+ }
79
+
80
+ result.push(...escapedSpans);
81
+ }
82
+
83
+ return result;
84
+ }
85
+
86
+ function expandSplitParagraphs(children: Element[]): Element[] {
87
+ const expandedChildren: Element[] = [];
88
+ for (const child of children) {
89
+ if (isContainer(child, "paragraph")) {
90
+ const data = getContainerData(child);
91
+ if (data) {
92
+ const split = getParagraphSplitKind(data.elements);
93
+ if (split === "blank-line-span") {
94
+ expandedChildren.push(...splitParagraphAtBlankLineSpans(child));
95
+ continue;
96
+ }
97
+ if (split === "empty-expr") {
98
+ expandedChildren.push(...splitParagraphAtEmptyExpr(child));
99
+ continue;
100
+ }
101
+ }
102
+ }
103
+ expandedChildren.push(child);
104
+ }
105
+ return expandedChildren;
106
+ }
107
+
108
+ function getParagraphSplitKind(elements: Element[]): "blank-line-span" | "empty-expr" | null {
109
+ let hasEmptyExpr = false;
110
+ for (const element of elements) {
111
+ if (isSplitSpan(element)) {
112
+ return "blank-line-span";
113
+ }
114
+ hasEmptyExpr ||= isEmptyExpr(element);
115
+ }
116
+ return hasEmptyExpr ? "empty-expr" : null;
117
+ }
@@ -0,0 +1,59 @@
1
+ import type { ContainerData, Element, ExprData } from "@wdprlib/ast";
2
+
3
+ export type InternalContainerData = ContainerData & {
4
+ _paragraphStrip?: boolean;
5
+ _emptyParagraphStrip?: boolean;
6
+ _escapedFromParagraph?: boolean;
7
+ _splitByBlankLine?: boolean;
8
+ };
9
+
10
+ export function isContainer(el: Element, type: string): boolean {
11
+ if (el.element !== "container") return false;
12
+ return el.data.type === type;
13
+ }
14
+
15
+ export function getContainerData(el: Element): ContainerData | null {
16
+ if (el.element !== "container") return null;
17
+ return el.data;
18
+ }
19
+
20
+ export function isSpanStripMarker(el: Element | undefined): boolean {
21
+ if (!el || el.element !== "container") return false;
22
+ const data = el.data as InternalContainerData;
23
+ return (
24
+ data.type === "span" && (data._paragraphStrip === true || data._emptyParagraphStrip === true)
25
+ );
26
+ }
27
+
28
+ export function hasParagraphStripSpan(para: Element): boolean {
29
+ const data = getContainerData(para);
30
+ if (!data || data.type !== "paragraph") return false;
31
+ return data.elements.some((child) => isSpanStripMarker(child));
32
+ }
33
+
34
+ export function isEscapedSpan(el: Element): boolean {
35
+ if (el.element !== "container") return false;
36
+ const data = el.data as InternalContainerData;
37
+ return data.type === "span" && data._escapedFromParagraph === true;
38
+ }
39
+
40
+ export function isSplitSpan(el: Element): boolean {
41
+ if (el.element !== "container") return false;
42
+ const data = el.data as InternalContainerData;
43
+ return data.type === "span" && data._splitByBlankLine === true;
44
+ }
45
+
46
+ export function isEmptyExpr(el: Element): boolean {
47
+ if (el.element !== "expr") return false;
48
+ const data = el.data as ExprData;
49
+ return data.expression === "";
50
+ }
51
+
52
+ export function isEmptySpan(el: Element): boolean {
53
+ if (el.element !== "container") return false;
54
+ return el.data.type === "span" && el.data.elements.length === 0;
55
+ }
56
+
57
+ export function isWhitespaceText(el: Element): boolean {
58
+ return el.element === "text" && typeof el.data === "string" && /^\s+$/.test(el.data);
59
+ }
@@ -0,0 +1,67 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { paragraphElement } from "./factory";
3
+ import { getContainerData, isEmptyExpr, isSplitSpan } from "./predicates";
4
+
5
+ export function splitParagraphAtBlankLineSpans(para: Element): Element[] {
6
+ const data = getContainerData(para);
7
+ if (!data || data.type !== "paragraph") return [para];
8
+
9
+ const result: Element[] = [];
10
+ let currentElements: Element[] = [];
11
+
12
+ for (const child of data.elements) {
13
+ if (isSplitSpan(child)) {
14
+ if (currentElements.length > 0) {
15
+ result.push(paragraphElement(currentElements));
16
+ currentElements = [];
17
+ }
18
+ currentElements.push(child);
19
+ } else {
20
+ currentElements.push(child);
21
+ }
22
+ }
23
+
24
+ if (currentElements.length > 0) {
25
+ result.push(paragraphElement(currentElements));
26
+ }
27
+
28
+ return result.length > 0 ? result : [para];
29
+ }
30
+
31
+ export function splitParagraphAtEmptyExpr(para: Element): Element[] {
32
+ const data = getContainerData(para);
33
+ if (!data || data.type !== "paragraph") return [para];
34
+ if (!data.elements.some(isEmptyExpr)) return [para];
35
+
36
+ const result: Element[] = [];
37
+ let currentElements: Element[] = [];
38
+
39
+ for (let i = 0; i < data.elements.length; i++) {
40
+ const child = data.elements[i];
41
+ if (!child) continue;
42
+
43
+ if (isEmptyExpr(child)) {
44
+ if (
45
+ currentElements.length > 0 &&
46
+ currentElements[currentElements.length - 1]?.element === "line-break"
47
+ ) {
48
+ currentElements.pop();
49
+ }
50
+ if (currentElements.length > 0) {
51
+ result.push(paragraphElement(currentElements));
52
+ currentElements = [];
53
+ }
54
+ if (i + 1 < data.elements.length && data.elements[i + 1]?.element === "line-break") {
55
+ i++;
56
+ }
57
+ } else {
58
+ currentElements.push(child);
59
+ }
60
+ }
61
+
62
+ if (currentElements.length > 0) {
63
+ result.push(paragraphElement(currentElements));
64
+ }
65
+
66
+ return result.length > 0 ? result : [];
67
+ }
@@ -0,0 +1,15 @@
1
+ export function isWhitespace(ch: string | undefined): boolean {
2
+ return ch === " " || ch === "\t" || ch === "\n" || ch === "\r";
3
+ }
4
+
5
+ export function isIdentChar(ch: string | undefined): boolean {
6
+ if (!ch) return false;
7
+ const code = ch.charCodeAt(0);
8
+ return (
9
+ (code >= 48 && code <= 57) ||
10
+ (code >= 65 && code <= 90) ||
11
+ (code >= 97 && code <= 122) ||
12
+ code === 95 ||
13
+ code === 45
14
+ );
15
+ }
@@ -0,0 +1,22 @@
1
+ import { evaluateExpression, formatExprValue, isTruthy } from "@wdprlib/ast";
2
+ import type { DirectiveKind, DirectiveMatch } from "./types";
3
+
4
+ /** Evaluate a parsed directive into its replacement string. */
5
+ export function evaluateDirective(kind: DirectiveKind, match: DirectiveMatch): string {
6
+ if (kind === "expr") {
7
+ const result = evaluateExpression(match.head);
8
+ if (result.success) return formatExprValue(result.value);
9
+ if (result.error === "empty expression") return "";
10
+ return "ERROR";
11
+ }
12
+
13
+ if (kind === "if") {
14
+ if (!match.hasPipe) return "";
15
+ return isTruthy(match.head) ? match.thenText : match.elseText;
16
+ }
17
+
18
+ if (!match.hasPipe) return "";
19
+ const result = evaluateExpression(match.head);
20
+ if (!result.success) return "ERROR";
21
+ return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
22
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ *
3
+ * Text-level expansion of `[[#if ...]]`, `[[#ifexpr ...]]`, and
4
+ * `[[#expr ...]]` directives that sit *inside* another block's opener.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { makeUniqueSentinels, maskRawRegions, restorePlaceholders } from "../utils";
10
+ import { expandInnermost } from "./scan";
11
+
12
+ /**
13
+ * Resolve every `[[#if]]` / `[[#ifexpr]]` / `[[#expr]]` that sits inside
14
+ * another block's opener (depth > 0). Top-level directives are left for
15
+ * the inline parser. Innermost-first reduction lets an outer directive
16
+ * re-process the flattened body on the next pass. Unmatched / malformed
17
+ * directives are left untouched.
18
+ */
19
+ export function preprocessExpr(source: string): string {
20
+ if (!source.includes("[[#")) return source;
21
+
22
+ const sentinels = makeUniqueSentinels(source);
23
+ const { masked, placeholders } = maskRawRegions(source, sentinels);
24
+ const reduced = reduceExpr(masked);
25
+ return restorePlaceholders(reduced, placeholders, sentinels);
26
+ }
27
+
28
+ /**
29
+ * Backwards-compatible alias for the older `preprocessIf` name (used by
30
+ * external callers that target the previous, `[[#if]]`-only behaviour).
31
+ * Both names point at the same implementation, which now also resolves
32
+ * `[[#ifexpr]]` and `[[#expr]]` in opener context.
33
+ */
34
+ export const preprocessIf: (source: string) => string = preprocessExpr;
35
+
36
+ function reduceExpr(source: string): string {
37
+ let current = source;
38
+ const maxIterations = source.length + 1;
39
+ for (let i = 0; i < maxIterations; i++) {
40
+ const next = expandInnermost(current);
41
+ if (next === current) return current;
42
+ current = next;
43
+ }
44
+ return current;
45
+ }
@@ -0,0 +1,19 @@
1
+ import type { DirectiveKind } from "./types";
2
+ import { isIdentChar } from "./chars";
3
+
4
+ /** Return the kind of `[[#xxx` directive at `i`, or null if none matches. */
5
+ export function matchDirectiveKind(source: string, i: number): DirectiveKind | null {
6
+ if (!source.startsWith("[[#", i)) return null;
7
+ // Order matters: `ifexpr` must be checked before `if` because the
8
+ // shorter `if` prefix would otherwise consume `ifexpr` openings.
9
+ if (source.startsWith("ifexpr", i + 3) && !isIdentChar(source[i + 9])) {
10
+ return "ifexpr";
11
+ }
12
+ if (source.startsWith("if", i + 3) && !isIdentChar(source[i + 5])) {
13
+ return "if";
14
+ }
15
+ if (source.startsWith("expr", i + 3) && !isIdentChar(source[i + 7])) {
16
+ return "expr";
17
+ }
18
+ return null;
19
+ }