@wdprlib/parser 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/dist/index.cjs +10451 -8402
  2. package/dist/index.d.cts +313 -337
  3. package/dist/index.d.ts +313 -337
  4. package/dist/index.js +10438 -8389
  5. package/package.json +1 -1
  6. package/src/index.ts +7 -0
  7. package/src/lexer/anchor.ts +48 -0
  8. package/src/lexer/index.ts +3 -2
  9. package/src/lexer/lexer.ts +73 -559
  10. package/src/lexer/options.ts +19 -0
  11. package/src/lexer/punctuation.ts +70 -0
  12. package/src/lexer/quoted-string.ts +16 -0
  13. package/src/lexer/runs.ts +85 -0
  14. package/src/lexer/spacing-actions.ts +24 -0
  15. package/src/lexer/state.ts +103 -0
  16. package/src/lexer/syntax-actions.ts +80 -0
  17. package/src/lexer/text-actions.ts +41 -0
  18. package/src/lexer/token-actions.ts +136 -0
  19. package/src/lexer/token-factory.ts +62 -0
  20. package/src/lexer/tokenize.ts +18 -0
  21. package/src/parser/constants.ts +2 -0
  22. package/src/parser/depth/index.ts +111 -0
  23. package/src/parser/depth/stack.ts +82 -0
  24. package/src/parser/parse/block.ts +42 -0
  25. package/src/parser/parse/context.ts +26 -0
  26. package/src/parser/parse/footnotes.ts +25 -0
  27. package/src/parser/parse/index.ts +42 -0
  28. package/src/parser/parse/options.ts +34 -0
  29. package/src/parser/parse/parser.ts +79 -0
  30. package/src/parser/parse/plain-non-ascii.ts +129 -0
  31. package/src/parser/parse/result.ts +57 -0
  32. package/src/parser/parse/source.ts +11 -0
  33. package/src/parser/postprocess/divAdjacentParagraph.ts +1 -1
  34. package/src/parser/postprocess/spanStrip/clean-element.ts +168 -0
  35. package/src/parser/postprocess/spanStrip/cleanup.ts +25 -0
  36. package/src/parser/postprocess/spanStrip/empty-spans.ts +36 -0
  37. package/src/parser/postprocess/spanStrip/escaped.ts +78 -0
  38. package/src/parser/postprocess/spanStrip/factory.ts +23 -0
  39. package/src/parser/postprocess/spanStrip/index.ts +8 -0
  40. package/src/parser/postprocess/spanStrip/merge.ts +117 -0
  41. package/src/parser/postprocess/spanStrip/predicates.ts +59 -0
  42. package/src/parser/postprocess/spanStrip/split.ts +67 -0
  43. package/src/parser/preprocess/expr/chars.ts +15 -0
  44. package/src/parser/preprocess/expr/evaluate.ts +22 -0
  45. package/src/parser/preprocess/expr/index.ts +45 -0
  46. package/src/parser/preprocess/expr/kind.ts +19 -0
  47. package/src/parser/preprocess/expr/parse.ts +103 -0
  48. package/src/parser/preprocess/expr/scan.ts +34 -0
  49. package/src/parser/preprocess/expr/types.ts +14 -0
  50. package/src/parser/preprocess/typography.ts +70 -5
  51. package/src/parser/preprocess/utils/bracket-depths.ts +98 -0
  52. package/src/parser/preprocess/utils/index.ts +13 -0
  53. package/src/parser/preprocess/utils/raw-regions.ts +153 -0
  54. package/src/parser/preprocess/whitespace/detection.ts +39 -0
  55. package/src/parser/preprocess/whitespace/index.ts +79 -0
  56. package/src/parser/preprocess/whitespace/leading-spaces.ts +11 -0
  57. package/src/parser/preprocess/whitespace/patterns.ts +23 -0
  58. package/src/parser/rules/block/align/body.ts +46 -0
  59. package/src/parser/rules/block/align/element.ts +13 -0
  60. package/src/parser/rules/block/align/index.ts +90 -0
  61. package/src/parser/rules/block/align/syntax.ts +113 -0
  62. package/src/parser/rules/block/bibliography/body.ts +81 -0
  63. package/src/parser/rules/block/bibliography/entries.ts +49 -0
  64. package/src/parser/rules/block/bibliography/entry-content.ts +73 -0
  65. package/src/parser/rules/block/bibliography/entry-key.ts +83 -0
  66. package/src/parser/rules/block/bibliography/index.ts +90 -0
  67. package/src/parser/rules/block/bibliography/open.ts +53 -0
  68. package/src/parser/rules/block/block-list/bare-content.ts +105 -0
  69. package/src/parser/rules/block/block-list/bare-paragraph.ts +60 -0
  70. package/src/parser/rules/block/block-list/index.ts +51 -0
  71. package/src/parser/rules/block/block-list/item-content.ts +132 -0
  72. package/src/parser/rules/block/block-list/li-content.ts +107 -0
  73. package/src/parser/rules/block/block-list/li-item.ts +77 -0
  74. package/src/parser/rules/block/block-list/list-block.ts +100 -0
  75. package/src/parser/rules/block/block-list/open.ts +51 -0
  76. package/src/parser/rules/block/block-list/tags.ts +50 -0
  77. package/src/parser/rules/block/blockquote/build.ts +62 -0
  78. package/src/parser/rules/block/blockquote/index.ts +80 -0
  79. package/src/parser/rules/block/blockquote/line.ts +79 -0
  80. package/src/parser/rules/block/blockquote/lines.ts +39 -0
  81. package/src/parser/rules/block/{center.ts → center/index.ts} +7 -22
  82. package/src/parser/rules/block/center/open.ts +27 -0
  83. package/src/parser/rules/block/{clear-float.ts → clear-float/index.ts} +6 -30
  84. package/src/parser/rules/block/clear-float/syntax.ts +43 -0
  85. package/src/parser/rules/block/code/attributes.ts +30 -0
  86. package/src/parser/rules/block/code/content.ts +57 -0
  87. package/src/parser/rules/block/code/index.ts +100 -0
  88. package/src/parser/rules/block/collapsible/attributes.ts +95 -0
  89. package/src/parser/rules/block/collapsible/body.ts +69 -0
  90. package/src/parser/rules/block/collapsible/index.ts +117 -0
  91. package/src/parser/rules/block/collapsible/open.ts +51 -0
  92. package/src/parser/rules/block/collapsible/orphans.ts +31 -0
  93. package/src/parser/rules/block/collapsible/tags.ts +17 -0
  94. package/src/parser/rules/block/comment/consume.ts +37 -0
  95. package/src/parser/rules/block/{comment.ts → comment/index.ts} +12 -38
  96. package/src/parser/rules/block/{content-separator.ts → content-separator/index.ts} +5 -35
  97. package/src/parser/rules/block/content-separator/syntax.ts +33 -0
  98. package/src/parser/rules/block/definition-list/collect.ts +40 -0
  99. package/src/parser/rules/block/definition-list/index.ts +63 -0
  100. package/src/parser/rules/block/definition-list/item-key.ts +95 -0
  101. package/src/parser/rules/block/definition-list/item-value.ts +56 -0
  102. package/src/parser/rules/block/definition-list/items.ts +54 -0
  103. package/src/parser/rules/block/div/body.ts +41 -0
  104. package/src/parser/rules/block/div/close.ts +41 -0
  105. package/src/parser/rules/block/div/failed.ts +117 -0
  106. package/src/parser/rules/block/div/index.ts +112 -0
  107. package/src/parser/rules/block/div/nesting.ts +37 -0
  108. package/src/parser/rules/block/div/open.ts +59 -0
  109. package/src/parser/rules/block/div/paragraph-strip.ts +44 -0
  110. package/src/parser/rules/block/embed-block/content.ts +53 -0
  111. package/src/parser/rules/block/embed-block/index.ts +91 -0
  112. package/src/parser/rules/block/embed-block/open.ts +52 -0
  113. package/src/parser/rules/block/embed-block/tags.ts +5 -0
  114. package/src/parser/rules/block/footnoteblock/attributes.ts +73 -0
  115. package/src/parser/rules/block/footnoteblock/index.ts +82 -0
  116. package/src/parser/rules/block/footnoteblock/open.ts +53 -0
  117. package/src/parser/rules/block/heading/index.ts +87 -0
  118. package/src/parser/rules/block/heading/open.ts +50 -0
  119. package/src/parser/rules/block/heading/toc-text.ts +26 -0
  120. package/src/parser/rules/block/{horizontal-rule.ts → horizontal-rule/index.ts} +4 -21
  121. package/src/parser/rules/block/horizontal-rule/syntax.ts +21 -0
  122. package/src/parser/rules/block/html/body.ts +114 -0
  123. package/src/parser/rules/block/html/diagnostics.ts +11 -0
  124. package/src/parser/rules/block/html/index.ts +95 -0
  125. package/src/parser/rules/block/html/open.ts +36 -0
  126. package/src/parser/rules/block/iframe/attributes.ts +106 -0
  127. package/src/parser/rules/block/iframe/index.ts +73 -0
  128. package/src/parser/rules/block/iframe/open.ts +58 -0
  129. package/src/parser/rules/block/iframe/source.ts +24 -0
  130. package/src/parser/rules/block/iframe/url.ts +38 -0
  131. package/src/parser/rules/block/iftags/body.ts +48 -0
  132. package/src/parser/rules/block/iftags/condition.ts +24 -0
  133. package/src/parser/rules/block/{iftags.ts → iftags/index.ts} +16 -58
  134. package/src/parser/rules/block/include/arguments.ts +48 -0
  135. package/src/parser/rules/block/include/index.ts +75 -0
  136. package/src/parser/rules/block/include/location.ts +24 -0
  137. package/src/parser/rules/block/include/variables.ts +37 -0
  138. package/src/parser/rules/block/list/index.ts +73 -0
  139. package/src/parser/rules/block/list/line.ts +77 -0
  140. package/src/parser/rules/block/list/native.ts +89 -0
  141. package/src/parser/rules/block/math/content.ts +54 -0
  142. package/src/parser/rules/block/math/index.ts +106 -0
  143. package/src/parser/rules/block/math/name.ts +35 -0
  144. package/src/parser/rules/block/module/body.ts +92 -0
  145. package/src/parser/rules/block/module/element.ts +33 -0
  146. package/src/parser/rules/block/module/include/directive.ts +91 -0
  147. package/src/parser/rules/block/module/include/index.ts +11 -2
  148. package/src/parser/rules/block/module/include/references.ts +42 -0
  149. package/src/parser/rules/block/module/include/resolve/cache.ts +44 -0
  150. package/src/parser/rules/block/module/include/resolve/index.ts +106 -0
  151. package/src/parser/rules/block/module/include/resolve/iterate.ts +202 -0
  152. package/src/parser/rules/block/module/include/resolve/replace.ts +31 -0
  153. package/src/parser/rules/block/module/include/resolve/types.ts +105 -0
  154. package/src/parser/rules/block/module/include/scanner.ts +121 -0
  155. package/src/parser/rules/block/module/index.ts +14 -2
  156. package/src/parser/rules/block/module/listpages/compiler.ts +12 -392
  157. package/src/parser/rules/block/module/listpages/extract.ts +25 -359
  158. package/src/parser/rules/block/module/listpages/extraction/listpages.ts +42 -0
  159. package/src/parser/rules/block/module/listpages/extraction/listusers.ts +30 -0
  160. package/src/parser/rules/block/module/listpages/extraction/query.ts +51 -0
  161. package/src/parser/rules/block/module/listpages/extraction/result.ts +18 -0
  162. package/src/parser/rules/block/module/listpages/extraction/template.ts +96 -0
  163. package/src/parser/rules/block/module/listpages/extraction/variables.ts +58 -0
  164. package/src/parser/rules/block/module/listpages/normalization/date-selector.ts +53 -0
  165. package/src/parser/rules/block/module/listpages/normalization/numeric-selector.ts +32 -0
  166. package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +82 -0
  167. package/src/parser/rules/block/module/listpages/normalization/selectors.ts +2 -0
  168. package/src/parser/rules/block/module/listpages/normalization/tags-category.ts +86 -0
  169. package/src/parser/rules/block/module/listpages/normalize.ts +8 -324
  170. package/src/parser/rules/block/module/listpages/resolution/items.ts +43 -0
  171. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +42 -0
  172. package/src/parser/rules/block/module/listpages/resolve.ts +5 -75
  173. package/src/parser/rules/block/module/listpages/template/format/content.ts +41 -0
  174. package/src/parser/rules/block/module/listpages/template/format/date.ts +116 -0
  175. package/src/parser/rules/block/module/listpages/template/format/index.ts +4 -0
  176. package/src/parser/rules/block/module/listpages/template/format/tags.ts +7 -0
  177. package/src/parser/rules/block/module/listpages/template/format/user.ts +9 -0
  178. package/src/parser/rules/block/module/listpages/template/getters/index.ts +36 -0
  179. package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +60 -0
  180. package/src/parser/rules/block/module/listpages/template/getters/simple.ts +65 -0
  181. package/src/parser/rules/block/module/listpages/template/getters/types.ts +3 -0
  182. package/src/parser/rules/block/module/listpages/template/syntax.ts +97 -0
  183. package/src/parser/rules/block/module/listpages/types/data-fetcher.ts +15 -0
  184. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +52 -0
  185. package/src/parser/rules/block/module/listpages/types/external-data.ts +77 -0
  186. package/src/parser/rules/block/module/listpages/types/index.ts +17 -0
  187. package/src/parser/rules/block/module/listpages/types/normalized-query.ts +120 -0
  188. package/src/parser/rules/block/module/listpages/types/query.ts +67 -0
  189. package/src/parser/rules/block/module/listpages/types/template.ts +17 -0
  190. package/src/parser/rules/block/module/listpages/types/variables.ts +69 -0
  191. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +48 -0
  192. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +19 -0
  193. package/src/parser/rules/block/module/listpages/url-resolution/query.ts +24 -0
  194. package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +53 -0
  195. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +25 -0
  196. package/src/parser/rules/block/module/listpages/url-resolver.ts +3 -160
  197. package/src/parser/rules/block/module/listusers/compiler.ts +4 -25
  198. package/src/parser/rules/block/module/listusers/extract.ts +4 -9
  199. package/src/parser/rules/block/module/listusers/getters.ts +21 -0
  200. package/src/parser/rules/block/module/listusers/variables.ts +15 -0
  201. package/src/parser/rules/block/module/open.ts +57 -0
  202. package/src/parser/rules/block/module/resolution/contexts.ts +78 -0
  203. package/src/parser/rules/block/module/resolution/data-maps.ts +39 -0
  204. package/src/parser/rules/block/module/resolution/dynamic-modules.ts +93 -0
  205. package/src/parser/rules/block/module/resolution/styles.ts +53 -0
  206. package/src/parser/rules/block/module/resolution/walk-resolve.ts +107 -0
  207. package/src/parser/rules/block/module/resolve.ts +79 -292
  208. package/src/parser/rules/block/module/rule.ts +56 -0
  209. package/src/parser/rules/block/module/types-common.ts +11 -0
  210. package/src/parser/rules/block/module/walk/children.ts +35 -0
  211. package/src/parser/rules/block/module/walk/index.ts +9 -0
  212. package/src/parser/rules/block/module/walk/map/index.ts +2 -0
  213. package/src/parser/rules/block/module/walk/map/stateful-definition-list.ts +25 -0
  214. package/src/parser/rules/block/module/walk/map/stateful-list.ts +40 -0
  215. package/src/parser/rules/block/module/walk/map/stateful-table.ts +23 -0
  216. package/src/parser/rules/block/module/walk/map/stateful-tabs.ts +19 -0
  217. package/src/parser/rules/block/module/walk/map/stateful.ts +71 -0
  218. package/src/parser/rules/block/module/walk/map/stateless-definition-list.ts +12 -0
  219. package/src/parser/rules/block/module/walk/map/stateless-list.ts +29 -0
  220. package/src/parser/rules/block/module/walk/map/stateless-table.ts +11 -0
  221. package/src/parser/rules/block/module/walk/map/stateless-tabs.ts +5 -0
  222. package/src/parser/rules/block/module/walk/map/stateless.ts +51 -0
  223. package/src/parser/rules/block/module/walk/map/types.ts +6 -0
  224. package/src/parser/rules/block/module/walk/traverse.ts +65 -0
  225. package/src/parser/rules/block/orphan-li/content.ts +60 -0
  226. package/src/parser/rules/block/orphan-li/index.ts +75 -0
  227. package/src/parser/rules/block/orphan-li/open.ts +25 -0
  228. package/src/parser/rules/block/orphan-li/tags.ts +40 -0
  229. package/src/parser/rules/block/paragraph/content.ts +12 -0
  230. package/src/parser/rules/block/paragraph/index.ts +60 -0
  231. package/src/parser/rules/block/paragraph/normalize.ts +52 -0
  232. package/src/parser/rules/block/paragraph/span-markers.ts +52 -0
  233. package/src/parser/rules/block/parsing/attributes/index.ts +32 -0
  234. package/src/parser/rules/block/parsing/attributes/names.ts +93 -0
  235. package/src/parser/rules/block/parsing/attributes/scanner.ts +75 -0
  236. package/src/parser/rules/block/parsing/attributes/values.ts +26 -0
  237. package/src/parser/rules/block/parsing/block-item.ts +29 -0
  238. package/src/parser/rules/block/parsing/content.ts +127 -0
  239. package/src/parser/rules/block/parsing/end-condition.ts +51 -0
  240. package/src/parser/rules/block/parsing/inline-content.ts +105 -0
  241. package/src/parser/rules/block/parsing/inline-newline.ts +41 -0
  242. package/src/parser/rules/block/parsing/non-boundary.ts +24 -0
  243. package/src/parser/rules/block/parsing/rule-dispatch.ts +44 -0
  244. package/src/parser/rules/block/table/index.ts +80 -0
  245. package/src/parser/rules/block/table/pipe/cell-start.ts +69 -0
  246. package/src/parser/rules/block/table/pipe/cell.ts +106 -0
  247. package/src/parser/rules/block/table/pipe/index.ts +2 -0
  248. package/src/parser/rules/block/table/pipe/row.ts +88 -0
  249. package/src/parser/rules/block/table/pipe/tokens.ts +14 -0
  250. package/src/parser/rules/block/table/pipe/trim.ts +50 -0
  251. package/src/parser/rules/block/table-block/body.ts +79 -0
  252. package/src/parser/rules/block/table-block/cell-attributes.ts +33 -0
  253. package/src/parser/rules/block/table-block/cell-boundary.ts +99 -0
  254. package/src/parser/rules/block/table-block/cell-content/index.ts +88 -0
  255. package/src/parser/rules/block/table-block/cell-content/segments.ts +134 -0
  256. package/src/parser/rules/block/table-block/cell-newline.ts +47 -0
  257. package/src/parser/rules/block/table-block/cell.ts +64 -0
  258. package/src/parser/rules/block/table-block/index.ts +113 -0
  259. package/src/parser/rules/block/table-block/row-boundary.ts +75 -0
  260. package/src/parser/rules/block/table-block/structure.ts +80 -0
  261. package/src/parser/rules/block/tabview/body.ts +64 -0
  262. package/src/parser/rules/block/tabview/index.ts +90 -0
  263. package/src/parser/rules/block/tabview/open.ts +50 -0
  264. package/src/parser/rules/block/tabview/tab.ts +92 -0
  265. package/src/parser/rules/block/tabview/tags.ts +30 -0
  266. package/src/parser/rules/block/toc/element.ts +11 -0
  267. package/src/parser/rules/block/toc/index.ts +44 -0
  268. package/src/parser/rules/block/toc/open.ts +84 -0
  269. package/src/parser/rules/block/utils.ts +10 -610
  270. package/src/parser/rules/{utils.ts → common/attribute-safety.ts} +3 -49
  271. package/src/parser/rules/common/block-name.ts +33 -0
  272. package/src/parser/rules/common/index.ts +2 -0
  273. package/src/parser/rules/contracts/index.ts +3 -0
  274. package/src/parser/rules/contracts/parse-context.ts +38 -0
  275. package/src/parser/rules/contracts/rule.ts +43 -0
  276. package/src/parser/rules/contracts/scope.ts +31 -0
  277. package/src/parser/rules/inline/anchor/attributes.ts +54 -0
  278. package/src/parser/rules/inline/anchor/child.ts +26 -0
  279. package/src/parser/rules/inline/anchor/close.ts +34 -0
  280. package/src/parser/rules/inline/anchor/content.ts +59 -0
  281. package/src/parser/rules/inline/anchor/index.ts +103 -0
  282. package/src/parser/rules/inline/anchor/newline.ts +26 -0
  283. package/src/parser/rules/inline/anchor/open.ts +47 -0
  284. package/src/parser/rules/inline/anchor/paragraph-strip.ts +14 -0
  285. package/src/parser/rules/inline/anchor/syntax.ts +40 -0
  286. package/src/parser/rules/inline/anchor-name/index.ts +38 -0
  287. package/src/parser/rules/inline/anchor-name/name.ts +39 -0
  288. package/src/parser/rules/inline/anchor-name/syntax.ts +46 -0
  289. package/src/parser/rules/inline/bibcite/element.ts +14 -0
  290. package/src/parser/rules/inline/bibcite/index.ts +34 -0
  291. package/src/parser/rules/inline/bibcite/syntax.ts +64 -0
  292. package/src/parser/rules/inline/bold.ts +2 -39
  293. package/src/parser/rules/inline/color/index.ts +35 -0
  294. package/src/parser/rules/inline/color/syntax.ts +69 -0
  295. package/src/parser/rules/inline/comment/consume.ts +31 -0
  296. package/src/parser/rules/inline/{comment.ts → comment/index.ts} +10 -36
  297. package/src/parser/rules/inline/equation-ref/element.ts +8 -0
  298. package/src/parser/rules/inline/equation-ref/index.ts +34 -0
  299. package/src/parser/rules/inline/equation-ref/syntax.ts +45 -0
  300. package/src/parser/rules/inline/expr/branch.ts +104 -0
  301. package/src/parser/rules/inline/expr/conditional-branch.ts +27 -0
  302. package/src/parser/rules/inline/expr/conditional.ts +80 -0
  303. package/src/parser/rules/inline/expr/depth.ts +25 -0
  304. package/src/parser/rules/inline/expr/elements.ts +39 -0
  305. package/src/parser/rules/inline/expr/index.ts +84 -0
  306. package/src/parser/rules/inline/expr/syntax.ts +45 -0
  307. package/src/parser/rules/inline/footnote/child.ts +22 -0
  308. package/src/parser/rules/inline/footnote/close.ts +33 -0
  309. package/src/parser/rules/inline/footnote/content.ts +54 -0
  310. package/src/parser/rules/inline/footnote/elements.ts +38 -0
  311. package/src/parser/rules/inline/footnote/index.ts +54 -0
  312. package/src/parser/rules/inline/footnote/newline.ts +27 -0
  313. package/src/parser/rules/inline/footnote/open.ts +38 -0
  314. package/src/parser/rules/inline/formatting/container.ts +50 -0
  315. package/src/parser/rules/inline/{guillemet.ts → guillemet/index.ts} +5 -13
  316. package/src/parser/rules/inline/guillemet/text.ts +11 -0
  317. package/src/parser/rules/inline/html/gate.ts +64 -0
  318. package/src/parser/rules/inline/{html.ts → html/index.ts} +9 -60
  319. package/src/parser/rules/inline/html/open.ts +37 -0
  320. package/src/parser/rules/inline/image/attributes.ts +22 -0
  321. package/src/parser/rules/inline/image/body.ts +36 -0
  322. package/src/parser/rules/inline/image/index.ts +89 -0
  323. package/src/parser/rules/inline/image/open.ts +56 -0
  324. package/src/parser/rules/inline/image/source.ts +62 -0
  325. package/src/parser/rules/inline/image/syntax.ts +76 -0
  326. package/src/parser/rules/inline/italic.ts +2 -30
  327. package/src/parser/rules/inline/line-break/backslash.ts +58 -0
  328. package/src/parser/rules/inline/line-break/elements.ts +9 -0
  329. package/src/parser/rules/inline/line-break/index.ts +3 -0
  330. package/src/parser/rules/inline/line-break/newline.ts +82 -0
  331. package/src/parser/rules/inline/line-break/underscore.ts +45 -0
  332. package/src/parser/rules/inline/link-anchor.ts +6 -81
  333. package/src/parser/rules/inline/link-bracket/anchor.ts +3 -0
  334. package/src/parser/rules/inline/link-bracket/direct-url.ts +5 -0
  335. package/src/parser/rules/inline/link-bracket/parsed.ts +81 -0
  336. package/src/parser/rules/inline/link-bracket/parts.ts +64 -0
  337. package/src/parser/rules/inline/link-bracket/prefix.ts +15 -0
  338. package/src/parser/rules/inline/link-single.ts +7 -98
  339. package/src/parser/rules/inline/link-star.ts +7 -69
  340. package/src/parser/rules/inline/link-triple/fallback.ts +10 -0
  341. package/src/parser/rules/inline/link-triple/index.ts +62 -0
  342. package/src/parser/rules/inline/link-triple/interwiki.ts +11 -0
  343. package/src/parser/rules/inline/link-triple/label.ts +35 -0
  344. package/src/parser/rules/inline/link-triple/syntax.ts +72 -0
  345. package/src/parser/rules/inline/link-triple/target.ts +36 -0
  346. package/src/parser/rules/inline/math-inline/index.ts +40 -0
  347. package/src/parser/rules/inline/math-inline/syntax.ts +55 -0
  348. package/src/parser/rules/inline/monospace.ts +2 -30
  349. package/src/parser/rules/inline/parsing/block-boundary.ts +42 -0
  350. package/src/parser/rules/inline/parsing/block-start-predicates.ts +117 -0
  351. package/src/parser/rules/inline/parsing/collect.ts +23 -0
  352. package/src/parser/rules/inline/parsing/inline-content.ts +115 -0
  353. package/src/parser/rules/inline/parsing/paragraph-boundary.ts +47 -0
  354. package/src/parser/rules/inline/parsing/plain-text.ts +69 -0
  355. package/src/parser/rules/inline/parsing/preserved-line-break.ts +11 -0
  356. package/src/parser/rules/inline/parsing/rules.ts +34 -0
  357. package/src/parser/rules/inline/parsing/simple-token.ts +26 -0
  358. package/src/parser/rules/inline/raw/angle.ts +40 -0
  359. package/src/parser/rules/inline/raw/double-at.ts +78 -0
  360. package/src/parser/rules/inline/raw/index.ts +26 -0
  361. package/src/parser/rules/inline/raw/result.ts +26 -0
  362. package/src/parser/rules/inline/size/content.ts +65 -0
  363. package/src/parser/rules/inline/size/index.ts +55 -0
  364. package/src/parser/rules/inline/size/open.ts +43 -0
  365. package/src/parser/rules/inline/size/value.ts +45 -0
  366. package/src/parser/rules/inline/span/content.ts +97 -0
  367. package/src/parser/rules/inline/span/elements.ts +108 -0
  368. package/src/parser/rules/inline/span/index.ts +79 -0
  369. package/src/parser/rules/inline/span/newline.ts +50 -0
  370. package/src/parser/rules/inline/span/syntax.ts +70 -0
  371. package/src/parser/rules/inline/{strikethrough.ts → strikethrough/index.ts} +5 -60
  372. package/src/parser/rules/inline/strikethrough/parse.ts +14 -0
  373. package/src/parser/rules/inline/strikethrough/syntax.ts +24 -0
  374. package/src/parser/rules/inline/subscript.ts +2 -39
  375. package/src/parser/rules/inline/superscript.ts +4 -39
  376. package/src/parser/rules/inline/text/element.ts +5 -0
  377. package/src/parser/rules/inline/{text.ts → text/index.ts} +5 -4
  378. package/src/parser/rules/inline/underline/child.ts +26 -0
  379. package/src/parser/rules/inline/underline/content.ts +29 -0
  380. package/src/parser/rules/inline/{underline.ts → underline/index.ts} +6 -49
  381. package/src/parser/rules/inline/user/element.ts +11 -0
  382. package/src/parser/rules/inline/user/index.ts +34 -0
  383. package/src/parser/rules/inline/user/syntax.ts +67 -0
  384. package/src/parser/rules/inline/utils.ts +4 -344
  385. package/src/parser/rules/tokens.ts +106 -0
  386. package/src/parser/rules/types.ts +9 -252
  387. package/src/parser/depth.ts +0 -251
  388. package/src/parser/parse.ts +0 -315
  389. package/src/parser/postprocess/spanStrip.ts +0 -697
  390. package/src/parser/preprocess/expr.ts +0 -265
  391. package/src/parser/preprocess/utils.ts +0 -250
  392. package/src/parser/preprocess/whitespace.ts +0 -111
  393. package/src/parser/rules/block/align.ts +0 -282
  394. package/src/parser/rules/block/bibliography.ts +0 -359
  395. package/src/parser/rules/block/block-list.ts +0 -689
  396. package/src/parser/rules/block/blockquote.ts +0 -238
  397. package/src/parser/rules/block/code.ts +0 -187
  398. package/src/parser/rules/block/collapsible.ts +0 -337
  399. package/src/parser/rules/block/definition-list.ts +0 -270
  400. package/src/parser/rules/block/div.ts +0 -400
  401. package/src/parser/rules/block/embed-block.ts +0 -153
  402. package/src/parser/rules/block/footnoteblock.ts +0 -200
  403. package/src/parser/rules/block/heading.ts +0 -142
  404. package/src/parser/rules/block/html.ts +0 -222
  405. package/src/parser/rules/block/iframe.ts +0 -239
  406. package/src/parser/rules/block/include.ts +0 -179
  407. package/src/parser/rules/block/list.ts +0 -244
  408. package/src/parser/rules/block/math.ts +0 -183
  409. package/src/parser/rules/block/module/include/resolve.ts +0 -556
  410. package/src/parser/rules/block/module/listpages/types.ts +0 -513
  411. package/src/parser/rules/block/module/walk.ts +0 -380
  412. package/src/parser/rules/block/module.ts +0 -164
  413. package/src/parser/rules/block/orphan-li.ts +0 -177
  414. package/src/parser/rules/block/paragraph.ts +0 -157
  415. package/src/parser/rules/block/table-block.ts +0 -726
  416. package/src/parser/rules/block/table.ts +0 -441
  417. package/src/parser/rules/block/tabview.ts +0 -331
  418. package/src/parser/rules/block/toc.ts +0 -129
  419. package/src/parser/rules/inline/anchor-name.ts +0 -154
  420. package/src/parser/rules/inline/anchor.ts +0 -327
  421. package/src/parser/rules/inline/bibcite.ts +0 -153
  422. package/src/parser/rules/inline/color.ts +0 -140
  423. package/src/parser/rules/inline/equation-ref.ts +0 -115
  424. package/src/parser/rules/inline/expr.ts +0 -526
  425. package/src/parser/rules/inline/footnote.ts +0 -223
  426. package/src/parser/rules/inline/image.ts +0 -328
  427. package/src/parser/rules/inline/line-break.ts +0 -326
  428. package/src/parser/rules/inline/link-triple.ts +0 -267
  429. package/src/parser/rules/inline/math-inline.ts +0 -126
  430. package/src/parser/rules/inline/raw.ts +0 -262
  431. package/src/parser/rules/inline/size.ts +0 -244
  432. package/src/parser/rules/inline/span.ts +0 -424
  433. package/src/parser/rules/inline/user.ts +0 -147
@@ -0,0 +1,42 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { ParseFunction } from "../../types";
3
+ import type { ListPagesModuleData } from "../resolve";
4
+
5
+ export function wrapListPagesResult(
6
+ module: ListPagesModuleData,
7
+ items: Element[],
8
+ parse: ParseFunction,
9
+ ): Element[] {
10
+ if (items.length === 0) {
11
+ return [];
12
+ }
13
+
14
+ const result: Element[] = [];
15
+
16
+ if (module["prepend-line"] && !module.separate) {
17
+ const prependAst = parse(module["prepend-line"]);
18
+ result.push(...prependAst.elements);
19
+ }
20
+
21
+ result.push(...items);
22
+
23
+ if (module["append-line"] && !module.separate) {
24
+ const appendAst = parse(module["append-line"]);
25
+ result.push(...appendAst.elements);
26
+ }
27
+
28
+ if (module.wrapper) {
29
+ return [
30
+ {
31
+ element: "container",
32
+ data: {
33
+ type: "div",
34
+ attributes: { class: "list-pages-box" },
35
+ elements: result,
36
+ },
37
+ },
38
+ ];
39
+ }
40
+
41
+ return result;
42
+ }
@@ -19,8 +19,10 @@
19
19
  */
20
20
 
21
21
  import type { Element, Module } from "@wdprlib/ast";
22
- import type { ListPagesExternalData, CompiledTemplate, VariableContext } from "./types";
22
+ import type { ListPagesExternalData, CompiledTemplate } from "./types";
23
23
  import type { ParseFunction } from "../types";
24
+ import { renderListPagesItems } from "./resolution/items";
25
+ import { wrapListPagesResult } from "./resolution/wrapper";
24
26
  export type { ParseFunction };
25
27
 
26
28
  /**
@@ -53,78 +55,6 @@ export function resolveListPages(
53
55
  compiledTemplate: CompiledTemplate,
54
56
  parse: ParseFunction,
55
57
  ): Element[] {
56
- const items: Element[] = [];
57
-
58
- // Process each page
59
- for (let i = 0; i < data.pages.length; i++) {
60
- const page = data.pages[i];
61
- if (!page) continue;
62
-
63
- const ctx: VariableContext = {
64
- page,
65
- index: i + 1,
66
- total: data.totalCount,
67
- limit: module.limit,
68
- site: data.site,
69
- };
70
-
71
- // Execute compiled template
72
- const substituted = compiledTemplate(ctx);
73
-
74
- // Re-parse as wikitext
75
- const itemAst = parse(substituted);
76
-
77
- if (module.separate) {
78
- // Wrap each item in div
79
- const wrapper: Element = {
80
- element: "container",
81
- data: {
82
- type: "div",
83
- attributes: { class: "list-pages-item" },
84
- elements: itemAst.elements,
85
- },
86
- };
87
- items.push(wrapper);
88
- } else {
89
- items.push(...itemAst.elements);
90
- }
91
- }
92
-
93
- // Handle empty results
94
- if (items.length === 0) {
95
- return [];
96
- }
97
-
98
- // Build final result
99
- const result: Element[] = [];
100
-
101
- // Prepend line (only when separate=false)
102
- if (module["prepend-line"] && !module.separate) {
103
- const prependAst = parse(module["prepend-line"]);
104
- result.push(...prependAst.elements);
105
- }
106
-
107
- result.push(...items);
108
-
109
- // Append line (only when separate=false)
110
- if (module["append-line"] && !module.separate) {
111
- const appendAst = parse(module["append-line"]);
112
- result.push(...appendAst.elements);
113
- }
114
-
115
- // Wrap everything if wrapper=true
116
- if (module.wrapper) {
117
- return [
118
- {
119
- element: "container",
120
- data: {
121
- type: "div",
122
- attributes: { class: "list-pages-box" },
123
- elements: result,
124
- },
125
- },
126
- ];
127
- }
128
-
129
- return result;
58
+ const items = renderListPagesItems(module, data, compiledTemplate, parse);
59
+ return wrapListPagesResult(module, items, parse);
130
60
  }
@@ -0,0 +1,41 @@
1
+ import type { PageData } from "../../types";
2
+
3
+ /**
4
+ * Split content by ==== separators.
5
+ *
6
+ * Wikidot uses preg_split('/^([=]{4,})$/m', $source); %%content{n}%%
7
+ * references sections[n-1] (1-indexed).
8
+ */
9
+ export function splitContentSections(content: string): string[] {
10
+ return content.split(/^={4,}$/m).map((section) => section.trim());
11
+ }
12
+
13
+ /**
14
+ * Extract a summary from page content.
15
+ */
16
+ export function getSummary(page: PageData): string {
17
+ if (page.content) {
18
+ const sections = splitContentSections(page.content);
19
+ if (sections.length > 1) {
20
+ return sections[0]?.trim() ?? "";
21
+ }
22
+ }
23
+ return getFirstParagraph(page.content);
24
+ }
25
+
26
+ /**
27
+ * Extract the first paragraph from wikitext content.
28
+ */
29
+ export function getFirstParagraph(content?: string): string {
30
+ if (!content) return "";
31
+
32
+ const stripped = content
33
+ .replace(/^(\+{1,6}) (.*)/gm, "")
34
+ .replace(/^\[\[toc(\s[^\]]+)?\]\]/gim, "")
35
+ .replace(/^\[\[\/?div(\s[^\]]+)?\]\]/gim, "")
36
+ .replace(/^\[\[\/?module(\s[^\]]+)?\]\]/gim, "")
37
+ .trim();
38
+
39
+ const paragraphs = stripped.split(/\n{2,}/);
40
+ return paragraphs[0]?.trim() ?? "";
41
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Format a Date object using an optional strftime-like format string.
3
+ *
4
+ * When no format is provided, returns the ISO 8601 string representation.
5
+ */
6
+ export function formatDate(date: Date, format?: string): string {
7
+ if (!format) {
8
+ return date.toISOString();
9
+ }
10
+ if (format === "%Y-%m-%d") {
11
+ return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
12
+ }
13
+ return strftime(date, format);
14
+ }
15
+
16
+ /** Full month names for strftime `%B` token. Static to avoid per-call allocation. */
17
+ const MONTHS = [
18
+ "January",
19
+ "February",
20
+ "March",
21
+ "April",
22
+ "May",
23
+ "June",
24
+ "July",
25
+ "August",
26
+ "September",
27
+ "October",
28
+ "November",
29
+ "December",
30
+ ];
31
+ /** Abbreviated month names for strftime `%b` token. */
32
+ const MONTHS_SHORT = [
33
+ "Jan",
34
+ "Feb",
35
+ "Mar",
36
+ "Apr",
37
+ "May",
38
+ "Jun",
39
+ "Jul",
40
+ "Aug",
41
+ "Sep",
42
+ "Oct",
43
+ "Nov",
44
+ "Dec",
45
+ ];
46
+ /** Full day names for strftime `%A` token. */
47
+ const DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
48
+ /** Abbreviated day names for strftime `%a` token. */
49
+ const DAYS_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
50
+
51
+ /** Pre-compiled regex matching strftime tokens (`%X` where X is supported). */
52
+ const STRFTIME_REGEX = /%([YymdHeHIMSpbBaAwjZz%])/g;
53
+
54
+ function strftime(date: Date, format: string): string {
55
+ return format.replace(STRFTIME_REGEX, (_, token: string) => {
56
+ switch (token) {
57
+ case "Y":
58
+ return String(date.getFullYear());
59
+ case "y":
60
+ return String(date.getFullYear()).slice(-2);
61
+ case "m":
62
+ return pad2(date.getMonth() + 1);
63
+ case "d":
64
+ return pad2(date.getDate());
65
+ case "e":
66
+ return String(date.getDate());
67
+ case "H":
68
+ return pad2(date.getHours());
69
+ case "I":
70
+ return pad2(date.getHours() % 12 || 12);
71
+ case "M":
72
+ return pad2(date.getMinutes());
73
+ case "S":
74
+ return pad2(date.getSeconds());
75
+ case "p":
76
+ return date.getHours() < 12 ? "AM" : "PM";
77
+ case "b":
78
+ return MONTHS_SHORT[date.getMonth()] ?? "";
79
+ case "B":
80
+ return MONTHS[date.getMonth()] ?? "";
81
+ case "a":
82
+ return DAYS_SHORT[date.getDay()] ?? "";
83
+ case "A":
84
+ return DAYS[date.getDay()] ?? "";
85
+ case "w":
86
+ return String(date.getDay());
87
+ case "j":
88
+ return pad3(getDayOfYear(date));
89
+ case "Z":
90
+ return "UTC";
91
+ case "z":
92
+ return "+0000";
93
+ case "%":
94
+ return "%";
95
+ default:
96
+ return `%${token}`;
97
+ }
98
+ });
99
+ }
100
+
101
+ function pad2(n: number): string {
102
+ return n < 10 ? `0${n}` : String(n);
103
+ }
104
+
105
+ function pad3(n: number): string {
106
+ if (n < 10) return `00${n}`;
107
+ if (n < 100) return `0${n}`;
108
+ return String(n);
109
+ }
110
+
111
+ function getDayOfYear(date: Date): number {
112
+ const start = new Date(date.getFullYear(), 0, 0);
113
+ const diff = date.getTime() - start.getTime();
114
+ const oneDay = 1000 * 60 * 60 * 24;
115
+ return Math.floor(diff / oneDay);
116
+ }
@@ -0,0 +1,4 @@
1
+ export { formatDate } from "./date";
2
+ export { getFirstParagraph, getSummary, splitContentSections } from "./content";
3
+ export { formatTagsLinked } from "./tags";
4
+ export { formatUserLinked } from "./user";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Format an array of tags as space-separated Wikidot link syntax.
3
+ */
4
+ export function formatTagsLinked(tags: string[], prefix: string): string {
5
+ if (tags.length === 0) return "";
6
+ return tags.map((tag) => `[${prefix}${tag} ${tag}]`).join(" ");
7
+ }
@@ -0,0 +1,9 @@
1
+ import type { UserInfo } from "../../types";
2
+
3
+ /**
4
+ * Format a user as Wikidot's `[[*user name]]` inline syntax for linked display.
5
+ */
6
+ export function formatUserLinked(user?: UserInfo): string {
7
+ if (!user) return "Anonymous";
8
+ return `[[*user ${user.name}]]`;
9
+ }
@@ -0,0 +1,36 @@
1
+ import {
2
+ createBraceParamGetter,
3
+ createFormattedGetter,
4
+ createParenParamGetter,
5
+ createTagsLinkedGetter,
6
+ } from "./parameterized";
7
+ import { SIMPLE_GETTERS } from "./simple";
8
+ import type { VariableGetter } from "./types";
9
+
10
+ /**
11
+ * Create a getter function for a specific template variable.
12
+ *
13
+ * Handles all variable variants: parameterized (`{param}`), parenthesized
14
+ * (`(param)`), formatted (`|format`), and simple. Unknown variable names return
15
+ * a function that always returns an empty string, matching Wikidot's behavior.
16
+ */
17
+ export function createVariableGetter(
18
+ name: string,
19
+ braceParam?: string,
20
+ parenParam?: string,
21
+ format?: string,
22
+ ): VariableGetter {
23
+ const braceGetter = braceParam !== undefined ? createBraceParamGetter(name, braceParam) : null;
24
+ if (braceGetter) return braceGetter;
25
+
26
+ const parenGetter = parenParam !== undefined ? createParenParamGetter(name, parenParam) : null;
27
+ if (parenGetter) return parenGetter;
28
+
29
+ const formattedGetter = format !== undefined ? createFormattedGetter(name, format) : null;
30
+ if (formattedGetter) return formattedGetter;
31
+
32
+ const linkedTagsGetter = createTagsLinkedGetter(name, format);
33
+ if (linkedTagsGetter) return linkedTagsGetter;
34
+
35
+ return SIMPLE_GETTERS[name] ?? (() => "");
36
+ }
@@ -0,0 +1,60 @@
1
+ import { formatDate, formatTagsLinked, splitContentSections } from "../format";
2
+ import type { VariableGetter } from "./types";
3
+
4
+ export function createBraceParamGetter(name: string, param: string): VariableGetter | null {
5
+ switch (name) {
6
+ case "content": {
7
+ const idx = Number(param) - 1;
8
+ return (ctx) => {
9
+ if (!ctx.page.content) return "";
10
+ const sections = splitContentSections(ctx.page.content);
11
+ return sections[idx] ?? "";
12
+ };
13
+ }
14
+ case "form_data":
15
+ return (ctx) => ctx.page.formData?.[param] ?? "";
16
+ case "form_raw":
17
+ return (ctx) => ctx.page.formRaw?.[param] ?? "";
18
+ case "form_label":
19
+ return (ctx) => ctx.page.formLabel?.[param] ?? "";
20
+ case "form_hint":
21
+ return (ctx) => ctx.page.formHint?.[param] ?? "";
22
+ default:
23
+ return null;
24
+ }
25
+ }
26
+
27
+ export function createParenParamGetter(name: string, param: string): VariableGetter | null {
28
+ if (name !== "preview") return null;
29
+
30
+ const len = Number(param);
31
+ return (ctx) => (ctx.page.content ?? "").slice(0, len);
32
+ }
33
+
34
+ export function createFormattedGetter(name: string, format: string): VariableGetter | null {
35
+ switch (name) {
36
+ case "created_at":
37
+ return (ctx) => formatDate(ctx.page.createdAt, format);
38
+ case "updated_at":
39
+ return (ctx) => formatDate(ctx.page.updatedAt, format);
40
+ case "commented_at":
41
+ return (ctx) => (ctx.page.commentedAt ? formatDate(ctx.page.commentedAt, format) : "");
42
+ default:
43
+ return null;
44
+ }
45
+ }
46
+
47
+ export function createTagsLinkedGetter(
48
+ name: string,
49
+ format: string | undefined,
50
+ ): VariableGetter | null {
51
+ if (name === "tags_linked") {
52
+ const prefix = format ?? "/system:page-tags/tag/";
53
+ return (ctx) => formatTagsLinked(ctx.page.tags, prefix);
54
+ }
55
+ if (name === "_tags_linked") {
56
+ const prefix = format ?? "/system:page-tags/tag/";
57
+ return (ctx) => formatTagsLinked(ctx.page.hiddenTags, prefix);
58
+ }
59
+ return null;
60
+ }
@@ -0,0 +1,65 @@
1
+ import { formatDate, formatUserLinked, getFirstParagraph, getSummary } from "../format";
2
+ import type { VariableGetter } from "./types";
3
+
4
+ /** Default character count for `%%preview%%` when no length is specified (Wikidot default). */
5
+ const DEFAULT_PREVIEW_LENGTH = 200;
6
+
7
+ export const SIMPLE_GETTERS: Record<string, VariableGetter> = {
8
+ created_at: (ctx) => formatDate(ctx.page.createdAt),
9
+ created_by: (ctx) => ctx.page.createdBy?.name ?? "Anonymous",
10
+ created_by_unix: (ctx) => ctx.page.createdBy?.unixName ?? "",
11
+ created_by_id: (ctx) => String(ctx.page.createdBy?.id ?? 0),
12
+ created_by_linked: (ctx) => formatUserLinked(ctx.page.createdBy),
13
+
14
+ updated_at: (ctx) => formatDate(ctx.page.updatedAt),
15
+ updated_by: (ctx) => ctx.page.updatedBy?.name ?? "Anonymous",
16
+ updated_by_unix: (ctx) => ctx.page.updatedBy?.unixName ?? "",
17
+ updated_by_id: (ctx) => String(ctx.page.updatedBy?.id ?? 0),
18
+ updated_by_linked: (ctx) => formatUserLinked(ctx.page.updatedBy),
19
+
20
+ commented_at: (ctx) => (ctx.page.commentedAt ? formatDate(ctx.page.commentedAt) : ""),
21
+ commented_by: (ctx) => ctx.page.commentedBy?.name ?? "",
22
+ commented_by_unix: (ctx) => ctx.page.commentedBy?.unixName ?? "",
23
+ commented_by_id: (ctx) => String(ctx.page.commentedBy?.id ?? 0),
24
+ commented_by_linked: (ctx) => formatUserLinked(ctx.page.commentedBy),
25
+
26
+ name: (ctx) => ctx.page.name,
27
+ category: (ctx) => ctx.page.category,
28
+ fullname: (ctx) => ctx.page.fullname,
29
+ title: (ctx) => ctx.page.title,
30
+ title_linked: (ctx) => `[[[${ctx.page.fullname} | ${ctx.page.title}]]]`,
31
+ link: (ctx) => `https://${ctx.site.domain}/${ctx.page.fullname}`,
32
+
33
+ parent_name: (ctx) => ctx.page.parentName ?? "",
34
+ parent_category: (ctx) => ctx.page.parentCategory ?? "",
35
+ parent_fullname: (ctx) => ctx.page.parentFullname ?? "",
36
+ parent_title: (ctx) => ctx.page.parentTitle ?? "",
37
+ parent_title_linked: (ctx) =>
38
+ ctx.page.parentFullname ? `[[[${ctx.page.parentFullname} | ${ctx.page.parentTitle}]]]` : "",
39
+
40
+ content: (ctx) => ctx.page.content ?? "",
41
+ preview: (ctx) => (ctx.page.content ?? "").slice(0, DEFAULT_PREVIEW_LENGTH),
42
+ summary: (ctx) => getSummary(ctx.page),
43
+ first_paragraph: (ctx) => getFirstParagraph(ctx.page.content),
44
+
45
+ tags: (ctx) => ctx.page.tags.join(" "),
46
+ _tags: (ctx) => ctx.page.hiddenTags.join(" "),
47
+
48
+ children: (ctx) => String(ctx.page.children),
49
+ comments: (ctx) => String(ctx.page.comments),
50
+ size: (ctx) => String(ctx.page.size),
51
+ rating: (ctx) => String(ctx.page.rating),
52
+ rating_votes: (ctx) => String(ctx.page.ratingVotes),
53
+ rating_percent: (ctx) => String(ctx.page.ratingPercent ?? 0),
54
+ revisions: (ctx) => String(ctx.page.revisions),
55
+
56
+ index: (ctx) => String(ctx.index),
57
+ total: (ctx) => String(ctx.total),
58
+ limit: (ctx) => (ctx.limit !== undefined ? String(ctx.limit) : ""),
59
+ total_or_limit: (ctx) =>
60
+ String(ctx.limit !== undefined ? Math.min(ctx.total, ctx.limit) : ctx.total),
61
+
62
+ site_title: (ctx) => ctx.site.title,
63
+ site_name: (ctx) => ctx.site.name,
64
+ site_domain: (ctx) => ctx.site.domain,
65
+ };
@@ -0,0 +1,3 @@
1
+ import type { VariableContext } from "../../types";
2
+
3
+ export type VariableGetter = (ctx: VariableContext) => string;
@@ -0,0 +1,97 @@
1
+ export interface TemplateVariableMatch {
2
+ raw: string;
3
+ index: number;
4
+ name: string;
5
+ braceParam?: string;
6
+ parenParam?: string;
7
+ format?: string;
8
+ }
9
+
10
+ /**
11
+ * Scans ListPages template variables without a backtracking regex.
12
+ *
13
+ * Supported syntax:
14
+ * - `%%name%%`
15
+ * - `%%name{param}%%`
16
+ * - `%%name(param)%%`
17
+ * - `%%name|format%%`
18
+ */
19
+ export function scanTemplateVariables(template: string): TemplateVariableMatch[] {
20
+ const matches: TemplateVariableMatch[] = [];
21
+ let searchFrom = 0;
22
+
23
+ while (searchFrom < template.length) {
24
+ const start = template.indexOf("%%", searchFrom);
25
+ if (start === -1) break;
26
+
27
+ const contentStart = start + 2;
28
+ const end = template.indexOf("%%", contentStart);
29
+ if (end === -1) break;
30
+
31
+ const parsed = parseTemplateVariableContent(template.slice(contentStart, end));
32
+ if (parsed !== null) {
33
+ matches.push({
34
+ raw: template.slice(start, end + 2),
35
+ index: start,
36
+ ...parsed,
37
+ });
38
+ }
39
+
40
+ searchFrom = end + 2;
41
+ }
42
+
43
+ return matches;
44
+ }
45
+
46
+ function parseTemplateVariableContent(
47
+ content: string,
48
+ ): Omit<TemplateVariableMatch, "raw" | "index"> | null {
49
+ let cursor = 0;
50
+ while (cursor < content.length && isVariableNameChar(content[cursor]!)) {
51
+ cursor++;
52
+ }
53
+ if (cursor === 0) return null;
54
+
55
+ const name = content.slice(0, cursor);
56
+ let braceParam: string | undefined;
57
+ let parenParam: string | undefined;
58
+ let format: string | undefined;
59
+
60
+ if (content[cursor] === "{") {
61
+ const close = content.indexOf("}", cursor + 1);
62
+ if (close === -1) return null;
63
+ braceParam = content.slice(cursor + 1, close);
64
+ cursor = close + 1;
65
+ }
66
+
67
+ if (content[cursor] === "(") {
68
+ const close = content.indexOf(")", cursor + 1);
69
+ if (close === -1) return null;
70
+ const value = content.slice(cursor + 1, close);
71
+ if (!isDigits(value)) return null;
72
+ parenParam = value;
73
+ cursor = close + 1;
74
+ }
75
+
76
+ if (content[cursor] === "|") {
77
+ format = content.slice(cursor + 1);
78
+ cursor = content.length;
79
+ }
80
+
81
+ if (cursor !== content.length) return null;
82
+ return { name, braceParam, parenParam, format };
83
+ }
84
+
85
+ function isVariableNameChar(char: string): boolean {
86
+ const code = char.charCodeAt(0);
87
+ return (code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a) || char === "_";
88
+ }
89
+
90
+ function isDigits(value: string): boolean {
91
+ if (value.length === 0) return false;
92
+ for (const char of value) {
93
+ const code = char.charCodeAt(0);
94
+ if (code < 0x30 || code > 0x39) return false;
95
+ }
96
+ return true;
97
+ }
@@ -0,0 +1,15 @@
1
+ import type { ListPagesDataRequirement } from "./data-requirements";
2
+ import type { ListPagesExternalData } from "./external-data";
3
+ import type { NormalizedListPagesQuery } from "./normalized-query";
4
+
5
+ /**
6
+ * Callback to fetch data for a ListPages module.
7
+ *
8
+ * Called by resolveModules for each ListPages module in the AST. Receives a
9
+ * normalized query with all `@URL` parameters resolved. Return null/undefined
10
+ * to skip the module.
11
+ */
12
+ export type ListPagesDataFetcher = (
13
+ query: NormalizedListPagesQuery,
14
+ requirement: ListPagesDataRequirement,
15
+ ) => ListPagesExternalData | null | undefined | Promise<ListPagesExternalData | null | undefined>;
@@ -0,0 +1,52 @@
1
+ import type { ListUsersDataRequirement } from "../../listusers/types";
2
+ import type { ListPagesQuery } from "./query";
3
+ import type { ListPagesVariable } from "./variables";
4
+
5
+ /**
6
+ * Data requirement for a single ListPages module.
7
+ */
8
+ export interface ListPagesDataRequirement {
9
+ /** Unique identifier for this module instance */
10
+ id: number;
11
+
12
+ /** Query parameters */
13
+ query: ListPagesQuery;
14
+
15
+ /** Variables used in the template */
16
+ neededVariables: ListPagesVariable[];
17
+
18
+ /** Indices needed for content{n} */
19
+ contentSectionIndices?: number[];
20
+
21
+ /** Lengths needed for preview(n) */
22
+ previewLengths?: number[];
23
+
24
+ /** Field names needed for form_data{field} etc. */
25
+ formFields?: string[];
26
+
27
+ /** Prefix for tags_linked|prefix */
28
+ tagsLinkPrefix?: string;
29
+
30
+ /** Prefix for _tags_linked|prefix */
31
+ hiddenTagsLinkPrefix?: string;
32
+
33
+ /**
34
+ * URL attribute prefix for multiple ListPages modules.
35
+ * When set, URL parameters are prefixed, e.g. "page2" -> "/page2_limit/1".
36
+ */
37
+ urlAttrPrefix?: string;
38
+
39
+ /**
40
+ * Raw attribute values before URL resolution.
41
+ * Contains original string values that may include "@URL" or "@URL|default".
42
+ */
43
+ rawAttributes: Record<string, string>;
44
+ }
45
+
46
+ /**
47
+ * All data requirements from parsing.
48
+ */
49
+ export interface DataRequirements {
50
+ listPages: ListPagesDataRequirement[];
51
+ listUsers: ListUsersDataRequirement[];
52
+ }