@wdprlib/parser 3.1.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/dist/index.cjs +10456 -8230
  2. package/dist/index.d.cts +313 -337
  3. package/dist/index.d.ts +313 -337
  4. package/dist/index.js +10460 -8234
  5. package/package.json +5 -3
  6. package/src/index.ts +170 -0
  7. package/src/lexer/anchor.ts +48 -0
  8. package/src/lexer/index.ts +21 -0
  9. package/src/lexer/lexer.ts +201 -0
  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/lexer/tokens.ts +141 -0
  22. package/src/parser/constants.ts +175 -0
  23. package/src/parser/depth/index.ts +111 -0
  24. package/src/parser/depth/stack.ts +82 -0
  25. package/src/parser/index.ts +18 -0
  26. package/src/parser/parse/block.ts +42 -0
  27. package/src/parser/parse/context.ts +26 -0
  28. package/src/parser/parse/footnotes.ts +25 -0
  29. package/src/parser/parse/index.ts +42 -0
  30. package/src/parser/parse/options.ts +34 -0
  31. package/src/parser/parse/parser.ts +79 -0
  32. package/src/parser/parse/plain-non-ascii.ts +129 -0
  33. package/src/parser/parse/result.ts +57 -0
  34. package/src/parser/parse/source.ts +11 -0
  35. package/src/parser/postprocess/divAdjacentParagraph.ts +76 -0
  36. package/src/parser/postprocess/index.ts +15 -0
  37. package/src/parser/postprocess/spanStrip/clean-element.ts +168 -0
  38. package/src/parser/postprocess/spanStrip/cleanup.ts +25 -0
  39. package/src/parser/postprocess/spanStrip/empty-spans.ts +36 -0
  40. package/src/parser/postprocess/spanStrip/escaped.ts +78 -0
  41. package/src/parser/postprocess/spanStrip/factory.ts +23 -0
  42. package/src/parser/postprocess/spanStrip/index.ts +8 -0
  43. package/src/parser/postprocess/spanStrip/merge.ts +117 -0
  44. package/src/parser/postprocess/spanStrip/predicates.ts +59 -0
  45. package/src/parser/postprocess/spanStrip/split.ts +67 -0
  46. package/src/parser/preprocess/expr/chars.ts +15 -0
  47. package/src/parser/preprocess/expr/evaluate.ts +22 -0
  48. package/src/parser/preprocess/expr/index.ts +45 -0
  49. package/src/parser/preprocess/expr/kind.ts +19 -0
  50. package/src/parser/preprocess/expr/parse.ts +103 -0
  51. package/src/parser/preprocess/expr/scan.ts +34 -0
  52. package/src/parser/preprocess/expr/types.ts +14 -0
  53. package/src/parser/preprocess/index.ts +38 -0
  54. package/src/parser/preprocess/typography.ts +132 -0
  55. package/src/parser/preprocess/utils/bracket-depths.ts +98 -0
  56. package/src/parser/preprocess/utils/index.ts +13 -0
  57. package/src/parser/preprocess/utils/raw-regions.ts +153 -0
  58. package/src/parser/preprocess/whitespace/detection.ts +39 -0
  59. package/src/parser/preprocess/whitespace/index.ts +79 -0
  60. package/src/parser/preprocess/whitespace/leading-spaces.ts +11 -0
  61. package/src/parser/preprocess/whitespace/patterns.ts +23 -0
  62. package/src/parser/rules/block/align/body.ts +46 -0
  63. package/src/parser/rules/block/align/element.ts +13 -0
  64. package/src/parser/rules/block/align/index.ts +90 -0
  65. package/src/parser/rules/block/align/syntax.ts +113 -0
  66. package/src/parser/rules/block/bibliography/body.ts +81 -0
  67. package/src/parser/rules/block/bibliography/entries.ts +49 -0
  68. package/src/parser/rules/block/bibliography/entry-content.ts +73 -0
  69. package/src/parser/rules/block/bibliography/entry-key.ts +83 -0
  70. package/src/parser/rules/block/bibliography/index.ts +90 -0
  71. package/src/parser/rules/block/bibliography/open.ts +53 -0
  72. package/src/parser/rules/block/block-list/bare-content.ts +105 -0
  73. package/src/parser/rules/block/block-list/bare-paragraph.ts +60 -0
  74. package/src/parser/rules/block/block-list/index.ts +51 -0
  75. package/src/parser/rules/block/block-list/item-content.ts +132 -0
  76. package/src/parser/rules/block/block-list/li-content.ts +107 -0
  77. package/src/parser/rules/block/block-list/li-item.ts +77 -0
  78. package/src/parser/rules/block/block-list/list-block.ts +100 -0
  79. package/src/parser/rules/block/block-list/open.ts +51 -0
  80. package/src/parser/rules/block/block-list/tags.ts +50 -0
  81. package/src/parser/rules/block/blockquote/build.ts +62 -0
  82. package/src/parser/rules/block/blockquote/index.ts +80 -0
  83. package/src/parser/rules/block/blockquote/line.ts +79 -0
  84. package/src/parser/rules/block/blockquote/lines.ts +39 -0
  85. package/src/parser/rules/block/center/index.ts +72 -0
  86. package/src/parser/rules/block/center/open.ts +27 -0
  87. package/src/parser/rules/block/clear-float/index.ts +51 -0
  88. package/src/parser/rules/block/clear-float/syntax.ts +43 -0
  89. package/src/parser/rules/block/code/attributes.ts +30 -0
  90. package/src/parser/rules/block/code/content.ts +57 -0
  91. package/src/parser/rules/block/code/index.ts +100 -0
  92. package/src/parser/rules/block/collapsible/attributes.ts +95 -0
  93. package/src/parser/rules/block/collapsible/body.ts +69 -0
  94. package/src/parser/rules/block/collapsible/index.ts +117 -0
  95. package/src/parser/rules/block/collapsible/open.ts +51 -0
  96. package/src/parser/rules/block/collapsible/orphans.ts +31 -0
  97. package/src/parser/rules/block/collapsible/tags.ts +17 -0
  98. package/src/parser/rules/block/comment/consume.ts +37 -0
  99. package/src/parser/rules/block/comment/index.ts +47 -0
  100. package/src/parser/rules/block/content-separator/index.ts +49 -0
  101. package/src/parser/rules/block/content-separator/syntax.ts +33 -0
  102. package/src/parser/rules/block/definition-list/collect.ts +40 -0
  103. package/src/parser/rules/block/definition-list/index.ts +63 -0
  104. package/src/parser/rules/block/definition-list/item-key.ts +95 -0
  105. package/src/parser/rules/block/definition-list/item-value.ts +56 -0
  106. package/src/parser/rules/block/definition-list/items.ts +54 -0
  107. package/src/parser/rules/block/div/body.ts +41 -0
  108. package/src/parser/rules/block/div/close.ts +41 -0
  109. package/src/parser/rules/block/div/failed.ts +117 -0
  110. package/src/parser/rules/block/div/index.ts +112 -0
  111. package/src/parser/rules/block/div/nesting.ts +37 -0
  112. package/src/parser/rules/block/div/open.ts +59 -0
  113. package/src/parser/rules/block/div/paragraph-strip.ts +44 -0
  114. package/src/parser/rules/block/embed-block/content.ts +53 -0
  115. package/src/parser/rules/block/embed-block/index.ts +91 -0
  116. package/src/parser/rules/block/embed-block/open.ts +52 -0
  117. package/src/parser/rules/block/embed-block/tags.ts +5 -0
  118. package/src/parser/rules/block/footnoteblock/attributes.ts +73 -0
  119. package/src/parser/rules/block/footnoteblock/index.ts +82 -0
  120. package/src/parser/rules/block/footnoteblock/open.ts +53 -0
  121. package/src/parser/rules/block/heading/index.ts +87 -0
  122. package/src/parser/rules/block/heading/open.ts +50 -0
  123. package/src/parser/rules/block/heading/toc-text.ts +26 -0
  124. package/src/parser/rules/block/horizontal-rule/index.ts +44 -0
  125. package/src/parser/rules/block/horizontal-rule/syntax.ts +21 -0
  126. package/src/parser/rules/block/html/body.ts +114 -0
  127. package/src/parser/rules/block/html/diagnostics.ts +11 -0
  128. package/src/parser/rules/block/html/index.ts +95 -0
  129. package/src/parser/rules/block/html/open.ts +36 -0
  130. package/src/parser/rules/block/iframe/attributes.ts +106 -0
  131. package/src/parser/rules/block/iframe/index.ts +73 -0
  132. package/src/parser/rules/block/iframe/open.ts +58 -0
  133. package/src/parser/rules/block/iframe/source.ts +24 -0
  134. package/src/parser/rules/block/iframe/url.ts +38 -0
  135. package/src/parser/rules/block/iftags/body.ts +48 -0
  136. package/src/parser/rules/block/iftags/condition.ts +24 -0
  137. package/src/parser/rules/block/iftags/index.ts +108 -0
  138. package/src/parser/rules/block/include/arguments.ts +48 -0
  139. package/src/parser/rules/block/include/index.ts +75 -0
  140. package/src/parser/rules/block/include/location.ts +24 -0
  141. package/src/parser/rules/block/include/variables.ts +37 -0
  142. package/src/parser/rules/block/index.ts +127 -0
  143. package/src/parser/rules/block/list/index.ts +73 -0
  144. package/src/parser/rules/block/list/line.ts +77 -0
  145. package/src/parser/rules/block/list/native.ts +89 -0
  146. package/src/parser/rules/block/math/content.ts +54 -0
  147. package/src/parser/rules/block/math/index.ts +106 -0
  148. package/src/parser/rules/block/math/name.ts +35 -0
  149. package/src/parser/rules/block/module/backlinks/index.ts +31 -0
  150. package/src/parser/rules/block/module/backlinks/types.ts +21 -0
  151. package/src/parser/rules/block/module/body.ts +92 -0
  152. package/src/parser/rules/block/module/categories/index.ts +34 -0
  153. package/src/parser/rules/block/module/categories/types.ts +21 -0
  154. package/src/parser/rules/block/module/css/index.ts +37 -0
  155. package/src/parser/rules/block/module/element.ts +33 -0
  156. package/src/parser/rules/block/module/iftags/condition.ts +109 -0
  157. package/src/parser/rules/block/module/iftags/index.ts +26 -0
  158. package/src/parser/rules/block/module/iftags/preprocess.ts +140 -0
  159. package/src/parser/rules/block/module/iftags/resolve.ts +73 -0
  160. package/src/parser/rules/block/module/iftags/types.ts +63 -0
  161. package/src/parser/rules/block/module/include/directive.ts +91 -0
  162. package/src/parser/rules/block/module/include/index.ts +29 -0
  163. package/src/parser/rules/block/module/include/references.ts +42 -0
  164. package/src/parser/rules/block/module/include/resolve/cache.ts +44 -0
  165. package/src/parser/rules/block/module/include/resolve/index.ts +106 -0
  166. package/src/parser/rules/block/module/include/resolve/iterate.ts +202 -0
  167. package/src/parser/rules/block/module/include/resolve/replace.ts +31 -0
  168. package/src/parser/rules/block/module/include/resolve/types.ts +105 -0
  169. package/src/parser/rules/block/module/include/scanner.ts +121 -0
  170. package/src/parser/rules/block/module/index.ts +134 -0
  171. package/src/parser/rules/block/module/join/index.ts +34 -0
  172. package/src/parser/rules/block/module/join/types.ts +23 -0
  173. package/src/parser/rules/block/module/listpages/compiler.ts +73 -0
  174. package/src/parser/rules/block/module/listpages/extract.ts +76 -0
  175. package/src/parser/rules/block/module/listpages/extraction/listpages.ts +42 -0
  176. package/src/parser/rules/block/module/listpages/extraction/listusers.ts +30 -0
  177. package/src/parser/rules/block/module/listpages/extraction/query.ts +51 -0
  178. package/src/parser/rules/block/module/listpages/extraction/result.ts +18 -0
  179. package/src/parser/rules/block/module/listpages/extraction/template.ts +96 -0
  180. package/src/parser/rules/block/module/listpages/extraction/variables.ts +58 -0
  181. package/src/parser/rules/block/module/listpages/index.ts +83 -0
  182. package/src/parser/rules/block/module/listpages/normalization/date-selector.ts +53 -0
  183. package/src/parser/rules/block/module/listpages/normalization/numeric-selector.ts +32 -0
  184. package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +82 -0
  185. package/src/parser/rules/block/module/listpages/normalization/selectors.ts +2 -0
  186. package/src/parser/rules/block/module/listpages/normalization/tags-category.ts +86 -0
  187. package/src/parser/rules/block/module/listpages/normalize.ts +74 -0
  188. package/src/parser/rules/block/module/listpages/parser.ts +106 -0
  189. package/src/parser/rules/block/module/listpages/resolution/items.ts +43 -0
  190. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +42 -0
  191. package/src/parser/rules/block/module/listpages/resolve.ts +60 -0
  192. package/src/parser/rules/block/module/listpages/template/format/content.ts +41 -0
  193. package/src/parser/rules/block/module/listpages/template/format/date.ts +116 -0
  194. package/src/parser/rules/block/module/listpages/template/format/index.ts +4 -0
  195. package/src/parser/rules/block/module/listpages/template/format/tags.ts +7 -0
  196. package/src/parser/rules/block/module/listpages/template/format/user.ts +9 -0
  197. package/src/parser/rules/block/module/listpages/template/getters/index.ts +36 -0
  198. package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +60 -0
  199. package/src/parser/rules/block/module/listpages/template/getters/simple.ts +65 -0
  200. package/src/parser/rules/block/module/listpages/template/getters/types.ts +3 -0
  201. package/src/parser/rules/block/module/listpages/template/syntax.ts +97 -0
  202. package/src/parser/rules/block/module/listpages/types/data-fetcher.ts +15 -0
  203. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +52 -0
  204. package/src/parser/rules/block/module/listpages/types/external-data.ts +77 -0
  205. package/src/parser/rules/block/module/listpages/types/index.ts +17 -0
  206. package/src/parser/rules/block/module/listpages/types/normalized-query.ts +120 -0
  207. package/src/parser/rules/block/module/listpages/types/query.ts +67 -0
  208. package/src/parser/rules/block/module/listpages/types/template.ts +17 -0
  209. package/src/parser/rules/block/module/listpages/types/variables.ts +69 -0
  210. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +48 -0
  211. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +19 -0
  212. package/src/parser/rules/block/module/listpages/url-resolution/query.ts +24 -0
  213. package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +53 -0
  214. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +25 -0
  215. package/src/parser/rules/block/module/listpages/url-resolver.ts +29 -0
  216. package/src/parser/rules/block/module/listusers/compiler.ts +56 -0
  217. package/src/parser/rules/block/module/listusers/extract.ts +40 -0
  218. package/src/parser/rules/block/module/listusers/getters.ts +21 -0
  219. package/src/parser/rules/block/module/listusers/index.ts +36 -0
  220. package/src/parser/rules/block/module/listusers/parser.ts +54 -0
  221. package/src/parser/rules/block/module/listusers/resolve.ts +58 -0
  222. package/src/parser/rules/block/module/listusers/types.ts +93 -0
  223. package/src/parser/rules/block/module/listusers/variables.ts +15 -0
  224. package/src/parser/rules/block/module/mapping.ts +61 -0
  225. package/src/parser/rules/block/module/open.ts +57 -0
  226. package/src/parser/rules/block/module/page-tree/index.ts +38 -0
  227. package/src/parser/rules/block/module/page-tree/types.ts +29 -0
  228. package/src/parser/rules/block/module/rate/index.ts +28 -0
  229. package/src/parser/rules/block/module/rate/types.ts +19 -0
  230. package/src/parser/rules/block/module/resolution/contexts.ts +78 -0
  231. package/src/parser/rules/block/module/resolution/data-maps.ts +39 -0
  232. package/src/parser/rules/block/module/resolution/dynamic-modules.ts +93 -0
  233. package/src/parser/rules/block/module/resolution/styles.ts +53 -0
  234. package/src/parser/rules/block/module/resolution/walk-resolve.ts +107 -0
  235. package/src/parser/rules/block/module/resolve.ts +198 -0
  236. package/src/parser/rules/block/module/rule.ts +56 -0
  237. package/src/parser/rules/block/module/types-common.ts +70 -0
  238. package/src/parser/rules/block/module/types.ts +61 -0
  239. package/src/parser/rules/block/module/utils.ts +43 -0
  240. package/src/parser/rules/block/module/walk/children.ts +35 -0
  241. package/src/parser/rules/block/module/walk/index.ts +9 -0
  242. package/src/parser/rules/block/module/walk/map/index.ts +2 -0
  243. package/src/parser/rules/block/module/walk/map/stateful-definition-list.ts +25 -0
  244. package/src/parser/rules/block/module/walk/map/stateful-list.ts +40 -0
  245. package/src/parser/rules/block/module/walk/map/stateful-table.ts +23 -0
  246. package/src/parser/rules/block/module/walk/map/stateful-tabs.ts +19 -0
  247. package/src/parser/rules/block/module/walk/map/stateful.ts +71 -0
  248. package/src/parser/rules/block/module/walk/map/stateless-definition-list.ts +12 -0
  249. package/src/parser/rules/block/module/walk/map/stateless-list.ts +29 -0
  250. package/src/parser/rules/block/module/walk/map/stateless-table.ts +11 -0
  251. package/src/parser/rules/block/module/walk/map/stateless-tabs.ts +5 -0
  252. package/src/parser/rules/block/module/walk/map/stateless.ts +51 -0
  253. package/src/parser/rules/block/module/walk/map/types.ts +6 -0
  254. package/src/parser/rules/block/module/walk/traverse.ts +65 -0
  255. package/src/parser/rules/block/orphan-li/content.ts +60 -0
  256. package/src/parser/rules/block/orphan-li/index.ts +75 -0
  257. package/src/parser/rules/block/orphan-li/open.ts +25 -0
  258. package/src/parser/rules/block/orphan-li/tags.ts +40 -0
  259. package/src/parser/rules/block/paragraph/content.ts +12 -0
  260. package/src/parser/rules/block/paragraph/index.ts +60 -0
  261. package/src/parser/rules/block/paragraph/normalize.ts +52 -0
  262. package/src/parser/rules/block/paragraph/span-markers.ts +52 -0
  263. package/src/parser/rules/block/parsing/attributes/index.ts +32 -0
  264. package/src/parser/rules/block/parsing/attributes/names.ts +93 -0
  265. package/src/parser/rules/block/parsing/attributes/scanner.ts +75 -0
  266. package/src/parser/rules/block/parsing/attributes/values.ts +26 -0
  267. package/src/parser/rules/block/parsing/block-item.ts +29 -0
  268. package/src/parser/rules/block/parsing/content.ts +127 -0
  269. package/src/parser/rules/block/parsing/end-condition.ts +51 -0
  270. package/src/parser/rules/block/parsing/inline-content.ts +105 -0
  271. package/src/parser/rules/block/parsing/inline-newline.ts +41 -0
  272. package/src/parser/rules/block/parsing/non-boundary.ts +24 -0
  273. package/src/parser/rules/block/parsing/rule-dispatch.ts +44 -0
  274. package/src/parser/rules/block/table/index.ts +80 -0
  275. package/src/parser/rules/block/table/pipe/cell-start.ts +69 -0
  276. package/src/parser/rules/block/table/pipe/cell.ts +106 -0
  277. package/src/parser/rules/block/table/pipe/index.ts +2 -0
  278. package/src/parser/rules/block/table/pipe/row.ts +88 -0
  279. package/src/parser/rules/block/table/pipe/tokens.ts +14 -0
  280. package/src/parser/rules/block/table/pipe/trim.ts +50 -0
  281. package/src/parser/rules/block/table-block/body.ts +79 -0
  282. package/src/parser/rules/block/table-block/cell-attributes.ts +33 -0
  283. package/src/parser/rules/block/table-block/cell-boundary.ts +99 -0
  284. package/src/parser/rules/block/table-block/cell-content/index.ts +88 -0
  285. package/src/parser/rules/block/table-block/cell-content/segments.ts +134 -0
  286. package/src/parser/rules/block/table-block/cell-newline.ts +47 -0
  287. package/src/parser/rules/block/table-block/cell.ts +64 -0
  288. package/src/parser/rules/block/table-block/index.ts +113 -0
  289. package/src/parser/rules/block/table-block/row-boundary.ts +75 -0
  290. package/src/parser/rules/block/table-block/structure.ts +80 -0
  291. package/src/parser/rules/block/tabview/body.ts +64 -0
  292. package/src/parser/rules/block/tabview/index.ts +90 -0
  293. package/src/parser/rules/block/tabview/open.ts +50 -0
  294. package/src/parser/rules/block/tabview/tab.ts +92 -0
  295. package/src/parser/rules/block/tabview/tags.ts +30 -0
  296. package/src/parser/rules/block/toc/element.ts +11 -0
  297. package/src/parser/rules/block/toc/index.ts +44 -0
  298. package/src/parser/rules/block/toc/open.ts +84 -0
  299. package/src/parser/rules/block/utils.ts +15 -0
  300. package/src/parser/rules/common/attribute-safety.ts +109 -0
  301. package/src/parser/rules/common/block-name.ts +33 -0
  302. package/src/parser/rules/common/index.ts +2 -0
  303. package/src/parser/rules/contracts/index.ts +3 -0
  304. package/src/parser/rules/contracts/parse-context.ts +38 -0
  305. package/src/parser/rules/contracts/rule.ts +43 -0
  306. package/src/parser/rules/contracts/scope.ts +31 -0
  307. package/src/parser/rules/index.ts +49 -0
  308. package/src/parser/rules/inline/anchor/attributes.ts +54 -0
  309. package/src/parser/rules/inline/anchor/child.ts +26 -0
  310. package/src/parser/rules/inline/anchor/close.ts +34 -0
  311. package/src/parser/rules/inline/anchor/content.ts +59 -0
  312. package/src/parser/rules/inline/anchor/index.ts +103 -0
  313. package/src/parser/rules/inline/anchor/newline.ts +26 -0
  314. package/src/parser/rules/inline/anchor/open.ts +47 -0
  315. package/src/parser/rules/inline/anchor/paragraph-strip.ts +14 -0
  316. package/src/parser/rules/inline/anchor/syntax.ts +40 -0
  317. package/src/parser/rules/inline/anchor-name/index.ts +38 -0
  318. package/src/parser/rules/inline/anchor-name/name.ts +39 -0
  319. package/src/parser/rules/inline/anchor-name/syntax.ts +46 -0
  320. package/src/parser/rules/inline/bibcite/element.ts +14 -0
  321. package/src/parser/rules/inline/bibcite/index.ts +34 -0
  322. package/src/parser/rules/inline/bibcite/syntax.ts +64 -0
  323. package/src/parser/rules/inline/bold.ts +49 -0
  324. package/src/parser/rules/inline/color/index.ts +35 -0
  325. package/src/parser/rules/inline/color/syntax.ts +69 -0
  326. package/src/parser/rules/inline/comment/consume.ts +31 -0
  327. package/src/parser/rules/inline/comment/index.ts +64 -0
  328. package/src/parser/rules/inline/equation-ref/element.ts +8 -0
  329. package/src/parser/rules/inline/equation-ref/index.ts +34 -0
  330. package/src/parser/rules/inline/equation-ref/syntax.ts +45 -0
  331. package/src/parser/rules/inline/expr/branch.ts +104 -0
  332. package/src/parser/rules/inline/expr/conditional-branch.ts +27 -0
  333. package/src/parser/rules/inline/expr/conditional.ts +80 -0
  334. package/src/parser/rules/inline/expr/depth.ts +25 -0
  335. package/src/parser/rules/inline/expr/elements.ts +39 -0
  336. package/src/parser/rules/inline/expr/index.ts +84 -0
  337. package/src/parser/rules/inline/expr/syntax.ts +45 -0
  338. package/src/parser/rules/inline/footnote/child.ts +22 -0
  339. package/src/parser/rules/inline/footnote/close.ts +33 -0
  340. package/src/parser/rules/inline/footnote/content.ts +54 -0
  341. package/src/parser/rules/inline/footnote/elements.ts +38 -0
  342. package/src/parser/rules/inline/footnote/index.ts +54 -0
  343. package/src/parser/rules/inline/footnote/newline.ts +27 -0
  344. package/src/parser/rules/inline/footnote/open.ts +38 -0
  345. package/src/parser/rules/inline/formatting/container.ts +50 -0
  346. package/src/parser/rules/inline/guillemet/index.ts +56 -0
  347. package/src/parser/rules/inline/guillemet/text.ts +11 -0
  348. package/src/parser/rules/inline/html/gate.ts +64 -0
  349. package/src/parser/rules/inline/html/index.ts +81 -0
  350. package/src/parser/rules/inline/html/open.ts +37 -0
  351. package/src/parser/rules/inline/image/attributes.ts +22 -0
  352. package/src/parser/rules/inline/image/body.ts +36 -0
  353. package/src/parser/rules/inline/image/index.ts +89 -0
  354. package/src/parser/rules/inline/image/open.ts +56 -0
  355. package/src/parser/rules/inline/image/source.ts +62 -0
  356. package/src/parser/rules/inline/image/syntax.ts +76 -0
  357. package/src/parser/rules/inline/index.ts +150 -0
  358. package/src/parser/rules/inline/italic.ts +46 -0
  359. package/src/parser/rules/inline/line-break/backslash.ts +58 -0
  360. package/src/parser/rules/inline/line-break/elements.ts +9 -0
  361. package/src/parser/rules/inline/line-break/index.ts +3 -0
  362. package/src/parser/rules/inline/line-break/newline.ts +82 -0
  363. package/src/parser/rules/inline/line-break/underscore.ts +45 -0
  364. package/src/parser/rules/inline/link-anchor.ts +72 -0
  365. package/src/parser/rules/inline/link-bracket/anchor.ts +3 -0
  366. package/src/parser/rules/inline/link-bracket/direct-url.ts +5 -0
  367. package/src/parser/rules/inline/link-bracket/parsed.ts +81 -0
  368. package/src/parser/rules/inline/link-bracket/parts.ts +64 -0
  369. package/src/parser/rules/inline/link-bracket/prefix.ts +15 -0
  370. package/src/parser/rules/inline/link-single.ts +73 -0
  371. package/src/parser/rules/inline/link-star.ts +72 -0
  372. package/src/parser/rules/inline/link-triple/fallback.ts +10 -0
  373. package/src/parser/rules/inline/link-triple/index.ts +62 -0
  374. package/src/parser/rules/inline/link-triple/interwiki.ts +11 -0
  375. package/src/parser/rules/inline/link-triple/label.ts +35 -0
  376. package/src/parser/rules/inline/link-triple/syntax.ts +72 -0
  377. package/src/parser/rules/inline/link-triple/target.ts +36 -0
  378. package/src/parser/rules/inline/math-inline/index.ts +40 -0
  379. package/src/parser/rules/inline/math-inline/syntax.ts +55 -0
  380. package/src/parser/rules/inline/monospace.ts +50 -0
  381. package/src/parser/rules/inline/parsing/block-boundary.ts +42 -0
  382. package/src/parser/rules/inline/parsing/block-start-predicates.ts +117 -0
  383. package/src/parser/rules/inline/parsing/collect.ts +23 -0
  384. package/src/parser/rules/inline/parsing/inline-content.ts +115 -0
  385. package/src/parser/rules/inline/parsing/paragraph-boundary.ts +47 -0
  386. package/src/parser/rules/inline/parsing/plain-text.ts +69 -0
  387. package/src/parser/rules/inline/parsing/preserved-line-break.ts +11 -0
  388. package/src/parser/rules/inline/parsing/rules.ts +34 -0
  389. package/src/parser/rules/inline/parsing/simple-token.ts +26 -0
  390. package/src/parser/rules/inline/raw/angle.ts +40 -0
  391. package/src/parser/rules/inline/raw/double-at.ts +78 -0
  392. package/src/parser/rules/inline/raw/index.ts +26 -0
  393. package/src/parser/rules/inline/raw/result.ts +26 -0
  394. package/src/parser/rules/inline/size/content.ts +65 -0
  395. package/src/parser/rules/inline/size/index.ts +55 -0
  396. package/src/parser/rules/inline/size/open.ts +43 -0
  397. package/src/parser/rules/inline/size/value.ts +45 -0
  398. package/src/parser/rules/inline/span/content.ts +97 -0
  399. package/src/parser/rules/inline/span/elements.ts +108 -0
  400. package/src/parser/rules/inline/span/index.ts +79 -0
  401. package/src/parser/rules/inline/span/newline.ts +50 -0
  402. package/src/parser/rules/inline/span/syntax.ts +70 -0
  403. package/src/parser/rules/inline/strikethrough/index.ts +60 -0
  404. package/src/parser/rules/inline/strikethrough/parse.ts +14 -0
  405. package/src/parser/rules/inline/strikethrough/syntax.ts +24 -0
  406. package/src/parser/rules/inline/subscript.ts +47 -0
  407. package/src/parser/rules/inline/superscript.ts +49 -0
  408. package/src/parser/rules/inline/text/element.ts +5 -0
  409. package/src/parser/rules/inline/text/index.ts +85 -0
  410. package/src/parser/rules/inline/underline/child.ts +26 -0
  411. package/src/parser/rules/inline/underline/content.ts +29 -0
  412. package/src/parser/rules/inline/underline/index.ts +84 -0
  413. package/src/parser/rules/inline/user/element.ts +11 -0
  414. package/src/parser/rules/inline/user/index.ts +34 -0
  415. package/src/parser/rules/inline/user/syntax.ts +67 -0
  416. package/src/parser/rules/inline/utils.ts +4 -0
  417. package/src/parser/rules/tokens.ts +106 -0
  418. package/src/parser/rules/types.ts +9 -0
  419. package/src/parser/toc.ts +130 -0
@@ -0,0 +1,73 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export interface FootnoteBlockAttributesResult {
4
+ attrs: Record<string, string>;
5
+ consumed: number;
6
+ }
7
+
8
+ /**
9
+ * Parses key/value attributes from tokens for `[[footnoteblock]]`.
10
+ *
11
+ * This is intentionally rule-local: the generic block attribute parser
12
+ * filters some names that this rule needs to preserve, notably `hide`.
13
+ */
14
+ export function parseFootnoteBlockAttributes(
15
+ ctx: ParseContext,
16
+ startPos: number,
17
+ ): FootnoteBlockAttributesResult {
18
+ const attrs: Record<string, string> = {};
19
+ let pos = startPos;
20
+ let consumed = 0;
21
+
22
+ while (pos < ctx.tokens.length) {
23
+ const token = ctx.tokens[pos];
24
+ if (
25
+ !token ||
26
+ token.type === "BLOCK_CLOSE" ||
27
+ token.type === "NEWLINE" ||
28
+ token.type === "EOF"
29
+ ) {
30
+ break;
31
+ }
32
+
33
+ if (token.type === "WHITESPACE") {
34
+ pos++;
35
+ consumed++;
36
+ continue;
37
+ }
38
+
39
+ if (token.type === "TEXT" || token.type === "IDENTIFIER") {
40
+ const name = token.value.toLowerCase();
41
+ pos++;
42
+ consumed++;
43
+
44
+ const eqToken = ctx.tokens[pos];
45
+ if (eqToken?.type === "EQUALS") {
46
+ pos++;
47
+ consumed++;
48
+
49
+ const valueToken = ctx.tokens[pos];
50
+ if (valueToken?.type === "QUOTED_STRING") {
51
+ attrs[name] = stripQuotes(valueToken.value);
52
+ pos++;
53
+ consumed++;
54
+ } else if (valueToken?.type === "TEXT" || valueToken?.type === "IDENTIFIER") {
55
+ attrs[name] = valueToken.value;
56
+ pos++;
57
+ consumed++;
58
+ }
59
+ } else {
60
+ attrs[name] = "true";
61
+ }
62
+ } else {
63
+ pos++;
64
+ consumed++;
65
+ }
66
+ }
67
+
68
+ return { attrs, consumed };
69
+ }
70
+
71
+ function stripQuotes(value: string): string {
72
+ return value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
73
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ *
3
+ * Block rule for the Wikidot footnote block: `[[footnoteblock]]`.
4
+ *
5
+ * This self-closing block tag marks the location in the page where all
6
+ * collected footnotes (from `[[footnote]]...[[/footnote]]` inline markers)
7
+ * should be rendered. It is analogous to a "footnotes section" placeholder.
8
+ *
9
+ * Optional attributes:
10
+ * - `title` -- custom heading text for the footnotes section.
11
+ * - `hide` -- when `"true"` or `"yes"`, suppresses footnote rendering.
12
+ *
13
+ * Wikidot only honours the FIRST `[[footnoteblock]]` in a document;
14
+ * subsequent occurrences are treated as plain text. The parser tracks
15
+ * this via `ctx.scope.footnoteBlockParsed`, but note: that flag is per
16
+ * spread copy of `ParseContext` (see {@link ScopeContext.footnoteBlockParsed}).
17
+ * In practice the duplicate-rejection only fires for two top-level
18
+ * `[[footnoteblock]]` tokens; siblings inside the same body or across
19
+ * nested bodies both succeed today. The auto-append decision in
20
+ * `Parser.parse` uses a post-parse AST walk, so it is unaffected.
21
+ *
22
+ * @module
23
+ */
24
+ import type { Element } from "@wdprlib/ast";
25
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
26
+ import { currentToken } from "../../types";
27
+ import { parseFootnoteBlockOpen } from "./open";
28
+
29
+ /**
30
+ * Block rule for `[[footnoteblock]]`.
31
+ *
32
+ * Parsing strategy:
33
+ * 1. Match BLOCK_OPEN + name "footnoteblock" (case-insensitive).
34
+ * 2. Parse optional attributes (`title`, `hide`) with the rule-local parser.
35
+ * 3. Consume closing `]]`.
36
+ * 4. If `ctx.scope.footnoteBlockParsed` is already `true` on the current
37
+ * `ParseContext` copy, fail. Because `parseBlocksUntil` spreads a
38
+ * fresh `ctx` per sibling rule, this only rejects a second
39
+ * `[[footnoteblock]]` that arrives via the parser's top-level
40
+ * dispatch loop in practice. See {@link ScopeContext.footnoteBlockParsed}.
41
+ * 5. Replace `ctx.scope` with the flag set to `true` and emit a `footnote-block`
42
+ * element.
43
+ */
44
+ export const footnoteBlockRule: BlockRule = {
45
+ name: "footnoteBlock",
46
+ startTokens: ["BLOCK_OPEN"],
47
+ requiresLineStart: true,
48
+
49
+ parse(ctx: ParseContext): RuleResult<Element> {
50
+ const openToken = currentToken(ctx);
51
+ if (openToken.type !== "BLOCK_OPEN") {
52
+ return { success: false };
53
+ }
54
+
55
+ const openResult = parseFootnoteBlockOpen(ctx, ctx.pos);
56
+ if (!openResult) {
57
+ return { success: false };
58
+ }
59
+
60
+ if (ctx.scope.footnoteBlockParsed) {
61
+ return { success: false };
62
+ }
63
+ ctx.scope = { ...ctx.scope, footnoteBlockParsed: true };
64
+
65
+ const title = openResult.attrs.title !== undefined ? openResult.attrs.title : null;
66
+ const hide = openResult.attrs.hide === "true" || openResult.attrs.hide === "yes";
67
+
68
+ return {
69
+ success: true,
70
+ elements: [
71
+ {
72
+ element: "footnote-block",
73
+ data: {
74
+ title,
75
+ hide,
76
+ },
77
+ },
78
+ ],
79
+ consumed: openResult.consumed,
80
+ };
81
+ },
82
+ };
@@ -0,0 +1,53 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseFootnoteBlockAttributes } from "./attributes";
3
+
4
+ export interface FootnoteBlockOpenResult {
5
+ attrs: Record<string, string>;
6
+ consumed: number;
7
+ }
8
+
9
+ export function parseFootnoteBlockOpen(
10
+ ctx: ParseContext,
11
+ startPos: number,
12
+ ): FootnoteBlockOpenResult | null {
13
+ if (ctx.tokens[startPos]?.type !== "BLOCK_OPEN") {
14
+ return null;
15
+ }
16
+
17
+ let pos = startPos + 1;
18
+ let consumed = 1;
19
+
20
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
21
+ pos++;
22
+ consumed++;
23
+ }
24
+
25
+ const nameToken = ctx.tokens[pos];
26
+ if (!nameToken || (nameToken.type !== "TEXT" && nameToken.type !== "IDENTIFIER")) {
27
+ return null;
28
+ }
29
+
30
+ if (nameToken.value.toLowerCase() !== "footnoteblock") {
31
+ return null;
32
+ }
33
+ pos++;
34
+ consumed++;
35
+
36
+ const attrResult = parseFootnoteBlockAttributes(ctx, pos);
37
+ pos += attrResult.consumed;
38
+ consumed += attrResult.consumed;
39
+
40
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
41
+ pos++;
42
+ consumed++;
43
+ }
44
+
45
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
46
+ return null;
47
+ }
48
+
49
+ return {
50
+ attrs: attrResult.attrs,
51
+ consumed: consumed + 1,
52
+ };
53
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot headings: `+ Heading` through `++++++ Heading`.
4
+ *
5
+ * Headings are written with one to six `+` characters at the start of a
6
+ * line, followed by mandatory whitespace and then inline content:
7
+ *
8
+ * ```
9
+ * + H1 heading
10
+ * ++ H2 heading
11
+ * +++ H3 heading
12
+ * ```
13
+ *
14
+ * An optional `*` immediately after the `+` markers hides the heading
15
+ * from the table of contents:
16
+ *
17
+ * ```
18
+ * +* Hidden H1
19
+ * ```
20
+ *
21
+ * Seven or more `+` characters are NOT valid headings in Wikidot and
22
+ * the rule will fail, letting them fall through to paragraph parsing.
23
+ *
24
+ * Non-hidden headings are registered in `ctx.tocEntries` for later use
25
+ * by the table-of-contents module.
26
+ *
27
+ * @module
28
+ */
29
+ import type { Element } from "@wdprlib/ast";
30
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
31
+ import { parseInlineUntil } from "../../inline/utils";
32
+ import { parseHeadingOpen } from "./open";
33
+ import { extractHeadingText } from "./toc-text";
34
+
35
+ /**
36
+ * Block rule for Wikidot headings (`+ ` through `++++++ `).
37
+ *
38
+ * Produces a container element with `type: { header: { level, "has-toc" } }`.
39
+ * The heading text is parsed for inline markup (bold, links, etc.).
40
+ */
41
+ export const headingRule: BlockRule = {
42
+ name: "heading",
43
+ startTokens: ["HEADING_MARKER"],
44
+ requiresLineStart: true,
45
+
46
+ parse(ctx: ParseContext): RuleResult<Element> {
47
+ const openResult = parseHeadingOpen(ctx);
48
+ if (!openResult) {
49
+ return { success: false };
50
+ }
51
+
52
+ // Parse inline content until newline
53
+ let pos = openResult.bodyStart;
54
+ let consumed = openResult.consumed;
55
+ const inlineCtx: ParseContext = { ...ctx, pos };
56
+ const inlineResult = parseInlineUntil(inlineCtx, "NEWLINE");
57
+ const children: Element[] = inlineResult.elements;
58
+ consumed += inlineResult.consumed;
59
+ pos += inlineResult.consumed;
60
+
61
+ // Consume newline
62
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
63
+ consumed++;
64
+ }
65
+
66
+ // Store TOC entry (only non-hidden headings)
67
+ if (!openResult.hidden) {
68
+ const headingText = extractHeadingText(children);
69
+ ctx.tocEntries.push({ level: openResult.level, text: headingText });
70
+ }
71
+
72
+ return {
73
+ success: true,
74
+ elements: [
75
+ {
76
+ element: "container",
77
+ data: {
78
+ type: { header: { level: openResult.level, "has-toc": !openResult.hidden } },
79
+ attributes: {},
80
+ elements: children,
81
+ },
82
+ },
83
+ ],
84
+ consumed,
85
+ };
86
+ },
87
+ };
@@ -0,0 +1,50 @@
1
+ import type { HeadingLevel } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+
4
+ export interface HeadingOpenResult {
5
+ level: HeadingLevel;
6
+ hidden: boolean;
7
+ bodyStart: number;
8
+ consumed: number;
9
+ }
10
+
11
+ export function parseHeadingOpen(ctx: ParseContext): HeadingOpenResult | null {
12
+ const marker = ctx.tokens[ctx.pos];
13
+ if (marker?.type !== "HEADING_MARKER" || !marker.lineStart) {
14
+ return null;
15
+ }
16
+
17
+ if (!isHeadingLevel(marker.value.length)) {
18
+ return null;
19
+ }
20
+
21
+ let pos = ctx.pos + 1;
22
+ let consumed = 1;
23
+ let hidden = false;
24
+
25
+ if (ctx.tokens[pos]?.type === "STAR") {
26
+ hidden = true;
27
+ pos++;
28
+ consumed++;
29
+ }
30
+
31
+ if (ctx.tokens[pos]?.type !== "WHITESPACE") {
32
+ return null;
33
+ }
34
+
35
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
36
+ pos++;
37
+ consumed++;
38
+ }
39
+
40
+ return {
41
+ level: marker.value.length,
42
+ hidden,
43
+ bodyStart: pos,
44
+ consumed,
45
+ };
46
+ }
47
+
48
+ function isHeadingLevel(length: number): length is HeadingLevel {
49
+ return length >= 1 && length <= 6;
50
+ }
@@ -0,0 +1,26 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+
3
+ /**
4
+ * Recursively extracts plain text from heading children for TOC entries.
5
+ */
6
+ export function extractHeadingText(elements: Element[]): string {
7
+ let text = "";
8
+ for (const el of elements) {
9
+ if (el.element === "text" && typeof el.data === "string") {
10
+ text += el.data;
11
+ } else if (hasNestedElements(el)) {
12
+ text += extractHeadingText(el.data.elements);
13
+ }
14
+ }
15
+ return text;
16
+ }
17
+
18
+ function hasNestedElements(el: Element): el is Extract<Element, { element: "container" }> {
19
+ return (
20
+ el.element === "container" &&
21
+ typeof el.data === "object" &&
22
+ el.data !== null &&
23
+ "elements" in el.data &&
24
+ Array.isArray(el.data.elements)
25
+ );
26
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ *
3
+ * Block rule for Wikidot horizontal rules: `----` (four or more hyphens
4
+ * at the start of a line).
5
+ *
6
+ * The lexer emits an HR_MARKER token for sequences of four or more `-`
7
+ * characters at line start. This rule consumes the marker, any remaining
8
+ * tokens on the line, and an optional trailing newline, producing a single
9
+ * `horizontal-rule` element (rendered as `<hr />`).
10
+ *
11
+ * Any text after the `----` on the same line is silently discarded,
12
+ * matching Wikidot's behaviour.
13
+ *
14
+ * @module
15
+ */
16
+ import type { Element } from "@wdprlib/ast";
17
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
18
+ import { currentToken } from "../../types";
19
+ import { consumeHorizontalRuleLine } from "./syntax";
20
+
21
+ /**
22
+ * Block rule for horizontal rules (`----`).
23
+ *
24
+ * Produces a `horizontal-rule` element with no data payload.
25
+ */
26
+ export const horizontalRuleRule: BlockRule = {
27
+ name: "horizontalRule",
28
+ startTokens: ["HR_MARKER"],
29
+ requiresLineStart: true,
30
+
31
+ parse(ctx: ParseContext): RuleResult<Element> {
32
+ const marker = currentToken(ctx);
33
+
34
+ if (!marker.lineStart) {
35
+ return { success: false };
36
+ }
37
+
38
+ return {
39
+ success: true,
40
+ elements: [{ element: "horizontal-rule" }],
41
+ consumed: consumeHorizontalRuleLine(ctx),
42
+ };
43
+ },
44
+ };
@@ -0,0 +1,21 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export function consumeHorizontalRuleLine(ctx: ParseContext): number {
4
+ let pos = ctx.pos + 1;
5
+ let consumed = 1;
6
+
7
+ while (pos < ctx.tokens.length) {
8
+ const token = ctx.tokens[pos];
9
+ if (!token || token.type === "NEWLINE" || token.type === "EOF") {
10
+ break;
11
+ }
12
+ pos++;
13
+ consumed++;
14
+ }
15
+
16
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
17
+ consumed++;
18
+ }
19
+
20
+ return consumed;
21
+ }
@@ -0,0 +1,114 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseBlockName } from "../utils";
3
+
4
+ export interface HtmlBodyResult {
5
+ contents: string;
6
+ consumed: number;
7
+ foundClose: boolean;
8
+ }
9
+
10
+ /**
11
+ * Scan forward from `from` to see whether a real `[[/html]]` close tag
12
+ * exists later in the token stream.
13
+ */
14
+ export function lookaheadHasHtmlClose(ctx: ParseContext, from: number): boolean {
15
+ for (let i = from; i < ctx.tokens.length; i++) {
16
+ const token = ctx.tokens[i];
17
+ if (!token || token.type === "EOF") return false;
18
+ if (token.type !== "BLOCK_END_OPEN") continue;
19
+
20
+ const closeName = parseBlockName(ctx, i + 1);
21
+ if (closeName?.name.toLowerCase() !== "html") continue;
22
+
23
+ let closePos = i + 1 + closeName.consumed;
24
+ while (ctx.tokens[closePos]?.type === "WHITESPACE") closePos++;
25
+ if (ctx.tokens[closePos]?.type === "BLOCK_CLOSE") return true;
26
+ }
27
+ return false;
28
+ }
29
+
30
+ export function collectHtmlBody(
31
+ ctx: ParseContext,
32
+ startPos: number,
33
+ disabled: boolean,
34
+ ): HtmlBodyResult {
35
+ const hasCloseAhead = disabled && lookaheadHasHtmlClose(ctx, startPos);
36
+ const contentParts: string[] = [];
37
+ let pos = startPos;
38
+ let consumed = 0;
39
+
40
+ while (pos < ctx.tokens.length) {
41
+ const token = ctx.tokens[pos];
42
+ if (!token || token.type === "EOF") break;
43
+
44
+ if (
45
+ disabled &&
46
+ !hasCloseAhead &&
47
+ token.type === "NEWLINE" &&
48
+ ctx.tokens[pos + 1]?.type === "NEWLINE"
49
+ ) {
50
+ break;
51
+ }
52
+
53
+ if (isHtmlCloseAt(ctx, pos)) {
54
+ return { contents: contentParts.join(""), consumed, foundClose: true };
55
+ }
56
+
57
+ if (!disabled) {
58
+ contentParts.push(token.value);
59
+ }
60
+ pos++;
61
+ consumed++;
62
+ }
63
+
64
+ return { contents: contentParts.join(""), consumed, foundClose: false };
65
+ }
66
+
67
+ export function consumeHtmlClose(ctx: ParseContext, startPos: number): number {
68
+ let pos = startPos;
69
+ let consumed = 0;
70
+
71
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
72
+ return 0;
73
+ }
74
+
75
+ pos++;
76
+ consumed++;
77
+
78
+ const closeNameResult = parseBlockName(ctx, pos);
79
+ if (closeNameResult) {
80
+ pos += closeNameResult.consumed;
81
+ consumed += closeNameResult.consumed;
82
+ }
83
+
84
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
85
+ pos++;
86
+ consumed++;
87
+ }
88
+
89
+ if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
90
+ pos++;
91
+ consumed++;
92
+ }
93
+
94
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
95
+ consumed++;
96
+ }
97
+
98
+ return consumed;
99
+ }
100
+
101
+ function isHtmlCloseAt(ctx: ParseContext, pos: number): boolean {
102
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
103
+ return false;
104
+ }
105
+
106
+ const closeNameResult = parseBlockName(ctx, pos + 1);
107
+ if (closeNameResult?.name.toLowerCase() !== "html") {
108
+ return false;
109
+ }
110
+
111
+ let checkPos = pos + 1 + closeNameResult.consumed;
112
+ while (ctx.tokens[checkPos]?.type === "WHITESPACE") checkPos++;
113
+ return ctx.tokens[checkPos]?.type === "BLOCK_CLOSE";
114
+ }
@@ -0,0 +1,11 @@
1
+ import type { Position } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+
4
+ export function addHtmlDisabledDiagnostic(ctx: ParseContext, position: Position): void {
5
+ ctx.diagnostics.push({
6
+ severity: "info",
7
+ code: "html-block-disabled",
8
+ message: "[[html]] block ignored: disabled by settings",
9
+ position,
10
+ });
11
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ *
3
+ * Block rule for the Wikidot HTML block: `[[html]]...[[/html]]`.
4
+ *
5
+ * An HTML block embeds raw HTML that Wikidot renders inside a sandboxed
6
+ * `<iframe>`. The content between the tags is captured verbatim (no inline
7
+ * parsing) and stored as an `html` element in the AST.
8
+ *
9
+ * Supported attributes on the opening tag:
10
+ * - `style` -- applied to the containing iframe. Other attributes are
11
+ * parsed but only `style` is used by Wikidot's renderer.
12
+ *
13
+ * The raw content is also pushed into `ctx.htmlBlocks` for document-level
14
+ * enumeration.
15
+ *
16
+ * If no `[[/html]]` closing tag is found, the rule fails and the opening
17
+ * tag falls through to text rendering (matching Wikidot behaviour).
18
+ *
19
+ * @module
20
+ */
21
+ import type { Element } from "@wdprlib/ast";
22
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
23
+ import { currentToken } from "../../types";
24
+ import { collectHtmlBody, consumeHtmlClose } from "./body";
25
+ import { addHtmlDisabledDiagnostic } from "./diagnostics";
26
+ import { parseHtmlOpen } from "./open";
27
+
28
+ export { lookaheadHasHtmlClose } from "./body";
29
+
30
+ /**
31
+ * Block rule for `[[html]]...[[/html]]`.
32
+ *
33
+ * Body content is stored as raw text. The optional `style` attribute is
34
+ * passed through to the AST element for iframe styling.
35
+ */
36
+ export const htmlBlockRule: BlockRule = {
37
+ name: "html",
38
+ startTokens: ["BLOCK_OPEN"],
39
+ requiresLineStart: false,
40
+
41
+ parse(ctx: ParseContext): RuleResult<Element> {
42
+ const openToken = currentToken(ctx);
43
+ if (openToken.type !== "BLOCK_OPEN") {
44
+ return { success: false };
45
+ }
46
+
47
+ const openResult = parseHtmlOpen(ctx, ctx.pos);
48
+ if (!openResult) {
49
+ return { success: false };
50
+ }
51
+
52
+ const disabled = ctx.settings.allowHtmlBlocks === false;
53
+ const bodyStart = ctx.pos + openResult.consumed;
54
+ const bodyResult = collectHtmlBody(ctx, bodyStart, disabled);
55
+ let consumed = openResult.consumed + bodyResult.consumed;
56
+
57
+ if (!bodyResult.foundClose) {
58
+ ctx.diagnostics.push({
59
+ severity: "warning",
60
+ code: "unclosed-block",
61
+ message: "Missing closing tag [[/html]] for [[html]]",
62
+ position: openToken.position,
63
+ });
64
+ if (!disabled) {
65
+ return { success: false };
66
+ }
67
+ addHtmlDisabledDiagnostic(ctx, openToken.position);
68
+ return { success: true, elements: [], consumed };
69
+ }
70
+
71
+ consumed += consumeHtmlClose(ctx, bodyStart + bodyResult.consumed);
72
+
73
+ if (disabled) {
74
+ addHtmlDisabledDiagnostic(ctx, openToken.position);
75
+ return { success: true, elements: [], consumed };
76
+ }
77
+
78
+ const contents = bodyResult.contents.trim();
79
+ ctx.htmlBlocks.push(contents);
80
+
81
+ return {
82
+ success: true,
83
+ elements: [
84
+ {
85
+ element: "html",
86
+ data: {
87
+ contents,
88
+ ...(openResult.style && { style: openResult.style }),
89
+ },
90
+ },
91
+ ],
92
+ consumed,
93
+ };
94
+ },
95
+ };
@@ -0,0 +1,36 @@
1
+ import type { ParseContext } from "../../types";
2
+ import { parseAttributesRaw, parseBlockName } from "../utils";
3
+
4
+ export interface HtmlOpenResult {
5
+ style: string | undefined;
6
+ consumed: number;
7
+ }
8
+
9
+ export function parseHtmlOpen(ctx: ParseContext, startPos: number): HtmlOpenResult | null {
10
+ if (ctx.tokens[startPos]?.type !== "BLOCK_OPEN") {
11
+ return null;
12
+ }
13
+
14
+ let pos = startPos + 1;
15
+ let consumed = 1;
16
+
17
+ const nameResult = parseBlockName(ctx, pos);
18
+ if (!nameResult || nameResult.name.toLowerCase() !== "html") {
19
+ return null;
20
+ }
21
+ pos += nameResult.consumed;
22
+ consumed += nameResult.consumed;
23
+
24
+ const attrResult = parseAttributesRaw(ctx, pos);
25
+ pos += attrResult.consumed;
26
+ consumed += attrResult.consumed;
27
+
28
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
29
+ return null;
30
+ }
31
+
32
+ return {
33
+ style: attrResult.attrs.style,
34
+ consumed: consumed + 1,
35
+ };
36
+ }