@wdprlib/parser 5.4.0 → 6.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 (44) hide show
  1. package/dist/index.cjs +420 -127
  2. package/dist/index.d.cts +93 -8
  3. package/dist/index.d.ts +93 -8
  4. package/dist/index.js +380 -84
  5. package/package.json +2 -2
  6. package/src/build-info.generated.ts +2 -2
  7. package/src/index.ts +3 -0
  8. package/src/parser/rules/block/module/index.ts +3 -2
  9. package/src/parser/rules/block/module/listpages/extraction/listpages.ts +5 -0
  10. package/src/parser/rules/block/module/listpages/extraction/query.ts +1 -0
  11. package/src/parser/rules/block/module/listpages/extraction/template.ts +16 -0
  12. package/src/parser/rules/block/module/listpages/extraction/variables.ts +1 -0
  13. package/src/parser/rules/block/module/listpages/index.ts +1 -0
  14. package/src/parser/rules/block/module/listpages/normalization/order-parent.ts +9 -1
  15. package/src/parser/rules/block/module/listpages/normalize.ts +1 -0
  16. package/src/parser/rules/block/module/listpages/parser.ts +1 -0
  17. package/src/parser/rules/block/module/listpages/resolve.ts +4 -2
  18. package/src/parser/rules/block/module/listpages/template/excerpt.ts +63 -0
  19. package/src/parser/rules/block/module/listpages/template/format/content.ts +0 -32
  20. package/src/parser/rules/block/module/listpages/template/format/index.ts +1 -1
  21. package/src/parser/rules/block/module/listpages/template/getters/index.ts +14 -0
  22. package/src/parser/rules/block/module/listpages/template/getters/parameterized.ts +3 -1
  23. package/src/parser/rules/block/module/listpages/template/getters/registered.ts +52 -0
  24. package/src/parser/rules/block/module/listpages/template/getters/simple.ts +15 -5
  25. package/src/parser/rules/block/module/listpages/template/literal.ts +6 -0
  26. package/src/parser/rules/block/module/listpages/template/syntax.ts +10 -1
  27. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +6 -0
  28. package/src/parser/rules/block/module/listpages/types/external-data.ts +36 -2
  29. package/src/parser/rules/block/module/listpages/types/normalized-query.ts +14 -4
  30. package/src/parser/rules/block/module/listpages/types/query.ts +2 -0
  31. package/src/parser/rules/block/module/listpages/types/variables.ts +5 -0
  32. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +2 -0
  33. package/src/parser/rules/block/module/listusers/resolve.ts +2 -1
  34. package/src/parser/rules/block/module/mapping.ts +2 -1
  35. package/src/parser/rules/block/module/rate/index.ts +16 -19
  36. package/src/parser/rules/block/module/rate/resolve.ts +108 -0
  37. package/src/parser/rules/block/module/rate/types.ts +6 -16
  38. package/src/parser/rules/block/module/resolution/resolve-async.ts +2 -1
  39. package/src/parser/rules/block/module/resolve.ts +10 -8
  40. package/src/parser/rules/block/module/types-common.ts +4 -0
  41. package/src/parser/rules/inline/parsing/inline-content.ts +10 -1
  42. package/src/parser/rules/inline/size/content.ts +31 -4
  43. package/src/pipeline/process.ts +13 -0
  44. package/src/pipeline/types.ts +19 -0
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __export = (target, all) => {
30
30
  var exports_src = {};
31
31
  __export(exports_src, {
32
32
  tokenize: () => tokenize,
33
- text: () => import_ast9.text,
33
+ text: () => import_ast12.text,
34
34
  resolveTagCloud: () => resolveTagCloud,
35
35
  resolveModules: () => resolveModules,
36
36
  resolveListUsers: () => resolveListUsers,
@@ -47,49 +47,49 @@ __export(exports_src, {
47
47
  parseDateSelector: () => parseDateSelector,
48
48
  parseCategory: () => parseCategory,
49
49
  parse: () => parse,
50
- paragraph: () => import_ast9.paragraph,
50
+ paragraph: () => import_ast12.paragraph,
51
51
  normalizeQuery: () => normalizeQuery,
52
52
  matchesListPagesSelectors: () => matchesListPagesSelectors,
53
- listItemSubList: () => import_ast9.listItemSubList,
54
- listItemElements: () => import_ast9.listItemElements,
55
- list: () => import_ast9.list,
56
- link: () => import_ast9.link,
57
- lineBreak: () => import_ast9.lineBreak,
58
- italics: () => import_ast9.italics,
53
+ listItemSubList: () => import_ast12.listItemSubList,
54
+ listItemElements: () => import_ast12.listItemElements,
55
+ list: () => import_ast12.list,
56
+ link: () => import_ast12.link,
57
+ lineBreak: () => import_ast12.lineBreak,
58
+ italics: () => import_ast12.italics,
59
59
  isTagCloudModule: () => isTagCloudModule,
60
60
  isListUsersModule: () => isListUsersModule2,
61
- horizontalRule: () => import_ast9.horizontalRule,
62
- heading: () => import_ast9.heading,
61
+ horizontalRule: () => import_ast12.horizontalRule,
62
+ heading: () => import_ast12.heading,
63
63
  extractListUsersVariables: () => extractListUsersVariables,
64
64
  extractIncludeReferences: () => extractIncludeReferences,
65
65
  extractDataRequirements: () => extractDataRequirements,
66
66
  definePageData: () => definePageData,
67
67
  createToken: () => createToken,
68
- createSettings: () => import_ast10.createSettings,
69
- createPosition: () => import_ast9.createPosition,
70
- createPoint: () => import_ast9.createPoint,
71
- container: () => import_ast9.container,
68
+ createSettings: () => import_ast13.createSettings,
69
+ createPosition: () => import_ast12.createPosition,
70
+ createPoint: () => import_ast12.createPoint,
71
+ container: () => import_ast12.container,
72
72
  compileTemplate: () => compileTemplate,
73
73
  compileListUsersTemplate: () => compileListUsersTemplate,
74
74
  buildInfo: () => buildInfo,
75
- bold: () => import_ast9.bold,
76
- STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
75
+ bold: () => import_ast12.bold,
76
+ STYLE_SLOT_PREFIX: () => import_ast7.STYLE_SLOT_PREFIX,
77
77
  Parser: () => Parser,
78
78
  Lexer: () => Lexer,
79
- DEFAULT_SETTINGS: () => import_ast10.DEFAULT_SETTINGS
79
+ DEFAULT_SETTINGS: () => import_ast13.DEFAULT_SETTINGS
80
80
  });
81
81
  module.exports = __toCommonJS(exports_src);
82
82
 
83
83
  // packages/parser/src/build-info.generated.ts
84
84
  var buildInfo = Object.freeze({
85
- version: "5.4.0",
86
- sha: "5e221ddeccc585e64dd1a2eb49b14817c3c1be5d",
85
+ version: "6.0.0",
86
+ sha: "705ff97e22abd7bfb49d7f8f30087e6f09654c91",
87
87
  dirty: false
88
88
  });
89
89
 
90
90
  // packages/parser/src/index.ts
91
- var import_ast9 = require("@wdprlib/ast");
92
- var import_ast10 = require("@wdprlib/ast");
91
+ var import_ast12 = require("@wdprlib/ast");
92
+ var import_ast13 = require("@wdprlib/ast");
93
93
 
94
94
  // packages/parser/src/lexer/tokens.ts
95
95
  function createToken(type, value, position, lineStart = false) {
@@ -2694,7 +2694,8 @@ function parseInlineUntil(ctx, endType) {
2694
2694
  let pos = ctx.pos;
2695
2695
  let consumedEmptyRaw = false;
2696
2696
  const paragraphMode = endType === "PARAGRAPH_BREAK";
2697
- const multiline = paragraphMode || FORMATTING_CLOSE_TOKENS.has(endType);
2697
+ const preserveNewlines = endType === "EOF";
2698
+ const multiline = paragraphMode || preserveNewlines || FORMATTING_CLOSE_TOKENS.has(endType);
2698
2699
  let inlineEnd = ctx.scope.inlineEnd ?? ctx.tokens.length;
2699
2700
  if (!multiline) {
2700
2701
  for (let end = ctx.pos;end < inlineEnd; end++) {
@@ -2732,6 +2733,12 @@ function parseInlineUntil(ctx, endType) {
2732
2733
  if (!multiline && token5.type === "NEWLINE") {
2733
2734
  break;
2734
2735
  }
2736
+ if (preserveNewlines && token5.type === "NEWLINE") {
2737
+ nodes.push({ element: "text", data: token5.value });
2738
+ pos++;
2739
+ consumed++;
2740
+ continue;
2741
+ }
2735
2742
  if (multiline && token5.type === "NEWLINE" && !ctx.scope.tableFormatting) {
2736
2743
  const boundary = getParagraphNewlineBoundary(ctx, pos, nodes.length > 0);
2737
2744
  if (boundary.shouldBreak) {
@@ -2852,7 +2859,7 @@ function parseNextBlock(ctx, skipWhitespace2, isAtEnd3) {
2852
2859
  }
2853
2860
 
2854
2861
  // packages/parser/src/parser/parse/context.ts
2855
- var import_ast6 = require("@wdprlib/ast");
2862
+ var import_ast9 = require("@wdprlib/ast");
2856
2863
  // packages/parser/src/parser/rules/block/heading/open.ts
2857
2864
  function parseHeadingOpen(ctx) {
2858
2865
  const marker = ctx.tokens[ctx.pos];
@@ -5764,8 +5771,18 @@ var rateModuleRule = {
5764
5771
  name: "module-rate",
5765
5772
  acceptsNames: ["rate"],
5766
5773
  hasBody: false,
5767
- parse() {
5768
- return { module: "rate" };
5774
+ parse(_ctx, _pos, args) {
5775
+ return { module: "rate", ref: Object.keys(args).length === 0 ? { kind: "main" } : null };
5776
+ }
5777
+ };
5778
+ var customRateModuleRule = {
5779
+ name: "module-custom-rate",
5780
+ acceptsNames: ["customrate"],
5781
+ hasBody: false,
5782
+ parse(_ctx, _pos, args) {
5783
+ const key = args.key;
5784
+ const valid = key !== undefined && key !== "" && Object.keys(args).every((name) => name === "key");
5785
+ return { module: "custom-rate", ref: valid ? { kind: "custom", axisKey: key } : null };
5769
5786
  }
5770
5787
  };
5771
5788
 
@@ -5900,6 +5917,7 @@ var listPagesModuleRule = {
5900
5917
  "created-at": createdAt,
5901
5918
  "updated-at": updatedAt,
5902
5919
  rating,
5920
+ "rating-axis": args["rating-axis"],
5903
5921
  votes,
5904
5922
  name,
5905
5923
  fullname,
@@ -6043,6 +6061,7 @@ var tagCloudModuleRule = {
6043
6061
  // packages/parser/src/parser/rules/block/module/mapping.ts
6044
6062
  var MODULE_RULES = [
6045
6063
  rateModuleRule,
6064
+ customRateModuleRule,
6046
6065
  cssModuleRule,
6047
6066
  backlinksModuleRule,
6048
6067
  categoriesModuleRule,
@@ -6613,22 +6632,6 @@ function getDayOfYear(date) {
6613
6632
  function splitContentSections(content) {
6614
6633
  return content.split(/^={4,}$/m).map((section) => section.trim());
6615
6634
  }
6616
- function getSummary(page) {
6617
- if (page.content) {
6618
- const sections = splitContentSections(page.content);
6619
- if (sections.length > 1) {
6620
- return sections[0]?.trim() ?? "";
6621
- }
6622
- }
6623
- return getFirstParagraph(page.content);
6624
- }
6625
- function getFirstParagraph(content) {
6626
- if (!content)
6627
- return "";
6628
- const stripped = content.replace(/^(\+{1,6}) (.*)/gm, "").replace(/^\[\[toc(\s[^\]]+)?\]\]/gim, "").replace(/^\[\[\/?div(\s[^\]]+)?\]\]/gim, "").replace(/^\[\[\/?module(\s[^\]]+)?\]\]/gim, "").trim();
6629
- const paragraphs = stripped.split(/\n{2,}/);
6630
- return paragraphs[0]?.trim() ?? "";
6631
- }
6632
6635
  // packages/parser/src/parser/rules/block/module/listpages/template/format/tags.ts
6633
6636
  function formatTagsLinked(tags, prefix) {
6634
6637
  if (tags.length === 0)
@@ -6641,6 +6644,16 @@ function formatUserLinked(user) {
6641
6644
  return "Anonymous";
6642
6645
  return `[[*user ${user.name}]]`;
6643
6646
  }
6647
+ // packages/parser/src/parser/rules/block/module/listpages/template/getters/parameterized.ts
6648
+ var import_ast2 = require("@wdprlib/ast");
6649
+
6650
+ // packages/parser/src/parser/rules/block/module/listpages/template/literal.ts
6651
+ function literalWikitext(value) {
6652
+ if (value === "")
6653
+ return "";
6654
+ return `@<${Array.from(value, (char) => `&#${char.codePointAt(0)};`).join("")}>@`;
6655
+ }
6656
+
6644
6657
  // packages/parser/src/parser/rules/block/module/listpages/template/getters/parameterized.ts
6645
6658
  function createBraceParamGetter(name, param) {
6646
6659
  switch (name) {
@@ -6669,7 +6682,7 @@ function createParenParamGetter(name, param) {
6669
6682
  if (name !== "preview")
6670
6683
  return null;
6671
6684
  const len = Number(param);
6672
- return (ctx) => (ctx.page.content ?? "").slice(0, len);
6685
+ return (ctx) => literalWikitext(import_ast2.excerptText(ctx.page.readableText ?? "", { maxLength: len }));
6673
6686
  }
6674
6687
  function createFormattedGetter(name, format) {
6675
6688
  switch (name) {
@@ -6696,6 +6709,7 @@ function createTagsLinkedGetter(name, format) {
6696
6709
  }
6697
6710
 
6698
6711
  // packages/parser/src/parser/rules/block/module/listpages/template/getters/simple.ts
6712
+ var import_ast3 = require("@wdprlib/ast");
6699
6713
  var DEFAULT_PREVIEW_LENGTH = 200;
6700
6714
  var SIMPLE_GETTERS = {
6701
6715
  created_at: (ctx) => formatDate(ctx.page.createdAt),
@@ -6725,14 +6739,14 @@ var SIMPLE_GETTERS = {
6725
6739
  parent_title: (ctx) => ctx.page.parentTitle ?? "",
6726
6740
  parent_title_linked: (ctx) => ctx.page.parentFullname ? `[[[${ctx.page.parentFullname} | ${ctx.page.parentTitle}]]]` : "",
6727
6741
  content: (ctx) => ctx.page.content ?? "",
6728
- preview: (ctx) => (ctx.page.content ?? "").slice(0, DEFAULT_PREVIEW_LENGTH),
6729
- summary: (ctx) => getSummary(ctx.page),
6730
- first_paragraph: (ctx) => getFirstParagraph(ctx.page.content),
6742
+ preview: (ctx) => literalWikitext(import_ast3.excerptText(ctx.page.readableText ?? "", { maxLength: DEFAULT_PREVIEW_LENGTH })),
6743
+ summary: (ctx) => literalWikitext(ctx.page.firstParagraph ?? ""),
6744
+ first_paragraph: (ctx) => literalWikitext(ctx.page.firstParagraph ?? ""),
6731
6745
  tags: (ctx) => ctx.page.tags.join(" "),
6732
6746
  _tags: (ctx) => ctx.page.hiddenTags.join(" "),
6733
6747
  children: (ctx) => String(ctx.page.children),
6734
6748
  comments: (ctx) => String(ctx.page.comments),
6735
- size: (ctx) => String(ctx.page.size),
6749
+ size: (ctx) => ctx.page.readableText !== undefined ? String(import_ast3.countCharacters(ctx.page.readableText)) : ctx.page.size !== undefined ? String(ctx.page.size) : "",
6736
6750
  rating: (ctx) => String(ctx.page.rating),
6737
6751
  rating_votes: (ctx) => String(ctx.page.ratingVotes),
6738
6752
  rating_percent: (ctx) => String(ctx.page.ratingPercent ?? 0),
@@ -6746,11 +6760,136 @@ var SIMPLE_GETTERS = {
6746
6760
  site_domain: (ctx) => ctx.site.domain
6747
6761
  };
6748
6762
 
6763
+ // packages/parser/src/parser/rules/block/module/listpages/template/getters/registered.ts
6764
+ function createRegisteredGetter(name, key, format) {
6765
+ if (name === "metadata")
6766
+ return (ctx) => {
6767
+ const metadata = ctx.page.metadata;
6768
+ const entry = metadata && Object.hasOwn(metadata, key) ? metadata[key] : null;
6769
+ if (!entry)
6770
+ return "";
6771
+ let value;
6772
+ switch (entry.type) {
6773
+ case "text":
6774
+ value = entry.value;
6775
+ break;
6776
+ case "number":
6777
+ value = String(entry.value);
6778
+ break;
6779
+ case "date":
6780
+ value = formatDate(entry.value, format);
6781
+ break;
6782
+ case "user":
6783
+ value = format === "id" ? String(entry.value.id) : format === "unix" ? entry.value.unixName : entry.value.name;
6784
+ break;
6785
+ }
6786
+ return literalWikitext(value);
6787
+ };
6788
+ if (name === "customrate" || name === "customrate_votes" || name === "customrate_percent")
6789
+ return (ctx) => {
6790
+ const ratings = ctx.page.customRates;
6791
+ const entry = ratings && Object.hasOwn(ratings, key) ? ratings[key] : null;
6792
+ if (!entry)
6793
+ return "";
6794
+ return String(name === "customrate" ? entry.points : name === "customrate_votes" ? entry.votes : entry.percent);
6795
+ };
6796
+ return null;
6797
+ }
6798
+
6799
+ // packages/parser/src/parser/rules/block/module/listpages/template/getters/index.ts
6800
+ var import_ast4 = require("@wdprlib/ast");
6801
+
6802
+ // packages/parser/src/parser/rules/block/module/listpages/template/excerpt.ts
6803
+ function findExcerptEnd(template, contentStart) {
6804
+ let quote;
6805
+ for (let cursor = contentStart + "excerpt{".length;cursor < template.length; cursor++) {
6806
+ const char = template[cursor];
6807
+ if (quote) {
6808
+ if (char === "\\")
6809
+ cursor++;
6810
+ else if (char === quote)
6811
+ quote = undefined;
6812
+ } else if (char === '"' || char === "'") {
6813
+ quote = char;
6814
+ } else if (char === "}") {
6815
+ return template.startsWith("%%", cursor + 1) ? cursor + 1 : -1;
6816
+ }
6817
+ }
6818
+ return -1;
6819
+ }
6820
+ function parseExcerptOptions(input) {
6821
+ if (input.length > 8192)
6822
+ return null;
6823
+ const attributes = new Map;
6824
+ let cursor = 0;
6825
+ while (cursor < input.length) {
6826
+ while (cursor < input.length && /\s/.test(input[cursor]))
6827
+ cursor++;
6828
+ if (cursor === input.length)
6829
+ break;
6830
+ const start = cursor;
6831
+ while (cursor < input.length && /[a-z]/.test(input[cursor]))
6832
+ cursor++;
6833
+ const name = input.slice(start, cursor);
6834
+ if (!["pattern", "flags", "group", "match", "max"].includes(name) || attributes.has(name))
6835
+ return null;
6836
+ while (cursor < input.length && /\s/.test(input[cursor]))
6837
+ cursor++;
6838
+ if (input[cursor++] !== "=")
6839
+ return null;
6840
+ while (cursor < input.length && /\s/.test(input[cursor]))
6841
+ cursor++;
6842
+ const quote = input[cursor++];
6843
+ if (quote !== '"' && quote !== "'")
6844
+ return null;
6845
+ let value = "";
6846
+ while (cursor < input.length && input[cursor] !== quote) {
6847
+ if (input[cursor] === "\\" && (input[cursor + 1] === quote || input[cursor + 1] === "\\")) {
6848
+ value += input[cursor + 1] === quote ? quote : "\\\\";
6849
+ cursor += 2;
6850
+ } else
6851
+ value += input[cursor++];
6852
+ }
6853
+ if (input[cursor++] !== quote)
6854
+ return null;
6855
+ if (cursor < input.length && !/\s/.test(input[cursor]))
6856
+ return null;
6857
+ attributes.set(name, value);
6858
+ }
6859
+ const pattern = attributes.get("pattern");
6860
+ if (pattern === undefined)
6861
+ return null;
6862
+ const group = attributes.get("group");
6863
+ const match = attributes.get("match");
6864
+ const max = attributes.get("max");
6865
+ if (match !== undefined && !/^\d+$/.test(match) || max !== undefined && !/^\d+$/.test(max))
6866
+ return null;
6867
+ return {
6868
+ pattern,
6869
+ flags: attributes.get("flags"),
6870
+ group: group === undefined ? undefined : /^\d+$/.test(group) ? Number(group) : group,
6871
+ match: match === undefined ? undefined : Number(match),
6872
+ maxLength: max === undefined ? undefined : Number(max)
6873
+ };
6874
+ }
6875
+
6749
6876
  // packages/parser/src/parser/rules/block/module/listpages/template/getters/index.ts
6750
6877
  function createVariableGetter(name, braceParam, parenParam, format) {
6878
+ if (name === "excerpt") {
6879
+ const options = braceParam === undefined ? null : parseExcerptOptions(braceParam);
6880
+ if (!options || parenParam !== undefined || format !== undefined)
6881
+ return () => "";
6882
+ const extract = import_ast4.compileTextExcerpt(options);
6883
+ return (ctx) => literalWikitext(extract(ctx.page.readableText ?? ""));
6884
+ }
6885
+ const registeredGetter = braceParam !== undefined ? createRegisteredGetter(name, braceParam, format) : null;
6886
+ if (registeredGetter)
6887
+ return registeredGetter;
6751
6888
  const braceGetter = braceParam !== undefined ? createBraceParamGetter(name, braceParam) : null;
6752
6889
  if (braceGetter)
6753
6890
  return braceGetter;
6891
+ if (braceParam !== undefined)
6892
+ return () => "";
6754
6893
  const parenGetter = parenParam !== undefined ? createParenParamGetter(name, parenParam) : null;
6755
6894
  if (parenGetter)
6756
6895
  return parenGetter;
@@ -6772,7 +6911,7 @@ function scanTemplateVariables(template) {
6772
6911
  if (start === -1)
6773
6912
  break;
6774
6913
  const contentStart = start + 2;
6775
- const end = template.indexOf("%%", contentStart);
6914
+ const end = template.slice(contentStart, contentStart + 8).toLowerCase() === "excerpt{" ? findExcerptEnd(template, contentStart) : template.indexOf("%%", contentStart);
6776
6915
  if (end === -1)
6777
6916
  break;
6778
6917
  const parsed = parseTemplateVariableContent(template.slice(contentStart, end));
@@ -6795,6 +6934,11 @@ function parseTemplateVariableContent(content) {
6795
6934
  if (cursor === 0)
6796
6935
  return null;
6797
6936
  const name = content.slice(0, cursor);
6937
+ if (name.toLowerCase() === "excerpt" && content[cursor] === "{") {
6938
+ if (!content.endsWith("}"))
6939
+ return null;
6940
+ return { name, braceParam: content.slice(cursor + 1, -1) };
6941
+ }
6798
6942
  let braceParam;
6799
6943
  let parenParam;
6800
6944
  let format;
@@ -6874,6 +7018,7 @@ function buildQuery(module2) {
6874
7018
  updatedAt: module2["updated-at"],
6875
7019
  createdBy: module2["created-by"],
6876
7020
  rating: module2.rating,
7021
+ ratingAxis: module2["rating-axis"],
6877
7022
  votes: module2.votes,
6878
7023
  name: module2.name,
6879
7024
  fullname: module2.fullname,
@@ -6928,6 +7073,7 @@ var KNOWN_VARIABLES = new Set([
6928
7073
  "parent_title_linked",
6929
7074
  "content",
6930
7075
  "preview",
7076
+ "excerpt",
6931
7077
  "summary",
6932
7078
  "first_paragraph",
6933
7079
  "tags",
@@ -6965,12 +7111,24 @@ function extractVariablesFromTemplate(template) {
6965
7111
  const contentIndices = new Set;
6966
7112
  const previewLengths = new Set;
6967
7113
  const formFields = new Set;
7114
+ const metadataKeys = new Set;
7115
+ const customRateKeys = new Set;
6968
7116
  let tagsLinkPrefix;
6969
7117
  let hiddenTagsLinkPrefix;
6970
7118
  for (const match of scanTemplateVariables(template)) {
6971
7119
  const varName = match.name.toLowerCase();
6972
7120
  if (match.braceParam !== undefined) {
6973
7121
  switch (varName) {
7122
+ case "metadata":
7123
+ metadataKeys.add(match.braceParam);
7124
+ variables.add("metadata");
7125
+ continue;
7126
+ case "customrate":
7127
+ case "customrate_votes":
7128
+ case "customrate_percent":
7129
+ customRateKeys.add(match.braceParam);
7130
+ variables.add(varName);
7131
+ continue;
6974
7132
  case "content":
6975
7133
  contentIndices.add(Number(match.braceParam));
6976
7134
  variables.add("content_n");
@@ -7020,6 +7178,8 @@ function extractVariablesFromTemplate(template) {
7020
7178
  contentIndices: Array.from(contentIndices).sort((a, b) => a - b),
7021
7179
  previewLengths: Array.from(previewLengths).sort((a, b) => a - b),
7022
7180
  formFields: Array.from(formFields).sort(),
7181
+ metadataKeys: [...metadataKeys].sort(),
7182
+ customRateKeys: [...customRateKeys].sort(),
7023
7183
  tagsLinkPrefix,
7024
7184
  hiddenTagsLinkPrefix
7025
7185
  };
@@ -7041,6 +7201,9 @@ function extractListPagesModule(listPages, state, result) {
7041
7201
  contentSectionIndices: extraction.contentIndices,
7042
7202
  previewLengths: extraction.previewLengths,
7043
7203
  formFields: extraction.formFields,
7204
+ metadataKeys: extraction.metadataKeys,
7205
+ customRateKeys: extraction.customRateKeys,
7206
+ needsReadableText: extraction.variables.some((name) => ["preview", "preview_n", "summary", "first_paragraph", "excerpt"].includes(name)),
7044
7207
  tagsLinkPrefix: extraction.tagsLinkPrefix,
7045
7208
  hiddenTagsLinkPrefix: extraction.hiddenTagsLinkPrefix,
7046
7209
  urlAttrPrefix: listPages["url-attr-prefix"],
@@ -7373,13 +7536,101 @@ function wrapListPagesResult(module2, items, parse, data) {
7373
7536
  return result;
7374
7537
  }
7375
7538
 
7539
+ // packages/parser/src/parser/rules/block/module/rate/resolve.ts
7540
+ function refKey(ref) {
7541
+ return ref.kind === "main" ? "main" : `custom:${ref.axisKey}`;
7542
+ }
7543
+ async function resolveRatings(ast, fetchRatings) {
7544
+ const refs = new Map;
7545
+ mapDocument(ast, (element) => {
7546
+ if (isRating(element) && element.data.ref)
7547
+ refs.set(refKey(element.data.ref), element.data.ref);
7548
+ return element;
7549
+ });
7550
+ const states = new Map;
7551
+ if (fetchRatings && refs.size > 0) {
7552
+ for (const state of await fetchRatings([...refs.values()])) {
7553
+ const key = refKey(state.ref);
7554
+ if (refs.has(key))
7555
+ states.set(key, state);
7556
+ }
7557
+ }
7558
+ return mapDocument(ast, (element) => {
7559
+ if (!isRating(element))
7560
+ return element;
7561
+ const { state: _previous, ...data } = element.data;
7562
+ const state = data.ref ? states.get(refKey(data.ref)) : undefined;
7563
+ return { ...element, data: state ? { ...data, state } : data };
7564
+ });
7565
+ }
7566
+ function suppressModuleRatings(result) {
7567
+ const ast = mapDocument(getModuleParseAst(result), (element) => isRating(element) ? null : element);
7568
+ return "ast" in result ? { ...result, ast } : ast;
7569
+ }
7570
+ function isRating(element) {
7571
+ return element.element === "module" && (element.data.module === "rate" || element.data.module === "custom-rate");
7572
+ }
7573
+ function mapDocument(ast, transform) {
7574
+ const map = (elements) => elements.flatMap((original) => {
7575
+ const element = transform(original);
7576
+ if (!element)
7577
+ return [];
7578
+ if (element.element === "if") {
7579
+ return [
7580
+ {
7581
+ ...element,
7582
+ data: {
7583
+ ...element.data,
7584
+ then: map(element.data.then),
7585
+ else: map(element.data.else)
7586
+ }
7587
+ }
7588
+ ];
7589
+ }
7590
+ if (element.element === "ifexpr") {
7591
+ return [
7592
+ {
7593
+ ...element,
7594
+ data: {
7595
+ ...element.data,
7596
+ then: map(element.data.then),
7597
+ else: map(element.data.else)
7598
+ }
7599
+ }
7600
+ ];
7601
+ }
7602
+ if (element.element === "bibliography-block") {
7603
+ return [
7604
+ {
7605
+ ...element,
7606
+ data: {
7607
+ ...element.data,
7608
+ entries: element.data.entries.map((entry) => ({
7609
+ ...entry,
7610
+ key: map(entry.key),
7611
+ value: map(entry.value)
7612
+ }))
7613
+ }
7614
+ }
7615
+ ];
7616
+ }
7617
+ return [mapElementChildren(element, map)];
7618
+ });
7619
+ return {
7620
+ ...ast,
7621
+ elements: map(ast.elements),
7622
+ ...ast.footnotes ? { footnotes: ast.footnotes.map(map) } : {}
7623
+ };
7624
+ }
7625
+
7376
7626
  // packages/parser/src/parser/rules/block/module/listpages/resolve.ts
7377
7627
  function isListPagesModule2(module2) {
7378
7628
  return module2.module === "list-pages";
7379
7629
  }
7380
7630
  function resolveListPages(module2, data, compiledTemplate, parse) {
7381
- const items = renderListPagesItems(module2, data, compiledTemplate, parse);
7382
- return wrapListPagesResult(module2, items, parse, data);
7631
+ const parseFragment = (source) => suppressModuleRatings(parse(source));
7632
+ const items = renderListPagesItems(module2, data, compiledTemplate, parseFragment);
7633
+ return wrapListPagesResult(module2, items, parseFragment, data);
7383
7634
  }
7384
7635
  // packages/parser/src/parser/rules/block/module/listpages/types/external-data.ts
7385
7636
  function definePageData(input) {
@@ -7393,7 +7644,6 @@ function definePageData(input) {
7393
7644
  hiddenTags: input.hiddenTags ?? [],
7394
7645
  children: input.children ?? 0,
7395
7646
  comments: input.comments ?? 0,
7396
- size: input.size ?? 0,
7397
7647
  rating: input.rating ?? 0,
7398
7648
  ratingVotes: input.ratingVotes ?? 0,
7399
7649
  revisions: input.revisions ?? 0
@@ -7471,6 +7721,7 @@ var URL_RESOLVABLE_FIELDS = [
7471
7721
  aliases: ["createdby", "created_by"]
7472
7722
  },
7473
7723
  { attr: "rating", queryKey: "rating", type: "string" },
7724
+ { attr: "rating-axis", queryKey: "ratingAxis", type: "string" },
7474
7725
  { attr: "votes", queryKey: "votes", type: "string" },
7475
7726
  { attr: "reverse", queryKey: "reverse", type: "boolean" }
7476
7727
  ];
@@ -7572,6 +7823,7 @@ var ORDER_FIELD_MAP = {
7572
7823
  votes: "votes",
7573
7824
  revisions: "revisions",
7574
7825
  comments: "comments",
7826
+ commented_at: "commented_at",
7575
7827
  pagelength: "size",
7576
7828
  size: "size",
7577
7829
  random: "random",
@@ -7579,6 +7831,13 @@ var ORDER_FIELD_MAP = {
7579
7831
  updated_at: "updated_at"
7580
7832
  };
7581
7833
  function parseOrder(value) {
7834
+ const metadata = /^metadata\{([^}]*)\}(?:\s+(asc|desc))?$/i.exec(value.trim());
7835
+ if (metadata)
7836
+ return {
7837
+ field: "metadata",
7838
+ key: metadata[1],
7839
+ direction: metadata[2]?.toLowerCase() === "asc" ? "asc" : "desc"
7840
+ };
7582
7841
  const defaultOrder = { field: "created_at", direction: "desc" };
7583
7842
  const trimmed = value.trim().toLowerCase();
7584
7843
  if (!trimmed)
@@ -7698,6 +7957,8 @@ function normalizeQuery(query) {
7698
7957
  result.linkTo = query.linkTo;
7699
7958
  if (query.createdBy)
7700
7959
  result.createdBy = query.createdBy;
7960
+ if (query.ratingAxis !== undefined)
7961
+ result.ratingAxis = query.ratingAxis;
7701
7962
  if (query.name)
7702
7963
  result.name = query.name;
7703
7964
  if (query.fullname)
@@ -8605,7 +8866,7 @@ function isListUsersModule2(module2) {
8605
8866
  function resolveListUsers(_module, data, compiledTemplate, parse) {
8606
8867
  const ctx = { user: data.user };
8607
8868
  const substituted = compiledTemplate(ctx);
8608
- const itemAst = getModuleParseAst(parse(substituted));
8869
+ const itemAst = getModuleParseAst(suppressModuleRatings(parse(substituted)));
8609
8870
  return itemAst.elements;
8610
8871
  }
8611
8872
  // packages/parser/src/parser/rules/block/module/resolution/data-maps.ts
@@ -8807,7 +9068,7 @@ function countDynamicModules(elements) {
8807
9068
  }
8808
9069
 
8809
9070
  // packages/parser/src/parser/rules/block/module/resolution/styles.ts
8810
- var import_ast2 = require("@wdprlib/ast");
9071
+ var import_ast5 = require("@wdprlib/ast");
8811
9072
  function collectStyles(elements, ignoredAnchors = new WeakSet) {
8812
9073
  const styles = [];
8813
9074
  const anchoredStyles = [];
@@ -8835,10 +9096,10 @@ function mergeCollectedStyles(existing, collected, resolvedSlots = new Map, anch
8835
9096
  return merged;
8836
9097
  }
8837
9098
  function isStyleSlotMarker(style) {
8838
- return style.startsWith(import_ast2.STYLE_SLOT_PREFIX);
9099
+ return style.startsWith(import_ast5.STYLE_SLOT_PREFIX);
8839
9100
  }
8840
9101
  function createStyleSlotMarker(slotId) {
8841
- return `${import_ast2.STYLE_SLOT_PREFIX}${slotId}`;
9102
+ return `${import_ast5.STYLE_SLOT_PREFIX}${slotId}`;
8842
9103
  }
8843
9104
  function getStyleSlotId(data) {
8844
9105
  const slotId = data._styleSlot;
@@ -8850,7 +9111,7 @@ function removeFirst(values, value) {
8850
9111
  values.splice(index, 1);
8851
9112
  }
8852
9113
  function appendStyleSlot(target, marker, resolvedSlots) {
8853
- const slotId = Number(marker.slice(import_ast2.STYLE_SLOT_PREFIX.length));
9114
+ const slotId = Number(marker.slice(import_ast5.STYLE_SLOT_PREFIX.length));
8854
9115
  const replacement = resolvedSlots.get(slotId);
8855
9116
  if (replacement)
8856
9117
  target.push(...replacement);
@@ -8880,24 +9141,24 @@ function collectStylesFromElements(elements, styles, anchoredStyles, anchors, ig
8880
9141
  for (const element of elements) {
8881
9142
  if (element.element === "style") {
8882
9143
  const css = element.data;
8883
- if (css.startsWith(import_ast2.STYLE_SLOT_PREFIX)) {
9144
+ if (css.startsWith(import_ast5.STYLE_SLOT_PREFIX)) {
8884
9145
  styles.push(css);
8885
9146
  continue;
8886
9147
  }
8887
- if (css.startsWith(import_ast2.STYLE_ANCHOR_PREFIX)) {
9148
+ if (css.startsWith(import_ast5.STYLE_ANCHOR_PREFIX)) {
8888
9149
  anchors.push(element);
8889
9150
  if (ignoredAnchors.has(element)) {
8890
9151
  result.push(element);
8891
9152
  continue;
8892
9153
  }
8893
- const anchoredCss = css.slice(import_ast2.STYLE_ANCHOR_PREFIX.length);
9154
+ const anchoredCss = css.slice(import_ast5.STYLE_ANCHOR_PREFIX.length);
8894
9155
  styles.push(anchoredCss);
8895
9156
  anchoredStyles.push(anchoredCss);
8896
9157
  result.push(element);
8897
9158
  continue;
8898
9159
  }
8899
9160
  styles.push(css);
8900
- const anchor = { element: "style", data: `${import_ast2.STYLE_ANCHOR_PREFIX}${css}` };
9161
+ const anchor = { element: "style", data: `${import_ast5.STYLE_ANCHOR_PREFIX}${css}` };
8901
9162
  anchors.push(anchor);
8902
9163
  result.push(anchor);
8903
9164
  continue;
@@ -9020,7 +9281,7 @@ function walkAndResolve(elements, ctx) {
9020
9281
  }
9021
9282
 
9022
9283
  // packages/parser/src/parser/rules/block/module/resolution/document.ts
9023
- var import_ast3 = require("@wdprlib/ast");
9284
+ var import_ast6 = require("@wdprlib/ast");
9024
9285
 
9025
9286
  // packages/parser/src/parser/toc.ts
9026
9287
  class TocIndexer {
@@ -9282,11 +9543,11 @@ function walkRenderOrder(elements, pageTags, callback) {
9282
9543
  for (const element of elements) {
9283
9544
  callback(element);
9284
9545
  if (element.element === "if") {
9285
- walkRenderOrder(import_ast3.isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
9546
+ walkRenderOrder(import_ast6.isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
9286
9547
  continue;
9287
9548
  }
9288
9549
  if (element.element === "ifexpr") {
9289
- const evaluated = import_ast3.evaluateExpression(element.data.expression);
9550
+ const evaluated = import_ast6.evaluateExpression(element.data.expression);
9290
9551
  if (evaluated.success) {
9291
9552
  walkRenderOrder(evaluated.value !== 0 ? element.data.then : element.data.else, pageTags, callback);
9292
9553
  }
@@ -9398,11 +9659,11 @@ async function resolveModules(ast, dataProvider, options) {
9398
9659
  if (mergedStyles.length > 0)
9399
9660
  result.styles = mergedStyles;
9400
9661
  options.onDiagnostics?.(registry.diagnostics);
9401
- return registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements));
9662
+ return resolveRatings(registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements)), dataProvider.fetchRatings);
9402
9663
  }
9403
9664
  function createModuleParseFunction(options, dataProvider, registry) {
9404
9665
  const transform = createModuleSourceTransform(options, dataProvider);
9405
- return (source) => registry.register(options.parse(transform ? transform(source) : source), {
9666
+ return (source) => registry.register(suppressModuleRatings(options.parse(transform ? transform(source) : source)), {
9406
9667
  stripLegacyImplicitFootnoteBlock: true
9407
9668
  });
9408
9669
  }
@@ -9419,7 +9680,7 @@ function createModuleSourceTransform(options, dataProvider) {
9419
9680
  }
9420
9681
 
9421
9682
  // packages/parser/src/parser/rules/block/module/index.ts
9422
- var import_ast4 = require("@wdprlib/ast");
9683
+ var import_ast7 = require("@wdprlib/ast");
9423
9684
 
9424
9685
  // packages/parser/src/parser/rules/block/footnoteblock/attributes.ts
9425
9686
  function parseFootnoteBlockAttributes(ctx, startPos) {
@@ -10109,7 +10370,7 @@ var tabviewRule = {
10109
10370
  };
10110
10371
 
10111
10372
  // packages/parser/src/parser/rules/block/include/index.ts
10112
- var import_ast5 = require("@wdprlib/ast");
10373
+ var import_ast8 = require("@wdprlib/ast");
10113
10374
 
10114
10375
  // packages/parser/src/parser/rules/block/include/arguments.ts
10115
10376
  function collectIncludeArguments(ctx, startPos) {
@@ -10242,11 +10503,11 @@ var includeRule = {
10242
10503
  `);
10243
10504
  for (let index = 0;index < lines.length; index++) {
10244
10505
  if (index > 0)
10245
- elements.push(import_ast5.lineBreak());
10506
+ elements.push(import_ast8.lineBreak());
10246
10507
  if (lines[index] !== "")
10247
- elements.push(import_ast5.text(lines[index]));
10508
+ elements.push(import_ast8.text(lines[index]));
10248
10509
  }
10249
- return { success: true, elements: [import_ast5.paragraph(elements)], consumed };
10510
+ return { success: true, elements: [import_ast8.paragraph(elements)], consumed };
10250
10511
  }
10251
10512
  return {
10252
10513
  success: true,
@@ -12875,55 +13136,6 @@ var dateRule = {
12875
13136
  }
12876
13137
  };
12877
13138
 
12878
- // packages/parser/src/parser/rules/inline/size/content.ts
12879
- function parseSizeContent(ctx, startPos) {
12880
- const children = [];
12881
- let pos = startPos;
12882
- let consumed = 0;
12883
- while (pos < ctx.tokens.length) {
12884
- const token5 = ctx.tokens[pos];
12885
- if (!token5 || token5.type === "EOF") {
12886
- break;
12887
- }
12888
- const closeResult = tryConsumeSizeClose(ctx, pos);
12889
- if (closeResult) {
12890
- return {
12891
- children,
12892
- consumed: consumed + closeResult.consumed,
12893
- foundClose: true
12894
- };
12895
- }
12896
- const inlineCtx = { ...ctx, pos };
12897
- const inlineResult = parseInlineUntil(inlineCtx, "BLOCK_END_OPEN");
12898
- if (inlineResult.elements.length > 0) {
12899
- for (const element of inlineResult.elements)
12900
- children.push(element);
12901
- pos += inlineResult.consumed;
12902
- consumed += inlineResult.consumed;
12903
- } else {
12904
- children.push({ element: "text", data: token5.value });
12905
- pos++;
12906
- consumed++;
12907
- }
12908
- }
12909
- return { children, consumed, foundClose: false };
12910
- }
12911
- function tryConsumeSizeClose(ctx, pos) {
12912
- if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
12913
- return null;
12914
- }
12915
- const closeNameResult = parseBlockName(ctx, pos + 1);
12916
- if (!closeNameResult || closeNameResult.name !== "size") {
12917
- return null;
12918
- }
12919
- let closePos = pos + 1 + closeNameResult.consumed;
12920
- let consumed = 1 + closeNameResult.consumed;
12921
- if (ctx.tokens[closePos]?.type === "BLOCK_CLOSE") {
12922
- consumed++;
12923
- }
12924
- return { consumed };
12925
- }
12926
-
12927
13139
  // packages/parser/src/parser/rules/inline/size/value.ts
12928
13140
  var VALID_SIZE_UNITS = ["px", "em", "rem", "ex", "%", "cm", "mm", "in", "pc"];
12929
13141
  var VALID_SIZE_KEYWORDS = [
@@ -12993,6 +13205,81 @@ function parseSizeOpen(ctx) {
12993
13205
  return { size: sizeResult.size, bodyStart: pos, consumed };
12994
13206
  }
12995
13207
 
13208
+ // packages/parser/src/parser/rules/inline/size/content.ts
13209
+ function parseSizeContent(ctx, startPos) {
13210
+ const children = [];
13211
+ let pos = startPos;
13212
+ let consumed = 0;
13213
+ const inlineEnd = findSizeClose(ctx, startPos);
13214
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
13215
+ const token5 = ctx.tokens[pos];
13216
+ if (!token5 || token5.type === "EOF") {
13217
+ break;
13218
+ }
13219
+ const closeResult = tryConsumeSizeClose(ctx, pos);
13220
+ if (closeResult) {
13221
+ return {
13222
+ children,
13223
+ consumed: consumed + closeResult.consumed,
13224
+ foundClose: true
13225
+ };
13226
+ }
13227
+ const inlineCtx = { ...ctx, pos, scope: { ...ctx.scope, inlineEnd } };
13228
+ const inlineResult = parseInlineUntil(inlineCtx, "EOF");
13229
+ if (inlineResult.consumed > 0) {
13230
+ for (const element of inlineResult.elements)
13231
+ children.push(element);
13232
+ pos += inlineResult.consumed;
13233
+ consumed += inlineResult.consumed;
13234
+ } else {
13235
+ children.push({ element: "text", data: token5.value });
13236
+ pos++;
13237
+ consumed++;
13238
+ }
13239
+ }
13240
+ return { children, consumed, foundClose: false };
13241
+ }
13242
+ function findSizeClose(ctx, startPos) {
13243
+ const end = ctx.scope.inlineEnd ?? ctx.tokens.length;
13244
+ let depth = 0;
13245
+ for (let pos = startPos;pos < end; pos++) {
13246
+ const protectedEnd = protectedInlineRegionEnd(ctx.tokens, pos, end);
13247
+ if (protectedEnd > pos) {
13248
+ pos = protectedEnd - 1;
13249
+ continue;
13250
+ }
13251
+ const open = ctx.tokens[pos]?.type === "BLOCK_OPEN" ? parseSizeOpen({ ...ctx, pos }) : null;
13252
+ if (open) {
13253
+ depth++;
13254
+ pos = open.bodyStart - 1;
13255
+ continue;
13256
+ }
13257
+ const close = tryConsumeSizeClose(ctx, pos);
13258
+ if (!close)
13259
+ continue;
13260
+ if (depth === 0)
13261
+ return pos;
13262
+ depth--;
13263
+ pos += close.consumed - 1;
13264
+ }
13265
+ return end;
13266
+ }
13267
+ function tryConsumeSizeClose(ctx, pos) {
13268
+ if (ctx.tokens[pos]?.type !== "BLOCK_END_OPEN") {
13269
+ return null;
13270
+ }
13271
+ const closeNameResult = parseBlockName(ctx, pos + 1);
13272
+ if (!closeNameResult || closeNameResult.name !== "size") {
13273
+ return null;
13274
+ }
13275
+ let closePos = pos + 1 + closeNameResult.consumed;
13276
+ let consumed = 1 + closeNameResult.consumed;
13277
+ if (ctx.tokens[closePos]?.type === "BLOCK_CLOSE") {
13278
+ consumed++;
13279
+ }
13280
+ return { consumed };
13281
+ }
13282
+
12996
13283
  // packages/parser/src/parser/rules/inline/size/index.ts
12997
13284
  var sizeRule = {
12998
13285
  name: "size",
@@ -14289,7 +14576,7 @@ function createParseContext(tokens, options = {}, deferInclude) {
14289
14576
  pos: 0,
14290
14577
  version: options.version ?? "wikidot",
14291
14578
  trackPositions: options.trackPositions ?? true,
14292
- settings: options.settings ?? import_ast6.DEFAULT_SETTINGS,
14579
+ settings: options.settings ?? import_ast9.DEFAULT_SETTINGS,
14293
14580
  appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
14294
14581
  deferInclude,
14295
14582
  footnotes: [],
@@ -15205,12 +15492,12 @@ function matchDirectiveKind(source, i) {
15205
15492
  }
15206
15493
 
15207
15494
  // packages/parser/src/parser/preprocess/expr/evaluate.ts
15208
- var import_ast7 = require("@wdprlib/ast");
15495
+ var import_ast10 = require("@wdprlib/ast");
15209
15496
  function evaluateDirective(kind, match) {
15210
15497
  if (kind === "expr") {
15211
- const result2 = import_ast7.evaluateExpression(match.head);
15498
+ const result2 = import_ast10.evaluateExpression(match.head);
15212
15499
  if (result2.success)
15213
- return import_ast7.formatExprValue(result2.value);
15500
+ return import_ast10.formatExprValue(result2.value);
15214
15501
  if (result2.error === "empty expression")
15215
15502
  return "";
15216
15503
  return "ERROR";
@@ -15218,11 +15505,11 @@ function evaluateDirective(kind, match) {
15218
15505
  if (kind === "if") {
15219
15506
  if (!match.hasPipe)
15220
15507
  return "";
15221
- return import_ast7.isTruthy(match.head) ? match.thenText : match.elseText;
15508
+ return import_ast10.isTruthy(match.head) ? match.thenText : match.elseText;
15222
15509
  }
15223
15510
  if (!match.hasPipe)
15224
15511
  return "";
15225
- const result = import_ast7.evaluateExpression(match.head);
15512
+ const result = import_ast10.evaluateExpression(match.head);
15226
15513
  if (!result.success)
15227
15514
  return "ERROR";
15228
15515
  return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
@@ -15404,13 +15691,13 @@ function parseSource(source, options, deferInclude) {
15404
15691
  return deferInclude ? parseTokensWithIncludeDeferral(tokens, options ?? {}, deferInclude) : new Parser(tokens, options).parse();
15405
15692
  }
15406
15693
  // packages/parser/src/pipeline/process.ts
15407
- var import_ast8 = require("@wdprlib/ast");
15694
+ var import_ast11 = require("@wdprlib/ast");
15408
15695
 
15409
15696
  // packages/parser/src/parser/rules/block/module/resolution/resolve-async.ts
15410
15697
  async function resolveModulesWithAsyncParse(ast, dataProvider, options) {
15411
15698
  const registry = new ModuleDocumentRegistry;
15412
15699
  registry.register(ast);
15413
- const parse2 = async (source) => registry.register(await options.parse(source));
15700
+ const parse2 = async (source) => registry.register(suppressModuleRatings(await options.parse(source)));
15414
15701
  const [listPagesData, listUsersData, tagCloudData] = await Promise.all([
15415
15702
  buildListPagesDataMap(dataProvider, options.requirements.listPages ?? [], options.urlPath, options.paginationState),
15416
15703
  buildListUsersDataMap(dataProvider, options.requirements.listUsers ?? []),
@@ -15587,7 +15874,7 @@ var PIPELINE_DIAGNOSTIC_POSITION = {
15587
15874
  end: { line: 1, column: 1, offset: 0 }
15588
15875
  };
15589
15876
  async function processWikitext(source, options) {
15590
- const settings = options.settings ?? import_ast8.DEFAULT_SETTINGS;
15877
+ const settings = options.settings ?? import_ast11.DEFAULT_SETTINGS;
15591
15878
  const callbackContext = {
15592
15879
  page: options.page,
15593
15880
  settings
@@ -15646,8 +15933,13 @@ async function processWikitext(source, options) {
15646
15933
  if (hasResolvableRequirements(extractDataRequirements(ast).requirements, options.dataProvider)) {
15647
15934
  diagnostics.push(createLimitDiagnostic("module-resolution-limit", `Module resolution stopped after ${DEFAULT_MODULE_MAX_PASSES} passes.`));
15648
15935
  }
15936
+ ast = await resolveRatings(ast, dataProvider.fetchRatings);
15937
+ const readableText = import_ast11.extractReadableText(ast, options.readableText);
15649
15938
  return {
15650
15939
  ast,
15940
+ readableText,
15941
+ firstParagraph: import_ast11.extractFirstParagraph(ast, options.readableText),
15942
+ characterCount: import_ast11.countCharacters(readableText),
15651
15943
  page: options.page,
15652
15944
  settings,
15653
15945
  diagnostics,
@@ -15676,6 +15968,7 @@ function createLimitDiagnostic(code, message) {
15676
15968
  function createModuleDataProvider(options, context) {
15677
15969
  const provider = options.dataProvider;
15678
15970
  return {
15971
+ fetchRatings: provider?.fetchRatings ? (refs) => provider.fetchRatings(refs, context) : undefined,
15679
15972
  fetchListPages: provider?.fetchListPages ? (query, requirement) => provider.fetchListPages(query, requirement, context) : undefined,
15680
15973
  fetchListUsers: provider?.fetchListUsers ? (requirement) => provider.fetchListUsers(requirement, context) : undefined,
15681
15974
  fetchTagCloud: provider?.fetchTagCloud ? (requirement) => provider.fetchTagCloud(requirement, context) : undefined,