@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,93 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { isListPagesModule, resolveListPages } from "../listpages/resolve";
3
+ import { isListUsersModule, resolveListUsers } from "../listusers/resolve";
4
+ import { walkElements } from "../walk";
5
+ import type { ListPagesContext, ListUsersContext } from "./contexts";
6
+
7
+ export interface DynamicModuleContext {
8
+ listPages: ListPagesContext | null;
9
+ listUsers: ListUsersContext | null;
10
+ fetchListPagesProvided: boolean;
11
+ fetchListUsersProvided: boolean;
12
+ }
13
+
14
+ export interface DynamicModuleIds {
15
+ listPagesId: number;
16
+ listUsersId: number;
17
+ }
18
+
19
+ export interface DynamicModuleResolution {
20
+ handled: boolean;
21
+ elements: Element[];
22
+ ids: DynamicModuleIds;
23
+ }
24
+
25
+ export function resolveDynamicModuleElement(
26
+ element: Element,
27
+ ctx: DynamicModuleContext,
28
+ ids: DynamicModuleIds,
29
+ ): DynamicModuleResolution {
30
+ if (element.element !== "module") {
31
+ return { handled: false, elements: [element], ids };
32
+ }
33
+
34
+ if (isListPagesModule(element.data)) {
35
+ const elements: Element[] = [];
36
+ const listPagesId = ids.listPagesId;
37
+
38
+ if (ctx.listPages) {
39
+ const moduleData = ctx.listPages.dataMap.get(listPagesId);
40
+ const template = ctx.listPages.compiledTemplates.get(listPagesId);
41
+
42
+ if (moduleData && template) {
43
+ elements.push(...resolveListPages(element.data, moduleData, template, ctx.listPages.parse));
44
+ }
45
+ } else if (!ctx.fetchListPagesProvided) {
46
+ elements.push(element);
47
+ }
48
+
49
+ return {
50
+ handled: true,
51
+ elements,
52
+ ids: { ...ids, listPagesId: listPagesId + 1 },
53
+ };
54
+ }
55
+
56
+ if (isListUsersModule(element.data)) {
57
+ const elements: Element[] = [];
58
+ const listUsersId = ids.listUsersId;
59
+
60
+ if (ctx.listUsers) {
61
+ const moduleData = ctx.listUsers.dataMap.get(listUsersId);
62
+ const template = ctx.listUsers.compiledTemplates.get(listUsersId);
63
+
64
+ if (moduleData && template) {
65
+ elements.push(...resolveListUsers(element.data, moduleData, template, ctx.listUsers.parse));
66
+ }
67
+ } else if (!ctx.fetchListUsersProvided) {
68
+ elements.push(element);
69
+ }
70
+
71
+ return {
72
+ handled: true,
73
+ elements,
74
+ ids: { ...ids, listUsersId: listUsersId + 1 },
75
+ };
76
+ }
77
+
78
+ return { handled: false, elements: [element], ids };
79
+ }
80
+
81
+ export function countDynamicModules(elements: Element[]): DynamicModuleIds {
82
+ const counts: DynamicModuleIds = { listPagesId: 0, listUsersId: 0 };
83
+ walkElements(elements, (element) => {
84
+ if (element.element !== "module") return;
85
+
86
+ if (isListPagesModule(element.data)) {
87
+ counts.listPagesId++;
88
+ } else if (isListUsersModule(element.data)) {
89
+ counts.listUsersId++;
90
+ }
91
+ });
92
+ return counts;
93
+ }
@@ -0,0 +1,53 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { STYLE_SLOT_PREFIX } from "@wdprlib/ast";
3
+ import { mapElementChildren } from "../walk";
4
+ import type { IfTagsData } from "../iftags/resolve";
5
+
6
+ type IfTagsDataWithStyleSlot = IfTagsData & {
7
+ _styleSlot: number;
8
+ };
9
+
10
+ /**
11
+ * Collect and remove style elements from the AST.
12
+ *
13
+ * Unresolved `if-tags` elements receive style-slot placeholders so render-time
14
+ * iftags evaluation can preserve style order relative to already collected CSS.
15
+ */
16
+ export function collectStyles(elements: Element[]): { elements: Element[]; styles: string[] } {
17
+ const styles: string[] = [];
18
+ const ctx = { nextSlotId: 0 };
19
+ const filtered = collectStylesFromElements(elements, styles, ctx);
20
+ return { elements: filtered, styles };
21
+ }
22
+
23
+ function collectStylesFromElements(
24
+ elements: Element[],
25
+ styles: string[],
26
+ ctx: { nextSlotId: number },
27
+ ): Element[] {
28
+ const result: Element[] = [];
29
+
30
+ for (const element of elements) {
31
+ if (element.element === "style") {
32
+ styles.push(element.data as string);
33
+ continue;
34
+ }
35
+
36
+ if (element.element === "if-tags") {
37
+ const slotId = ctx.nextSlotId++;
38
+ styles.push(`${STYLE_SLOT_PREFIX}${slotId}`);
39
+ const data: IfTagsDataWithStyleSlot = { ...(element.data as IfTagsData), _styleSlot: slotId };
40
+ result.push({
41
+ element: "if-tags",
42
+ data,
43
+ });
44
+ continue;
45
+ }
46
+
47
+ result.push(
48
+ mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx)),
49
+ );
50
+ }
51
+
52
+ return result;
53
+ }
@@ -0,0 +1,107 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import { mapElementChildrenWithState } from "../walk";
3
+ import { isIfTagsElement, resolveIfTags, type IfTagsData } from "../iftags/resolve";
4
+ import type { ListPagesContext, ListUsersContext } from "./contexts";
5
+ import { countDynamicModules, resolveDynamicModuleElement } from "./dynamic-modules";
6
+
7
+ /**
8
+ * Resolution context passed through AST traversal.
9
+ */
10
+ export interface WalkContext {
11
+ listPages: ListPagesContext | null;
12
+ listUsers: ListUsersContext | null;
13
+ /** Whether fetchListPages callback was provided, even if no data returned. */
14
+ fetchListPagesProvided: boolean;
15
+ /** Whether fetchListUsers callback was provided, even if no data returned. */
16
+ fetchListUsersProvided: boolean;
17
+ pageTags: string[] | null;
18
+ listPagesIdCounter: number;
19
+ listUsersIdCounter: number;
20
+ }
21
+
22
+ export interface WalkResult {
23
+ elements: Element[];
24
+ nextListPagesId: number;
25
+ nextListUsersId: number;
26
+ }
27
+
28
+ /**
29
+ * Walk AST and resolve modules/iftags.
30
+ */
31
+ export function walkAndResolve(elements: Element[], ctx: WalkContext): WalkResult {
32
+ const result: Element[] = [];
33
+ let listPagesId = ctx.listPagesIdCounter;
34
+ let listUsersId = ctx.listUsersIdCounter;
35
+
36
+ for (const element of elements) {
37
+ const dynamicModule = resolveDynamicModuleElement(element, ctx, { listPagesId, listUsersId });
38
+ if (dynamicModule.handled) {
39
+ result.push(...dynamicModule.elements);
40
+ listPagesId = dynamicModule.ids.listPagesId;
41
+ listUsersId = dynamicModule.ids.listUsersId;
42
+ continue;
43
+ }
44
+
45
+ if (isIfTagsElement(element)) {
46
+ const ifTagsData = element.data as IfTagsData;
47
+ const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
48
+
49
+ if (resolveResult.evaluated) {
50
+ if (resolveResult.matched) {
51
+ const childResult = walkAndResolve(ifTagsData.elements, {
52
+ ...ctx,
53
+ listPagesIdCounter: listPagesId,
54
+ listUsersIdCounter: listUsersId,
55
+ });
56
+ result.push(...childResult.elements);
57
+ listPagesId = childResult.nextListPagesId;
58
+ listUsersId = childResult.nextListUsersId;
59
+ } else {
60
+ const counts = countDynamicModules(ifTagsData.elements);
61
+ listPagesId += counts.listPagesId;
62
+ listUsersId += counts.listUsersId;
63
+ }
64
+ } else {
65
+ const childResult = walkAndResolve(ifTagsData.elements, {
66
+ ...ctx,
67
+ listPagesIdCounter: listPagesId,
68
+ listUsersIdCounter: listUsersId,
69
+ });
70
+ result.push({
71
+ element: "if-tags",
72
+ data: {
73
+ ...ifTagsData,
74
+ elements: childResult.elements,
75
+ },
76
+ });
77
+ listPagesId = childResult.nextListPagesId;
78
+ listUsersId = childResult.nextListUsersId;
79
+ }
80
+ continue;
81
+ }
82
+
83
+ const mapped = mapElementChildrenWithState(
84
+ element,
85
+ { listPagesId, listUsersId },
86
+ (children, state) => {
87
+ const childResult = walkAndResolve(children, {
88
+ ...ctx,
89
+ listPagesIdCounter: state.listPagesId,
90
+ listUsersIdCounter: state.listUsersId,
91
+ });
92
+ return {
93
+ elements: childResult.elements,
94
+ state: {
95
+ listPagesId: childResult.nextListPagesId,
96
+ listUsersId: childResult.nextListUsersId,
97
+ },
98
+ };
99
+ },
100
+ );
101
+ result.push(mapped.element);
102
+ listPagesId = mapped.state.listPagesId;
103
+ listUsersId = mapped.state.listUsersId;
104
+ }
105
+
106
+ return { elements: result, nextListPagesId: listPagesId, nextListUsersId: listUsersId };
107
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Unified resolver that walks a parsed AST and expands dynamic modules.
3
+ *
4
+ * Handles three module families in a single traversal:
5
+ *
6
+ * - **ListPages** — fetches page data via {@link DataProvider.fetchListPages},
7
+ * resolves `@URL` parameters from the page path (HPC support), and
8
+ * expands `%%variable%%` templates.
9
+ * - **ListUsers** — fetches user data via {@link DataProvider.fetchListUsers}
10
+ * and expands `%%variable%%` templates.
11
+ * - **IfTags** — evaluates tag conditions against the current page's tags
12
+ * (from {@link DataProvider.getPageTags}) and keeps or discards content.
13
+ *
14
+ * The main entry point is {@link resolveModules}.
15
+ *
16
+ * @module
17
+ */
18
+
19
+ import type { SyntaxTree } from "@wdprlib/ast";
20
+ import type { DataProvider } from "./types-common";
21
+ import { resolveIncludes } from "./include";
22
+ import type { ListPagesDataRequirement, CompiledTemplate } from "./listpages/types";
23
+ import type { ListUsersDataRequirement, ListUsersCompiledTemplate } from "./listusers/types";
24
+ import type { ParseFunction } from "./listpages/resolve";
25
+ import { buildListPagesContext, buildListUsersContext } from "./resolution/contexts";
26
+ import { walkAndResolve } from "./resolution/walk-resolve";
27
+ import { collectStyles } from "./resolution/styles";
28
+
29
+ const MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
30
+
31
+ // Re-export from listpages/resolve for external use
32
+ export type { ParseFunction } from "./listpages/resolve";
33
+
34
+ /**
35
+ * Transform module-generated wikitext before it is parsed back into AST nodes.
36
+ *
37
+ * Applications can use this hook to inject include resolution, parse caches, or
38
+ * diagnostics for ListPages/ListUsers secondary transformations.
39
+ *
40
+ * This hook receives the string after module variables such as `%%title%%` have
41
+ * already been substituted. Returning a different string changes what is parsed
42
+ * for that module item. When this hook is supplied it replaces the built-in
43
+ * secondary include pass, so callers that still need Wikidot-style secondary
44
+ * includes must call `resolveIncludes()` or equivalent logic from the hook.
45
+ */
46
+ export type ModuleSourceTransform = (source: string) => string;
47
+
48
+ /**
49
+ * Configuration for {@link resolveModules}.
50
+ *
51
+ * Callers must supply pre-extracted requirements and pre-compiled
52
+ * templates (obtained from `extractDataRequirements()` and
53
+ * `compileTemplate()` / `compileListUsersTemplate()`).
54
+ *
55
+ * @group Module Resolution
56
+ */
57
+ export interface ResolveOptions {
58
+ /** Parser function used to re-parse expanded template markup into AST nodes */
59
+ parse: ParseFunction;
60
+
61
+ /** Pre-compiled ListPages body templates, keyed by requirement ID */
62
+ compiledListPagesTemplates: Map<number, CompiledTemplate>;
63
+
64
+ /** Pre-compiled ListUsers body templates, keyed by requirement ID */
65
+ compiledListUsersTemplates?: Map<number, ListUsersCompiledTemplate>;
66
+
67
+ /**
68
+ * Data requirements grouped by module type.
69
+ * Obtained from `extractDataRequirements()`.
70
+ */
71
+ requirements: {
72
+ listPages?: ListPagesDataRequirement[];
73
+ listUsers?: ListUsersDataRequirement[];
74
+ };
75
+
76
+ /**
77
+ * URL path for `@URL` parameter resolution (HPC / pagination support).
78
+ *
79
+ * Wikidot encodes pagination state in the URL path as key/value pairs
80
+ * after the page name, e.g. `"/scp-001/offset/10/page2_limit/5"`.
81
+ * When provided, `@URL` references in ListPages queries are replaced
82
+ * with the corresponding values from this path.
83
+ */
84
+ urlPath?: string;
85
+
86
+ /**
87
+ * Maximum include expansion iterations for secondary transformations inside
88
+ * modules such as ListPages/ListUsers. Defaults to Wikidot's observed
89
+ * secondary transformation limit.
90
+ */
91
+ includeMaxIterations?: number;
92
+
93
+ /**
94
+ * Transform module-generated wikitext before re-parsing it.
95
+ *
96
+ * When omitted, `resolveModules()` preserves the existing default: if
97
+ * `dataProvider.fetchInclude` is present, secondary `[[include]]` expansion
98
+ * is performed with `includeMaxIterations`; otherwise the source is parsed
99
+ * unchanged. When supplied, this hook owns the whole transformation.
100
+ *
101
+ * This is the extension point for application-level parse/include caches. The
102
+ * parser package does not persist cache entries itself because cache keys and
103
+ * invalidation depend on site/page revisions, tags, URL parameters, and user
104
+ * state outside wdpr.
105
+ */
106
+ transformModuleSource?: ModuleSourceTransform;
107
+ }
108
+
109
+ /**
110
+ * Resolve all modules in the AST
111
+ *
112
+ * Fetches data for each module using the provided callback,
113
+ * then expands the modules with the fetched data.
114
+ *
115
+ * Handles:
116
+ * - ListPages: fetches page data and expands templates
117
+ * - IfTags: evaluates tag conditions and includes/excludes content
118
+ *
119
+ * @param ast - Parsed AST
120
+ * @param dataProvider - Callback provider to fetch data for each module
121
+ * @param options - Resolution options including requirements
122
+ */
123
+ export async function resolveModules(
124
+ ast: SyntaxTree,
125
+ dataProvider: DataProvider,
126
+ options: ResolveOptions,
127
+ ): Promise<SyntaxTree> {
128
+ const parse = createModuleParseFunction(options, dataProvider);
129
+ const listPagesCtx = await buildListPagesContext(
130
+ dataProvider,
131
+ options.requirements.listPages ?? [],
132
+ options.compiledListPagesTemplates,
133
+ parse,
134
+ options.urlPath,
135
+ );
136
+ const listUsersCtx = await buildListUsersContext(
137
+ dataProvider,
138
+ options.requirements.listUsers ?? [],
139
+ options.compiledListUsersTemplates,
140
+ parse,
141
+ );
142
+ const pageTags = dataProvider.getPageTags?.() ?? null;
143
+
144
+ // Resolve AST
145
+ const resolvedElements = walkAndResolve(ast.elements, {
146
+ listPages: listPagesCtx,
147
+ listUsers: listUsersCtx,
148
+ fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
149
+ fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
150
+ pageTags,
151
+ listPagesIdCounter: 0,
152
+ listUsersIdCounter: 0,
153
+ });
154
+
155
+ // Collect style elements from resolved AST
156
+ const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
157
+
158
+ const result: SyntaxTree = {
159
+ ...ast,
160
+ elements: finalElements,
161
+ };
162
+
163
+ if (styles.length > 0) {
164
+ result.styles = styles;
165
+ }
166
+
167
+ return result;
168
+ }
169
+
170
+ function createModuleParseFunction(
171
+ options: ResolveOptions,
172
+ dataProvider: DataProvider,
173
+ ): ParseFunction {
174
+ const transform = createModuleSourceTransform(options, dataProvider);
175
+ if (!transform) {
176
+ return options.parse;
177
+ }
178
+
179
+ return (source: string) => options.parse(transform(source));
180
+ }
181
+
182
+ function createModuleSourceTransform(
183
+ options: ResolveOptions,
184
+ dataProvider: DataProvider,
185
+ ): ModuleSourceTransform | null {
186
+ if (options.transformModuleSource) {
187
+ return options.transformModuleSource;
188
+ }
189
+
190
+ if (!dataProvider.fetchInclude) {
191
+ return null;
192
+ }
193
+
194
+ return (source: string) =>
195
+ resolveIncludes(source, dataProvider.fetchInclude!, {
196
+ maxIterations: options.includeMaxIterations ?? MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS,
197
+ });
198
+ }
@@ -0,0 +1,56 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { BlockRule, ParseContext, RuleResult } from "../../types";
3
+ import { currentToken } from "../../types";
4
+ import { parseModuleBody } from "./body";
5
+ import { createUnknownModuleElement, moduleParseResultToElement } from "./element";
6
+ import { getModuleRuleByName } from "./mapping";
7
+ import { parseModuleOpen } from "./open";
8
+
9
+ export const moduleRule: BlockRule = {
10
+ name: "module",
11
+ startTokens: ["BLOCK_OPEN"],
12
+ requiresLineStart: false,
13
+
14
+ parse(ctx: ParseContext): RuleResult<Element> {
15
+ const openToken = currentToken(ctx);
16
+ if (openToken.type !== "BLOCK_OPEN") {
17
+ return { success: false };
18
+ }
19
+
20
+ const openResult = parseModuleOpen(ctx);
21
+ if (!openResult) {
22
+ return { success: false };
23
+ }
24
+
25
+ // Page syntax disabled (e.g., forum-post mode)
26
+ if (!ctx.settings.enablePageSyntax) {
27
+ return { success: false };
28
+ }
29
+
30
+ // Dispatch to specific module parser
31
+ const moduleParseRule = getModuleRuleByName(openResult.moduleName);
32
+
33
+ // Check for body based on module rule's hasBody flag
34
+ // For unknown modules, default to no body (they will be parsed as bodyless)
35
+ const bodyResult = parseModuleBody(ctx, openResult.pos, moduleParseRule?.hasBody ?? false);
36
+ const consumed = openResult.consumed + bodyResult.consumed;
37
+
38
+ if (moduleParseRule) {
39
+ const result = moduleParseRule.parse(ctx, bodyResult.pos, openResult.attrs, bodyResult.body);
40
+
41
+ return {
42
+ success: true,
43
+ elements: [moduleParseResultToElement(result)],
44
+ consumed,
45
+ };
46
+ }
47
+
48
+ return {
49
+ success: true,
50
+ elements: [
51
+ createUnknownModuleElement(openResult.moduleName, openResult.attrs, bodyResult.body),
52
+ ],
53
+ consumed,
54
+ };
55
+ },
56
+ };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared callback interface for module resolution.
3
+ *
4
+ * `DataProvider` is the single object that callers pass to
5
+ * `resolveModules()` to supply external data. Each property is an
6
+ * optional async callback; if omitted the corresponding module type is
7
+ * left unresolved in the AST.
8
+ *
9
+ * Include resolution uses a separate API (`resolveIncludes()`)
10
+ * because it operates on raw wikitext before parsing, not on AST nodes.
11
+ *
12
+ * @module
13
+ */
14
+
15
+ import type { ListPagesDataFetcher } from "./listpages/types";
16
+ import type { ListUsersDataFetcher } from "./listusers/types";
17
+ import type { IfTagsResolver } from "./iftags/types";
18
+ import type { IncludeFetcher } from "./include/resolve/types";
19
+
20
+ /**
21
+ * Callback bag for supplying external data during module resolution.
22
+ *
23
+ * Pass an instance to `resolveModules()`. Every callback is optional:
24
+ * when a callback is missing the corresponding module node is kept as-is
25
+ * in the output AST — useful when you only need to resolve a subset of
26
+ * modules (e.g. only `[[iftags]]` on the client side).
27
+ *
28
+ * @group Module Resolution
29
+ */
30
+ export interface DataProvider {
31
+ /**
32
+ * Fetch page data for `[[module ListPages]]` expansion.
33
+ *
34
+ * Called once per ListPages instance in the AST with the normalised
35
+ * query parameters extracted from the module's wikitext attributes.
36
+ *
37
+ * @security The query fields originate from **untrusted user input**.
38
+ * When building database queries from the returned requirement:
39
+ * - **Never** interpolate `req.query` / `req.rawAttributes` into SQL
40
+ * - **Always** use parameterised queries or prepared statements
41
+ * - For `order` (ORDER BY), validate against a whitelist of column names
42
+ */
43
+ fetchListPages?: ListPagesDataFetcher;
44
+
45
+ /**
46
+ * Fetch user data for `[[module ListUsers]]` expansion.
47
+ *
48
+ * Called once per ListUsers instance with the parsed query parameters.
49
+ */
50
+ fetchListUsers?: ListUsersDataFetcher;
51
+
52
+ /**
53
+ * Fetch raw wikitext for `[[include]]` directives that are created during
54
+ * module secondary transformations such as ListPages/ListUsers item rendering.
55
+ *
56
+ * Top-level include expansion still uses `resolveIncludes()` directly before
57
+ * parsing. This callback is only for module-rendered wikitext that needs its
58
+ * own include pass before being parsed again.
59
+ */
60
+ fetchInclude?: IncludeFetcher;
61
+
62
+ /**
63
+ * Return the current page's tags for `[[iftags]]` evaluation.
64
+ *
65
+ * If provided, `[[iftags]]` blocks are evaluated and either kept or
66
+ * discarded based on whether the page's tags satisfy the condition.
67
+ * If omitted, `[[iftags]]` blocks pass through unresolved.
68
+ */
69
+ getPageTags?: IfTagsResolver;
70
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ *
3
+ * Core type definitions for the Wikidot module system.
4
+ *
5
+ * Wikidot modules are block-level constructs invoked with `[[module Name ...]]`
6
+ * syntax. Each module type (ListPages, CSS, Rate, etc.) is implemented as a
7
+ * `ModuleRule` that defines how to parse the module's attributes and body into
8
+ * an AST node.
9
+ *
10
+ * @module
11
+ */
12
+
13
+ import type { Element, Module } from "@wdprlib/ast";
14
+ import type { ParseContext } from "../../types";
15
+
16
+ /**
17
+ * Parser function type for re-parsing substituted template output as wikitext.
18
+ *
19
+ * Used by ListPages and ListUsers modules during the resolution phase. After
20
+ * template variables are substituted with actual data, the resulting string
21
+ * needs to be parsed as wikitext to produce AST elements.
22
+ *
23
+ * @param input - Wikitext string to parse
24
+ * @returns Object containing the parsed elements
25
+ */
26
+ export type ParseFunction = (input: string) => { elements: Element[] };
27
+
28
+ /**
29
+ * Definition of a module rule that handles a specific Wikidot module type.
30
+ *
31
+ * Each module rule declares which module names it handles (e.g., "listpages",
32
+ * "css"), whether the module accepts a body (content between `[[module Name]]`
33
+ * and `[[/module]]`), and a parse function that produces the AST representation.
34
+ *
35
+ * The parse function's return type determines how the result is handled:
36
+ * - `Module`: Wrapped as `{ element: "module", data: Module }` in the AST
37
+ * - `Element`: Used directly as an AST element (e.g., CSS module returns a `style` element)
38
+ */
39
+ export interface ModuleRule {
40
+ /** Internal identifier for the rule (e.g., "module-listpages") */
41
+ name: string;
42
+ /** Module names this rule handles, matched case-insensitively (e.g., ["listpages"]) */
43
+ acceptsNames: string[];
44
+ /** Whether this module accepts a body (content between `[[module]]` and `[[/module]]`) */
45
+ hasBody: boolean;
46
+ /**
47
+ * Parse the module's attributes and optional body into an AST node.
48
+ *
49
+ * @param ctx - Current parse context (token stream, settings, etc.)
50
+ * @param pos - Current token position
51
+ * @param args - Key-value attributes from the module's opening tag
52
+ * @param body - Raw text content between opening and closing tags (only if `hasBody` is true)
53
+ * @returns A Module data object or a direct Element
54
+ */
55
+ parse: (
56
+ ctx: ParseContext,
57
+ pos: number,
58
+ args: Record<string, string>,
59
+ body?: string,
60
+ ) => Module | Element;
61
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ *
3
+ * Utility functions for parsing Wikidot module attribute values.
4
+ *
5
+ * Wikidot modules accept attributes as string key-value pairs. These utilities
6
+ * convert common attribute types (booleans, integers) from their string
7
+ * representation to proper TypeScript types, following Wikidot's conventions
8
+ * for truthy/falsy values.
9
+ *
10
+ * @module
11
+ */
12
+
13
+ /**
14
+ * Parse a boolean value from a Wikidot attribute string.
15
+ *
16
+ * Wikidot accepts both "yes"/"no" and "true"/"false" as boolean attribute values.
17
+ * If the value does not match any recognized boolean string, the default is returned.
18
+ *
19
+ * @param value - The attribute string value, or undefined if the attribute was not specified
20
+ * @param defaultValue - Value to return when the attribute is undefined or unrecognized
21
+ * @returns The parsed boolean value
22
+ */
23
+ export function parseBool(value: string | undefined, defaultValue: boolean): boolean {
24
+ if (value === undefined) return defaultValue;
25
+ if (value === "yes" || value === "true") return true;
26
+ if (value === "no" || value === "false") return false;
27
+ return defaultValue;
28
+ }
29
+
30
+ /**
31
+ * Parse a 32-bit integer value from a Wikidot attribute string.
32
+ *
33
+ * Uses base-10 parsing. Returns undefined for non-numeric strings or
34
+ * when the attribute is not specified.
35
+ *
36
+ * @param value - The attribute string value, or undefined if not specified
37
+ * @returns The parsed integer, or undefined if parsing fails
38
+ */
39
+ export function parseInt32(value: string | undefined): number | undefined {
40
+ if (value === undefined) return undefined;
41
+ const num = Number.parseInt(value, 10);
42
+ return Number.isNaN(num) ? undefined : num;
43
+ }