@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,43 @@
1
+ import type { Element } from "@wdprlib/ast";
2
+ import type { CompiledTemplate, ListPagesExternalData, VariableContext } from "../types";
3
+ import type { ParseFunction } from "../../types";
4
+ import type { ListPagesModuleData } from "../resolve";
5
+
6
+ export function renderListPagesItems(
7
+ module: ListPagesModuleData,
8
+ data: ListPagesExternalData,
9
+ compiledTemplate: CompiledTemplate,
10
+ parse: ParseFunction,
11
+ ): Element[] {
12
+ const items: Element[] = [];
13
+
14
+ for (let i = 0; i < data.pages.length; i++) {
15
+ const page = data.pages[i];
16
+ if (!page) continue;
17
+
18
+ const ctx: VariableContext = {
19
+ page,
20
+ index: i + 1,
21
+ total: data.totalCount,
22
+ limit: module.limit,
23
+ site: data.site,
24
+ };
25
+
26
+ const itemAst = parse(compiledTemplate(ctx));
27
+
28
+ if (module.separate) {
29
+ items.push({
30
+ element: "container",
31
+ data: {
32
+ type: "div",
33
+ attributes: { class: "list-pages-item" },
34
+ elements: itemAst.elements,
35
+ },
36
+ });
37
+ } else {
38
+ items.push(...itemAst.elements);
39
+ }
40
+ }
41
+
42
+ return items;
43
+ }
@@ -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
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ *
3
+ * ListPages module resolution (phase 3 of the ListPages lifecycle).
4
+ *
5
+ * After the application has fetched page data based on the extracted requirements,
6
+ * this module substitutes that data into the pre-compiled templates and re-parses
7
+ * the resulting wikitext to produce final AST elements.
8
+ *
9
+ * For each page in the fetched data:
10
+ * 1. Build a `VariableContext` with page data, index, total count, and site info
11
+ * 2. Execute the compiled template to produce a wikitext string
12
+ * 3. Re-parse the wikitext string into AST elements
13
+ * 4. Optionally wrap each item in a `div.list-pages-item` (when `separate=true`)
14
+ *
15
+ * The final result may also include prepend/append lines and be wrapped in a
16
+ * `div.list-pages-box` (when `wrapper=true`).
17
+ *
18
+ * @module
19
+ */
20
+
21
+ import type { Element, Module } from "@wdprlib/ast";
22
+ import type { ListPagesExternalData, CompiledTemplate } from "./types";
23
+ import type { ParseFunction } from "../types";
24
+ import { renderListPagesItems } from "./resolution/items";
25
+ import { wrapListPagesResult } from "./resolution/wrapper";
26
+ export type { ParseFunction };
27
+
28
+ /**
29
+ * Narrowed type for the list-pages variant of the Module discriminated union.
30
+ */
31
+ export type ListPagesModuleData = Extract<Module, { module: "list-pages" }>;
32
+
33
+ /**
34
+ * Type guard to check if a Module is a list-pages module.
35
+ *
36
+ * @param module - A Module discriminated union value
37
+ * @returns true if the module is a list-pages module
38
+ */
39
+ export function isListPagesModule(module: Module): module is ListPagesModuleData {
40
+ return module.module === "list-pages";
41
+ }
42
+
43
+ /**
44
+ * Resolve a single ListPages module
45
+ *
46
+ * @param module - ListPages module data from AST
47
+ * @param data - External data fetched for this module
48
+ * @param compiledTemplate - Pre-compiled template function
49
+ * @param parse - Parser function for re-parsing templates
50
+ * @returns Resolved elements
51
+ */
52
+ export function resolveListPages(
53
+ module: ListPagesModuleData,
54
+ data: ListPagesExternalData,
55
+ compiledTemplate: CompiledTemplate,
56
+ parse: ParseFunction,
57
+ ): Element[] {
58
+ const items = renderListPagesItems(module, data, compiledTemplate, parse);
59
+ return wrapListPagesResult(module, items, parse);
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
+ }