@wdprlib/parser 3.2.0 → 4.1.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 +10471 -8406
  2. package/dist/index.d.cts +313 -337
  3. package/dist/index.d.ts +313 -337
  4. package/dist/index.js +10457 -8392
  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 +30 -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 +62 -0
  195. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +34 -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,50 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+
4
+ export type ListBlockType = "ul" | "ol";
5
+
6
+ export function isListBlockType(name: string): name is ListBlockType {
7
+ return name === "ul" || name === "ol";
8
+ }
9
+
10
+ export function isListClose(ctx: ParseContext, pos: number, expectedType?: ListBlockType): boolean {
11
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") return false;
12
+ const nameResult = parseBlockName(ctx, pos + 1);
13
+ if (!nameResult) return false;
14
+ return expectedType ? nameResult.name === expectedType : isListBlockType(nameResult.name);
15
+ }
16
+
17
+ export function isLiClose(ctx: ParseContext, pos: number): boolean {
18
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") return false;
19
+ const nameResult = parseBlockName(ctx, pos + 1);
20
+ return nameResult?.name === "li";
21
+ }
22
+
23
+ export function isLiOpen(
24
+ ctx: ParseContext,
25
+ pos: number,
26
+ ): { name: string; consumed: number } | null {
27
+ if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") return null;
28
+ const nameResult = parseBlockName(ctx, pos + 1);
29
+ if (!nameResult || nameResult.name !== "li") return null;
30
+ return { name: nameResult.name, consumed: 1 + nameResult.consumed };
31
+ }
32
+
33
+ export function isNestedListOpen(
34
+ ctx: ParseContext,
35
+ pos: number,
36
+ ): { type: ListBlockType; consumed: number } | null {
37
+ if (ctx.tokens[pos]?.type !== "BLOCK_OPEN") return null;
38
+ const nameResult = parseBlockName(ctx, pos + 1);
39
+ if (!nameResult || !isListBlockType(nameResult.name)) return null;
40
+ return { type: nameResult.name, consumed: 1 + nameResult.consumed };
41
+ }
42
+
43
+ export function consumeCloseTag(ctx: ParseContext, pos: number): number {
44
+ let closeConsumed = 1;
45
+ const nameResult = parseBlockName(ctx, pos + 1);
46
+ if (nameResult) closeConsumed += nameResult.consumed;
47
+ if (ctx.tokens[pos + closeConsumed]?.type === "BLOCK_CLOSE") closeConsumed++;
48
+ if (ctx.tokens[pos + closeConsumed]?.type === "NEWLINE") closeConsumed++;
49
+ return closeConsumed;
50
+ }
@@ -0,0 +1,62 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { processDepths, type DepthList } from "../../../depth";
3
+ import type { BlockquoteLine, ParsedBlockquoteLine } from "./lines";
4
+
5
+ export function buildBlockquoteElements(lines: ParsedBlockquoteLine[]): Element[] {
6
+ const depthTrees = processDepths<null, BlockquoteLine>(null, lines);
7
+ return depthTrees.map(({ list }) => buildBlockquoteElement(list));
8
+ }
9
+
10
+ function buildBlockquoteElement(list: DepthList<null, BlockquoteLine>): Element {
11
+ const children: Element[] = [];
12
+ let currentParagraphChildren: Element[] = [];
13
+
14
+ function flushParagraph() {
15
+ if (currentParagraphChildren.length > 0) {
16
+ while (
17
+ currentParagraphChildren.length > 0 &&
18
+ currentParagraphChildren[currentParagraphChildren.length - 1]?.element === "line-break"
19
+ ) {
20
+ currentParagraphChildren.pop();
21
+ }
22
+ if (currentParagraphChildren.length > 0) {
23
+ children.push({
24
+ element: "container",
25
+ data: {
26
+ type: "paragraph",
27
+ attributes: {},
28
+ elements: currentParagraphChildren,
29
+ },
30
+ });
31
+ }
32
+ currentParagraphChildren = [];
33
+ }
34
+ }
35
+
36
+ for (const item of list) {
37
+ if (item.kind === "item") {
38
+ if (item.value.elements.length === 0) {
39
+ flushParagraph();
40
+ continue;
41
+ }
42
+ currentParagraphChildren.push(...item.value.elements);
43
+ if (item.value.hasLineBreak) {
44
+ currentParagraphChildren.push({ element: "line-break" });
45
+ }
46
+ } else {
47
+ flushParagraph();
48
+ children.push(buildBlockquoteElement(item.children));
49
+ }
50
+ }
51
+
52
+ flushParagraph();
53
+
54
+ return {
55
+ element: "container",
56
+ data: {
57
+ type: "blockquote",
58
+ attributes: {},
59
+ elements: children,
60
+ },
61
+ };
62
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot-style blockquotes using `>` markers.
4
+ *
5
+ * Wikidot blockquotes are written with one or more `>` characters at the
6
+ * start of a line, followed by a mandatory space and then the content:
7
+ *
8
+ * ```
9
+ * > First level
10
+ * >> Second level
11
+ * > Back to first
12
+ * ```
13
+ *
14
+ * Key behaviours:
15
+ * - The depth is determined by the number of consecutive `>` characters.
16
+ * - A space after the `>` markers is required; lines like `>No space` are
17
+ * consumed but silently discarded from output.
18
+ * - An empty line (just `> `) within the same depth acts as a paragraph
19
+ * separator inside the blockquote.
20
+ * - Nesting is handled by the generic {@link processDepths} utility, which
21
+ * converts flat depth-annotated rows into a recursive tree structure.
22
+ * - Maximum depth is capped at `MAX_BLOCKQUOTE_DEPTH` (30) to guard
23
+ * against pathological input.
24
+ *
25
+ * @module
26
+ */
27
+ import type { Element } from "@wdprlib/ast";
28
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
29
+ import { currentToken } from "../../types";
30
+ import { buildBlockquoteElements, collectBlockquoteLines } from "./lines";
31
+
32
+ /**
33
+ * Block rule for `>` prefix blockquotes.
34
+ *
35
+ * Parsing strategy:
36
+ * 1. Collect consecutive lines that begin with BLOCKQUOTE_MARKER at line start.
37
+ * 2. For each line, record the depth (number of `>` chars, zero-indexed)
38
+ * and parse the inline content after the mandatory space.
39
+ * 3. Lines missing the required space are consumed but produce no output.
40
+ * 4. Feed the flat depth list into {@link processDepths} to build a nested tree.
41
+ * 5. Recursively convert the tree into nested blockquote container elements
42
+ * via `buildBlockquoteElement()`.
43
+ */
44
+ export const blockquoteRule: BlockRule = {
45
+ name: "blockquote",
46
+ startTokens: ["BLOCKQUOTE_MARKER"],
47
+ requiresLineStart: true,
48
+
49
+ parse(ctx: ParseContext): RuleResult<Element> {
50
+ const firstToken = currentToken(ctx);
51
+
52
+ if (!firstToken.lineStart) {
53
+ return { success: false };
54
+ }
55
+
56
+ const blockquoteLines = collectBlockquoteLines(ctx);
57
+
58
+ // No rows parsed
59
+ if (blockquoteLines.lines.length === 0) {
60
+ // If we consumed tokens (e.g. lines without space after >), return empty success
61
+ if (blockquoteLines.consumed > 0) {
62
+ return { success: true, elements: [], consumed: blockquoteLines.consumed };
63
+ }
64
+ return { success: false };
65
+ }
66
+
67
+ const blockquotes = buildBlockquoteElements(blockquoteLines.lines);
68
+
69
+ // Return first blockquote (should usually be only one)
70
+ if (blockquotes.length === 0) {
71
+ return { success: false };
72
+ }
73
+
74
+ return {
75
+ success: true,
76
+ elements: blockquotes,
77
+ consumed: blockquoteLines.consumed,
78
+ };
79
+ },
80
+ };
@@ -0,0 +1,79 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseInlineUntil } from "../../inline/utils";
3
+ import type { ParsedBlockquoteLine } from "./lines";
4
+
5
+ /**
6
+ * Safety limit for blockquote nesting depth.
7
+ * Lines exceeding this depth are not parsed, preventing stack issues
8
+ * on deeply nested or malicious input.
9
+ */
10
+ const MAX_BLOCKQUOTE_DEPTH = 30;
11
+
12
+ export type BlockquoteLineParseResult =
13
+ | { kind: "parsed"; line: ParsedBlockquoteLine; consumed: number }
14
+ | { kind: "skipped"; consumed: number }
15
+ | { kind: "stop" };
16
+
17
+ export function parseBlockquoteLine(
18
+ ctx: ParseContext,
19
+ startPos: number,
20
+ ): BlockquoteLineParseResult {
21
+ const markerToken = ctx.tokens[startPos];
22
+ if (!markerToken || !markerToken.lineStart || markerToken.type !== "BLOCKQUOTE_MARKER") {
23
+ return { kind: "stop" };
24
+ }
25
+
26
+ const depth = markerToken.value.length;
27
+ if (depth > MAX_BLOCKQUOTE_DEPTH) {
28
+ return { kind: "stop" };
29
+ }
30
+
31
+ let pos = startPos + 1;
32
+ let consumed = 1;
33
+
34
+ if (ctx.tokens[pos]?.type !== "WHITESPACE") {
35
+ return { kind: "skipped", consumed: consumeLineRemainder(ctx, pos) + consumed };
36
+ }
37
+
38
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
39
+ pos++;
40
+ consumed++;
41
+ }
42
+
43
+ const inlineCtx: ParseContext = { ...ctx, pos };
44
+ const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
45
+ consumed += inlineResult.consumed;
46
+ pos += inlineResult.consumed;
47
+
48
+ let hasLineBreak = false;
49
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
50
+ hasLineBreak = true;
51
+ consumed++;
52
+ }
53
+
54
+ return {
55
+ kind: "parsed",
56
+ line: {
57
+ depth: depth - 1,
58
+ ltype: null,
59
+ value: { elements: inlineResult.elements, hasLineBreak },
60
+ },
61
+ consumed,
62
+ };
63
+ }
64
+
65
+ function consumeLineRemainder(ctx: ParseContext, startPos: number): number {
66
+ let pos = startPos;
67
+ let consumed = 0;
68
+
69
+ while (pos < ctx.tokens.length && ctx.tokens[pos]?.type !== "NEWLINE") {
70
+ pos++;
71
+ consumed++;
72
+ }
73
+
74
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
75
+ consumed++;
76
+ }
77
+
78
+ return consumed;
79
+ }
@@ -0,0 +1,39 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseBlockquoteLine } from "./line";
4
+ export { buildBlockquoteElements } from "./build";
5
+
6
+ export interface BlockquoteLine {
7
+ elements: Element[];
8
+ hasLineBreak: boolean;
9
+ }
10
+
11
+ export interface ParsedBlockquoteLine {
12
+ depth: number;
13
+ ltype: null;
14
+ value: BlockquoteLine;
15
+ }
16
+
17
+ export interface ParsedBlockquoteLines {
18
+ lines: ParsedBlockquoteLine[];
19
+ consumed: number;
20
+ }
21
+
22
+ export function collectBlockquoteLines(ctx: ParseContext): ParsedBlockquoteLines {
23
+ const lines: ParsedBlockquoteLine[] = [];
24
+ let pos = ctx.pos;
25
+ let consumed = 0;
26
+
27
+ while (pos < ctx.tokens.length) {
28
+ const result = parseBlockquoteLine(ctx, pos);
29
+ if (result.kind === "stop") break;
30
+
31
+ pos += result.consumed;
32
+ consumed += result.consumed;
33
+ if (result.kind === "parsed") {
34
+ lines.push(result.line);
35
+ }
36
+ }
37
+
38
+ return { lines, consumed };
39
+ }
@@ -20,9 +20,9 @@
20
20
  * @module
21
21
  */
22
22
  import type { Element } from "@wdprlib/ast";
23
- import type { BlockRule, ParseContext, RuleResult } from "../types";
24
- import { currentToken } from "../types";
25
- import { parseInlineUntil } from "../inline/utils";
23
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
24
+ import { parseInlineUntil } from "../../inline/utils";
25
+ import { parseCenterOpen } from "./open";
26
26
 
27
27
  /**
28
28
  * Block rule for single-line center alignment (`= text`).
@@ -35,27 +35,12 @@ export const centerRule: BlockRule = {
35
35
  requiresLineStart: true,
36
36
 
37
37
  parse(ctx: ParseContext): RuleResult<Element> {
38
- const marker = currentToken(ctx);
39
-
40
- if (!marker.lineStart) {
41
- return { success: false };
42
- }
43
-
44
- // Wikidot requires whitespace after = for center alignment
45
- let pos = ctx.pos + 1;
46
- let consumed = 1;
47
-
48
- if (ctx.tokens[pos]?.type !== "WHITESPACE") {
49
- return { success: false };
50
- }
51
-
52
- // Skip whitespace
53
- while (ctx.tokens[pos]?.type === "WHITESPACE") {
54
- pos++;
55
- consumed++;
56
- }
38
+ const openResult = parseCenterOpen(ctx);
39
+ if (!openResult) return { success: false };
57
40
 
58
41
  // Parse inline content until newline
42
+ let pos = openResult.bodyStart;
43
+ let consumed = openResult.consumed;
59
44
  const inlineCtx: ParseContext = { ...ctx, pos };
60
45
  const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
61
46
  const children: Element[] = inlineResult.elements;
@@ -0,0 +1,27 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export interface CenterOpenResult {
4
+ bodyStart: number;
5
+ consumed: number;
6
+ }
7
+
8
+ export function parseCenterOpen(ctx: ParseContext): CenterOpenResult | null {
9
+ const marker = ctx.tokens[ctx.pos];
10
+ if (marker?.type !== "EQUALS" || !marker.lineStart) {
11
+ return null;
12
+ }
13
+
14
+ let pos = ctx.pos + 1;
15
+ let consumed = 1;
16
+
17
+ if (ctx.tokens[pos]?.type !== "WHITESPACE") {
18
+ return null;
19
+ }
20
+
21
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
22
+ pos++;
23
+ consumed++;
24
+ }
25
+
26
+ return { bodyStart: pos, consumed };
27
+ }
@@ -19,8 +19,8 @@
19
19
  * @module
20
20
  */
21
21
  import type { Element } from "@wdprlib/ast";
22
- import type { BlockRule, ParseContext, RuleResult } from "../types";
23
- import { currentToken } from "../types";
22
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
23
+ import { parseClearFloatSyntax } from "./syntax";
24
24
 
25
25
  /**
26
26
  * Block rule for the clear-float directive (`~~~~`, `~~~~<`, `~~~~>`).
@@ -34,42 +34,18 @@ export const clearFloatRule: BlockRule = {
34
34
  requiresLineStart: true,
35
35
 
36
36
  parse(ctx: ParseContext): RuleResult<Element> {
37
- const token = currentToken(ctx);
38
-
39
- if (!token.lineStart) {
40
- return { success: false };
41
- }
42
-
43
- // Count tildes - Wikidot requires at least 4
44
- const tildeCount = token.value.replace(/[<>]$/, "").length;
45
- if (tildeCount < 4) {
46
- return { success: false };
47
- }
48
-
49
- // Determine direction
50
- let direction: "both" | "left" | "right" = "both";
51
- if (token.type === "CLEAR_FLOAT_LEFT") {
52
- direction = "left";
53
- } else if (token.type === "CLEAR_FLOAT_RIGHT") {
54
- direction = "right";
55
- }
56
-
57
- let consumed = 1;
58
-
59
- // Consume newline if present
60
- if (ctx.tokens[ctx.pos + 1]?.type === "NEWLINE") {
61
- consumed++;
62
- }
37
+ const syntax = parseClearFloatSyntax(ctx);
38
+ if (!syntax) return { success: false };
63
39
 
64
40
  return {
65
41
  success: true,
66
42
  elements: [
67
43
  {
68
44
  element: "clear-float",
69
- data: direction,
45
+ data: syntax.direction,
70
46
  },
71
47
  ],
72
- consumed,
48
+ consumed: syntax.consumed,
73
49
  };
74
50
  },
75
51
  };
@@ -0,0 +1,43 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ type ClearFloatDirection = "both" | "left" | "right";
4
+
5
+ export interface ClearFloatSyntax {
6
+ direction: ClearFloatDirection;
7
+ consumed: number;
8
+ }
9
+
10
+ export function parseClearFloatSyntax(ctx: ParseContext): ClearFloatSyntax | null {
11
+ const token = ctx.tokens[ctx.pos];
12
+ if (
13
+ !token ||
14
+ !token.lineStart ||
15
+ (token.type !== "CLEAR_FLOAT" &&
16
+ token.type !== "CLEAR_FLOAT_LEFT" &&
17
+ token.type !== "CLEAR_FLOAT_RIGHT")
18
+ ) {
19
+ return null;
20
+ }
21
+
22
+ const tildeCount = token.value.replace(/[<>]$/, "").length;
23
+ if (tildeCount < 4) {
24
+ return null;
25
+ }
26
+
27
+ return {
28
+ direction: clearFloatDirection(token.type),
29
+ consumed: 1 + (ctx.tokens[ctx.pos + 1]?.type === "NEWLINE" ? 1 : 0),
30
+ };
31
+ }
32
+
33
+ function clearFloatDirection(
34
+ tokenType: "CLEAR_FLOAT" | "CLEAR_FLOAT_LEFT" | "CLEAR_FLOAT_RIGHT",
35
+ ): ClearFloatDirection {
36
+ if (tokenType === "CLEAR_FLOAT_LEFT") {
37
+ return "left";
38
+ }
39
+ if (tokenType === "CLEAR_FLOAT_RIGHT") {
40
+ return "right";
41
+ }
42
+ return "both";
43
+ }
@@ -0,0 +1,30 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export function repairSwallowedCodeClose(
4
+ ctx: ParseContext,
5
+ pos: number,
6
+ attrs: Record<string, string>,
7
+ ): { closingSwallowed: boolean } | null {
8
+ const prevToken = ctx.tokens[pos - 1];
9
+ if (prevToken?.type !== "QUOTED_STRING" || !prevToken.value.includes("]]")) {
10
+ return null;
11
+ }
12
+
13
+ const rawValue = prevToken.value;
14
+ const bracketIdx = rawValue.indexOf("]]");
15
+ const truncatedValue = rawValue.startsWith('"')
16
+ ? rawValue.slice(1, bracketIdx)
17
+ : rawValue.slice(0, bracketIdx);
18
+
19
+ for (const key of Object.keys(attrs)) {
20
+ const stored = attrs[key]!;
21
+ if (stored === rawValue || stored === rawValue.slice(1, -1) || stored === rawValue.slice(1)) {
22
+ attrs[key] = truncatedValue;
23
+ break;
24
+ }
25
+ }
26
+
27
+ return {
28
+ closingSwallowed: rawValue.includes("[[/code]]"),
29
+ };
30
+ }
@@ -0,0 +1,57 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+
4
+ export interface CodeContentResult {
5
+ contents: string;
6
+ consumed: number;
7
+ foundClose: boolean;
8
+ }
9
+
10
+ export function collectCodeContent(
11
+ ctx: ParseContext,
12
+ startPos: number,
13
+ closingSwallowed: boolean,
14
+ ): CodeContentResult {
15
+ const contentParts: string[] = [];
16
+ let pos = startPos;
17
+ let consumed = 0;
18
+ let foundClose = closingSwallowed;
19
+
20
+ while (!closingSwallowed && pos < ctx.tokens.length) {
21
+ const token = ctx.tokens[pos];
22
+ if (!token || token.type === "EOF") {
23
+ break;
24
+ }
25
+
26
+ if (token.type === "BLOCK_END_OPEN") {
27
+ const closeNameResult = parseBlockName(ctx, pos + 1);
28
+ if (closeNameResult?.name === "code") {
29
+ foundClose = true;
30
+ const closeConsumed = consumeCodeClose(ctx, pos, closeNameResult.consumed);
31
+ consumed += closeConsumed;
32
+ break;
33
+ }
34
+ }
35
+
36
+ contentParts.push(token.value);
37
+ pos++;
38
+ consumed++;
39
+ }
40
+
41
+ return { contents: contentParts.join(""), consumed, foundClose };
42
+ }
43
+
44
+ function consumeCodeClose(ctx: ParseContext, startPos: number, closeNameConsumed: number): number {
45
+ let pos = startPos + 1 + closeNameConsumed;
46
+ let consumed = 1 + closeNameConsumed;
47
+
48
+ if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
49
+ pos++;
50
+ consumed++;
51
+ }
52
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
53
+ consumed++;
54
+ }
55
+
56
+ return consumed;
57
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ *
3
+ * Block rule for the Wikidot code block: `[[code]]...[[/code]]`.
4
+ *
5
+ * A code block captures its body as raw text (no inline parsing) and
6
+ * supports two optional attributes:
7
+ * - `type` -- the programming language for syntax highlighting.
8
+ * - `name` -- a label or filename displayed alongside the code.
9
+ *
10
+ * @module
11
+ */
12
+ import type { Element, CodeBlockData } from "@wdprlib/ast";
13
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
14
+ import { currentToken } from "../../types";
15
+ import { parseBlockName } from "../utils";
16
+ import { parseAttributesRaw } from "../utils";
17
+ import { repairSwallowedCodeClose } from "./attributes";
18
+ import { collectCodeContent } from "./content";
19
+
20
+ /**
21
+ * Block rule for `[[code type="..." name="..."]]...[[/code]]`.
22
+ *
23
+ * Body content is stored as-is (not parsed for inline markup). The rule
24
+ * also registers the code block in `ctx.codeBlocks` for document-level
25
+ * introspection.
26
+ */
27
+ export const codeBlockRule: BlockRule = {
28
+ name: "code",
29
+ startTokens: ["BLOCK_OPEN"],
30
+ requiresLineStart: false,
31
+
32
+ parse(ctx: ParseContext): RuleResult<Element> {
33
+ const openToken = currentToken(ctx);
34
+ if (openToken.type !== "BLOCK_OPEN") {
35
+ return { success: false };
36
+ }
37
+
38
+ let pos = ctx.pos + 1;
39
+ let consumed = 1;
40
+
41
+ const nameResult = parseBlockName(ctx, pos);
42
+ if (!nameResult || nameResult.name !== "code") {
43
+ return { success: false };
44
+ }
45
+
46
+ pos += nameResult.consumed;
47
+ consumed += nameResult.consumed;
48
+
49
+ const attrResult = parseAttributesRaw(ctx, pos);
50
+ pos += attrResult.consumed;
51
+ consumed += attrResult.consumed;
52
+
53
+ let closingSwallowed = false;
54
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
55
+ const repaired = repairSwallowedCodeClose(ctx, pos, attrResult.attrs);
56
+ if (!repaired) return { success: false };
57
+ closingSwallowed = repaired.closingSwallowed;
58
+ } else {
59
+ pos++;
60
+ consumed++;
61
+ }
62
+
63
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
64
+ pos++;
65
+ consumed++;
66
+ }
67
+
68
+ const contentResult = collectCodeContent(ctx, pos, closingSwallowed);
69
+ let codeContent = contentResult.contents.replace(/\n$/, "");
70
+ consumed += contentResult.consumed;
71
+ pos += contentResult.consumed;
72
+
73
+ if (!contentResult.foundClose) {
74
+ ctx.diagnostics.push({
75
+ severity: "warning",
76
+ code: "unclosed-block",
77
+ message: "Missing closing tag [[/code]] for [[code]]",
78
+ position: openToken.position,
79
+ });
80
+ }
81
+
82
+ const codeBlockData: CodeBlockData = {
83
+ contents: codeContent,
84
+ language: attrResult.attrs.type ?? null,
85
+ name: attrResult.attrs.name ?? null,
86
+ };
87
+ ctx.codeBlocks.push(codeBlockData);
88
+
89
+ return {
90
+ success: true,
91
+ elements: [
92
+ {
93
+ element: "code",
94
+ data: codeBlockData,
95
+ },
96
+ ],
97
+ consumed,
98
+ };
99
+ },
100
+ };