@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,95 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseInlineUntil } from "../../inline/utils";
4
+
5
+ export interface DefinitionItemKeyResult {
6
+ keyString: string;
7
+ key: Element[];
8
+ consumed: number;
9
+ }
10
+
11
+ export function parseDefinitionItemKey(
12
+ ctx: ParseContext,
13
+ startPos: number,
14
+ ): DefinitionItemKeyResult | null {
15
+ let pos = startPos;
16
+ let consumed = 0;
17
+
18
+ const colonToken = ctx.tokens[pos];
19
+ if (!colonToken || colonToken.type !== "COLON" || !colonToken.lineStart) {
20
+ return null;
21
+ }
22
+ pos++;
23
+ consumed++;
24
+
25
+ const whitespaceAfterColon = ctx.tokens[pos];
26
+ if (!whitespaceAfterColon || whitespaceAfterColon.type !== "WHITESPACE") {
27
+ return null;
28
+ }
29
+
30
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
31
+ pos++;
32
+ consumed++;
33
+ }
34
+
35
+ const keyTokens: string[] = [];
36
+ const key: Element[] = [];
37
+ let foundSecondColon = false;
38
+
39
+ while (pos < ctx.tokens.length) {
40
+ const token = ctx.tokens[pos];
41
+ if (!token || token.type === "NEWLINE" || token.type === "EOF") {
42
+ break;
43
+ }
44
+ if (token.type === "COLON") {
45
+ foundSecondColon = true;
46
+ pos++;
47
+ consumed++;
48
+ break;
49
+ }
50
+
51
+ const inlineCtx: ParseContext = { ...ctx, pos };
52
+ const result = parseInlineUntil(inlineCtx, "COLON");
53
+ if (result.elements.length > 0) {
54
+ key.push(...result.elements);
55
+ for (let i = 0; i < result.consumed; i++) {
56
+ const t = ctx.tokens[pos + i];
57
+ if (t) keyTokens.push(t.value);
58
+ }
59
+ pos += result.consumed;
60
+ consumed += result.consumed;
61
+ } else {
62
+ keyTokens.push(token.value);
63
+ pos++;
64
+ consumed++;
65
+ }
66
+ }
67
+
68
+ if (!foundSecondColon) {
69
+ return null;
70
+ }
71
+
72
+ trimTrailingWhitespaceText(key);
73
+
74
+ return {
75
+ keyString: keyTokens.join("").trim(),
76
+ key,
77
+ consumed,
78
+ };
79
+ }
80
+
81
+ function trimTrailingWhitespaceText(nodes: Element[]): void {
82
+ while (nodes.length > 0) {
83
+ const lastNode = nodes[nodes.length - 1];
84
+ if (
85
+ lastNode &&
86
+ lastNode.element === "text" &&
87
+ typeof lastNode.data === "string" &&
88
+ lastNode.data.trim() === ""
89
+ ) {
90
+ nodes.pop();
91
+ } else {
92
+ break;
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,56 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseInlineUntil } from "../../inline/utils";
4
+
5
+ export interface DefinitionItemValueResult {
6
+ value: Element[];
7
+ consumed: number;
8
+ }
9
+
10
+ export function parseDefinitionItemValue(
11
+ ctx: ParseContext,
12
+ startPos: number,
13
+ ): DefinitionItemValueResult {
14
+ const value: Element[] = [];
15
+ let pos = startPos;
16
+ let consumed = 0;
17
+
18
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
19
+ pos++;
20
+ consumed++;
21
+ }
22
+
23
+ while (pos < ctx.tokens.length) {
24
+ const token = ctx.tokens[pos];
25
+ if (!token || token.type === "EOF") {
26
+ break;
27
+ }
28
+
29
+ if (token.type === "NEWLINE") {
30
+ const nextToken = ctx.tokens[pos + 1];
31
+ if (nextToken?.type === "COLON" && nextToken.lineStart) {
32
+ pos++;
33
+ consumed++;
34
+ break;
35
+ }
36
+ if (nextToken?.type === "NEWLINE" || !nextToken || nextToken.type === "EOF") {
37
+ pos++;
38
+ consumed++;
39
+ break;
40
+ }
41
+ }
42
+
43
+ const inlineCtx: ParseContext = { ...ctx, pos };
44
+ const result = parseInlineUntil(inlineCtx, "NEWLINE");
45
+ if (result.elements.length > 0) {
46
+ value.push(...result.elements);
47
+ pos += result.consumed;
48
+ consumed += result.consumed;
49
+ } else {
50
+ pos++;
51
+ consumed++;
52
+ }
53
+ }
54
+
55
+ return { value, consumed };
56
+ }
@@ -0,0 +1,54 @@
1
+ import type { DefinitionListItem, Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseDefinitionItemKey } from "./item-key";
4
+ import { parseDefinitionItemValue } from "./item-value";
5
+
6
+ /**
7
+ * Internal representation of one definition list item before conversion
8
+ * to the AST's DefinitionListItem format.
9
+ */
10
+ export interface ParsedDefinitionItem {
11
+ /** Raw string of the key, used for `key_string` in the AST. */
12
+ keyString: string;
13
+ /** Parsed inline elements representing the key / term. */
14
+ key: Element[];
15
+ /** Parsed inline elements representing the value / definition. */
16
+ value: Element[];
17
+ }
18
+
19
+ /**
20
+ * Parses a single definition list entry of the form `: key : value`.
21
+ *
22
+ * The function expects `startPos` to point at a line-start COLON token.
23
+ * It consumes the first colon, mandatory whitespace, key tokens up to
24
+ * the second colon, then value tokens until a double newline, a new entry,
25
+ * or end of input.
26
+ */
27
+ export function parseDefinitionItem(
28
+ ctx: ParseContext,
29
+ startPos: number,
30
+ ): { item: ParsedDefinitionItem; consumed: number } | null {
31
+ const keyResult = parseDefinitionItemKey(ctx, startPos);
32
+ if (!keyResult) {
33
+ return null;
34
+ }
35
+
36
+ const valueResult = parseDefinitionItemValue(ctx, startPos + keyResult.consumed);
37
+
38
+ return {
39
+ item: {
40
+ keyString: keyResult.keyString,
41
+ key: keyResult.key,
42
+ value: valueResult.value,
43
+ },
44
+ consumed: keyResult.consumed + valueResult.consumed,
45
+ };
46
+ }
47
+
48
+ export function toDefinitionListItems(items: ParsedDefinitionItem[]): DefinitionListItem[] {
49
+ return items.map((item) => ({
50
+ key_string: item.keyString,
51
+ key: item.key,
52
+ value: item.value,
53
+ }));
54
+ }
@@ -0,0 +1,41 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseBlocksUntil } from "../utils";
4
+ import { isDivClose } from "./close";
5
+ import { countDivCloses } from "./nesting";
6
+ import { unwrapEdgeParagraphs } from "./paragraph-strip";
7
+
8
+ export interface DivBodyResult {
9
+ elements: Element[];
10
+ consumed: number;
11
+ }
12
+
13
+ export function parseDivBody(
14
+ ctx: ParseContext,
15
+ startPos: number,
16
+ paragraphStrip: boolean,
17
+ ): DivBodyResult {
18
+ const bodyBudget = resolveDivBodyBudget(ctx, startPos);
19
+ const bodyCtx: ParseContext = {
20
+ ...ctx,
21
+ pos: startPos,
22
+ scope: { ...ctx.scope, divClosesBudget: bodyBudget },
23
+ };
24
+
25
+ const bodyResult = parseBlocksUntil(bodyCtx, isDivClose);
26
+ const elements = paragraphStrip ? unwrapEdgeParagraphs(bodyResult.elements) : bodyResult.elements;
27
+
28
+ return {
29
+ elements,
30
+ consumed: bodyResult.consumed,
31
+ };
32
+ }
33
+
34
+ function resolveDivBodyBudget(ctx: ParseContext, startPos: number): number {
35
+ if (ctx.scope.divClosesBudget !== undefined) {
36
+ return ctx.scope.divClosesBudget - 1;
37
+ }
38
+
39
+ const closesInScope = countDivCloses(ctx, startPos);
40
+ return closesInScope > 0 ? closesInScope - 1 : 0;
41
+ }
@@ -0,0 +1,41 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+
4
+ export function isDivClose(ctx: ParseContext): boolean {
5
+ const token = ctx.tokens[ctx.pos];
6
+ if (token?.type !== "BLOCK_END_OPEN") return false;
7
+
8
+ const closeNameResult = parseBlockName(ctx, ctx.pos + 1);
9
+ return closeNameResult?.name === "div";
10
+ }
11
+
12
+ export function consumeDivClose(
13
+ ctx: ParseContext,
14
+ startPos: number,
15
+ ): { pos: number; consumed: number } {
16
+ let pos = startPos;
17
+ let consumed = 0;
18
+
19
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
20
+ return { pos, consumed };
21
+ }
22
+
23
+ pos++;
24
+ consumed++;
25
+
26
+ const closeNameResult = parseBlockName(ctx, pos);
27
+ if (closeNameResult) {
28
+ pos += closeNameResult.consumed;
29
+ consumed += closeNameResult.consumed;
30
+ }
31
+ if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
32
+ pos++;
33
+ consumed++;
34
+ }
35
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
36
+ pos++;
37
+ consumed++;
38
+ }
39
+
40
+ return { pos, consumed };
41
+ }
@@ -0,0 +1,117 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext, RuleResult } from "../../types";
3
+ import { parseAttributes, parseBlockName } from "../utils";
4
+
5
+ /**
6
+ * Handles the case where `[[div]]` fails as a block element because
7
+ * the closing `]]` is not followed by a NEWLINE.
8
+ */
9
+ export function consumeFailedDiv(ctx: ParseContext): RuleResult<Element> {
10
+ const elements: Element[] = [];
11
+ let pos = ctx.pos;
12
+ let consumed = 0;
13
+ let lastClosePos = -1;
14
+ let lastCloseConsumed = 0;
15
+
16
+ let scanPos = pos;
17
+ while (scanPos < ctx.tokens.length) {
18
+ const t = ctx.tokens[scanPos];
19
+ if (!t || t.type === "EOF") break;
20
+
21
+ if (t.type === "BLOCK_OPEN" && t.lineStart && scanPos > pos) {
22
+ const nameResult = parseBlockName(ctx, scanPos + 1);
23
+ if (nameResult?.name === "div" || nameResult?.name === "div_") {
24
+ let checkPos = scanPos + 1 + nameResult.consumed;
25
+ const attrResult = parseAttributes(ctx, checkPos);
26
+ checkPos += attrResult.consumed;
27
+ if (ctx.tokens[checkPos]?.type === "BLOCK_CLOSE") {
28
+ checkPos++;
29
+ if (ctx.tokens[checkPos]?.type === "NEWLINE" || ctx.tokens[checkPos]?.type === "EOF") {
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ }
35
+
36
+ if (t.type === "BLOCK_END_OPEN") {
37
+ const nameResult = parseBlockName(ctx, scanPos + 1);
38
+ if (nameResult?.name === "div") {
39
+ lastClosePos = scanPos;
40
+ lastCloseConsumed = 1 + nameResult.consumed;
41
+ const closeToken = ctx.tokens[scanPos + 1 + nameResult.consumed];
42
+ if (closeToken?.type === "BLOCK_CLOSE") {
43
+ lastCloseConsumed++;
44
+ }
45
+ }
46
+ }
47
+ scanPos++;
48
+ }
49
+
50
+ if (lastClosePos === -1) {
51
+ return { success: false };
52
+ }
53
+
54
+ const endPosForDiag = lastClosePos;
55
+ for (let diagPos = ctx.pos; diagPos < endPosForDiag; diagPos++) {
56
+ const t = ctx.tokens[diagPos];
57
+ if (t?.type === "BLOCK_OPEN") {
58
+ const nameResult = parseBlockName(ctx, diagPos + 1);
59
+ if (nameResult?.name === "div" || nameResult?.name === "div_") {
60
+ if (t.position) {
61
+ ctx.diagnostics.push({
62
+ severity: "error",
63
+ code: "inline-block-element",
64
+ message: `[[${nameResult.name}]] must be followed by a newline to be a block element`,
65
+ position: t.position,
66
+ });
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ const endPos = lastClosePos + lastCloseConsumed;
73
+ while (pos < endPos && pos < ctx.tokens.length) {
74
+ const t = ctx.tokens[pos];
75
+ if (!t || t.type === "EOF") break;
76
+
77
+ if (t.type === "NEWLINE") {
78
+ let peekPos = pos + 1;
79
+ while (ctx.tokens[peekPos]?.type === "WHITESPACE") peekPos++;
80
+ if (ctx.tokens[peekPos]?.type === "NEWLINE") {
81
+ while (ctx.tokens[pos]?.type === "NEWLINE" || ctx.tokens[pos]?.type === "WHITESPACE") {
82
+ pos++;
83
+ consumed++;
84
+ }
85
+ continue;
86
+ }
87
+ elements.push({ element: "line-break" });
88
+ pos++;
89
+ consumed++;
90
+ continue;
91
+ }
92
+
93
+ elements.push({ element: "text", data: t.value });
94
+ pos++;
95
+ consumed++;
96
+ }
97
+
98
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
99
+ pos++;
100
+ consumed++;
101
+ }
102
+
103
+ return {
104
+ success: true,
105
+ elements: [
106
+ {
107
+ element: "container",
108
+ data: {
109
+ type: "paragraph",
110
+ attributes: {},
111
+ elements,
112
+ },
113
+ },
114
+ ],
115
+ consumed,
116
+ };
117
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot `[[div]]` and `[[div_]]` container blocks.
4
+ *
5
+ * `[[div]]` wraps its body content in a `<div>` element, with full
6
+ * paragraph processing for the body. `[[div_]]` (paragraph strip mode)
7
+ * unwraps the first and last paragraphs so their content appears directly
8
+ * inside the `<div>`, while middle paragraphs keep their `<p>` wrappers.
9
+ *
10
+ * Both variants accept HTML attributes (class, style, id, etc.) on the
11
+ * opening tag.
12
+ *
13
+ * Wikidot-specific edge cases:
14
+ * - The opening `]]` MUST be followed by a NEWLINE for the block to be
15
+ * recognised. `[[div]]inline[[/div]]` is NOT a valid div -- it becomes
16
+ * a failed div (see `consumeFailedDiv()`).
17
+ * - When a div fails, everything from the opening `[[div]]` through the
18
+ * last `[[/div]]` is collected as a single paragraph of text/line-break
19
+ * elements. Blank lines within that span are silently removed.
20
+ * - `[[div_]]` uses `unwrapEdgeParagraphs()` to strip paragraph
21
+ * wrappers from the first and last elements.
22
+ *
23
+ * @module
24
+ */
25
+ import type { Element } from "@wdprlib/ast";
26
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
27
+ import { currentToken } from "../../types";
28
+ import { parseDivBody } from "./body";
29
+ import { consumeDivClose } from "./close";
30
+ import { consumeFailedDiv } from "./failed";
31
+ import { parseDivOpen } from "./open";
32
+
33
+ /**
34
+ * Block rule for `[[div]]`/`[[div_]]` container blocks.
35
+ *
36
+ * `requiresLineStart` is `false` because nested `[[div_]]` inside another
37
+ * `[[div_]]` may appear after inline content.
38
+ */
39
+ export const divRule: BlockRule = {
40
+ name: "div",
41
+ startTokens: ["BLOCK_OPEN"],
42
+ requiresLineStart: false, // Allow nested [[div_]] inside [[div_]]
43
+
44
+ parse(ctx: ParseContext): RuleResult<Element> {
45
+ const openToken = currentToken(ctx);
46
+ if (openToken.type !== "BLOCK_OPEN") {
47
+ return { success: false };
48
+ }
49
+
50
+ const openResult = parseDivOpen(ctx);
51
+ if (!openResult) {
52
+ return { success: false };
53
+ }
54
+
55
+ // Wikidot: [[div]] must be followed by newline to be recognized as block
56
+ // [[div]]inline[[/div]] is NOT recognized as div
57
+ // When this fails, Wikidot consumes everything up to the last [[/div]]
58
+ // as text in a single paragraph (blank lines are ignored)
59
+ if (!openResult.hasRequiredNewline) {
60
+ return consumeFailedDiv(ctx);
61
+ }
62
+
63
+ // Wikidot matches [[div]]/[[/div]] pairs from outside-in. When there are
64
+ // more opens than closes, the innermost excess opens become text. We enforce
65
+ // this with a "closes budget": the number of additional nested divs that can
66
+ // open. When budget reaches 0, this div cannot open.
67
+ if (ctx.scope.divClosesBudget === 0) {
68
+ return { success: false };
69
+ }
70
+
71
+ // Record opening tag position for diagnostics
72
+ const openPosition = openToken.position;
73
+
74
+ let pos = openResult.bodyStart;
75
+ let consumed = openResult.consumed;
76
+ const bodyResult = parseDivBody(ctx, pos, openResult.paragraphStrip);
77
+ consumed += bodyResult.consumed;
78
+ pos += bodyResult.consumed;
79
+
80
+ // Check for missing close tag
81
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
82
+ ctx.diagnostics.push({
83
+ severity: "warning",
84
+ code: "unclosed-block",
85
+ message: `Missing closing tag [[/div]] for [[${openResult.blockName}]]`,
86
+ position: openPosition,
87
+ });
88
+ }
89
+
90
+ // Consume [[/div]]
91
+ if (ctx.tokens[pos]?.type === "BLOCK_END_OPEN") {
92
+ const closeResult = consumeDivClose(ctx, pos);
93
+ pos = closeResult.pos;
94
+ consumed += closeResult.consumed;
95
+ }
96
+
97
+ return {
98
+ success: true,
99
+ elements: [
100
+ {
101
+ element: "container",
102
+ data: {
103
+ type: "div",
104
+ attributes: openResult.attributes,
105
+ elements: bodyResult.elements,
106
+ },
107
+ },
108
+ ],
109
+ consumed,
110
+ };
111
+ },
112
+ };
@@ -0,0 +1,37 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ const divCloseCountCache = new WeakMap<ParseContext["tokens"], Uint32Array>();
4
+
5
+ /**
6
+ * Counts `[[/div]]` close tags from a given position to the end of the
7
+ * token stream. Used to calculate the nesting budget for div blocks.
8
+ */
9
+ export function countDivCloses(ctx: ParseContext, startPos: number): number {
10
+ let counts = divCloseCountCache.get(ctx.tokens);
11
+ if (!counts) {
12
+ counts = new Uint32Array(ctx.tokens.length + 1);
13
+ for (let i = ctx.tokens.length - 1; i >= 0; i--) {
14
+ let count = counts[i + 1]!;
15
+ if (isDivCloseToken(ctx, i)) {
16
+ count++;
17
+ }
18
+ counts[i] = count;
19
+ }
20
+ divCloseCountCache.set(ctx.tokens, counts);
21
+ }
22
+ return counts[startPos] ?? 0;
23
+ }
24
+
25
+ function isDivCloseToken(ctx: ParseContext, pos: number): boolean {
26
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") return false;
27
+ const name = ctx.tokens[pos + 1];
28
+ if (!name || (name.type !== "TEXT" && name.type !== "IDENTIFIER")) return false;
29
+ if (name.value.length !== 3) return false;
30
+ const d = name.value.charCodeAt(0);
31
+ const i = name.value.charCodeAt(1);
32
+ const v = name.value.charCodeAt(2);
33
+ if (!((d === 100 || d === 68) && (i === 105 || i === 73) && (v === 118 || v === 86))) {
34
+ return false;
35
+ }
36
+ return ctx.tokens[pos + 2]?.type !== "UNDERSCORE";
37
+ }
@@ -0,0 +1,59 @@
1
+ import type { AttributeMap } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseAttributes, parseBlockName } from "../utils";
4
+
5
+ export interface DivOpenResult {
6
+ blockName: "div" | "div_";
7
+ paragraphStrip: boolean;
8
+ attributes: AttributeMap;
9
+ bodyStart: number;
10
+ consumed: number;
11
+ hasRequiredNewline: boolean;
12
+ }
13
+
14
+ export function parseDivOpen(ctx: ParseContext): DivOpenResult | null {
15
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
16
+ return null;
17
+ }
18
+
19
+ let pos = ctx.pos + 1;
20
+ let consumed = 1;
21
+
22
+ const nameResult = parseBlockName(ctx, pos);
23
+ if (!nameResult || !isDivBlockName(nameResult.name)) {
24
+ return null;
25
+ }
26
+
27
+ pos += nameResult.consumed;
28
+ consumed += nameResult.consumed;
29
+
30
+ const attrResult = parseAttributes(ctx, pos);
31
+ pos += attrResult.consumed;
32
+ consumed += attrResult.consumed;
33
+
34
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
35
+ return null;
36
+ }
37
+
38
+ pos++;
39
+ consumed++;
40
+
41
+ const hasRequiredNewline = ctx.tokens[pos]?.type === "NEWLINE";
42
+ if (hasRequiredNewline) {
43
+ pos++;
44
+ consumed++;
45
+ }
46
+
47
+ return {
48
+ blockName: nameResult.name,
49
+ paragraphStrip: nameResult.name === "div_",
50
+ attributes: attrResult.attrs,
51
+ bodyStart: pos,
52
+ consumed,
53
+ hasRequiredNewline,
54
+ };
55
+ }
56
+
57
+ function isDivBlockName(name: string): name is "div" | "div_" {
58
+ return name === "div" || name === "div_";
59
+ }
@@ -0,0 +1,44 @@
1
+ import type { ContainerData, Element } from "@wdprlib/ast";
2
+
3
+ /**
4
+ * Implements the `[[div_]]` paragraph-strip behaviour.
5
+ *
6
+ * In Wikidot's `div_` mode, the first and last paragraph containers have
7
+ * their `<p>` wrappers removed, leaving the inner elements bare. Any
8
+ * middle paragraphs retain their wrapping.
9
+ */
10
+ export function unwrapEdgeParagraphs(elements: Element[]): Element[] {
11
+ if (elements.length === 0) return elements;
12
+
13
+ const result = [...elements];
14
+
15
+ const first = result[0];
16
+ if (isParagraphContainer(first)) {
17
+ const inner = first.data.elements;
18
+ result.splice(0, 1, ...inner);
19
+ }
20
+
21
+ const lastIdx = result.length - 1;
22
+ const last = result[lastIdx];
23
+ if (lastIdx >= 0 && isParagraphContainer(last)) {
24
+ const inner = last.data.elements;
25
+ result.splice(lastIdx, 1, ...inner);
26
+ }
27
+
28
+ return result;
29
+ }
30
+
31
+ type ParagraphContainer = Extract<Element, { element: "container" }> & {
32
+ data: ContainerData & { type: "paragraph" };
33
+ };
34
+
35
+ function isParagraphContainer(el: Element | undefined): el is ParagraphContainer {
36
+ return (
37
+ el !== undefined &&
38
+ el.element === "container" &&
39
+ typeof el.data === "object" &&
40
+ el.data !== null &&
41
+ "type" in el.data &&
42
+ el.data.type === "paragraph"
43
+ );
44
+ }