@wdprlib/parser 3.2.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/dist/index.cjs +10471 -8406
  2. package/dist/index.d.cts +313 -337
  3. package/dist/index.d.ts +313 -337
  4. package/dist/index.js +10457 -8392
  5. package/package.json +1 -1
  6. package/src/index.ts +7 -0
  7. package/src/lexer/anchor.ts +48 -0
  8. package/src/lexer/index.ts +3 -2
  9. package/src/lexer/lexer.ts +73 -559
  10. package/src/lexer/options.ts +19 -0
  11. package/src/lexer/punctuation.ts +70 -0
  12. package/src/lexer/quoted-string.ts +16 -0
  13. package/src/lexer/runs.ts +85 -0
  14. package/src/lexer/spacing-actions.ts +24 -0
  15. package/src/lexer/state.ts +103 -0
  16. package/src/lexer/syntax-actions.ts +80 -0
  17. package/src/lexer/text-actions.ts +41 -0
  18. package/src/lexer/token-actions.ts +136 -0
  19. package/src/lexer/token-factory.ts +62 -0
  20. package/src/lexer/tokenize.ts +18 -0
  21. package/src/parser/constants.ts +2 -0
  22. package/src/parser/depth/index.ts +111 -0
  23. package/src/parser/depth/stack.ts +82 -0
  24. package/src/parser/parse/block.ts +42 -0
  25. package/src/parser/parse/context.ts +26 -0
  26. package/src/parser/parse/footnotes.ts +25 -0
  27. package/src/parser/parse/index.ts +42 -0
  28. package/src/parser/parse/options.ts +34 -0
  29. package/src/parser/parse/parser.ts +79 -0
  30. package/src/parser/parse/plain-non-ascii.ts +129 -0
  31. package/src/parser/parse/result.ts +57 -0
  32. package/src/parser/parse/source.ts +11 -0
  33. package/src/parser/postprocess/divAdjacentParagraph.ts +1 -1
  34. package/src/parser/postprocess/spanStrip/clean-element.ts +168 -0
  35. package/src/parser/postprocess/spanStrip/cleanup.ts +25 -0
  36. package/src/parser/postprocess/spanStrip/empty-spans.ts +36 -0
  37. package/src/parser/postprocess/spanStrip/escaped.ts +78 -0
  38. package/src/parser/postprocess/spanStrip/factory.ts +23 -0
  39. package/src/parser/postprocess/spanStrip/index.ts +8 -0
  40. package/src/parser/postprocess/spanStrip/merge.ts +117 -0
  41. package/src/parser/postprocess/spanStrip/predicates.ts +59 -0
  42. package/src/parser/postprocess/spanStrip/split.ts +67 -0
  43. package/src/parser/preprocess/expr/chars.ts +15 -0
  44. package/src/parser/preprocess/expr/evaluate.ts +22 -0
  45. package/src/parser/preprocess/expr/index.ts +45 -0
  46. package/src/parser/preprocess/expr/kind.ts +19 -0
  47. package/src/parser/preprocess/expr/parse.ts +103 -0
  48. package/src/parser/preprocess/expr/scan.ts +34 -0
  49. package/src/parser/preprocess/expr/types.ts +14 -0
  50. package/src/parser/preprocess/typography.ts +70 -5
  51. package/src/parser/preprocess/utils/bracket-depths.ts +98 -0
  52. package/src/parser/preprocess/utils/index.ts +13 -0
  53. package/src/parser/preprocess/utils/raw-regions.ts +153 -0
  54. package/src/parser/preprocess/whitespace/detection.ts +39 -0
  55. package/src/parser/preprocess/whitespace/index.ts +79 -0
  56. package/src/parser/preprocess/whitespace/leading-spaces.ts +11 -0
  57. package/src/parser/preprocess/whitespace/patterns.ts +23 -0
  58. package/src/parser/rules/block/align/body.ts +46 -0
  59. package/src/parser/rules/block/align/element.ts +13 -0
  60. package/src/parser/rules/block/align/index.ts +90 -0
  61. package/src/parser/rules/block/align/syntax.ts +113 -0
  62. package/src/parser/rules/block/bibliography/body.ts +81 -0
  63. package/src/parser/rules/block/bibliography/entries.ts +49 -0
  64. package/src/parser/rules/block/bibliography/entry-content.ts +73 -0
  65. package/src/parser/rules/block/bibliography/entry-key.ts +83 -0
  66. package/src/parser/rules/block/bibliography/index.ts +90 -0
  67. package/src/parser/rules/block/bibliography/open.ts +53 -0
  68. package/src/parser/rules/block/block-list/bare-content.ts +105 -0
  69. package/src/parser/rules/block/block-list/bare-paragraph.ts +60 -0
  70. package/src/parser/rules/block/block-list/index.ts +51 -0
  71. package/src/parser/rules/block/block-list/item-content.ts +132 -0
  72. package/src/parser/rules/block/block-list/li-content.ts +107 -0
  73. package/src/parser/rules/block/block-list/li-item.ts +77 -0
  74. package/src/parser/rules/block/block-list/list-block.ts +100 -0
  75. package/src/parser/rules/block/block-list/open.ts +51 -0
  76. package/src/parser/rules/block/block-list/tags.ts +50 -0
  77. package/src/parser/rules/block/blockquote/build.ts +62 -0
  78. package/src/parser/rules/block/blockquote/index.ts +80 -0
  79. package/src/parser/rules/block/blockquote/line.ts +79 -0
  80. package/src/parser/rules/block/blockquote/lines.ts +39 -0
  81. package/src/parser/rules/block/{center.ts → center/index.ts} +7 -22
  82. package/src/parser/rules/block/center/open.ts +27 -0
  83. package/src/parser/rules/block/{clear-float.ts → clear-float/index.ts} +6 -30
  84. package/src/parser/rules/block/clear-float/syntax.ts +43 -0
  85. package/src/parser/rules/block/code/attributes.ts +30 -0
  86. package/src/parser/rules/block/code/content.ts +57 -0
  87. package/src/parser/rules/block/code/index.ts +100 -0
  88. package/src/parser/rules/block/collapsible/attributes.ts +95 -0
  89. package/src/parser/rules/block/collapsible/body.ts +69 -0
  90. package/src/parser/rules/block/collapsible/index.ts +117 -0
  91. package/src/parser/rules/block/collapsible/open.ts +51 -0
  92. package/src/parser/rules/block/collapsible/orphans.ts +31 -0
  93. package/src/parser/rules/block/collapsible/tags.ts +17 -0
  94. package/src/parser/rules/block/comment/consume.ts +37 -0
  95. package/src/parser/rules/block/{comment.ts → comment/index.ts} +12 -38
  96. package/src/parser/rules/block/{content-separator.ts → content-separator/index.ts} +5 -35
  97. package/src/parser/rules/block/content-separator/syntax.ts +33 -0
  98. package/src/parser/rules/block/definition-list/collect.ts +40 -0
  99. package/src/parser/rules/block/definition-list/index.ts +63 -0
  100. package/src/parser/rules/block/definition-list/item-key.ts +95 -0
  101. package/src/parser/rules/block/definition-list/item-value.ts +56 -0
  102. package/src/parser/rules/block/definition-list/items.ts +54 -0
  103. package/src/parser/rules/block/div/body.ts +41 -0
  104. package/src/parser/rules/block/div/close.ts +41 -0
  105. package/src/parser/rules/block/div/failed.ts +117 -0
  106. package/src/parser/rules/block/div/index.ts +112 -0
  107. package/src/parser/rules/block/div/nesting.ts +37 -0
  108. package/src/parser/rules/block/div/open.ts +59 -0
  109. package/src/parser/rules/block/div/paragraph-strip.ts +44 -0
  110. package/src/parser/rules/block/embed-block/content.ts +53 -0
  111. package/src/parser/rules/block/embed-block/index.ts +91 -0
  112. package/src/parser/rules/block/embed-block/open.ts +52 -0
  113. package/src/parser/rules/block/embed-block/tags.ts +5 -0
  114. package/src/parser/rules/block/footnoteblock/attributes.ts +73 -0
  115. package/src/parser/rules/block/footnoteblock/index.ts +82 -0
  116. package/src/parser/rules/block/footnoteblock/open.ts +53 -0
  117. package/src/parser/rules/block/heading/index.ts +87 -0
  118. package/src/parser/rules/block/heading/open.ts +50 -0
  119. package/src/parser/rules/block/heading/toc-text.ts +26 -0
  120. package/src/parser/rules/block/{horizontal-rule.ts → horizontal-rule/index.ts} +4 -21
  121. package/src/parser/rules/block/horizontal-rule/syntax.ts +21 -0
  122. package/src/parser/rules/block/html/body.ts +114 -0
  123. package/src/parser/rules/block/html/diagnostics.ts +11 -0
  124. package/src/parser/rules/block/html/index.ts +95 -0
  125. package/src/parser/rules/block/html/open.ts +36 -0
  126. package/src/parser/rules/block/iframe/attributes.ts +106 -0
  127. package/src/parser/rules/block/iframe/index.ts +73 -0
  128. package/src/parser/rules/block/iframe/open.ts +58 -0
  129. package/src/parser/rules/block/iframe/source.ts +24 -0
  130. package/src/parser/rules/block/iframe/url.ts +38 -0
  131. package/src/parser/rules/block/iftags/body.ts +48 -0
  132. package/src/parser/rules/block/iftags/condition.ts +24 -0
  133. package/src/parser/rules/block/{iftags.ts → iftags/index.ts} +16 -58
  134. package/src/parser/rules/block/include/arguments.ts +48 -0
  135. package/src/parser/rules/block/include/index.ts +75 -0
  136. package/src/parser/rules/block/include/location.ts +24 -0
  137. package/src/parser/rules/block/include/variables.ts +37 -0
  138. package/src/parser/rules/block/list/index.ts +73 -0
  139. package/src/parser/rules/block/list/line.ts +77 -0
  140. package/src/parser/rules/block/list/native.ts +89 -0
  141. package/src/parser/rules/block/math/content.ts +54 -0
  142. package/src/parser/rules/block/math/index.ts +106 -0
  143. package/src/parser/rules/block/math/name.ts +35 -0
  144. package/src/parser/rules/block/module/body.ts +92 -0
  145. package/src/parser/rules/block/module/element.ts +33 -0
  146. package/src/parser/rules/block/module/include/directive.ts +91 -0
  147. package/src/parser/rules/block/module/include/index.ts +11 -2
  148. package/src/parser/rules/block/module/include/references.ts +42 -0
  149. package/src/parser/rules/block/module/include/resolve/cache.ts +44 -0
  150. package/src/parser/rules/block/module/include/resolve/index.ts +106 -0
  151. package/src/parser/rules/block/module/include/resolve/iterate.ts +202 -0
  152. package/src/parser/rules/block/module/include/resolve/replace.ts +31 -0
  153. package/src/parser/rules/block/module/include/resolve/types.ts +105 -0
  154. package/src/parser/rules/block/module/include/scanner.ts +121 -0
  155. package/src/parser/rules/block/module/index.ts +14 -2
  156. package/src/parser/rules/block/module/listpages/compiler.ts +12 -392
  157. package/src/parser/rules/block/module/listpages/extract.ts +25 -359
  158. package/src/parser/rules/block/module/listpages/extraction/listpages.ts +42 -0
  159. package/src/parser/rules/block/module/listpages/extraction/listusers.ts +30 -0
  160. package/src/parser/rules/block/module/listpages/extraction/query.ts +51 -0
  161. package/src/parser/rules/block/module/listpages/extraction/result.ts +18 -0
  162. package/src/parser/rules/block/module/listpages/extraction/template.ts +96 -0
  163. package/src/parser/rules/block/module/listpages/extraction/variables.ts +58 -0
  164. package/src/parser/rules/block/module/listpages/normalization/date-selector.ts +53 -0
  165. package/src/parser/rules/block/module/listpages/normalization/numeric-selector.ts +32 -0
  166. package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +82 -0
  167. package/src/parser/rules/block/module/listpages/normalization/selectors.ts +2 -0
  168. package/src/parser/rules/block/module/listpages/normalization/tags-category.ts +86 -0
  169. package/src/parser/rules/block/module/listpages/normalize.ts +8 -324
  170. package/src/parser/rules/block/module/listpages/resolution/items.ts +43 -0
  171. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +42 -0
  172. package/src/parser/rules/block/module/listpages/resolve.ts +5 -75
  173. package/src/parser/rules/block/module/listpages/template/format/content.ts +41 -0
  174. package/src/parser/rules/block/module/listpages/template/format/date.ts +116 -0
  175. package/src/parser/rules/block/module/listpages/template/format/index.ts +4 -0
  176. package/src/parser/rules/block/module/listpages/template/format/tags.ts +7 -0
  177. package/src/parser/rules/block/module/listpages/template/format/user.ts +9 -0
  178. package/src/parser/rules/block/module/listpages/template/getters/index.ts +36 -0
  179. package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +60 -0
  180. package/src/parser/rules/block/module/listpages/template/getters/simple.ts +65 -0
  181. package/src/parser/rules/block/module/listpages/template/getters/types.ts +3 -0
  182. package/src/parser/rules/block/module/listpages/template/syntax.ts +97 -0
  183. package/src/parser/rules/block/module/listpages/types/data-fetcher.ts +15 -0
  184. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +52 -0
  185. package/src/parser/rules/block/module/listpages/types/external-data.ts +77 -0
  186. package/src/parser/rules/block/module/listpages/types/index.ts +17 -0
  187. package/src/parser/rules/block/module/listpages/types/normalized-query.ts +120 -0
  188. package/src/parser/rules/block/module/listpages/types/query.ts +67 -0
  189. package/src/parser/rules/block/module/listpages/types/template.ts +17 -0
  190. package/src/parser/rules/block/module/listpages/types/variables.ts +69 -0
  191. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +48 -0
  192. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +30 -0
  193. package/src/parser/rules/block/module/listpages/url-resolution/query.ts +24 -0
  194. package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +62 -0
  195. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +34 -0
  196. package/src/parser/rules/block/module/listpages/url-resolver.ts +3 -160
  197. package/src/parser/rules/block/module/listusers/compiler.ts +4 -25
  198. package/src/parser/rules/block/module/listusers/extract.ts +4 -9
  199. package/src/parser/rules/block/module/listusers/getters.ts +21 -0
  200. package/src/parser/rules/block/module/listusers/variables.ts +15 -0
  201. package/src/parser/rules/block/module/open.ts +57 -0
  202. package/src/parser/rules/block/module/resolution/contexts.ts +78 -0
  203. package/src/parser/rules/block/module/resolution/data-maps.ts +39 -0
  204. package/src/parser/rules/block/module/resolution/dynamic-modules.ts +93 -0
  205. package/src/parser/rules/block/module/resolution/styles.ts +53 -0
  206. package/src/parser/rules/block/module/resolution/walk-resolve.ts +107 -0
  207. package/src/parser/rules/block/module/resolve.ts +79 -292
  208. package/src/parser/rules/block/module/rule.ts +56 -0
  209. package/src/parser/rules/block/module/types-common.ts +11 -0
  210. package/src/parser/rules/block/module/walk/children.ts +35 -0
  211. package/src/parser/rules/block/module/walk/index.ts +9 -0
  212. package/src/parser/rules/block/module/walk/map/index.ts +2 -0
  213. package/src/parser/rules/block/module/walk/map/stateful-definition-list.ts +25 -0
  214. package/src/parser/rules/block/module/walk/map/stateful-list.ts +40 -0
  215. package/src/parser/rules/block/module/walk/map/stateful-table.ts +23 -0
  216. package/src/parser/rules/block/module/walk/map/stateful-tabs.ts +19 -0
  217. package/src/parser/rules/block/module/walk/map/stateful.ts +71 -0
  218. package/src/parser/rules/block/module/walk/map/stateless-definition-list.ts +12 -0
  219. package/src/parser/rules/block/module/walk/map/stateless-list.ts +29 -0
  220. package/src/parser/rules/block/module/walk/map/stateless-table.ts +11 -0
  221. package/src/parser/rules/block/module/walk/map/stateless-tabs.ts +5 -0
  222. package/src/parser/rules/block/module/walk/map/stateless.ts +51 -0
  223. package/src/parser/rules/block/module/walk/map/types.ts +6 -0
  224. package/src/parser/rules/block/module/walk/traverse.ts +65 -0
  225. package/src/parser/rules/block/orphan-li/content.ts +60 -0
  226. package/src/parser/rules/block/orphan-li/index.ts +75 -0
  227. package/src/parser/rules/block/orphan-li/open.ts +25 -0
  228. package/src/parser/rules/block/orphan-li/tags.ts +40 -0
  229. package/src/parser/rules/block/paragraph/content.ts +12 -0
  230. package/src/parser/rules/block/paragraph/index.ts +60 -0
  231. package/src/parser/rules/block/paragraph/normalize.ts +52 -0
  232. package/src/parser/rules/block/paragraph/span-markers.ts +52 -0
  233. package/src/parser/rules/block/parsing/attributes/index.ts +32 -0
  234. package/src/parser/rules/block/parsing/attributes/names.ts +93 -0
  235. package/src/parser/rules/block/parsing/attributes/scanner.ts +75 -0
  236. package/src/parser/rules/block/parsing/attributes/values.ts +26 -0
  237. package/src/parser/rules/block/parsing/block-item.ts +29 -0
  238. package/src/parser/rules/block/parsing/content.ts +127 -0
  239. package/src/parser/rules/block/parsing/end-condition.ts +51 -0
  240. package/src/parser/rules/block/parsing/inline-content.ts +105 -0
  241. package/src/parser/rules/block/parsing/inline-newline.ts +41 -0
  242. package/src/parser/rules/block/parsing/non-boundary.ts +24 -0
  243. package/src/parser/rules/block/parsing/rule-dispatch.ts +44 -0
  244. package/src/parser/rules/block/table/index.ts +80 -0
  245. package/src/parser/rules/block/table/pipe/cell-start.ts +69 -0
  246. package/src/parser/rules/block/table/pipe/cell.ts +106 -0
  247. package/src/parser/rules/block/table/pipe/index.ts +2 -0
  248. package/src/parser/rules/block/table/pipe/row.ts +88 -0
  249. package/src/parser/rules/block/table/pipe/tokens.ts +14 -0
  250. package/src/parser/rules/block/table/pipe/trim.ts +50 -0
  251. package/src/parser/rules/block/table-block/body.ts +79 -0
  252. package/src/parser/rules/block/table-block/cell-attributes.ts +33 -0
  253. package/src/parser/rules/block/table-block/cell-boundary.ts +99 -0
  254. package/src/parser/rules/block/table-block/cell-content/index.ts +88 -0
  255. package/src/parser/rules/block/table-block/cell-content/segments.ts +134 -0
  256. package/src/parser/rules/block/table-block/cell-newline.ts +47 -0
  257. package/src/parser/rules/block/table-block/cell.ts +64 -0
  258. package/src/parser/rules/block/table-block/index.ts +113 -0
  259. package/src/parser/rules/block/table-block/row-boundary.ts +75 -0
  260. package/src/parser/rules/block/table-block/structure.ts +80 -0
  261. package/src/parser/rules/block/tabview/body.ts +64 -0
  262. package/src/parser/rules/block/tabview/index.ts +90 -0
  263. package/src/parser/rules/block/tabview/open.ts +50 -0
  264. package/src/parser/rules/block/tabview/tab.ts +92 -0
  265. package/src/parser/rules/block/tabview/tags.ts +30 -0
  266. package/src/parser/rules/block/toc/element.ts +11 -0
  267. package/src/parser/rules/block/toc/index.ts +44 -0
  268. package/src/parser/rules/block/toc/open.ts +84 -0
  269. package/src/parser/rules/block/utils.ts +10 -610
  270. package/src/parser/rules/{utils.ts → common/attribute-safety.ts} +3 -49
  271. package/src/parser/rules/common/block-name.ts +33 -0
  272. package/src/parser/rules/common/index.ts +2 -0
  273. package/src/parser/rules/contracts/index.ts +3 -0
  274. package/src/parser/rules/contracts/parse-context.ts +38 -0
  275. package/src/parser/rules/contracts/rule.ts +43 -0
  276. package/src/parser/rules/contracts/scope.ts +31 -0
  277. package/src/parser/rules/inline/anchor/attributes.ts +54 -0
  278. package/src/parser/rules/inline/anchor/child.ts +26 -0
  279. package/src/parser/rules/inline/anchor/close.ts +34 -0
  280. package/src/parser/rules/inline/anchor/content.ts +59 -0
  281. package/src/parser/rules/inline/anchor/index.ts +103 -0
  282. package/src/parser/rules/inline/anchor/newline.ts +26 -0
  283. package/src/parser/rules/inline/anchor/open.ts +47 -0
  284. package/src/parser/rules/inline/anchor/paragraph-strip.ts +14 -0
  285. package/src/parser/rules/inline/anchor/syntax.ts +40 -0
  286. package/src/parser/rules/inline/anchor-name/index.ts +38 -0
  287. package/src/parser/rules/inline/anchor-name/name.ts +39 -0
  288. package/src/parser/rules/inline/anchor-name/syntax.ts +46 -0
  289. package/src/parser/rules/inline/bibcite/element.ts +14 -0
  290. package/src/parser/rules/inline/bibcite/index.ts +34 -0
  291. package/src/parser/rules/inline/bibcite/syntax.ts +64 -0
  292. package/src/parser/rules/inline/bold.ts +2 -39
  293. package/src/parser/rules/inline/color/index.ts +35 -0
  294. package/src/parser/rules/inline/color/syntax.ts +69 -0
  295. package/src/parser/rules/inline/comment/consume.ts +31 -0
  296. package/src/parser/rules/inline/{comment.ts → comment/index.ts} +10 -36
  297. package/src/parser/rules/inline/equation-ref/element.ts +8 -0
  298. package/src/parser/rules/inline/equation-ref/index.ts +34 -0
  299. package/src/parser/rules/inline/equation-ref/syntax.ts +45 -0
  300. package/src/parser/rules/inline/expr/branch.ts +104 -0
  301. package/src/parser/rules/inline/expr/conditional-branch.ts +27 -0
  302. package/src/parser/rules/inline/expr/conditional.ts +80 -0
  303. package/src/parser/rules/inline/expr/depth.ts +25 -0
  304. package/src/parser/rules/inline/expr/elements.ts +39 -0
  305. package/src/parser/rules/inline/expr/index.ts +84 -0
  306. package/src/parser/rules/inline/expr/syntax.ts +45 -0
  307. package/src/parser/rules/inline/footnote/child.ts +22 -0
  308. package/src/parser/rules/inline/footnote/close.ts +33 -0
  309. package/src/parser/rules/inline/footnote/content.ts +54 -0
  310. package/src/parser/rules/inline/footnote/elements.ts +38 -0
  311. package/src/parser/rules/inline/footnote/index.ts +54 -0
  312. package/src/parser/rules/inline/footnote/newline.ts +27 -0
  313. package/src/parser/rules/inline/footnote/open.ts +38 -0
  314. package/src/parser/rules/inline/formatting/container.ts +50 -0
  315. package/src/parser/rules/inline/{guillemet.ts → guillemet/index.ts} +5 -13
  316. package/src/parser/rules/inline/guillemet/text.ts +11 -0
  317. package/src/parser/rules/inline/html/gate.ts +64 -0
  318. package/src/parser/rules/inline/{html.ts → html/index.ts} +9 -60
  319. package/src/parser/rules/inline/html/open.ts +37 -0
  320. package/src/parser/rules/inline/image/attributes.ts +22 -0
  321. package/src/parser/rules/inline/image/body.ts +36 -0
  322. package/src/parser/rules/inline/image/index.ts +89 -0
  323. package/src/parser/rules/inline/image/open.ts +56 -0
  324. package/src/parser/rules/inline/image/source.ts +62 -0
  325. package/src/parser/rules/inline/image/syntax.ts +76 -0
  326. package/src/parser/rules/inline/italic.ts +2 -30
  327. package/src/parser/rules/inline/line-break/backslash.ts +58 -0
  328. package/src/parser/rules/inline/line-break/elements.ts +9 -0
  329. package/src/parser/rules/inline/line-break/index.ts +3 -0
  330. package/src/parser/rules/inline/line-break/newline.ts +82 -0
  331. package/src/parser/rules/inline/line-break/underscore.ts +45 -0
  332. package/src/parser/rules/inline/link-anchor.ts +6 -81
  333. package/src/parser/rules/inline/link-bracket/anchor.ts +3 -0
  334. package/src/parser/rules/inline/link-bracket/direct-url.ts +5 -0
  335. package/src/parser/rules/inline/link-bracket/parsed.ts +81 -0
  336. package/src/parser/rules/inline/link-bracket/parts.ts +64 -0
  337. package/src/parser/rules/inline/link-bracket/prefix.ts +15 -0
  338. package/src/parser/rules/inline/link-single.ts +7 -98
  339. package/src/parser/rules/inline/link-star.ts +7 -69
  340. package/src/parser/rules/inline/link-triple/fallback.ts +10 -0
  341. package/src/parser/rules/inline/link-triple/index.ts +62 -0
  342. package/src/parser/rules/inline/link-triple/interwiki.ts +11 -0
  343. package/src/parser/rules/inline/link-triple/label.ts +35 -0
  344. package/src/parser/rules/inline/link-triple/syntax.ts +72 -0
  345. package/src/parser/rules/inline/link-triple/target.ts +36 -0
  346. package/src/parser/rules/inline/math-inline/index.ts +40 -0
  347. package/src/parser/rules/inline/math-inline/syntax.ts +55 -0
  348. package/src/parser/rules/inline/monospace.ts +2 -30
  349. package/src/parser/rules/inline/parsing/block-boundary.ts +42 -0
  350. package/src/parser/rules/inline/parsing/block-start-predicates.ts +117 -0
  351. package/src/parser/rules/inline/parsing/collect.ts +23 -0
  352. package/src/parser/rules/inline/parsing/inline-content.ts +115 -0
  353. package/src/parser/rules/inline/parsing/paragraph-boundary.ts +47 -0
  354. package/src/parser/rules/inline/parsing/plain-text.ts +69 -0
  355. package/src/parser/rules/inline/parsing/preserved-line-break.ts +11 -0
  356. package/src/parser/rules/inline/parsing/rules.ts +34 -0
  357. package/src/parser/rules/inline/parsing/simple-token.ts +26 -0
  358. package/src/parser/rules/inline/raw/angle.ts +40 -0
  359. package/src/parser/rules/inline/raw/double-at.ts +78 -0
  360. package/src/parser/rules/inline/raw/index.ts +26 -0
  361. package/src/parser/rules/inline/raw/result.ts +26 -0
  362. package/src/parser/rules/inline/size/content.ts +65 -0
  363. package/src/parser/rules/inline/size/index.ts +55 -0
  364. package/src/parser/rules/inline/size/open.ts +43 -0
  365. package/src/parser/rules/inline/size/value.ts +45 -0
  366. package/src/parser/rules/inline/span/content.ts +97 -0
  367. package/src/parser/rules/inline/span/elements.ts +108 -0
  368. package/src/parser/rules/inline/span/index.ts +79 -0
  369. package/src/parser/rules/inline/span/newline.ts +50 -0
  370. package/src/parser/rules/inline/span/syntax.ts +70 -0
  371. package/src/parser/rules/inline/{strikethrough.ts → strikethrough/index.ts} +5 -60
  372. package/src/parser/rules/inline/strikethrough/parse.ts +14 -0
  373. package/src/parser/rules/inline/strikethrough/syntax.ts +24 -0
  374. package/src/parser/rules/inline/subscript.ts +2 -39
  375. package/src/parser/rules/inline/superscript.ts +4 -39
  376. package/src/parser/rules/inline/text/element.ts +5 -0
  377. package/src/parser/rules/inline/{text.ts → text/index.ts} +5 -4
  378. package/src/parser/rules/inline/underline/child.ts +26 -0
  379. package/src/parser/rules/inline/underline/content.ts +29 -0
  380. package/src/parser/rules/inline/{underline.ts → underline/index.ts} +6 -49
  381. package/src/parser/rules/inline/user/element.ts +11 -0
  382. package/src/parser/rules/inline/user/index.ts +34 -0
  383. package/src/parser/rules/inline/user/syntax.ts +67 -0
  384. package/src/parser/rules/inline/utils.ts +4 -344
  385. package/src/parser/rules/tokens.ts +106 -0
  386. package/src/parser/rules/types.ts +9 -252
  387. package/src/parser/depth.ts +0 -251
  388. package/src/parser/parse.ts +0 -315
  389. package/src/parser/postprocess/spanStrip.ts +0 -697
  390. package/src/parser/preprocess/expr.ts +0 -265
  391. package/src/parser/preprocess/utils.ts +0 -250
  392. package/src/parser/preprocess/whitespace.ts +0 -111
  393. package/src/parser/rules/block/align.ts +0 -282
  394. package/src/parser/rules/block/bibliography.ts +0 -359
  395. package/src/parser/rules/block/block-list.ts +0 -689
  396. package/src/parser/rules/block/blockquote.ts +0 -238
  397. package/src/parser/rules/block/code.ts +0 -187
  398. package/src/parser/rules/block/collapsible.ts +0 -337
  399. package/src/parser/rules/block/definition-list.ts +0 -270
  400. package/src/parser/rules/block/div.ts +0 -400
  401. package/src/parser/rules/block/embed-block.ts +0 -153
  402. package/src/parser/rules/block/footnoteblock.ts +0 -200
  403. package/src/parser/rules/block/heading.ts +0 -142
  404. package/src/parser/rules/block/html.ts +0 -222
  405. package/src/parser/rules/block/iframe.ts +0 -239
  406. package/src/parser/rules/block/include.ts +0 -179
  407. package/src/parser/rules/block/list.ts +0 -244
  408. package/src/parser/rules/block/math.ts +0 -183
  409. package/src/parser/rules/block/module/include/resolve.ts +0 -556
  410. package/src/parser/rules/block/module/listpages/types.ts +0 -513
  411. package/src/parser/rules/block/module/walk.ts +0 -380
  412. package/src/parser/rules/block/module.ts +0 -164
  413. package/src/parser/rules/block/orphan-li.ts +0 -177
  414. package/src/parser/rules/block/paragraph.ts +0 -157
  415. package/src/parser/rules/block/table-block.ts +0 -726
  416. package/src/parser/rules/block/table.ts +0 -441
  417. package/src/parser/rules/block/tabview.ts +0 -331
  418. package/src/parser/rules/block/toc.ts +0 -129
  419. package/src/parser/rules/inline/anchor-name.ts +0 -154
  420. package/src/parser/rules/inline/anchor.ts +0 -327
  421. package/src/parser/rules/inline/bibcite.ts +0 -153
  422. package/src/parser/rules/inline/color.ts +0 -140
  423. package/src/parser/rules/inline/equation-ref.ts +0 -115
  424. package/src/parser/rules/inline/expr.ts +0 -526
  425. package/src/parser/rules/inline/footnote.ts +0 -223
  426. package/src/parser/rules/inline/image.ts +0 -328
  427. package/src/parser/rules/inline/line-break.ts +0 -326
  428. package/src/parser/rules/inline/link-triple.ts +0 -267
  429. package/src/parser/rules/inline/math-inline.ts +0 -126
  430. package/src/parser/rules/inline/raw.ts +0 -262
  431. package/src/parser/rules/inline/size.ts +0 -244
  432. package/src/parser/rules/inline/span.ts +0 -424
  433. package/src/parser/rules/inline/user.ts +0 -147
@@ -0,0 +1,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
+ }
@@ -0,0 +1,106 @@
1
+ import type { AttributeMap } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+
4
+ /**
5
+ * Whitelist of attributes permitted on `[[iframe]]`. Wikidot strips
6
+ * `id` but permits `class`.
7
+ */
8
+ const ALLOWED_IFRAME_ATTRS = new Set([
9
+ "align",
10
+ "class",
11
+ "frameborder",
12
+ "height",
13
+ "scrolling",
14
+ "style",
15
+ "width",
16
+ ]);
17
+
18
+ export function parseIframeAttributes(
19
+ ctx: ParseContext,
20
+ startPos: number,
21
+ ): { attributes: AttributeMap; consumed: number } {
22
+ const attributes: AttributeMap = {};
23
+ let pos = startPos;
24
+ let consumed = 0;
25
+
26
+ while (pos < ctx.tokens.length) {
27
+ const token = ctx.tokens[pos];
28
+ if (!token || token.type === "BLOCK_CLOSE") break;
29
+
30
+ if (token.type === "NEWLINE") {
31
+ break;
32
+ }
33
+
34
+ if (token.type === "WHITESPACE") {
35
+ pos++;
36
+ consumed++;
37
+ continue;
38
+ }
39
+
40
+ if (token.type === "IDENTIFIER" || token.type === "TEXT") {
41
+ const key = token.value;
42
+ pos++;
43
+ consumed++;
44
+
45
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
46
+ pos++;
47
+ consumed++;
48
+ }
49
+
50
+ if (ctx.tokens[pos]?.type === "EQUALS") {
51
+ pos++;
52
+ consumed++;
53
+
54
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
55
+ pos++;
56
+ consumed++;
57
+ }
58
+
59
+ const valueResult = parseIframeAttributeValue(ctx, pos);
60
+ pos += valueResult.consumed;
61
+ consumed += valueResult.consumed;
62
+
63
+ const normalizedKey = key.toLowerCase();
64
+ if (ALLOWED_IFRAME_ATTRS.has(normalizedKey)) {
65
+ attributes[normalizedKey] = valueResult.value;
66
+ }
67
+ }
68
+ } else {
69
+ pos++;
70
+ consumed++;
71
+ }
72
+ }
73
+
74
+ return { attributes, consumed };
75
+ }
76
+
77
+ function parseIframeAttributeValue(
78
+ ctx: ParseContext,
79
+ startPos: number,
80
+ ): { value: string; consumed: number } {
81
+ const valueToken = ctx.tokens[startPos];
82
+ if (valueToken?.type === "QUOTED_STRING") {
83
+ return { value: valueToken.value.slice(1, -1), consumed: 1 };
84
+ }
85
+
86
+ let value = "";
87
+ let pos = startPos;
88
+ let consumed = 0;
89
+
90
+ while (pos < ctx.tokens.length) {
91
+ const token = ctx.tokens[pos];
92
+ if (
93
+ !token ||
94
+ token.type === "BLOCK_CLOSE" ||
95
+ token.type === "WHITESPACE" ||
96
+ token.type === "NEWLINE"
97
+ ) {
98
+ break;
99
+ }
100
+ value += token.value;
101
+ pos++;
102
+ consumed++;
103
+ }
104
+
105
+ return { value, consumed };
106
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ *
3
+ * Block rule for the Wikidot iframe block: `[[iframe URL attributes]]`.
4
+ *
5
+ * The `[[iframe]]` tag is a self-closing block that embeds an external
6
+ * page in an `<iframe>`. The first argument after the block name is the
7
+ * URL, followed by optional attributes.
8
+ *
9
+ * Security measures:
10
+ * - Only `http://` and `https://` URLs are accepted.
11
+ * - `javascript:`, `data:`, and `vbscript:` schemes are rejected.
12
+ * - URL normalisation strips whitespace and control characters to prevent
13
+ * evasion via character insertion.
14
+ * - Only a specific set of HTML attributes is allowed (Wikidot filters
15
+ * out `id` but permits `class`).
16
+ *
17
+ * Allowed attributes: `align`, `class`, `frameborder`, `height`,
18
+ * `scrolling`, `style`, `width`.
19
+ *
20
+ * @module
21
+ */
22
+ import type { Element } from "@wdprlib/ast";
23
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
24
+ import { currentToken } from "../../types";
25
+ import { parseIframeOpen } from "./open";
26
+ import { isAllowedIframeUrl } from "./url";
27
+
28
+ /**
29
+ * Block rule for `[[iframe URL ...attributes]]`.
30
+ *
31
+ * Parsing strategy:
32
+ * 1. Match BLOCK_OPEN + name "iframe".
33
+ * 2. Consume the URL (all tokens until whitespace, BLOCK_CLOSE, or newline).
34
+ * 3. Validate the URL: normalise, reject dangerous schemes, require http(s).
35
+ * 4. Parse key/value attributes, filtering through `ALLOWED_IFRAME_ATTRS`.
36
+ * 5. Consume closing `]]` and optional trailing newline.
37
+ * 6. Emit an `iframe` element with `url` and `attributes`.
38
+ */
39
+ export const iframeRule: BlockRule = {
40
+ name: "iframe",
41
+ startTokens: ["BLOCK_OPEN"],
42
+ requiresLineStart: false,
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 = parseIframeOpen(ctx);
51
+ if (!openResult) {
52
+ return { success: false };
53
+ }
54
+
55
+ if (!isAllowedIframeUrl(openResult.url)) {
56
+ return { success: false };
57
+ }
58
+
59
+ return {
60
+ success: true,
61
+ elements: [
62
+ {
63
+ element: "iframe",
64
+ data: {
65
+ url: openResult.url,
66
+ attributes: openResult.attributes,
67
+ },
68
+ },
69
+ ],
70
+ consumed: openResult.consumed,
71
+ };
72
+ },
73
+ };
@@ -0,0 +1,58 @@
1
+ import type { AttributeMap } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseBlockName } from "../utils";
4
+ import { parseIframeAttributes } from "./attributes";
5
+ import { parseIframeSource } from "./source";
6
+
7
+ export interface IframeOpenResult {
8
+ url: string;
9
+ attributes: AttributeMap;
10
+ consumed: number;
11
+ }
12
+
13
+ export function parseIframeOpen(ctx: ParseContext): IframeOpenResult | null {
14
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
15
+ return null;
16
+ }
17
+
18
+ let pos = ctx.pos + 1;
19
+ let consumed = 1;
20
+
21
+ const nameResult = parseBlockName(ctx, pos);
22
+ if (!nameResult || nameResult.name.toLowerCase() !== "iframe") {
23
+ return null;
24
+ }
25
+
26
+ pos += nameResult.consumed;
27
+ consumed += nameResult.consumed;
28
+
29
+ while (ctx.tokens[pos]?.type === "WHITESPACE") {
30
+ pos++;
31
+ consumed++;
32
+ }
33
+
34
+ const sourceResult = parseIframeSource(ctx, pos);
35
+ if (!sourceResult) {
36
+ return null;
37
+ }
38
+
39
+ pos += sourceResult.consumed;
40
+ consumed += sourceResult.consumed;
41
+
42
+ const attrResult = parseIframeAttributes(ctx, pos);
43
+ pos += attrResult.consumed;
44
+ consumed += attrResult.consumed;
45
+
46
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
47
+ return null;
48
+ }
49
+
50
+ pos++;
51
+ consumed++;
52
+
53
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
54
+ consumed++;
55
+ }
56
+
57
+ return { url: sourceResult.url, attributes: attrResult.attributes, consumed };
58
+ }
@@ -0,0 +1,24 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export interface IframeSourceResult {
4
+ url: string;
5
+ consumed: number;
6
+ }
7
+
8
+ export function parseIframeSource(ctx: ParseContext, startPos: number): IframeSourceResult | null {
9
+ let pos = startPos;
10
+ let url = "";
11
+
12
+ while (pos < ctx.tokens.length) {
13
+ const token = ctx.tokens[pos];
14
+ if (!token) break;
15
+ if (token.type === "BLOCK_CLOSE" || token.type === "WHITESPACE" || token.type === "NEWLINE") {
16
+ break;
17
+ }
18
+ url += token.value;
19
+ pos++;
20
+ }
21
+
22
+ if (!url) return null;
23
+ return { url, consumed: pos - startPos };
24
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Normalises a URL string for security checks by removing whitespace and
3
+ * control characters that could be used to evade scheme detection, then
4
+ * lowercasing the result.
5
+ */
6
+ export function normalizeIframeUrl(url: string): string {
7
+ return stripControlAndWhitespace(url).toLowerCase();
8
+ }
9
+
10
+ const WHITESPACE = /\s/;
11
+
12
+ function stripControlAndWhitespace(value: string): string {
13
+ let result = "";
14
+ for (const char of value) {
15
+ const code = char.charCodeAt(0);
16
+ if (WHITESPACE.test(char) || code <= 0x1f || (code >= 0x7f && code <= 0x9f)) {
17
+ continue;
18
+ }
19
+ result += char;
20
+ }
21
+ return result;
22
+ }
23
+
24
+ /**
25
+ * Tests whether a normalised URL begins with a dangerous scheme that must
26
+ * be rejected.
27
+ */
28
+ export function isDangerousIframeUrl(normalizedUrl: string): boolean {
29
+ return /^(javascript|data|vbscript):/i.test(normalizedUrl);
30
+ }
31
+
32
+ export function isAllowedIframeUrl(url: string): boolean {
33
+ const normalizedUrl = normalizeIframeUrl(url);
34
+ if (isDangerousIframeUrl(normalizedUrl)) {
35
+ return false;
36
+ }
37
+ return /^https?:\/\//i.test(normalizedUrl);
38
+ }
@@ -0,0 +1,48 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseContext } from "../../types";
3
+ import { parseBlockName, parseBlocksUntil } from "../utils";
4
+
5
+ export interface IftagsBodyResult {
6
+ elements: Element[];
7
+ consumed: number;
8
+ }
9
+
10
+ export function parseIftagsBody(ctx: ParseContext, startPos: number): IftagsBodyResult {
11
+ const bodyCtx: ParseContext = { ...ctx, pos: startPos };
12
+ const bodyResult = parseBlocksUntil(bodyCtx, (checkCtx) => isIftagsClose(checkCtx, checkCtx.pos));
13
+
14
+ return {
15
+ elements: bodyResult.elements,
16
+ consumed: bodyResult.consumed,
17
+ };
18
+ }
19
+
20
+ export function isIftagsClose(ctx: ParseContext, pos: number): boolean {
21
+ const token = ctx.tokens[pos];
22
+ if (token?.type !== "BLOCK_END_OPEN") {
23
+ return false;
24
+ }
25
+
26
+ const closeNameResult = parseBlockName(ctx, pos + 1);
27
+ return closeNameResult?.name.toLowerCase() === "iftags";
28
+ }
29
+
30
+ export function consumeIftagsClose(ctx: ParseContext, startPos: number): number {
31
+ let pos = startPos + 1;
32
+ let consumed = 1;
33
+
34
+ const closeNameResult = parseBlockName(ctx, pos);
35
+ if (closeNameResult) {
36
+ pos += closeNameResult.consumed;
37
+ consumed += closeNameResult.consumed;
38
+ }
39
+ if (ctx.tokens[pos]?.type === "BLOCK_CLOSE") {
40
+ pos++;
41
+ consumed++;
42
+ }
43
+ if (ctx.tokens[pos]?.type === "NEWLINE") {
44
+ consumed++;
45
+ }
46
+
47
+ return consumed;
48
+ }
@@ -0,0 +1,24 @@
1
+ import type { ParseContext } from "../../types";
2
+
3
+ export interface IftagsConditionResult {
4
+ condition: string;
5
+ consumed: number;
6
+ }
7
+
8
+ export function collectIftagsCondition(ctx: ParseContext, startPos: number): IftagsConditionResult {
9
+ let condition = "";
10
+ let pos = startPos;
11
+ let consumed = 0;
12
+
13
+ while (pos < ctx.tokens.length) {
14
+ const token = ctx.tokens[pos];
15
+ if (!token || token.type === "BLOCK_CLOSE" || token.type === "NEWLINE") {
16
+ break;
17
+ }
18
+ condition += token.value;
19
+ pos++;
20
+ consumed++;
21
+ }
22
+
23
+ return { condition, consumed };
24
+ }