@wdprlib/parser 4.0.0 → 4.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 (26) hide show
  1. package/README.md +9 -1
  2. package/dist/index.cjs +345 -64
  3. package/dist/index.d.cts +121 -2
  4. package/dist/index.d.ts +121 -2
  5. package/dist/index.js +317 -36
  6. package/package.json +2 -2
  7. package/src/index.ts +9 -0
  8. package/src/parser/rules/block/module/index.ts +10 -0
  9. package/src/parser/rules/block/module/listpages/extract.ts +9 -0
  10. package/src/parser/rules/block/module/listpages/extraction/tagcloud.ts +25 -0
  11. package/src/parser/rules/block/module/listpages/types/data-requirements.ts +2 -0
  12. package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +4 -4
  13. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +12 -1
  14. package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +10 -1
  15. package/src/parser/rules/block/module/listpages/url-resolution/value.ts +13 -4
  16. package/src/parser/rules/block/module/mapping.ts +2 -0
  17. package/src/parser/rules/block/module/resolution/contexts.ts +29 -1
  18. package/src/parser/rules/block/module/resolution/data-maps.ts +17 -0
  19. package/src/parser/rules/block/module/resolution/dynamic-modules.ts +29 -2
  20. package/src/parser/rules/block/module/resolution/walk-resolve.ts +28 -4
  21. package/src/parser/rules/block/module/resolve.ts +11 -1
  22. package/src/parser/rules/block/module/tagcloud/index.ts +15 -0
  23. package/src/parser/rules/block/module/tagcloud/parser.ts +127 -0
  24. package/src/parser/rules/block/module/tagcloud/resolve.ts +173 -0
  25. package/src/parser/rules/block/module/tagcloud/types.ts +85 -0
  26. package/src/parser/rules/block/module/types-common.ts +15 -0
package/dist/index.cjs CHANGED
@@ -31,7 +31,8 @@ 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
+ resolveTagCloud: () => resolveTagCloud,
35
36
  resolveModules: () => resolveModules,
36
37
  resolveListUsers: () => resolveListUsers,
37
38
  resolveIncludesWithTrace: () => resolveIncludesWithTrace,
@@ -45,36 +46,37 @@ __export(exports_src, {
45
46
  parseDateSelector: () => parseDateSelector,
46
47
  parseCategory: () => parseCategory,
47
48
  parse: () => parse,
48
- paragraph: () => import_ast5.paragraph,
49
+ paragraph: () => import_ast6.paragraph,
49
50
  normalizeQuery: () => normalizeQuery,
50
- listItemSubList: () => import_ast5.listItemSubList,
51
- listItemElements: () => import_ast5.listItemElements,
52
- list: () => import_ast5.list,
53
- link: () => import_ast5.link,
54
- lineBreak: () => import_ast5.lineBreak,
55
- italics: () => import_ast5.italics,
51
+ listItemSubList: () => import_ast6.listItemSubList,
52
+ listItemElements: () => import_ast6.listItemElements,
53
+ list: () => import_ast6.list,
54
+ link: () => import_ast6.link,
55
+ lineBreak: () => import_ast6.lineBreak,
56
+ italics: () => import_ast6.italics,
57
+ isTagCloudModule: () => isTagCloudModule,
56
58
  isListUsersModule: () => isListUsersModule2,
57
- horizontalRule: () => import_ast5.horizontalRule,
58
- heading: () => import_ast5.heading,
59
+ horizontalRule: () => import_ast6.horizontalRule,
60
+ heading: () => import_ast6.heading,
59
61
  extractListUsersVariables: () => extractListUsersVariables,
60
62
  extractIncludeReferences: () => extractIncludeReferences,
61
63
  extractDataRequirements: () => extractDataRequirements,
62
64
  createToken: () => createToken,
63
- createSettings: () => import_ast6.createSettings,
64
- createPosition: () => import_ast5.createPosition,
65
- createPoint: () => import_ast5.createPoint,
66
- container: () => import_ast5.container,
65
+ createSettings: () => import_ast7.createSettings,
66
+ createPosition: () => import_ast6.createPosition,
67
+ createPoint: () => import_ast6.createPoint,
68
+ container: () => import_ast6.container,
67
69
  compileTemplate: () => compileTemplate,
68
70
  compileListUsersTemplate: () => compileListUsersTemplate,
69
- bold: () => import_ast5.bold,
70
- STYLE_SLOT_PREFIX: () => import_ast2.STYLE_SLOT_PREFIX,
71
+ bold: () => import_ast6.bold,
72
+ STYLE_SLOT_PREFIX: () => import_ast3.STYLE_SLOT_PREFIX,
71
73
  Parser: () => Parser,
72
74
  Lexer: () => Lexer,
73
- DEFAULT_SETTINGS: () => import_ast6.DEFAULT_SETTINGS
75
+ DEFAULT_SETTINGS: () => import_ast7.DEFAULT_SETTINGS
74
76
  });
75
77
  module.exports = __toCommonJS(exports_src);
76
- var import_ast5 = require("@wdprlib/ast");
77
78
  var import_ast6 = require("@wdprlib/ast");
79
+ var import_ast7 = require("@wdprlib/ast");
78
80
 
79
81
  // packages/parser/src/lexer/tokens.ts
80
82
  function createToken(type, value, position, lineStart = false) {
@@ -1441,7 +1443,7 @@ function parseNextBlock(ctx, skipWhitespace2, isAtEnd2) {
1441
1443
  }
1442
1444
 
1443
1445
  // packages/parser/src/parser/parse/context.ts
1444
- var import_ast3 = require("@wdprlib/ast");
1446
+ var import_ast4 = require("@wdprlib/ast");
1445
1447
 
1446
1448
  // packages/parser/src/parser/rules/tokens.ts
1447
1449
  function currentToken(ctx) {
@@ -4527,6 +4529,92 @@ var listUsersModuleRule = {
4527
4529
  }
4528
4530
  };
4529
4531
 
4532
+ // packages/parser/src/parser/rules/block/module/tagcloud/parser.ts
4533
+ var import_ast = require("@wdprlib/ast");
4534
+ var FONT_SIZE_PATTERN = new RegExp(`^([0-9]+)(${import_ast.CSS_LENGTH_UNITS.join("|")})$`, "i");
4535
+ var COLOR_PATTERN = /^[0-9]+,[0-9]+,[0-9]+$/;
4536
+ var POSITIVE_INT_PATTERN = /^[0-9]+$/;
4537
+ var ERROR_FONT_FORMAT = "Unsupported format for font size. Use a number followed by a CSS length unit such as px, em or %.";
4538
+ var ERROR_FONT_MISMATCH = "Format for minFontSize and maxFontSize must use the same unit.";
4539
+ var ERROR_COLOR_FORMAT = 'Unsupported color format. Use "RRR,GGG,BBB" for Red,Green,Blue each within 0-255 range.';
4540
+ function errorBlock(message) {
4541
+ return {
4542
+ element: "container",
4543
+ data: {
4544
+ type: "div",
4545
+ attributes: { class: "error-block" },
4546
+ elements: [{ element: "text", data: message }]
4547
+ }
4548
+ };
4549
+ }
4550
+ function parseLimit(value) {
4551
+ if (!value || !POSITIVE_INT_PATTERN.test(value))
4552
+ return 50;
4553
+ const num = Number.parseInt(value, 10);
4554
+ return Number.isSafeInteger(num) && num > 0 ? num : 50;
4555
+ }
4556
+ function normalizeTarget(value) {
4557
+ if (!value)
4558
+ return "/system:page-tags/tag/";
4559
+ let target = value;
4560
+ if (!target.startsWith("/"))
4561
+ target = `/${target}`;
4562
+ if (!target.endsWith("/"))
4563
+ target = `${target}/`;
4564
+ return `${target}tag/`;
4565
+ }
4566
+ function parseColor(value) {
4567
+ const [r = 0, g = 0, b = 0] = value.split(",").map((part) => Number.parseInt(part, 10));
4568
+ return [r, g, b];
4569
+ }
4570
+ var tagCloudModuleRule = {
4571
+ name: "module-tagcloud",
4572
+ acceptsNames: ["tagcloud"],
4573
+ hasBody: false,
4574
+ parse(_ctx, _pos, args) {
4575
+ const maxFontSize = args.maxfontsize;
4576
+ const minFontSize = args.minfontsize;
4577
+ const maxColor = args.maxcolor;
4578
+ const minColor = args.mincolor;
4579
+ let sizeSmall = 100;
4580
+ let sizeBig = 300;
4581
+ let fontSizeUnit = "%";
4582
+ if (maxFontSize && minFontSize) {
4583
+ const maxMatch = FONT_SIZE_PATTERN.exec(maxFontSize);
4584
+ if (!maxMatch)
4585
+ return errorBlock(ERROR_FONT_FORMAT);
4586
+ const maxUnit = maxMatch[2].toLowerCase();
4587
+ const minMatch = FONT_SIZE_PATTERN.exec(minFontSize);
4588
+ if (!minMatch || minMatch[2].toLowerCase() !== maxUnit) {
4589
+ return errorBlock(ERROR_FONT_MISMATCH);
4590
+ }
4591
+ sizeBig = Number.parseInt(maxMatch[1], 10);
4592
+ sizeSmall = Number.parseInt(minMatch[1], 10);
4593
+ fontSizeUnit = maxUnit;
4594
+ }
4595
+ let colorSmall = [128, 128, 192];
4596
+ let colorBig = [64, 64, 128];
4597
+ if (maxColor && minColor) {
4598
+ if (!COLOR_PATTERN.test(maxColor) || !COLOR_PATTERN.test(minColor)) {
4599
+ return errorBlock(ERROR_COLOR_FORMAT);
4600
+ }
4601
+ colorSmall = parseColor(minColor);
4602
+ colorBig = parseColor(maxColor);
4603
+ }
4604
+ return {
4605
+ module: "tag-cloud",
4606
+ "min-font-size": sizeSmall,
4607
+ "max-font-size": sizeBig,
4608
+ "font-size-unit": fontSizeUnit,
4609
+ "min-color": colorSmall,
4610
+ "max-color": colorBig,
4611
+ target: normalizeTarget(args.target),
4612
+ limit: parseLimit(args.limit),
4613
+ category: args.category || null
4614
+ };
4615
+ }
4616
+ };
4617
+
4530
4618
  // packages/parser/src/parser/rules/block/module/mapping.ts
4531
4619
  var MODULE_RULES = [
4532
4620
  rateModuleRule,
@@ -4536,7 +4624,8 @@ var MODULE_RULES = [
4536
4624
  joinModuleRule,
4537
4625
  pageTreeModuleRule,
4538
4626
  listPagesModuleRule,
4539
- listUsersModuleRule
4627
+ listUsersModuleRule,
4628
+ tagCloudModuleRule
4540
4629
  ];
4541
4630
  var moduleRuleMap = new Map;
4542
4631
  for (const rule of MODULE_RULES) {
@@ -5617,18 +5706,130 @@ function extractListUsersModule(listUsers, state, result) {
5617
5706
  result.compiledListUsersTemplates.set(id, compileListUsersTemplate(body));
5618
5707
  }
5619
5708
 
5709
+ // packages/parser/src/parser/rules/block/module/tagcloud/resolve.ts
5710
+ function isTagCloudModule(module2) {
5711
+ return module2.module === "tag-cloud";
5712
+ }
5713
+ var NO_TAGS_MESSAGE_PREFIX = "It seems you have no tags attached to pages. To attach a tag simply click on the ";
5714
+ var NO_TAGS_MESSAGE_SUFFIX = " button at the bottom of any page.";
5715
+ function rawUrlEncode(value) {
5716
+ return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
5717
+ }
5718
+ function selectTags(tags, limit) {
5719
+ return tags.toSorted((a, b) => b.weight - a.weight || compareTags(a.tag, b.tag)).slice(0, limit).toSorted((a, b) => compareTags(a.tag, b.tag));
5720
+ }
5721
+ function compareTags(a, b) {
5722
+ return a < b ? -1 : a > b ? 1 : 0;
5723
+ }
5724
+ function resolveTagCloud(module2, data) {
5725
+ if (data.status === "category-not-found") {
5726
+ return [
5727
+ {
5728
+ element: "container",
5729
+ data: {
5730
+ type: "div",
5731
+ attributes: { class: "error-block" },
5732
+ elements: [{ element: "text", data: `Category "${data.category}" can not be found.` }]
5733
+ }
5734
+ }
5735
+ ];
5736
+ }
5737
+ const tags = selectTags(data.tags, module2.limit);
5738
+ if (tags.length === 0) {
5739
+ return [noTagsMessage()];
5740
+ }
5741
+ let minWeight = Number.POSITIVE_INFINITY;
5742
+ let maxWeight = Number.NEGATIVE_INFINITY;
5743
+ for (const tag of tags) {
5744
+ if (tag.weight < minWeight)
5745
+ minWeight = tag.weight;
5746
+ if (tag.weight > maxWeight)
5747
+ maxWeight = tag.weight;
5748
+ }
5749
+ const weightRange = maxWeight - minWeight;
5750
+ const categorySuffix = data.category !== null ? `/category/${rawUrlEncode(data.category)}` : "";
5751
+ const anchors = [];
5752
+ for (const tag of tags) {
5753
+ const a = weightRange === 0 ? 0 : (tag.weight - minWeight) / weightRange;
5754
+ const fontSize = interpolate(module2["min-font-size"], module2["max-font-size"], a);
5755
+ const [r, g, b] = [0, 1, 2].map((i) => interpolate(module2["min-color"][i], module2["max-color"][i], a));
5756
+ anchors.push({ element: "text", data: `
5757
+ ` });
5758
+ anchors.push({
5759
+ element: "anchor",
5760
+ data: {
5761
+ target: null,
5762
+ attributes: {
5763
+ class: "tag",
5764
+ href: `${module2.target}${rawUrlEncode(tag.tag)}${categorySuffix}`,
5765
+ style: `font-size: ${fontSize}${module2["font-size-unit"]}; color: rgb(${r}, ${g}, ${b});`
5766
+ },
5767
+ elements: [{ element: "text", data: tag.tag }]
5768
+ }
5769
+ });
5770
+ }
5771
+ anchors.push({ element: "text", data: `
5772
+ ` });
5773
+ return [
5774
+ {
5775
+ element: "container",
5776
+ data: {
5777
+ type: "div",
5778
+ attributes: { class: "pages-tag-cloud-box" },
5779
+ elements: anchors
5780
+ }
5781
+ }
5782
+ ];
5783
+ }
5784
+ function interpolate(min, max, a) {
5785
+ return Math.round(min + (max - min) * a);
5786
+ }
5787
+ function noTagsMessage() {
5788
+ return {
5789
+ element: "container",
5790
+ data: {
5791
+ type: "paragraph",
5792
+ attributes: {},
5793
+ elements: [
5794
+ { element: "text", data: NO_TAGS_MESSAGE_PREFIX },
5795
+ {
5796
+ element: "container",
5797
+ data: {
5798
+ type: "italics",
5799
+ attributes: {},
5800
+ elements: [{ element: "text", data: "tags" }]
5801
+ }
5802
+ },
5803
+ { element: "text", data: NO_TAGS_MESSAGE_SUFFIX }
5804
+ ]
5805
+ }
5806
+ };
5807
+ }
5808
+
5809
+ // packages/parser/src/parser/rules/block/module/listpages/extraction/tagcloud.ts
5810
+ function extractTagCloudModule(tagCloud, state, result) {
5811
+ const id = state.nextId++;
5812
+ result.requirements.tagCloud.push({
5813
+ id,
5814
+ category: tagCloud.category,
5815
+ limit: tagCloud.limit
5816
+ });
5817
+ }
5818
+
5620
5819
  // packages/parser/src/parser/rules/block/module/listpages/extract.ts
5621
5820
  function extractDataRequirements(ast) {
5622
5821
  const result = {
5623
5822
  requirements: {
5624
5823
  listPages: [],
5625
- listUsers: []
5824
+ listUsers: [],
5825
+ tagCloud: []
5626
5826
  },
5627
5827
  compiledListPagesTemplates: new Map,
5628
5828
  compiledListUsersTemplates: new Map
5629
5829
  };
5630
5830
  const listPagesState = { nextId: 0 };
5631
5831
  const listUsersState = { nextId: 0 };
5832
+ const tagCloudState = { nextId: 0 };
5632
5833
  walkElements(ast.elements, (element) => {
5633
5834
  if (element.element !== "module")
5634
5835
  return;
@@ -5636,6 +5837,8 @@ function extractDataRequirements(ast) {
5636
5837
  extractListPagesModule(element.data, listPagesState, result);
5637
5838
  } else if (isListUsersModule(element.data)) {
5638
5839
  extractListUsersModule(element.data, listUsersState, result);
5840
+ } else if (isTagCloudModule(element.data)) {
5841
+ extractTagCloudModule(element.data, tagCloudState, result);
5639
5842
  }
5640
5843
  });
5641
5844
  return result;
@@ -5709,11 +5912,32 @@ function resolveListPages(module2, data, compiledTemplate, parse) {
5709
5912
  const items = renderListPagesItems(module2, data, compiledTemplate, parse);
5710
5913
  return wrapListPagesResult(module2, items, parse);
5711
5914
  }
5915
+ // packages/parser/src/parser/rules/block/module/listpages/url-resolution/fields.ts
5916
+ var URL_RESOLVABLE_FIELDS = [
5917
+ { attr: "offset", queryKey: "offset", type: "number" },
5918
+ { attr: "limit", queryKey: "limit", type: "number" },
5919
+ { attr: "per-page", queryKey: "perPage", type: "number" },
5920
+ { attr: "order", queryKey: "order", type: "string" },
5921
+ { attr: "tags", queryKey: "tags", type: "string", urlAttrs: ["tag"] },
5922
+ { attr: "category", queryKey: "category", type: "string" },
5923
+ { attr: "parent", queryKey: "parent", type: "string" },
5924
+ { attr: "range", queryKey: "range", type: "string" },
5925
+ { attr: "name", queryKey: "name", type: "string" },
5926
+ { attr: "fullname", queryKey: "fullname", type: "string" },
5927
+ { attr: "created-at", queryKey: "createdAt", type: "string" },
5928
+ { attr: "updated-at", queryKey: "updatedAt", type: "string" },
5929
+ { attr: "created-by", queryKey: "createdBy", type: "string" },
5930
+ { attr: "rating", queryKey: "rating", type: "string" },
5931
+ { attr: "votes", queryKey: "votes", type: "string" },
5932
+ { attr: "reverse", queryKey: "reverse", type: "boolean" }
5933
+ ];
5934
+
5712
5935
  // packages/parser/src/parser/rules/block/module/listpages/url-resolution/params.ts
5713
5936
  function parseUrlParams(url) {
5714
5937
  const params = new Map;
5715
5938
  const parts = url.split("/").filter(Boolean);
5716
- for (let i = 1;i < parts.length - 1; i += 2) {
5939
+ const pairStart = isUrlParameter(parts[0]) ? 0 : 1;
5940
+ for (let i = pairStart;i < parts.length - 1; i += 2) {
5717
5941
  const key = parts[i];
5718
5942
  const value = parts[i + 1];
5719
5943
  if (key && value) {
@@ -5722,6 +5946,10 @@ function parseUrlParams(url) {
5722
5946
  }
5723
5947
  return params;
5724
5948
  }
5949
+ var URL_PARAMETER_NAMES = new Set(URL_RESOLVABLE_FIELDS.flatMap((field) => [field.attr, ...field.urlAttrs ?? []]));
5950
+ function isUrlParameter(param) {
5951
+ return param !== undefined && URL_PARAMETER_NAMES.has(param);
5952
+ }
5725
5953
  // packages/parser/src/parser/rules/block/module/listpages/normalization/tags-category.ts
5726
5954
  var TOKEN_SEPARATOR = /[,;\s]+/;
5727
5955
  function parseTags(value) {
@@ -5977,26 +6205,6 @@ function normalizeQuery(query) {
5977
6205
  return result;
5978
6206
  }
5979
6207
 
5980
- // packages/parser/src/parser/rules/block/module/listpages/url-resolution/fields.ts
5981
- var URL_RESOLVABLE_FIELDS = [
5982
- { attr: "offset", queryKey: "offset", type: "number" },
5983
- { attr: "limit", queryKey: "limit", type: "number" },
5984
- { attr: "per-page", queryKey: "perPage", type: "number" },
5985
- { attr: "order", queryKey: "order", type: "string" },
5986
- { attr: "tags", queryKey: "tags", type: "string" },
5987
- { attr: "category", queryKey: "category", type: "string" },
5988
- { attr: "parent", queryKey: "parent", type: "string" },
5989
- { attr: "range", queryKey: "range", type: "string" },
5990
- { attr: "name", queryKey: "name", type: "string" },
5991
- { attr: "fullname", queryKey: "fullname", type: "string" },
5992
- { attr: "created-at", queryKey: "createdAt", type: "string" },
5993
- { attr: "updated-at", queryKey: "updatedAt", type: "string" },
5994
- { attr: "created-by", queryKey: "createdBy", type: "string" },
5995
- { attr: "rating", queryKey: "rating", type: "string" },
5996
- { attr: "votes", queryKey: "votes", type: "string" },
5997
- { attr: "reverse", queryKey: "reverse", type: "boolean" }
5998
- ];
5999
-
6000
6208
  // packages/parser/src/parser/rules/block/module/listpages/url-resolution/query.ts
6001
6209
  function assignResolvedUrlField(query, field, value) {
6002
6210
  switch (field.type) {
@@ -6017,15 +6225,23 @@ function assignResolvedUrlField(query, field, value) {
6017
6225
  }
6018
6226
 
6019
6227
  // packages/parser/src/parser/rules/block/module/listpages/url-resolution/value.ts
6020
- function resolveUrlValue(rawValue, paramName, urlParams, prefix) {
6228
+ function resolveUrlValue(rawValue, paramNames, urlParams, prefix) {
6021
6229
  if (!rawValue)
6022
6230
  return;
6023
6231
  if (!rawValue.startsWith("@URL")) {
6024
6232
  return rawValue;
6025
6233
  }
6026
6234
  const defaultValue = rawValue.includes("|") ? rawValue.split("|")[1] : undefined;
6027
- const actualParamName = prefix ? `${prefix}_${paramName}` : paramName;
6028
- return urlParams.get(actualParamName) ?? defaultValue;
6235
+ for (const paramName of toParamNames(paramNames)) {
6236
+ const actualParamName = prefix ? `${prefix}_${paramName}` : paramName;
6237
+ const value = urlParams.get(actualParamName);
6238
+ if (value !== undefined)
6239
+ return value;
6240
+ }
6241
+ return defaultValue;
6242
+ }
6243
+ function toParamNames(paramNames) {
6244
+ return typeof paramNames === "string" ? [paramNames] : paramNames;
6029
6245
  }
6030
6246
 
6031
6247
  // packages/parser/src/parser/rules/block/module/listpages/url-resolution/resolve.ts
@@ -6036,13 +6252,16 @@ function resolveQuery(requirement, urlParams) {
6036
6252
  const rawValue = rawAttributes[field.attr];
6037
6253
  if (!rawValue)
6038
6254
  continue;
6039
- const resolvedValue = resolveUrlValue(rawValue, field.attr, urlParams, urlAttrPrefix);
6255
+ const resolvedValue = resolveUrlValue(rawValue, getUrlParamNames(field), urlParams, urlAttrPrefix);
6040
6256
  if (resolvedValue === undefined)
6041
6257
  continue;
6042
6258
  assignResolvedUrlField(resolved, field, resolvedValue);
6043
6259
  }
6044
6260
  return resolved;
6045
6261
  }
6262
+ function getUrlParamNames(field) {
6263
+ return field.urlAttrs ? [field.attr, ...field.urlAttrs] : [field.attr];
6264
+ }
6046
6265
  function resolveAndNormalizeQuery(requirement, urlParams) {
6047
6266
  const resolved = resolveQuery(requirement, urlParams);
6048
6267
  return normalizeQuery(resolved);
@@ -6735,6 +6954,16 @@ async function buildListUsersDataMap(dataProvider, requirements) {
6735
6954
  }
6736
6955
  return dataMap;
6737
6956
  }
6957
+ async function buildTagCloudDataMap(dataProvider, requirements) {
6958
+ const dataMap = new Map;
6959
+ for (const req of requirements) {
6960
+ const data = await dataProvider.fetchTagCloud?.(req);
6961
+ if (data) {
6962
+ dataMap.set(req.id, data);
6963
+ }
6964
+ }
6965
+ return dataMap;
6966
+ }
6738
6967
 
6739
6968
  // packages/parser/src/parser/rules/block/module/resolution/contexts.ts
6740
6969
  async function buildListPagesContext(dataProvider, requirements, compiledTemplates, parse, urlPath) {
@@ -6751,6 +6980,16 @@ async function buildListPagesContext(dataProvider, requirements, compiledTemplat
6751
6980
  parse
6752
6981
  };
6753
6982
  }
6983
+ async function buildTagCloudContext(dataProvider, requirements) {
6984
+ if (requirements.length === 0 || !dataProvider.fetchTagCloud) {
6985
+ return null;
6986
+ }
6987
+ const dataMap = await buildTagCloudDataMap(dataProvider, requirements);
6988
+ if (dataMap.size === 0) {
6989
+ return null;
6990
+ }
6991
+ return { dataMap };
6992
+ }
6754
6993
  async function buildListUsersContext(dataProvider, requirements, compiledTemplates, parse) {
6755
6994
  if (requirements.length === 0 || !dataProvider.fetchListUsers) {
6756
6995
  return null;
@@ -6807,10 +7046,27 @@ function resolveDynamicModuleElement(element, ctx, ids) {
6807
7046
  ids: { ...ids, listUsersId: listUsersId + 1 }
6808
7047
  };
6809
7048
  }
7049
+ if (isTagCloudModule(element.data)) {
7050
+ const elements = [];
7051
+ const tagCloudId = ids.tagCloudId;
7052
+ if (ctx.tagCloud) {
7053
+ const moduleData = ctx.tagCloud.dataMap.get(tagCloudId);
7054
+ if (moduleData) {
7055
+ elements.push(...resolveTagCloud(element.data, moduleData));
7056
+ }
7057
+ } else if (!ctx.fetchTagCloudProvided) {
7058
+ elements.push(element);
7059
+ }
7060
+ return {
7061
+ handled: true,
7062
+ elements,
7063
+ ids: { ...ids, tagCloudId: tagCloudId + 1 }
7064
+ };
7065
+ }
6810
7066
  return { handled: false, elements: [element], ids };
6811
7067
  }
6812
7068
  function countDynamicModules(elements) {
6813
- const counts = { listPagesId: 0, listUsersId: 0 };
7069
+ const counts = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
6814
7070
  walkElements(elements, (element) => {
6815
7071
  if (element.element !== "module")
6816
7072
  return;
@@ -6818,6 +7074,8 @@ function countDynamicModules(elements) {
6818
7074
  counts.listPagesId++;
6819
7075
  } else if (isListUsersModule2(element.data)) {
6820
7076
  counts.listUsersId++;
7077
+ } else if (isTagCloudModule(element.data)) {
7078
+ counts.tagCloudId++;
6821
7079
  }
6822
7080
  });
6823
7081
  return counts;
@@ -6828,12 +7086,18 @@ function walkAndResolve(elements, ctx) {
6828
7086
  const result = [];
6829
7087
  let listPagesId = ctx.listPagesIdCounter;
6830
7088
  let listUsersId = ctx.listUsersIdCounter;
7089
+ let tagCloudId = ctx.tagCloudIdCounter;
6831
7090
  for (const element of elements) {
6832
- const dynamicModule = resolveDynamicModuleElement(element, ctx, { listPagesId, listUsersId });
7091
+ const dynamicModule = resolveDynamicModuleElement(element, ctx, {
7092
+ listPagesId,
7093
+ listUsersId,
7094
+ tagCloudId
7095
+ });
6833
7096
  if (dynamicModule.handled) {
6834
7097
  result.push(...dynamicModule.elements);
6835
7098
  listPagesId = dynamicModule.ids.listPagesId;
6836
7099
  listUsersId = dynamicModule.ids.listUsersId;
7100
+ tagCloudId = dynamicModule.ids.tagCloudId;
6837
7101
  continue;
6838
7102
  }
6839
7103
  if (isIfTagsElement(element)) {
@@ -6844,21 +7108,25 @@ function walkAndResolve(elements, ctx) {
6844
7108
  const childResult = walkAndResolve(ifTagsData.elements, {
6845
7109
  ...ctx,
6846
7110
  listPagesIdCounter: listPagesId,
6847
- listUsersIdCounter: listUsersId
7111
+ listUsersIdCounter: listUsersId,
7112
+ tagCloudIdCounter: tagCloudId
6848
7113
  });
6849
7114
  result.push(...childResult.elements);
6850
7115
  listPagesId = childResult.nextListPagesId;
6851
7116
  listUsersId = childResult.nextListUsersId;
7117
+ tagCloudId = childResult.nextTagCloudId;
6852
7118
  } else {
6853
7119
  const counts = countDynamicModules(ifTagsData.elements);
6854
7120
  listPagesId += counts.listPagesId;
6855
7121
  listUsersId += counts.listUsersId;
7122
+ tagCloudId += counts.tagCloudId;
6856
7123
  }
6857
7124
  } else {
6858
7125
  const childResult = walkAndResolve(ifTagsData.elements, {
6859
7126
  ...ctx,
6860
7127
  listPagesIdCounter: listPagesId,
6861
- listUsersIdCounter: listUsersId
7128
+ listUsersIdCounter: listUsersId,
7129
+ tagCloudIdCounter: tagCloudId
6862
7130
  });
6863
7131
  result.push({
6864
7132
  element: "if-tags",
@@ -6869,32 +7137,41 @@ function walkAndResolve(elements, ctx) {
6869
7137
  });
6870
7138
  listPagesId = childResult.nextListPagesId;
6871
7139
  listUsersId = childResult.nextListUsersId;
7140
+ tagCloudId = childResult.nextTagCloudId;
6872
7141
  }
6873
7142
  continue;
6874
7143
  }
6875
- const mapped = mapElementChildrenWithState(element, { listPagesId, listUsersId }, (children, state) => {
7144
+ const mapped = mapElementChildrenWithState(element, { listPagesId, listUsersId, tagCloudId }, (children, state) => {
6876
7145
  const childResult = walkAndResolve(children, {
6877
7146
  ...ctx,
6878
7147
  listPagesIdCounter: state.listPagesId,
6879
- listUsersIdCounter: state.listUsersId
7148
+ listUsersIdCounter: state.listUsersId,
7149
+ tagCloudIdCounter: state.tagCloudId
6880
7150
  });
6881
7151
  return {
6882
7152
  elements: childResult.elements,
6883
7153
  state: {
6884
7154
  listPagesId: childResult.nextListPagesId,
6885
- listUsersId: childResult.nextListUsersId
7155
+ listUsersId: childResult.nextListUsersId,
7156
+ tagCloudId: childResult.nextTagCloudId
6886
7157
  }
6887
7158
  };
6888
7159
  });
6889
7160
  result.push(mapped.element);
6890
7161
  listPagesId = mapped.state.listPagesId;
6891
7162
  listUsersId = mapped.state.listUsersId;
7163
+ tagCloudId = mapped.state.tagCloudId;
6892
7164
  }
6893
- return { elements: result, nextListPagesId: listPagesId, nextListUsersId: listUsersId };
7165
+ return {
7166
+ elements: result,
7167
+ nextListPagesId: listPagesId,
7168
+ nextListUsersId: listUsersId,
7169
+ nextTagCloudId: tagCloudId
7170
+ };
6894
7171
  }
6895
7172
 
6896
7173
  // packages/parser/src/parser/rules/block/module/resolution/styles.ts
6897
- var import_ast = require("@wdprlib/ast");
7174
+ var import_ast2 = require("@wdprlib/ast");
6898
7175
  function collectStyles(elements) {
6899
7176
  const styles = [];
6900
7177
  const ctx = { nextSlotId: 0 };
@@ -6910,7 +7187,7 @@ function collectStylesFromElements(elements, styles, ctx) {
6910
7187
  }
6911
7188
  if (element.element === "if-tags") {
6912
7189
  const slotId = ctx.nextSlotId++;
6913
- styles.push(`${import_ast.STYLE_SLOT_PREFIX}${slotId}`);
7190
+ styles.push(`${import_ast2.STYLE_SLOT_PREFIX}${slotId}`);
6914
7191
  const data = { ...element.data, _styleSlot: slotId };
6915
7192
  result.push({
6916
7193
  element: "if-tags",
@@ -6929,15 +7206,19 @@ async function resolveModules(ast, dataProvider, options) {
6929
7206
  const parse = createModuleParseFunction(options, dataProvider);
6930
7207
  const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
6931
7208
  const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
7209
+ const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
6932
7210
  const pageTags = dataProvider.getPageTags?.() ?? null;
6933
7211
  const resolvedElements = walkAndResolve(ast.elements, {
6934
7212
  listPages: listPagesCtx,
6935
7213
  listUsers: listUsersCtx,
7214
+ tagCloud: tagCloudCtx,
6936
7215
  fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
6937
7216
  fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
7217
+ fetchTagCloudProvided: dataProvider.fetchTagCloud !== undefined,
6938
7218
  pageTags,
6939
7219
  listPagesIdCounter: 0,
6940
- listUsersIdCounter: 0
7220
+ listUsersIdCounter: 0,
7221
+ tagCloudIdCounter: 0
6941
7222
  });
6942
7223
  const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
6943
7224
  const result = {
@@ -6969,7 +7250,7 @@ function createModuleSourceTransform(options, dataProvider) {
6969
7250
  }
6970
7251
 
6971
7252
  // packages/parser/src/parser/rules/block/module/index.ts
6972
- var import_ast2 = require("@wdprlib/ast");
7253
+ var import_ast3 = require("@wdprlib/ast");
6973
7254
 
6974
7255
  // packages/parser/src/parser/rules/block/footnoteblock/attributes.ts
6975
7256
  function parseFootnoteBlockAttributes(ctx, startPos) {
@@ -11916,7 +12197,7 @@ function createParseContext(tokens, options = {}) {
11916
12197
  pos: 0,
11917
12198
  version: options.version ?? "wikidot",
11918
12199
  trackPositions: options.trackPositions ?? true,
11919
- settings: options.settings ?? import_ast3.DEFAULT_SETTINGS,
12200
+ settings: options.settings ?? import_ast4.DEFAULT_SETTINGS,
11920
12201
  footnotes: [],
11921
12202
  tocEntries: [],
11922
12203
  codeBlocks: [],
@@ -12881,12 +13162,12 @@ function preprocess(text) {
12881
13162
  }
12882
13163
 
12883
13164
  // packages/parser/src/parser/preprocess/expr/evaluate.ts
12884
- var import_ast4 = require("@wdprlib/ast");
13165
+ var import_ast5 = require("@wdprlib/ast");
12885
13166
  function evaluateDirective(kind, match) {
12886
13167
  if (kind === "expr") {
12887
- const result2 = import_ast4.evaluateExpression(match.head);
13168
+ const result2 = import_ast5.evaluateExpression(match.head);
12888
13169
  if (result2.success)
12889
- return import_ast4.formatExprValue(result2.value);
13170
+ return import_ast5.formatExprValue(result2.value);
12890
13171
  if (result2.error === "empty expression")
12891
13172
  return "";
12892
13173
  return "ERROR";
@@ -12894,11 +13175,11 @@ function evaluateDirective(kind, match) {
12894
13175
  if (kind === "if") {
12895
13176
  if (!match.hasPipe)
12896
13177
  return "";
12897
- return import_ast4.isTruthy(match.head) ? match.thenText : match.elseText;
13178
+ return import_ast5.isTruthy(match.head) ? match.thenText : match.elseText;
12898
13179
  }
12899
13180
  if (!match.hasPipe)
12900
13181
  return "";
12901
- const result = import_ast4.evaluateExpression(match.head);
13182
+ const result = import_ast5.evaluateExpression(match.head);
12902
13183
  if (!result.success)
12903
13184
  return "ERROR";
12904
13185
  return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;