@wdprlib/parser 3.1.2 → 3.2.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 (124) hide show
  1. package/dist/index.cjs +295 -118
  2. package/dist/index.js +272 -95
  3. package/package.json +5 -3
  4. package/src/index.ts +163 -0
  5. package/src/lexer/index.ts +20 -0
  6. package/src/lexer/lexer.ts +687 -0
  7. package/src/lexer/tokens.ts +141 -0
  8. package/src/parser/constants.ts +173 -0
  9. package/src/parser/depth.ts +251 -0
  10. package/src/parser/index.ts +18 -0
  11. package/src/parser/parse.ts +315 -0
  12. package/src/parser/postprocess/divAdjacentParagraph.ts +76 -0
  13. package/src/parser/postprocess/index.ts +15 -0
  14. package/src/parser/postprocess/spanStrip.ts +697 -0
  15. package/src/parser/preprocess/expr.ts +265 -0
  16. package/src/parser/preprocess/index.ts +38 -0
  17. package/src/parser/preprocess/typography.ts +67 -0
  18. package/src/parser/preprocess/utils.ts +250 -0
  19. package/src/parser/preprocess/whitespace.ts +111 -0
  20. package/src/parser/rules/block/align.ts +282 -0
  21. package/src/parser/rules/block/bibliography.ts +359 -0
  22. package/src/parser/rules/block/block-list.ts +689 -0
  23. package/src/parser/rules/block/blockquote.ts +238 -0
  24. package/src/parser/rules/block/center.ts +87 -0
  25. package/src/parser/rules/block/clear-float.ts +75 -0
  26. package/src/parser/rules/block/code.ts +187 -0
  27. package/src/parser/rules/block/collapsible.ts +337 -0
  28. package/src/parser/rules/block/comment.ts +73 -0
  29. package/src/parser/rules/block/content-separator.ts +79 -0
  30. package/src/parser/rules/block/definition-list.ts +270 -0
  31. package/src/parser/rules/block/div.ts +400 -0
  32. package/src/parser/rules/block/embed-block.ts +153 -0
  33. package/src/parser/rules/block/footnoteblock.ts +200 -0
  34. package/src/parser/rules/block/heading.ts +142 -0
  35. package/src/parser/rules/block/horizontal-rule.ts +61 -0
  36. package/src/parser/rules/block/html.ts +222 -0
  37. package/src/parser/rules/block/iframe.ts +239 -0
  38. package/src/parser/rules/block/iftags.ts +150 -0
  39. package/src/parser/rules/block/include.ts +179 -0
  40. package/src/parser/rules/block/index.ts +127 -0
  41. package/src/parser/rules/block/list.ts +244 -0
  42. package/src/parser/rules/block/math.ts +183 -0
  43. package/src/parser/rules/block/module/backlinks/index.ts +31 -0
  44. package/src/parser/rules/block/module/backlinks/types.ts +21 -0
  45. package/src/parser/rules/block/module/categories/index.ts +34 -0
  46. package/src/parser/rules/block/module/categories/types.ts +21 -0
  47. package/src/parser/rules/block/module/css/index.ts +37 -0
  48. package/src/parser/rules/block/module/iftags/condition.ts +109 -0
  49. package/src/parser/rules/block/module/iftags/index.ts +26 -0
  50. package/src/parser/rules/block/module/iftags/preprocess.ts +140 -0
  51. package/src/parser/rules/block/module/iftags/resolve.ts +73 -0
  52. package/src/parser/rules/block/module/iftags/types.ts +63 -0
  53. package/src/parser/rules/block/module/include/index.ts +20 -0
  54. package/src/parser/rules/block/module/include/resolve.ts +556 -0
  55. package/src/parser/rules/block/module/index.ts +122 -0
  56. package/src/parser/rules/block/module/join/index.ts +34 -0
  57. package/src/parser/rules/block/module/join/types.ts +23 -0
  58. package/src/parser/rules/block/module/listpages/compiler.ts +453 -0
  59. package/src/parser/rules/block/module/listpages/extract.ts +410 -0
  60. package/src/parser/rules/block/module/listpages/index.ts +83 -0
  61. package/src/parser/rules/block/module/listpages/normalize.ts +390 -0
  62. package/src/parser/rules/block/module/listpages/parser.ts +106 -0
  63. package/src/parser/rules/block/module/listpages/resolve.ts +130 -0
  64. package/src/parser/rules/block/module/listpages/types.ts +513 -0
  65. package/src/parser/rules/block/module/listpages/url-resolver.ts +186 -0
  66. package/src/parser/rules/block/module/listusers/compiler.ts +77 -0
  67. package/src/parser/rules/block/module/listusers/extract.ts +45 -0
  68. package/src/parser/rules/block/module/listusers/index.ts +36 -0
  69. package/src/parser/rules/block/module/listusers/parser.ts +54 -0
  70. package/src/parser/rules/block/module/listusers/resolve.ts +58 -0
  71. package/src/parser/rules/block/module/listusers/types.ts +93 -0
  72. package/src/parser/rules/block/module/mapping.ts +61 -0
  73. package/src/parser/rules/block/module/page-tree/index.ts +38 -0
  74. package/src/parser/rules/block/module/page-tree/types.ts +29 -0
  75. package/src/parser/rules/block/module/rate/index.ts +28 -0
  76. package/src/parser/rules/block/module/rate/types.ts +19 -0
  77. package/src/parser/rules/block/module/resolve.ts +411 -0
  78. package/src/parser/rules/block/module/types-common.ts +59 -0
  79. package/src/parser/rules/block/module/types.ts +61 -0
  80. package/src/parser/rules/block/module/utils.ts +43 -0
  81. package/src/parser/rules/block/module/walk.ts +380 -0
  82. package/src/parser/rules/block/module.ts +164 -0
  83. package/src/parser/rules/block/orphan-li.ts +177 -0
  84. package/src/parser/rules/block/paragraph.ts +157 -0
  85. package/src/parser/rules/block/table-block.ts +726 -0
  86. package/src/parser/rules/block/table.ts +441 -0
  87. package/src/parser/rules/block/tabview.ts +331 -0
  88. package/src/parser/rules/block/toc.ts +129 -0
  89. package/src/parser/rules/block/utils.ts +615 -0
  90. package/src/parser/rules/index.ts +49 -0
  91. package/src/parser/rules/inline/anchor-name.ts +154 -0
  92. package/src/parser/rules/inline/anchor.ts +327 -0
  93. package/src/parser/rules/inline/bibcite.ts +153 -0
  94. package/src/parser/rules/inline/bold.ts +86 -0
  95. package/src/parser/rules/inline/color.ts +140 -0
  96. package/src/parser/rules/inline/comment.ts +90 -0
  97. package/src/parser/rules/inline/equation-ref.ts +115 -0
  98. package/src/parser/rules/inline/expr.ts +526 -0
  99. package/src/parser/rules/inline/footnote.ts +223 -0
  100. package/src/parser/rules/inline/guillemet.ts +64 -0
  101. package/src/parser/rules/inline/html.ts +132 -0
  102. package/src/parser/rules/inline/image.ts +328 -0
  103. package/src/parser/rules/inline/index.ts +150 -0
  104. package/src/parser/rules/inline/italic.ts +74 -0
  105. package/src/parser/rules/inline/line-break.ts +326 -0
  106. package/src/parser/rules/inline/link-anchor.ts +147 -0
  107. package/src/parser/rules/inline/link-single.ts +164 -0
  108. package/src/parser/rules/inline/link-star.ts +134 -0
  109. package/src/parser/rules/inline/link-triple.ts +267 -0
  110. package/src/parser/rules/inline/math-inline.ts +126 -0
  111. package/src/parser/rules/inline/monospace.ts +78 -0
  112. package/src/parser/rules/inline/raw.ts +262 -0
  113. package/src/parser/rules/inline/size.ts +244 -0
  114. package/src/parser/rules/inline/span.ts +424 -0
  115. package/src/parser/rules/inline/strikethrough.ts +115 -0
  116. package/src/parser/rules/inline/subscript.ts +84 -0
  117. package/src/parser/rules/inline/superscript.ts +84 -0
  118. package/src/parser/rules/inline/text.ts +84 -0
  119. package/src/parser/rules/inline/underline.ts +127 -0
  120. package/src/parser/rules/inline/user.ts +147 -0
  121. package/src/parser/rules/inline/utils.ts +344 -0
  122. package/src/parser/rules/types.ts +252 -0
  123. package/src/parser/rules/utils.ts +155 -0
  124. package/src/parser/toc.ts +130 -0
package/dist/index.cjs CHANGED
@@ -31,7 +31,7 @@ var __export = (target, all) => {
31
31
  var exports_src = {};
32
32
  __export(exports_src, {
33
33
  tokenize: () => tokenize,
34
- text: () => import_ast5.text,
34
+ text: () => import_ast6.text,
35
35
  resolveModules: () => resolveModules,
36
36
  resolveListUsers: () => resolveListUsers,
37
37
  resolveIncludesAsync: () => resolveIncludesAsync,
@@ -44,35 +44,35 @@ __export(exports_src, {
44
44
  parseDateSelector: () => parseDateSelector,
45
45
  parseCategory: () => parseCategory,
46
46
  parse: () => parse,
47
- paragraph: () => import_ast5.paragraph,
47
+ paragraph: () => import_ast6.paragraph,
48
48
  normalizeQuery: () => normalizeQuery,
49
- listItemSubList: () => import_ast5.listItemSubList,
50
- listItemElements: () => import_ast5.listItemElements,
51
- list: () => import_ast5.list,
52
- link: () => import_ast5.link,
53
- lineBreak: () => import_ast5.lineBreak,
54
- italics: () => import_ast5.italics,
49
+ listItemSubList: () => import_ast6.listItemSubList,
50
+ listItemElements: () => import_ast6.listItemElements,
51
+ list: () => import_ast6.list,
52
+ link: () => import_ast6.link,
53
+ lineBreak: () => import_ast6.lineBreak,
54
+ italics: () => import_ast6.italics,
55
55
  isListUsersModule: () => isListUsersModule2,
56
- horizontalRule: () => import_ast5.horizontalRule,
57
- heading: () => import_ast5.heading,
56
+ horizontalRule: () => import_ast6.horizontalRule,
57
+ heading: () => import_ast6.heading,
58
58
  extractListUsersVariables: () => extractListUsersVariables,
59
59
  extractDataRequirements: () => extractDataRequirements,
60
60
  createToken: () => createToken,
61
- createSettings: () => import_ast6.createSettings,
62
- createPosition: () => import_ast5.createPosition,
63
- createPoint: () => import_ast5.createPoint,
64
- container: () => import_ast5.container,
61
+ createSettings: () => import_ast7.createSettings,
62
+ createPosition: () => import_ast6.createPosition,
63
+ createPoint: () => import_ast6.createPoint,
64
+ container: () => import_ast6.container,
65
65
  compileTemplate: () => compileTemplate,
66
66
  compileListUsersTemplate: () => compileListUsersTemplate,
67
- bold: () => import_ast5.bold,
68
- STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
67
+ bold: () => import_ast6.bold,
68
+ STYLE_SLOT_PREFIX: () => import_ast5.STYLE_SLOT_PREFIX,
69
69
  Parser: () => Parser,
70
70
  Lexer: () => Lexer,
71
- DEFAULT_SETTINGS: () => import_ast6.DEFAULT_SETTINGS
71
+ DEFAULT_SETTINGS: () => import_ast7.DEFAULT_SETTINGS
72
72
  });
73
73
  module.exports = __toCommonJS(exports_src);
74
- var import_ast5 = require("@wdprlib/ast");
75
74
  var import_ast6 = require("@wdprlib/ast");
75
+ var import_ast7 = require("@wdprlib/ast");
76
76
 
77
77
  // packages/parser/src/lexer/tokens.ts
78
78
  function createToken(type, value, position, lineStart = false) {
@@ -582,7 +582,7 @@ function preprocess(text) {
582
582
  }
583
583
 
584
584
  // packages/parser/src/parser/parse.ts
585
- var import_ast2 = require("@wdprlib/ast");
585
+ var import_ast3 = require("@wdprlib/ast");
586
586
 
587
587
  // packages/parser/src/parser/rules/types.ts
588
588
  function currentToken(ctx) {
@@ -9134,6 +9134,8 @@ function parseTagCondition(condition) {
9134
9134
  const required = [];
9135
9135
  const forbidden = [];
9136
9136
  const optional = [];
9137
+ let hasEmptyRequired = false;
9138
+ let hasEmptyForbidden = false;
9137
9139
  const parts = condition.trim().split(/\s+/);
9138
9140
  for (const part of parts) {
9139
9141
  if (!part)
@@ -9142,20 +9144,31 @@ function parseTagCondition(condition) {
9142
9144
  const tag = part.slice(1);
9143
9145
  if (tag)
9144
9146
  required.push(tag);
9147
+ else
9148
+ hasEmptyRequired = true;
9145
9149
  } else if (part.startsWith("-")) {
9146
9150
  const tag = part.slice(1);
9147
9151
  if (tag)
9148
9152
  forbidden.push(tag);
9153
+ else
9154
+ hasEmptyForbidden = true;
9149
9155
  } else {
9150
9156
  optional.push(part);
9151
9157
  }
9152
9158
  }
9153
- return { required, forbidden, optional };
9159
+ return { required, forbidden, optional, hasEmptyRequired, hasEmptyForbidden };
9154
9160
  }
9155
9161
  function evaluateTagCondition(condition, pageTags) {
9156
- if (condition.required.length === 0 && condition.forbidden.length === 0 && condition.optional.length === 0) {
9162
+ const noNamedTokens = condition.required.length === 0 && condition.forbidden.length === 0 && condition.optional.length === 0;
9163
+ if (noNamedTokens && !condition.hasEmptyRequired && !condition.hasEmptyForbidden) {
9164
+ return false;
9165
+ }
9166
+ if (condition.hasEmptyRequired) {
9157
9167
  return false;
9158
9168
  }
9169
+ if (condition.hasEmptyForbidden && noNamedTokens) {
9170
+ return true;
9171
+ }
9159
9172
  const tagSet = new Set(pageTags);
9160
9173
  for (const tag of condition.required) {
9161
9174
  if (!tagSet.has(tag)) {
@@ -9175,19 +9188,10 @@ function evaluateTagCondition(condition, pageTags) {
9175
9188
  return true;
9176
9189
  }
9177
9190
 
9178
- // packages/parser/src/parser/rules/block/module/iftags/preprocess.ts
9179
- var BASE_PLACEHOLDER_OPEN = "";
9180
- var BASE_PLACEHOLDER_CLOSE = "";
9181
- var INNERMOST_IFTAGS_PATTERN = /\[\[\s*iftags\b([^\]]*)\]\]((?:(?!\[\[\s*iftags\b|\[\[\/\s*iftags\s*\]\]).)*)\[\[\/\s*iftags\s*\]\]/gis;
9191
+ // packages/parser/src/parser/preprocess/utils.ts
9192
+ var BASE_PLACEHOLDER_OPEN = "";
9193
+ var BASE_PLACEHOLDER_CLOSE = "";
9182
9194
  var RAW_BLOCK_OPEN_PATTERN = /\[\[\s*(code|html)\b[^\]]*\]\]/iy;
9183
- function preprocessIftags(source, pageTags) {
9184
- if (!source.includes("[["))
9185
- return source;
9186
- const sentinels = makeUniqueSentinels(source);
9187
- const { masked, placeholders } = maskRawRegions(source, sentinels);
9188
- const reduced = reduceIftags(masked, pageTags);
9189
- return restorePlaceholders(reduced, placeholders, sentinels);
9190
- }
9191
9195
  function makeUniqueSentinels(source) {
9192
9196
  let open = BASE_PLACEHOLDER_OPEN;
9193
9197
  let close = BASE_PLACEHOLDER_CLOSE;
@@ -9197,46 +9201,91 @@ function makeUniqueSentinels(source) {
9197
9201
  }
9198
9202
  return { open, close };
9199
9203
  }
9200
- function reduceIftags(source, pageTags) {
9201
- let current = source;
9202
- const maxIterations = source.length + 1;
9203
- const tagSet = pageTags ?? [];
9204
- for (let i = 0;i < maxIterations; i++) {
9205
- const depths = pageTags === null ? computeBracketDepths(current) : null;
9206
- let changed = false;
9207
- const next = current.replace(INNERMOST_IFTAGS_PATTERN, (match, cond, body, offset) => {
9208
- if (depths !== null && depths[offset] === 0) {
9209
- return match;
9204
+ function maskRawRegions(source, sentinels) {
9205
+ const placeholders = [];
9206
+ let masked = "";
9207
+ let i = 0;
9208
+ while (i < source.length) {
9209
+ if (source[i] === "[" && source[i + 1] === "[") {
9210
+ RAW_BLOCK_OPEN_PATTERN.lastIndex = i;
9211
+ const openMatch = RAW_BLOCK_OPEN_PATTERN.exec(source);
9212
+ if (openMatch) {
9213
+ const name = openMatch[1].toLowerCase();
9214
+ const openLen = openMatch[0].length;
9215
+ const closePattern = new RegExp(`\\[\\[\\/\\s*${name}\\s*\\]\\]`, "ig");
9216
+ closePattern.lastIndex = i + openLen;
9217
+ const closeMatch = closePattern.exec(source);
9218
+ if (closeMatch) {
9219
+ const regionEnd = closeMatch.index + closeMatch[0].length;
9220
+ masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9221
+ i = regionEnd;
9222
+ continue;
9223
+ }
9224
+ if (name === "code") {
9225
+ masked += pushPlaceholder(placeholders, source.slice(i), sentinels);
9226
+ i = source.length;
9227
+ continue;
9228
+ }
9210
9229
  }
9211
- changed = true;
9212
- const condition = parseTagCondition(cond);
9213
- return evaluateTagCondition(condition, tagSet) ? body : "";
9214
- });
9215
- if (!changed)
9216
- return current;
9217
- current = next;
9230
+ }
9231
+ if (source[i] === "@" && source[i + 1] === "<") {
9232
+ const close = source.indexOf(">@", i + 2);
9233
+ const newline = source.indexOf(`
9234
+ `, i + 2);
9235
+ if (close !== -1 && (newline === -1 || close < newline)) {
9236
+ const regionEnd = close + 2;
9237
+ masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9238
+ i = regionEnd;
9239
+ continue;
9240
+ }
9241
+ }
9242
+ if (source[i] === "@" && source[i + 1] === "@") {
9243
+ const close = source.indexOf("@@", i + 2);
9244
+ const newline = source.indexOf(`
9245
+ `, i + 2);
9246
+ if (close !== -1 && (newline === -1 || close < newline)) {
9247
+ const regionEnd = close + 2;
9248
+ masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9249
+ i = regionEnd;
9250
+ continue;
9251
+ }
9252
+ }
9253
+ masked += source[i];
9254
+ i++;
9218
9255
  }
9219
- return current;
9256
+ return { masked, placeholders };
9257
+ }
9258
+ function pushPlaceholder(placeholders, text, sentinels) {
9259
+ const idx = placeholders.length;
9260
+ placeholders.push(text);
9261
+ return `${sentinels.open}${idx}${sentinels.close}`;
9262
+ }
9263
+ function escapeRegex(str) {
9264
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9265
+ }
9266
+ function restorePlaceholders(source, placeholders, sentinels) {
9267
+ const pattern = new RegExp(`${escapeRegex(sentinels.open)}(\\d+)${escapeRegex(sentinels.close)}`, "g");
9268
+ return source.replace(pattern, (_, idx) => placeholders[Number(idx)] ?? "");
9220
9269
  }
9221
- function computeBracketDepths(masked) {
9222
- const n = masked.length;
9270
+ function computeBracketDepths(source) {
9271
+ const n = source.length;
9223
9272
  const depths = new Int32Array(n + 1);
9224
9273
  let depth = 0;
9225
9274
  let i = 0;
9226
9275
  while (i < n) {
9227
9276
  depths[i] = depth;
9228
- const c = masked.charCodeAt(i);
9229
- const c1 = i + 1 < n ? masked.charCodeAt(i + 1) : -1;
9230
- const c2 = i + 2 < n ? masked.charCodeAt(i + 2) : -1;
9231
- if (depth > 0 && c === 34 && precededByEqualsAttr(masked, i)) {
9232
- const end = findQuoteEnd(masked, i + 1);
9277
+ const c = source.charCodeAt(i);
9278
+ const c1 = i + 1 < n ? source.charCodeAt(i + 1) : -1;
9279
+ const c2 = i + 2 < n ? source.charCodeAt(i + 2) : -1;
9280
+ if (depth > 0 && c === 34 && precededByEqualsAttr(source, i)) {
9281
+ const end = findQuoteEnd(source, i + 1);
9233
9282
  for (let k = i;k <= end; k++)
9234
9283
  depths[k] = depth;
9235
9284
  i = end + 1;
9236
9285
  continue;
9237
9286
  }
9238
9287
  if (c === 91 && c1 === 91 && c2 === 91) {
9239
- const end = findTripleLinkEnd(masked, i + 3);
9288
+ const end = findTripleLinkEnd(source, i + 3);
9240
9289
  for (let k = i;k <= end; k++)
9241
9290
  depths[k] = depth;
9242
9291
  i = end + 1;
@@ -9293,71 +9342,198 @@ function findTripleLinkEnd(s, from) {
9293
9342
  }
9294
9343
  return s.length - 1;
9295
9344
  }
9296
- function maskRawRegions(source, sentinels) {
9297
- const placeholders = [];
9298
- let masked = "";
9345
+
9346
+ // packages/parser/src/parser/rules/block/module/iftags/preprocess.ts
9347
+ var INNERMOST_IFTAGS_PATTERN = /\[\[\s*iftags\b([^\]]*)\]\]((?:(?!\[\[\s*iftags\b|\[\[\/\s*iftags\s*\]\]).)*)\[\[\/\s*iftags\s*\]\]/gis;
9348
+ function preprocessIftags(source, pageTags) {
9349
+ if (!source.includes("[["))
9350
+ return source;
9351
+ const sentinels = makeUniqueSentinels(source);
9352
+ const { masked, placeholders } = maskRawRegions(source, sentinels);
9353
+ const reduced = reduceIftags(masked, pageTags);
9354
+ return restorePlaceholders(reduced, placeholders, sentinels);
9355
+ }
9356
+ function reduceIftags(source, pageTags) {
9357
+ let current = source;
9358
+ const maxIterations = source.length + 1;
9359
+ const tagSet = pageTags ?? [];
9360
+ for (let i = 0;i < maxIterations; i++) {
9361
+ const depths = pageTags === null ? computeBracketDepths(current) : null;
9362
+ let changed = false;
9363
+ const next = current.replace(INNERMOST_IFTAGS_PATTERN, (match, cond, body, offset) => {
9364
+ if (depths !== null && depths[offset] === 0) {
9365
+ return match;
9366
+ }
9367
+ changed = true;
9368
+ const condition = parseTagCondition(cond);
9369
+ return evaluateTagCondition(condition, tagSet) ? body : "";
9370
+ });
9371
+ if (!changed)
9372
+ return current;
9373
+ current = next;
9374
+ }
9375
+ return current;
9376
+ }
9377
+
9378
+ // packages/parser/src/parser/preprocess/expr.ts
9379
+ var import_ast2 = require("@wdprlib/ast");
9380
+ function preprocessExpr(source) {
9381
+ if (!source.includes("[[#"))
9382
+ return source;
9383
+ const sentinels = makeUniqueSentinels(source);
9384
+ const { masked, placeholders } = maskRawRegions(source, sentinels);
9385
+ const reduced = reduceExpr(masked);
9386
+ return restorePlaceholders(reduced, placeholders, sentinels);
9387
+ }
9388
+ function reduceExpr(source) {
9389
+ let current = source;
9390
+ const maxIterations = source.length + 1;
9391
+ for (let i = 0;i < maxIterations; i++) {
9392
+ const next = expandInnermost(current);
9393
+ if (next === current)
9394
+ return current;
9395
+ current = next;
9396
+ }
9397
+ return current;
9398
+ }
9399
+ function expandInnermost(source) {
9400
+ const depths = computeBracketDepths(source);
9401
+ let result = "";
9299
9402
  let i = 0;
9403
+ let replaced = false;
9300
9404
  while (i < source.length) {
9301
- if (source[i] === "[" && source[i + 1] === "[") {
9302
- RAW_BLOCK_OPEN_PATTERN.lastIndex = i;
9303
- const openMatch = RAW_BLOCK_OPEN_PATTERN.exec(source);
9304
- if (openMatch) {
9305
- const name = openMatch[1].toLowerCase();
9306
- const openLen = openMatch[0].length;
9307
- const closePattern = new RegExp(`\\[\\[\\/\\s*${name}\\s*\\]\\]`, "ig");
9308
- closePattern.lastIndex = i + openLen;
9309
- const closeMatch = closePattern.exec(source);
9310
- if (closeMatch) {
9311
- const regionEnd = closeMatch.index + closeMatch[0].length;
9312
- masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9313
- i = regionEnd;
9314
- continue;
9315
- }
9316
- if (name === "code") {
9317
- masked += pushPlaceholder(placeholders, source.slice(i), sentinels);
9318
- i = source.length;
9319
- continue;
9320
- }
9321
- }
9322
- }
9323
- if (source[i] === "@" && source[i + 1] === "<") {
9324
- const close = source.indexOf(">@", i + 2);
9325
- const newline = source.indexOf(`
9326
- `, i + 2);
9327
- if (close !== -1 && (newline === -1 || close < newline)) {
9328
- const regionEnd = close + 2;
9329
- masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9330
- i = regionEnd;
9405
+ const kind = matchDirectiveKind(source, i);
9406
+ if (kind !== null && depths[i] > 0) {
9407
+ const match = tryParseInnermostDirective(source, i, kind);
9408
+ if (match !== null) {
9409
+ result += evaluateDirective(kind, match);
9410
+ i = match.end;
9411
+ replaced = true;
9331
9412
  continue;
9332
9413
  }
9333
9414
  }
9334
- if (source[i] === "@" && source[i + 1] === "@") {
9335
- const close = source.indexOf("@@", i + 2);
9336
- const newline = source.indexOf(`
9337
- `, i + 2);
9338
- if (close !== -1 && (newline === -1 || close < newline)) {
9339
- const regionEnd = close + 2;
9340
- masked += pushPlaceholder(placeholders, source.slice(i, regionEnd), sentinels);
9341
- i = regionEnd;
9342
- continue;
9415
+ result += source[i];
9416
+ i++;
9417
+ }
9418
+ return replaced ? result : source;
9419
+ }
9420
+ function matchDirectiveKind(source, i) {
9421
+ if (!source.startsWith("[[#", i))
9422
+ return null;
9423
+ if (source.startsWith("ifexpr", i + 3) && !isIdentChar(source[i + 9])) {
9424
+ return "ifexpr";
9425
+ }
9426
+ if (source.startsWith("if", i + 3) && !isIdentChar(source[i + 5])) {
9427
+ return "if";
9428
+ }
9429
+ if (source.startsWith("expr", i + 3) && !isIdentChar(source[i + 7])) {
9430
+ return "expr";
9431
+ }
9432
+ return null;
9433
+ }
9434
+ function tryParseInnermostDirective(source, start, kind) {
9435
+ const keywordLen = kind === "ifexpr" ? 6 : kind === "expr" ? 4 : 2;
9436
+ let pos = start + 3 + keywordLen;
9437
+ while (pos < source.length && isWhitespace(source[pos]))
9438
+ pos++;
9439
+ const headStart = pos;
9440
+ let blockDepth = 0;
9441
+ let linkDepth = 0;
9442
+ const pipes = [];
9443
+ let closeStart = -1;
9444
+ while (pos < source.length) {
9445
+ if (matchDirectiveKind(source, pos) !== null) {
9446
+ return null;
9447
+ }
9448
+ if (source.startsWith("[[[", pos)) {
9449
+ linkDepth++;
9450
+ pos += 3;
9451
+ continue;
9452
+ }
9453
+ if (linkDepth > 0 && source.startsWith("]]]", pos)) {
9454
+ linkDepth--;
9455
+ pos += 3;
9456
+ continue;
9457
+ }
9458
+ if (linkDepth > 0) {
9459
+ pos++;
9460
+ continue;
9461
+ }
9462
+ if (source.startsWith("[[", pos)) {
9463
+ blockDepth++;
9464
+ pos += 2;
9465
+ continue;
9466
+ }
9467
+ if (source.startsWith("]]", pos)) {
9468
+ if (blockDepth === 0) {
9469
+ closeStart = pos;
9470
+ break;
9343
9471
  }
9472
+ blockDepth--;
9473
+ pos += 2;
9474
+ continue;
9344
9475
  }
9345
- masked += source[i];
9346
- i++;
9476
+ if (source[pos] === "|" && blockDepth === 0 && linkDepth === 0) {
9477
+ pipes.push(pos);
9478
+ }
9479
+ pos++;
9347
9480
  }
9348
- return { masked, placeholders };
9481
+ if (closeStart === -1)
9482
+ return null;
9483
+ const hasPipe = pipes.length > 0;
9484
+ if (!hasPipe && (kind === "if" || kind === "ifexpr"))
9485
+ return null;
9486
+ let head;
9487
+ let thenText = "";
9488
+ let elseText = "";
9489
+ if (!hasPipe) {
9490
+ head = source.slice(headStart, closeStart).trim();
9491
+ } else {
9492
+ head = source.slice(headStart, pipes[0]).trim();
9493
+ if (pipes.length >= 2) {
9494
+ thenText = source.slice(pipes[0] + 1, pipes[1]).trim();
9495
+ elseText = source.slice(pipes[1] + 1, closeStart).trim();
9496
+ } else {
9497
+ thenText = source.slice(pipes[0] + 1, closeStart).trim();
9498
+ }
9499
+ }
9500
+ return {
9501
+ end: closeStart + 2,
9502
+ head,
9503
+ thenText,
9504
+ elseText,
9505
+ hasPipe
9506
+ };
9349
9507
  }
9350
- function pushPlaceholder(placeholders, text, sentinels) {
9351
- const idx = placeholders.length;
9352
- placeholders.push(text);
9353
- return `${sentinels.open}${idx}${sentinels.close}`;
9508
+ function evaluateDirective(kind, m) {
9509
+ if (kind === "expr") {
9510
+ const result2 = import_ast2.evaluateExpression(m.head);
9511
+ if (result2.success)
9512
+ return import_ast2.formatExprValue(result2.value);
9513
+ if (result2.error === "empty expression")
9514
+ return "";
9515
+ return "ERROR";
9516
+ }
9517
+ if (kind === "if") {
9518
+ if (!m.hasPipe)
9519
+ return "";
9520
+ return import_ast2.isTruthy(m.head) ? m.thenText : m.elseText;
9521
+ }
9522
+ if (!m.hasPipe)
9523
+ return "";
9524
+ const result = import_ast2.evaluateExpression(m.head);
9525
+ if (!result.success)
9526
+ return "ERROR";
9527
+ return result.value !== 0 && !Number.isNaN(result.value) ? m.thenText : m.elseText;
9354
9528
  }
9355
- function escapeRegex(str) {
9356
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9529
+ function isWhitespace(ch) {
9530
+ return ch === " " || ch === "\t" || ch === `
9531
+ ` || ch === "\r";
9357
9532
  }
9358
- function restorePlaceholders(source, placeholders, sentinels) {
9359
- const pattern = new RegExp(`${escapeRegex(sentinels.open)}(\\d+)${escapeRegex(sentinels.close)}`, "g");
9360
- return source.replace(pattern, (_, idx) => placeholders[Number(idx)] ?? "");
9533
+ function isIdentChar(ch) {
9534
+ if (!ch)
9535
+ return false;
9536
+ return /[a-z0-9_-]/i.test(ch);
9361
9537
  }
9362
9538
 
9363
9539
  // packages/parser/src/parser/parse.ts
@@ -9369,7 +9545,7 @@ class Parser {
9369
9545
  pos: 0,
9370
9546
  version: options.version ?? "wikidot",
9371
9547
  trackPositions: options.trackPositions ?? true,
9372
- settings: options.settings ?? import_ast2.DEFAULT_SETTINGS,
9548
+ settings: options.settings ?? import_ast3.DEFAULT_SETTINGS,
9373
9549
  footnotes: [],
9374
9550
  tocEntries: [],
9375
9551
  codeBlocks: [],
@@ -9468,7 +9644,8 @@ class Parser {
9468
9644
  }
9469
9645
  }
9470
9646
  function parse(source, options) {
9471
- const iftagsProcessed = options?.pageTags !== undefined ? preprocessIftags(source, options.pageTags) : source;
9647
+ const ifProcessed = preprocessExpr(source);
9648
+ const iftagsProcessed = options?.pageTags !== undefined ? preprocessIftags(ifProcessed, options.pageTags) : ifProcessed;
9472
9649
  const preprocessed = preprocess(iftagsProcessed);
9473
9650
  const tokens = tokenize(preprocessed, { trackPositions: options?.trackPositions });
9474
9651
  return new Parser(tokens, options).parse();
@@ -10659,7 +10836,7 @@ function resolveListUsers(_module, data, compiledTemplate, parse2) {
10659
10836
  return itemAst.elements;
10660
10837
  }
10661
10838
  // packages/parser/src/parser/rules/block/module/resolve.ts
10662
- var import_ast3 = require("@wdprlib/ast");
10839
+ var import_ast4 = require("@wdprlib/ast");
10663
10840
  async function resolveModules(ast, dataProvider, options) {
10664
10841
  let listPagesCtx = null;
10665
10842
  const listPagesReqs = options.requirements.listPages ?? [];
@@ -10837,7 +11014,7 @@ function collectStylesFromElements(elements, styles, ctx) {
10837
11014
  }
10838
11015
  if (element.element === "if-tags") {
10839
11016
  const slotId = ctx.nextSlotId++;
10840
- styles.push(`${import_ast3.STYLE_SLOT_PREFIX}${slotId}`);
11017
+ styles.push(`${import_ast4.STYLE_SLOT_PREFIX}${slotId}`);
10841
11018
  result.push({
10842
11019
  element: "if-tags",
10843
11020
  data: { ...element.data, _styleSlot: slotId }
@@ -10851,4 +11028,4 @@ function collectStylesFromElements(elements, styles, ctx) {
10851
11028
  }
10852
11029
 
10853
11030
  // packages/parser/src/parser/rules/block/module/index.ts
10854
- var import_ast4 = require("@wdprlib/ast");
11031
+ var import_ast5 = require("@wdprlib/ast");