@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,53 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+ import { isEmbedBlockName } from "./tags";
4
+
5
+ export interface EmbedContentResult {
6
+ contents: string;
7
+ consumed: number;
8
+ foundClose: boolean;
9
+ }
10
+
11
+ export function collectEmbedContent(ctx: ParseContext, startPos: number): EmbedContentResult {
12
+ const contentParts: string[] = [];
13
+ let pos = startPos;
14
+ let consumed = 0;
15
+
16
+ while (pos < ctx.tokens.length) {
17
+ const token = ctx.tokens[pos];
18
+ if (!token) break;
19
+
20
+ if (token.type === "BLOCK_END_OPEN") {
21
+ const closeNameResult = parseBlockName(ctx, pos + 1);
22
+ if (closeNameResult && isEmbedBlockName(closeNameResult.name.toLowerCase())) {
23
+ return { contents: contentParts.join(""), consumed, foundClose: true };
24
+ }
25
+ }
26
+
27
+ contentParts.push(token.value);
28
+ pos++;
29
+ consumed++;
30
+ }
31
+
32
+ return { contents: contentParts.join(""), consumed, foundClose: false };
33
+ }
34
+
35
+ export function consumeEmbedClose(ctx: ParseContext, startPos: number): number {
36
+ let pos = startPos + 1;
37
+ let consumed = 1;
38
+
39
+ const closeNameResult = parseBlockName(ctx, pos);
40
+ if (closeNameResult) {
41
+ pos += closeNameResult.consumed;
42
+ consumed += closeNameResult.consumed;
43
+ }
44
+ if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
45
+ pos++;
46
+ consumed++;
47
+ }
48
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
49
+ consumed++;
50
+ }
51
+
52
+ return consumed;
53
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot embed blocks: `[[embed]]`, `[[embedvideo]]`,
4
+ * and `[[embedaudio]]` (each with a matching closing tag).
5
+ *
6
+ * In original Wikidot, only HTML that matches a server-side allow-list is
7
+ * rendered. This parser does not perform that filtering -- the raw content
8
+ * between the tags is stored verbatim as an `embed-block` element. Validation
9
+ * and sanitisation are expected to happen at rendering time or on the server.
10
+ *
11
+ * The embed block is wrapped in a paragraph container in the AST, matching
12
+ * Wikidot's rendering behaviour where embeds sit inside `<p>` tags.
13
+ *
14
+ * If no closing tag is found, the rule fails to prevent consuming the rest
15
+ * of the document.
16
+ *
17
+ * @module
18
+ */
19
+ import type { Element } from "@wdprlib/ast";
20
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
21
+ import { currentToken } from "../../types";
22
+ import { collectEmbedContent, consumeEmbedClose } from "./content";
23
+ import { parseEmbedBlockOpen } from "./open";
24
+
25
+ /**
26
+ * Block rule for `[[embed]]`, `[[embedvideo]]`, and `[[embedaudio]]`.
27
+ *
28
+ * Content between the opening and closing tags is captured as raw text.
29
+ * The block name matching is case-insensitive; the closing tag may use
30
+ * any of the three names (`embed`, `embedvideo`, `embedaudio`) regardless
31
+ * of which was used to open.
32
+ */
33
+ export const embedBlockRule: BlockRule = {
34
+ name: "embed-block",
35
+ startTokens: ["BLOCK_OPEN"],
36
+ requiresLineStart: false,
37
+
38
+ parse(ctx: ParseContext): RuleResult<Element> {
39
+ const openToken = currentToken(ctx);
40
+ if (openToken.type !== "BLOCK_OPEN") {
41
+ return { success: false };
42
+ }
43
+
44
+ const openResult = parseEmbedBlockOpen(ctx, ctx.pos);
45
+ if (!openResult) {
46
+ return { success: false };
47
+ }
48
+
49
+ let pos = openResult.pos;
50
+ let consumed = openResult.consumed;
51
+ const contentResult = collectEmbedContent(ctx, pos);
52
+ pos += contentResult.consumed;
53
+ consumed += contentResult.consumed;
54
+
55
+ if (!contentResult.foundClose) {
56
+ ctx.diagnostics.push({
57
+ severity: "warning",
58
+ code: "unclosed-block",
59
+ message: `Missing closing tag [[/${openResult.blockName}]] for [[${openResult.blockName}]]`,
60
+ position: openToken.position,
61
+ });
62
+ return { success: false };
63
+ }
64
+
65
+ const closeConsumed = consumeEmbedClose(ctx, pos);
66
+ pos += closeConsumed;
67
+ consumed += closeConsumed;
68
+
69
+ return {
70
+ success: true,
71
+ elements: [
72
+ {
73
+ element: "container",
74
+ data: {
75
+ type: "paragraph",
76
+ attributes: {},
77
+ elements: [
78
+ {
79
+ element: "embed-block",
80
+ data: {
81
+ contents: contentResult.contents.trim(),
82
+ },
83
+ },
84
+ ],
85
+ },
86
+ },
87
+ ],
88
+ consumed,
89
+ };
90
+ },
91
+ };
@@ -0,0 +1,52 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+ import { isEmbedBlockName } from "./tags";
4
+
5
+ export interface EmbedBlockOpenResult {
6
+ blockName: string;
7
+ pos: number;
8
+ consumed: number;
9
+ }
10
+
11
+ export function parseEmbedBlockOpen(
12
+ ctx: ParseContext,
13
+ startPos: number,
14
+ ): EmbedBlockOpenResult | null {
15
+ let pos = startPos;
16
+ let consumed = 0;
17
+
18
+ if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") {
19
+ return null;
20
+ }
21
+ pos++;
22
+ consumed++;
23
+
24
+ const nameResult = parseBlockName(ctx, pos);
25
+ if (!nameResult) {
26
+ return null;
27
+ }
28
+
29
+ const blockName = nameResult.name.toLowerCase();
30
+ if (!isEmbedBlockName(blockName)) {
31
+ return null;
32
+ }
33
+ pos += nameResult.consumed;
34
+ consumed += nameResult.consumed;
35
+
36
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
37
+ pos++;
38
+ consumed++;
39
+ }
40
+
41
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
42
+ return null;
43
+ }
44
+ pos++;
45
+ consumed++;
46
+
47
+ return {
48
+ blockName,
49
+ pos,
50
+ consumed,
51
+ };
52
+ }
@@ -0,0 +1,5 @@
1
+ const EMBED_BLOCK_NAMES = new Set(["embed", "embedvideo", "embedaudio"]);
2
+
3
+ export function isEmbedBlockName(name: string): boolean {
4
+ return EMBED_BLOCK_NAMES.has(name);
5
+ }
@@ -0,0 +1,73 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export interface FootnoteBlockAttributesResult {
4
+ attrs: Record<string, string>;
5
+ consumed: number;
6
+ }
7
+
8
+ /**
9
+ * Parses key/value attributes from tokens for `[[footnoteblock]]`.
10
+ *
11
+ * This is intentionally rule-local: the generic block attribute parser
12
+ * filters some names that this rule needs to preserve, notably `hide`.
13
+ */
14
+ export function parseFootnoteBlockAttributes(
15
+ ctx: ParseContext,
16
+ startPos: number,
17
+ ): FootnoteBlockAttributesResult {
18
+ const attrs: Record<string, string> = {};
19
+ let pos = startPos;
20
+ let consumed = 0;
21
+
22
+ while (pos < ctx.tokens.length) {
23
+ const token = ctx.tokens[pos];
24
+ if (
25
+ !token ||
26
+ token.type === "BLOCK_CLOSE" ||
27
+ token.type === "NEWLINE" ||
28
+ token.type === "EOF"
29
+ ) {
30
+ break;
31
+ }
32
+
33
+ if (token.type === "WHITESPACE") {
34
+ pos++;
35
+ consumed++;
36
+ continue;
37
+ }
38
+
39
+ if (token.type === "TEXT" || token.type === "IDENTIFIER") {
40
+ const name = token.value.toLowerCase();
41
+ pos++;
42
+ consumed++;
43
+
44
+ const eqToken = ctx.tokens[pos];
45
+ if (eqToken?.type === "EQUALS") {
46
+ pos++;
47
+ consumed++;
48
+
49
+ const valueToken = ctx.tokens[pos];
50
+ if (valueToken?.type === "QUOTED_STRING") {
51
+ attrs[name] = stripQuotes(valueToken.value);
52
+ pos++;
53
+ consumed++;
54
+ } else if (valueToken?.type === "TEXT" || valueToken?.type === "IDENTIFIER") {
55
+ attrs[name] = valueToken.value;
56
+ pos++;
57
+ consumed++;
58
+ }
59
+ } else {
60
+ attrs[name] = "true";
61
+ }
62
+ } else {
63
+ pos++;
64
+ consumed++;
65
+ }
66
+ }
67
+
68
+ return { attrs, consumed };
69
+ }
70
+
71
+ function stripQuotes(value: string): string {
72
+ return value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
73
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ *
3
+ * Block rule for the Wikidot footnote block: `[[footnoteblock]]`.
4
+ *
5
+ * This self-closing block tag marks the location in the page where all
6
+ * collected footnotes (from `[[footnote]]...[[/footnote]]` inline markers)
7
+ * should be rendered. It is analogous to a "footnotes section" placeholder.
8
+ *
9
+ * Optional attributes:
10
+ * - `title` -- custom heading text for the footnotes section.
11
+ * - `hide` -- when `"true"` or `"yes"`, suppresses footnote rendering.
12
+ *
13
+ * Wikidot only honours the FIRST `[[footnoteblock]]` in a document;
14
+ * subsequent occurrences are treated as plain text. The parser tracks
15
+ * this via `ctx.scope.footnoteBlockParsed`, but note: that flag is per
16
+ * spread copy of `ParseContext` (see {@link ScopeContext.footnoteBlockParsed}).
17
+ * In practice the duplicate-rejection only fires for two top-level
18
+ * `[[footnoteblock]]` tokens; siblings inside the same body or across
19
+ * nested bodies both succeed today. The auto-append decision in
20
+ * `Parser.parse` uses a post-parse AST walk, so it is unaffected.
21
+ *
22
+ * @module
23
+ */
24
+ import type { Element } from "@wdprlib/ast";
25
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
26
+ import { currentToken } from "../../types";
27
+ import { parseFootnoteBlockOpen } from "./open";
28
+
29
+ /**
30
+ * Block rule for `[[footnoteblock]]`.
31
+ *
32
+ * Parsing strategy:
33
+ * 1. Match BLOCK_OPEN + name "footnoteblock" (case-insensitive).
34
+ * 2. Parse optional attributes (`title`, `hide`) with the rule-local parser.
35
+ * 3. Consume closing `]]`.
36
+ * 4. If `ctx.scope.footnoteBlockParsed` is already `true` on the current
37
+ * `ParseContext` copy, fail. Because `parseBlocksUntil` spreads a
38
+ * fresh `ctx` per sibling rule, this only rejects a second
39
+ * `[[footnoteblock]]` that arrives via the parser's top-level
40
+ * dispatch loop in practice. See {@link ScopeContext.footnoteBlockParsed}.
41
+ * 5. Replace `ctx.scope` with the flag set to `true` and emit a `footnote-block`
42
+ * element.
43
+ */
44
+ export const footnoteBlockRule: BlockRule = {
45
+ name: "footnoteBlock",
46
+ startTokens: ["BLOCK_OPEN"],
47
+ requiresLineStart: true,
48
+
49
+ parse(ctx: ParseContext): RuleResult<Element> {
50
+ const openToken = currentToken(ctx);
51
+ if (openToken.type !== "BLOCK_OPEN") {
52
+ return { success: false };
53
+ }
54
+
55
+ const openResult = parseFootnoteBlockOpen(ctx, ctx.pos);
56
+ if (!openResult) {
57
+ return { success: false };
58
+ }
59
+
60
+ if (ctx.scope.footnoteBlockParsed) {
61
+ return { success: false };
62
+ }
63
+ ctx.scope = { ...ctx.scope, footnoteBlockParsed: true };
64
+
65
+ const title = openResult.attrs.title !== undefined ? openResult.attrs.title : null;
66
+ const hide = openResult.attrs.hide === "true" || openResult.attrs.hide === "yes";
67
+
68
+ return {
69
+ success: true,
70
+ elements: [
71
+ {
72
+ element: "footnote-block",
73
+ data: {
74
+ title,
75
+ hide,
76
+ },
77
+ },
78
+ ],
79
+ consumed: openResult.consumed,
80
+ };
81
+ },
82
+ };
@@ -0,0 +1,53 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseFootnoteBlockAttributes } from "./attributes";
3
+
4
+ export interface FootnoteBlockOpenResult {
5
+ attrs: Record<string, string>;
6
+ consumed: number;
7
+ }
8
+
9
+ export function parseFootnoteBlockOpen(
10
+ ctx: ParseContext,
11
+ startPos: number,
12
+ ): FootnoteBlockOpenResult | null {
13
+ if (ctx.tokens[startPos]?.type !== "BLOCK_OPEN") {
14
+ return null;
15
+ }
16
+
17
+ let pos = startPos + 1;
18
+ let consumed = 1;
19
+
20
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
21
+ pos++;
22
+ consumed++;
23
+ }
24
+
25
+ const nameToken = ctx.tokens[pos];
26
+ if (!nameToken || (nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER")) {
27
+ return null;
28
+ }
29
+
30
+ if (nameToken.value.toLowerCase() !== "footnoteblock") {
31
+ return null;
32
+ }
33
+ pos++;
34
+ consumed++;
35
+
36
+ const attrResult = parseFootnoteBlockAttributes(ctx, pos);
37
+ pos += attrResult.consumed;
38
+ consumed += attrResult.consumed;
39
+
40
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
41
+ pos++;
42
+ consumed++;
43
+ }
44
+
45
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
46
+ return null;
47
+ }
48
+
49
+ return {
50
+ attrs: attrResult.attrs,
51
+ consumed: consumed + 1,
52
+ };
53
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot headings: `+ Heading` through `++++++ Heading`.
4
+ *
5
+ * Headings are written with one to six `+` characters at the start of a
6
+ * line, followed by mandatory whitespace and then inline content:
7
+ *
8
+ * ```
9
+ * + H1 heading
10
+ * ++ H2 heading
11
+ * +++ H3 heading
12
+ * ```
13
+ *
14
+ * An optional `*` immediately after the `+` markers hides the heading
15
+ * from the table of contents:
16
+ *
17
+ * ```
18
+ * +* Hidden H1
19
+ * ```
20
+ *
21
+ * Seven or more `+` characters are NOT valid headings in Wikidot and
22
+ * the rule will fail, letting them fall through to paragraph parsing.
23
+ *
24
+ * Non-hidden headings are registered in `ctx.tocEntries` for later use
25
+ * by the table-of-contents module.
26
+ *
27
+ * @module
28
+ */
29
+ import type { Element } from "@wdprlib/ast";
30
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
31
+ import { parseInlineUntil } from "../../inline/utils";
32
+ import { parseHeadingOpen } from "./open";
33
+ import { extractHeadingText } from "./toc-text";
34
+
35
+ /**
36
+ * Block rule for Wikidot headings (`+ ` through `++++++ `).
37
+ *
38
+ * Produces a container element with `type: { header: { level, "has-toc" } }`.
39
+ * The heading text is parsed for inline markup (bold, links, etc.).
40
+ */
41
+ export const headingRule: BlockRule = {
42
+ name: "heading",
43
+ startTokens: ["HEADING_MARKER"],
44
+ requiresLineStart: true,
45
+
46
+ parse(ctx: ParseContext): RuleResult<Element> {
47
+ const openResult = parseHeadingOpen(ctx);
48
+ if (!openResult) {
49
+ return { success: false };
50
+ }
51
+
52
+ // Parse inline content until newline
53
+ let pos = openResult.bodyStart;
54
+ let consumed = openResult.consumed;
55
+ const inlineCtx: ParseContext = { ...ctx, pos };
56
+ const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
57
+ const children: Element[] = inlineResult.elements;
58
+ consumed += inlineResult.consumed;
59
+ pos += inlineResult.consumed;
60
+
61
+ // Consume newline
62
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
63
+ consumed++;
64
+ }
65
+
66
+ // Store TOC entry (only non-hidden headings)
67
+ if (!openResult.hidden) {
68
+ const headingText = extractHeadingText(children);
69
+ ctx.tocEntries.push({ level: openResult.level, text: headingText });
70
+ }
71
+
72
+ return {
73
+ success: true,
74
+ elements: [
75
+ {
76
+ element: "container",
77
+ data: {
78
+ type: { header: { level: openResult.level, "has-toc": !openResult.hidden } },
79
+ attributes: {},
80
+ elements: children,
81
+ },
82
+ },
83
+ ],
84
+ consumed,
85
+ };
86
+ },
87
+ };
@@ -0,0 +1,50 @@
1
+ import type { HeadingLevel } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+
4
+ export interface HeadingOpenResult {
5
+ level: HeadingLevel;
6
+ hidden: boolean;
7
+ bodyStart: number;
8
+ consumed: number;
9
+ }
10
+
11
+ export function parseHeadingOpen(ctx: ParseContext): HeadingOpenResult | null {
12
+ const marker = ctx.tokens[ctx.pos];
13
+ if (marker?.type !== "HEADING_MARKER" || !marker.lineStart) {
14
+ return null;
15
+ }
16
+
17
+ if (!isHeadingLevel(marker.value.length)) {
18
+ return null;
19
+ }
20
+
21
+ let pos = ctx.pos + 1;
22
+ let consumed = 1;
23
+ let hidden = false;
24
+
25
+ if (ctx.tokens[pos]?.type === "STAR") {
26
+ hidden = true;
27
+ pos++;
28
+ consumed++;
29
+ }
30
+
31
+ if (ctx.tokens[pos]?.type !== "WHITESPACE") {
32
+ return null;
33
+ }
34
+
35
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
36
+ pos++;
37
+ consumed++;
38
+ }
39
+
40
+ return {
41
+ level: marker.value.length,
42
+ hidden,
43
+ bodyStart: pos,
44
+ consumed,
45
+ };
46
+ }
47
+
48
+ function isHeadingLevel(length: number): length is HeadingLevel {
49
+ return length >= 1 && length <= 6;
50
+ }
@@ -0,0 +1,26 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+
3
+ /**
4
+ * Recursively extracts plain text from heading children for TOC entries.
5
+ */
6
+ export function extractHeadingText(elements: Element[]): string {
7
+ let text = "";
8
+ for (const el of elements) {
9
+ if (el.element === "text" && typeof el.data === "string") {
10
+ text += el.data;
11
+ } else if (hasNestedElements(el)) {
12
+ text += extractHeadingText(el.data.elements);
13
+ }
14
+ }
15
+ return text;
16
+ }
17
+
18
+ function hasNestedElements(el: Element): el is Extract<Element, { element: "container" }> {
19
+ return (
20
+ el.element === "container" &&
21
+ typeof el.data === "object" &&
22
+ el.data !== null &&
23
+ "elements" in el.data &&
24
+ Array.isArray(el.data.elements)
25
+ );
26
+ }
@@ -14,8 +14,9 @@
14
14
  * @module
15
15
  */
16
16
  import type { Element } from "@wdprlib/ast";
17
- import type { BlockRule, ParseContext, RuleResult } from "../types";
18
- import { currentToken } from "../types";
17
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
18
+ import { currentToken } from "../../types";
19
+ import { consumeHorizontalRuleLine } from "./syntax";
19
20
 
20
21
  /**
21
22
  * Block rule for horizontal rules (`----`).
@@ -34,28 +35,10 @@ export const horizontalRuleRule: BlockRule = {
34
35
  return { success: false };
35
36
  }
36
37
 
37
- let pos = ctx.pos + 1;
38
- let consumed = 1;
39
-
40
- // Skip to end of line
41
- while (pos < ctx.tokens.length) {
42
- const token = ctx.tokens[pos];
43
- if (!token || token.type === "NEWLINE" || token.type === "EOF") {
44
- break;
45
- }
46
- pos++;
47
- consumed++;
48
- }
49
-
50
- // Consume newline
51
- if (ctx.tokens[pos]?.type === "NEWLINE") {
52
- consumed++;
53
- }
54
-
55
38
  return {
56
39
  success: true,
57
40
  elements: [{ element: "horizontal-rule" }],
58
- consumed,
41
+ consumed: consumeHorizontalRuleLine(ctx),
59
42
  };
60
43
  },
61
44
  };
@@ -0,0 +1,21 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export function consumeHorizontalRuleLine(ctx: ParseContext): number {
4
+ let pos = ctx.pos + 1;
5
+ let consumed = 1;
6
+
7
+ while (pos < ctx.tokens.length) {
8
+ const token = ctx.tokens[pos];
9
+ if (!token || token.type === "NEWLINE" || token.type === "EOF") {
10
+ break;
11
+ }
12
+ pos++;
13
+ consumed++;
14
+ }
15
+
16
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
17
+ consumed++;
18
+ }
19
+
20
+ return consumed;
21
+ }