@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.
- package/README.md +9 -1
- package/dist/index.cjs +345 -64
- package/dist/index.d.cts +121 -2
- package/dist/index.d.ts +121 -2
- package/dist/index.js +317 -36
- package/package.json +2 -2
- package/src/index.ts +9 -0
- package/src/parser/rules/block/module/index.ts +10 -0
- package/src/parser/rules/block/module/listpages/extract.ts +9 -0
- package/src/parser/rules/block/module/listpages/extraction/tagcloud.ts +25 -0
- package/src/parser/rules/block/module/listpages/types/data-requirements.ts +2 -0
- package/src/parser/rules/block/module/listpages/url-resolution/fields.ts +4 -4
- package/src/parser/rules/block/module/listpages/url-resolution/params.ts +12 -1
- package/src/parser/rules/block/module/listpages/url-resolution/resolve.ts +10 -1
- package/src/parser/rules/block/module/listpages/url-resolution/value.ts +13 -4
- package/src/parser/rules/block/module/mapping.ts +2 -0
- package/src/parser/rules/block/module/resolution/contexts.ts +29 -1
- package/src/parser/rules/block/module/resolution/data-maps.ts +17 -0
- package/src/parser/rules/block/module/resolution/dynamic-modules.ts +29 -2
- package/src/parser/rules/block/module/resolution/walk-resolve.ts +28 -4
- package/src/parser/rules/block/module/resolve.ts +11 -1
- package/src/parser/rules/block/module/tagcloud/index.ts +15 -0
- package/src/parser/rules/block/module/tagcloud/parser.ts +127 -0
- package/src/parser/rules/block/module/tagcloud/resolve.ts +173 -0
- package/src/parser/rules/block/module/tagcloud/types.ts +85 -0
- package/src/parser/rules/block/module/types-common.ts +15 -0
package/dist/index.js
CHANGED
|
@@ -4468,6 +4468,92 @@ var listUsersModuleRule = {
|
|
|
4468
4468
|
}
|
|
4469
4469
|
};
|
|
4470
4470
|
|
|
4471
|
+
// packages/parser/src/parser/rules/block/module/tagcloud/parser.ts
|
|
4472
|
+
import { CSS_LENGTH_UNITS } from "@wdprlib/ast";
|
|
4473
|
+
var FONT_SIZE_PATTERN = new RegExp(`^([0-9]+)(${CSS_LENGTH_UNITS.join("|")})$`, "i");
|
|
4474
|
+
var COLOR_PATTERN = /^[0-9]+,[0-9]+,[0-9]+$/;
|
|
4475
|
+
var POSITIVE_INT_PATTERN = /^[0-9]+$/;
|
|
4476
|
+
var ERROR_FONT_FORMAT = "Unsupported format for font size. Use a number followed by a CSS length unit such as px, em or %.";
|
|
4477
|
+
var ERROR_FONT_MISMATCH = "Format for minFontSize and maxFontSize must use the same unit.";
|
|
4478
|
+
var ERROR_COLOR_FORMAT = 'Unsupported color format. Use "RRR,GGG,BBB" for Red,Green,Blue each within 0-255 range.';
|
|
4479
|
+
function errorBlock(message) {
|
|
4480
|
+
return {
|
|
4481
|
+
element: "container",
|
|
4482
|
+
data: {
|
|
4483
|
+
type: "div",
|
|
4484
|
+
attributes: { class: "error-block" },
|
|
4485
|
+
elements: [{ element: "text", data: message }]
|
|
4486
|
+
}
|
|
4487
|
+
};
|
|
4488
|
+
}
|
|
4489
|
+
function parseLimit(value) {
|
|
4490
|
+
if (!value || !POSITIVE_INT_PATTERN.test(value))
|
|
4491
|
+
return 50;
|
|
4492
|
+
const num = Number.parseInt(value, 10);
|
|
4493
|
+
return Number.isSafeInteger(num) && num > 0 ? num : 50;
|
|
4494
|
+
}
|
|
4495
|
+
function normalizeTarget(value) {
|
|
4496
|
+
if (!value)
|
|
4497
|
+
return "/system:page-tags/tag/";
|
|
4498
|
+
let target = value;
|
|
4499
|
+
if (!target.startsWith("/"))
|
|
4500
|
+
target = `/${target}`;
|
|
4501
|
+
if (!target.endsWith("/"))
|
|
4502
|
+
target = `${target}/`;
|
|
4503
|
+
return `${target}tag/`;
|
|
4504
|
+
}
|
|
4505
|
+
function parseColor(value) {
|
|
4506
|
+
const [r = 0, g = 0, b = 0] = value.split(",").map((part) => Number.parseInt(part, 10));
|
|
4507
|
+
return [r, g, b];
|
|
4508
|
+
}
|
|
4509
|
+
var tagCloudModuleRule = {
|
|
4510
|
+
name: "module-tagcloud",
|
|
4511
|
+
acceptsNames: ["tagcloud"],
|
|
4512
|
+
hasBody: false,
|
|
4513
|
+
parse(_ctx, _pos, args) {
|
|
4514
|
+
const maxFontSize = args.maxfontsize;
|
|
4515
|
+
const minFontSize = args.minfontsize;
|
|
4516
|
+
const maxColor = args.maxcolor;
|
|
4517
|
+
const minColor = args.mincolor;
|
|
4518
|
+
let sizeSmall = 100;
|
|
4519
|
+
let sizeBig = 300;
|
|
4520
|
+
let fontSizeUnit = "%";
|
|
4521
|
+
if (maxFontSize && minFontSize) {
|
|
4522
|
+
const maxMatch = FONT_SIZE_PATTERN.exec(maxFontSize);
|
|
4523
|
+
if (!maxMatch)
|
|
4524
|
+
return errorBlock(ERROR_FONT_FORMAT);
|
|
4525
|
+
const maxUnit = maxMatch[2].toLowerCase();
|
|
4526
|
+
const minMatch = FONT_SIZE_PATTERN.exec(minFontSize);
|
|
4527
|
+
if (!minMatch || minMatch[2].toLowerCase() !== maxUnit) {
|
|
4528
|
+
return errorBlock(ERROR_FONT_MISMATCH);
|
|
4529
|
+
}
|
|
4530
|
+
sizeBig = Number.parseInt(maxMatch[1], 10);
|
|
4531
|
+
sizeSmall = Number.parseInt(minMatch[1], 10);
|
|
4532
|
+
fontSizeUnit = maxUnit;
|
|
4533
|
+
}
|
|
4534
|
+
let colorSmall = [128, 128, 192];
|
|
4535
|
+
let colorBig = [64, 64, 128];
|
|
4536
|
+
if (maxColor && minColor) {
|
|
4537
|
+
if (!COLOR_PATTERN.test(maxColor) || !COLOR_PATTERN.test(minColor)) {
|
|
4538
|
+
return errorBlock(ERROR_COLOR_FORMAT);
|
|
4539
|
+
}
|
|
4540
|
+
colorSmall = parseColor(minColor);
|
|
4541
|
+
colorBig = parseColor(maxColor);
|
|
4542
|
+
}
|
|
4543
|
+
return {
|
|
4544
|
+
module: "tag-cloud",
|
|
4545
|
+
"min-font-size": sizeSmall,
|
|
4546
|
+
"max-font-size": sizeBig,
|
|
4547
|
+
"font-size-unit": fontSizeUnit,
|
|
4548
|
+
"min-color": colorSmall,
|
|
4549
|
+
"max-color": colorBig,
|
|
4550
|
+
target: normalizeTarget(args.target),
|
|
4551
|
+
limit: parseLimit(args.limit),
|
|
4552
|
+
category: args.category || null
|
|
4553
|
+
};
|
|
4554
|
+
}
|
|
4555
|
+
};
|
|
4556
|
+
|
|
4471
4557
|
// packages/parser/src/parser/rules/block/module/mapping.ts
|
|
4472
4558
|
var MODULE_RULES = [
|
|
4473
4559
|
rateModuleRule,
|
|
@@ -4477,7 +4563,8 @@ var MODULE_RULES = [
|
|
|
4477
4563
|
joinModuleRule,
|
|
4478
4564
|
pageTreeModuleRule,
|
|
4479
4565
|
listPagesModuleRule,
|
|
4480
|
-
listUsersModuleRule
|
|
4566
|
+
listUsersModuleRule,
|
|
4567
|
+
tagCloudModuleRule
|
|
4481
4568
|
];
|
|
4482
4569
|
var moduleRuleMap = new Map;
|
|
4483
4570
|
for (const rule of MODULE_RULES) {
|
|
@@ -5558,18 +5645,130 @@ function extractListUsersModule(listUsers, state, result) {
|
|
|
5558
5645
|
result.compiledListUsersTemplates.set(id, compileListUsersTemplate(body));
|
|
5559
5646
|
}
|
|
5560
5647
|
|
|
5648
|
+
// packages/parser/src/parser/rules/block/module/tagcloud/resolve.ts
|
|
5649
|
+
function isTagCloudModule(module) {
|
|
5650
|
+
return module.module === "tag-cloud";
|
|
5651
|
+
}
|
|
5652
|
+
var NO_TAGS_MESSAGE_PREFIX = "It seems you have no tags attached to pages. To attach a tag simply click on the ";
|
|
5653
|
+
var NO_TAGS_MESSAGE_SUFFIX = " button at the bottom of any page.";
|
|
5654
|
+
function rawUrlEncode(value) {
|
|
5655
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
5656
|
+
}
|
|
5657
|
+
function selectTags(tags, limit) {
|
|
5658
|
+
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));
|
|
5659
|
+
}
|
|
5660
|
+
function compareTags(a, b) {
|
|
5661
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
5662
|
+
}
|
|
5663
|
+
function resolveTagCloud(module, data) {
|
|
5664
|
+
if (data.status === "category-not-found") {
|
|
5665
|
+
return [
|
|
5666
|
+
{
|
|
5667
|
+
element: "container",
|
|
5668
|
+
data: {
|
|
5669
|
+
type: "div",
|
|
5670
|
+
attributes: { class: "error-block" },
|
|
5671
|
+
elements: [{ element: "text", data: `Category "${data.category}" can not be found.` }]
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5674
|
+
];
|
|
5675
|
+
}
|
|
5676
|
+
const tags = selectTags(data.tags, module.limit);
|
|
5677
|
+
if (tags.length === 0) {
|
|
5678
|
+
return [noTagsMessage()];
|
|
5679
|
+
}
|
|
5680
|
+
let minWeight = Number.POSITIVE_INFINITY;
|
|
5681
|
+
let maxWeight = Number.NEGATIVE_INFINITY;
|
|
5682
|
+
for (const tag of tags) {
|
|
5683
|
+
if (tag.weight < minWeight)
|
|
5684
|
+
minWeight = tag.weight;
|
|
5685
|
+
if (tag.weight > maxWeight)
|
|
5686
|
+
maxWeight = tag.weight;
|
|
5687
|
+
}
|
|
5688
|
+
const weightRange = maxWeight - minWeight;
|
|
5689
|
+
const categorySuffix = data.category !== null ? `/category/${rawUrlEncode(data.category)}` : "";
|
|
5690
|
+
const anchors = [];
|
|
5691
|
+
for (const tag of tags) {
|
|
5692
|
+
const a = weightRange === 0 ? 0 : (tag.weight - minWeight) / weightRange;
|
|
5693
|
+
const fontSize = interpolate(module["min-font-size"], module["max-font-size"], a);
|
|
5694
|
+
const [r, g, b] = [0, 1, 2].map((i) => interpolate(module["min-color"][i], module["max-color"][i], a));
|
|
5695
|
+
anchors.push({ element: "text", data: `
|
|
5696
|
+
` });
|
|
5697
|
+
anchors.push({
|
|
5698
|
+
element: "anchor",
|
|
5699
|
+
data: {
|
|
5700
|
+
target: null,
|
|
5701
|
+
attributes: {
|
|
5702
|
+
class: "tag",
|
|
5703
|
+
href: `${module.target}${rawUrlEncode(tag.tag)}${categorySuffix}`,
|
|
5704
|
+
style: `font-size: ${fontSize}${module["font-size-unit"]}; color: rgb(${r}, ${g}, ${b});`
|
|
5705
|
+
},
|
|
5706
|
+
elements: [{ element: "text", data: tag.tag }]
|
|
5707
|
+
}
|
|
5708
|
+
});
|
|
5709
|
+
}
|
|
5710
|
+
anchors.push({ element: "text", data: `
|
|
5711
|
+
` });
|
|
5712
|
+
return [
|
|
5713
|
+
{
|
|
5714
|
+
element: "container",
|
|
5715
|
+
data: {
|
|
5716
|
+
type: "div",
|
|
5717
|
+
attributes: { class: "pages-tag-cloud-box" },
|
|
5718
|
+
elements: anchors
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5721
|
+
];
|
|
5722
|
+
}
|
|
5723
|
+
function interpolate(min, max, a) {
|
|
5724
|
+
return Math.round(min + (max - min) * a);
|
|
5725
|
+
}
|
|
5726
|
+
function noTagsMessage() {
|
|
5727
|
+
return {
|
|
5728
|
+
element: "container",
|
|
5729
|
+
data: {
|
|
5730
|
+
type: "paragraph",
|
|
5731
|
+
attributes: {},
|
|
5732
|
+
elements: [
|
|
5733
|
+
{ element: "text", data: NO_TAGS_MESSAGE_PREFIX },
|
|
5734
|
+
{
|
|
5735
|
+
element: "container",
|
|
5736
|
+
data: {
|
|
5737
|
+
type: "italics",
|
|
5738
|
+
attributes: {},
|
|
5739
|
+
elements: [{ element: "text", data: "tags" }]
|
|
5740
|
+
}
|
|
5741
|
+
},
|
|
5742
|
+
{ element: "text", data: NO_TAGS_MESSAGE_SUFFIX }
|
|
5743
|
+
]
|
|
5744
|
+
}
|
|
5745
|
+
};
|
|
5746
|
+
}
|
|
5747
|
+
|
|
5748
|
+
// packages/parser/src/parser/rules/block/module/listpages/extraction/tagcloud.ts
|
|
5749
|
+
function extractTagCloudModule(tagCloud, state, result) {
|
|
5750
|
+
const id = state.nextId++;
|
|
5751
|
+
result.requirements.tagCloud.push({
|
|
5752
|
+
id,
|
|
5753
|
+
category: tagCloud.category,
|
|
5754
|
+
limit: tagCloud.limit
|
|
5755
|
+
});
|
|
5756
|
+
}
|
|
5757
|
+
|
|
5561
5758
|
// packages/parser/src/parser/rules/block/module/listpages/extract.ts
|
|
5562
5759
|
function extractDataRequirements(ast) {
|
|
5563
5760
|
const result = {
|
|
5564
5761
|
requirements: {
|
|
5565
5762
|
listPages: [],
|
|
5566
|
-
listUsers: []
|
|
5763
|
+
listUsers: [],
|
|
5764
|
+
tagCloud: []
|
|
5567
5765
|
},
|
|
5568
5766
|
compiledListPagesTemplates: new Map,
|
|
5569
5767
|
compiledListUsersTemplates: new Map
|
|
5570
5768
|
};
|
|
5571
5769
|
const listPagesState = { nextId: 0 };
|
|
5572
5770
|
const listUsersState = { nextId: 0 };
|
|
5771
|
+
const tagCloudState = { nextId: 0 };
|
|
5573
5772
|
walkElements(ast.elements, (element) => {
|
|
5574
5773
|
if (element.element !== "module")
|
|
5575
5774
|
return;
|
|
@@ -5577,6 +5776,8 @@ function extractDataRequirements(ast) {
|
|
|
5577
5776
|
extractListPagesModule(element.data, listPagesState, result);
|
|
5578
5777
|
} else if (isListUsersModule(element.data)) {
|
|
5579
5778
|
extractListUsersModule(element.data, listUsersState, result);
|
|
5779
|
+
} else if (isTagCloudModule(element.data)) {
|
|
5780
|
+
extractTagCloudModule(element.data, tagCloudState, result);
|
|
5580
5781
|
}
|
|
5581
5782
|
});
|
|
5582
5783
|
return result;
|
|
@@ -5650,11 +5851,32 @@ function resolveListPages(module, data, compiledTemplate, parse) {
|
|
|
5650
5851
|
const items = renderListPagesItems(module, data, compiledTemplate, parse);
|
|
5651
5852
|
return wrapListPagesResult(module, items, parse);
|
|
5652
5853
|
}
|
|
5854
|
+
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/fields.ts
|
|
5855
|
+
var URL_RESOLVABLE_FIELDS = [
|
|
5856
|
+
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
5857
|
+
{ attr: "limit", queryKey: "limit", type: "number" },
|
|
5858
|
+
{ attr: "per-page", queryKey: "perPage", type: "number" },
|
|
5859
|
+
{ attr: "order", queryKey: "order", type: "string" },
|
|
5860
|
+
{ attr: "tags", queryKey: "tags", type: "string", urlAttrs: ["tag"] },
|
|
5861
|
+
{ attr: "category", queryKey: "category", type: "string" },
|
|
5862
|
+
{ attr: "parent", queryKey: "parent", type: "string" },
|
|
5863
|
+
{ attr: "range", queryKey: "range", type: "string" },
|
|
5864
|
+
{ attr: "name", queryKey: "name", type: "string" },
|
|
5865
|
+
{ attr: "fullname", queryKey: "fullname", type: "string" },
|
|
5866
|
+
{ attr: "created-at", queryKey: "createdAt", type: "string" },
|
|
5867
|
+
{ attr: "updated-at", queryKey: "updatedAt", type: "string" },
|
|
5868
|
+
{ attr: "created-by", queryKey: "createdBy", type: "string" },
|
|
5869
|
+
{ attr: "rating", queryKey: "rating", type: "string" },
|
|
5870
|
+
{ attr: "votes", queryKey: "votes", type: "string" },
|
|
5871
|
+
{ attr: "reverse", queryKey: "reverse", type: "boolean" }
|
|
5872
|
+
];
|
|
5873
|
+
|
|
5653
5874
|
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/params.ts
|
|
5654
5875
|
function parseUrlParams(url) {
|
|
5655
5876
|
const params = new Map;
|
|
5656
5877
|
const parts = url.split("/").filter(Boolean);
|
|
5657
|
-
|
|
5878
|
+
const pairStart = isUrlParameter(parts[0]) ? 0 : 1;
|
|
5879
|
+
for (let i = pairStart;i < parts.length - 1; i += 2) {
|
|
5658
5880
|
const key = parts[i];
|
|
5659
5881
|
const value = parts[i + 1];
|
|
5660
5882
|
if (key && value) {
|
|
@@ -5663,6 +5885,10 @@ function parseUrlParams(url) {
|
|
|
5663
5885
|
}
|
|
5664
5886
|
return params;
|
|
5665
5887
|
}
|
|
5888
|
+
var URL_PARAMETER_NAMES = new Set(URL_RESOLVABLE_FIELDS.flatMap((field) => [field.attr, ...field.urlAttrs ?? []]));
|
|
5889
|
+
function isUrlParameter(param) {
|
|
5890
|
+
return param !== undefined && URL_PARAMETER_NAMES.has(param);
|
|
5891
|
+
}
|
|
5666
5892
|
// packages/parser/src/parser/rules/block/module/listpages/normalization/tags-category.ts
|
|
5667
5893
|
var TOKEN_SEPARATOR = /[,;\s]+/;
|
|
5668
5894
|
function parseTags(value) {
|
|
@@ -5918,26 +6144,6 @@ function normalizeQuery(query) {
|
|
|
5918
6144
|
return result;
|
|
5919
6145
|
}
|
|
5920
6146
|
|
|
5921
|
-
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/fields.ts
|
|
5922
|
-
var URL_RESOLVABLE_FIELDS = [
|
|
5923
|
-
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
5924
|
-
{ attr: "limit", queryKey: "limit", type: "number" },
|
|
5925
|
-
{ attr: "per-page", queryKey: "perPage", type: "number" },
|
|
5926
|
-
{ attr: "order", queryKey: "order", type: "string" },
|
|
5927
|
-
{ attr: "tags", queryKey: "tags", type: "string" },
|
|
5928
|
-
{ attr: "category", queryKey: "category", type: "string" },
|
|
5929
|
-
{ attr: "parent", queryKey: "parent", type: "string" },
|
|
5930
|
-
{ attr: "range", queryKey: "range", type: "string" },
|
|
5931
|
-
{ attr: "name", queryKey: "name", type: "string" },
|
|
5932
|
-
{ attr: "fullname", queryKey: "fullname", type: "string" },
|
|
5933
|
-
{ attr: "created-at", queryKey: "createdAt", type: "string" },
|
|
5934
|
-
{ attr: "updated-at", queryKey: "updatedAt", type: "string" },
|
|
5935
|
-
{ attr: "created-by", queryKey: "createdBy", type: "string" },
|
|
5936
|
-
{ attr: "rating", queryKey: "rating", type: "string" },
|
|
5937
|
-
{ attr: "votes", queryKey: "votes", type: "string" },
|
|
5938
|
-
{ attr: "reverse", queryKey: "reverse", type: "boolean" }
|
|
5939
|
-
];
|
|
5940
|
-
|
|
5941
6147
|
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/query.ts
|
|
5942
6148
|
function assignResolvedUrlField(query, field, value) {
|
|
5943
6149
|
switch (field.type) {
|
|
@@ -5958,15 +6164,23 @@ function assignResolvedUrlField(query, field, value) {
|
|
|
5958
6164
|
}
|
|
5959
6165
|
|
|
5960
6166
|
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/value.ts
|
|
5961
|
-
function resolveUrlValue(rawValue,
|
|
6167
|
+
function resolveUrlValue(rawValue, paramNames, urlParams, prefix) {
|
|
5962
6168
|
if (!rawValue)
|
|
5963
6169
|
return;
|
|
5964
6170
|
if (!rawValue.startsWith("@URL")) {
|
|
5965
6171
|
return rawValue;
|
|
5966
6172
|
}
|
|
5967
6173
|
const defaultValue = rawValue.includes("|") ? rawValue.split("|")[1] : undefined;
|
|
5968
|
-
const
|
|
5969
|
-
|
|
6174
|
+
for (const paramName of toParamNames(paramNames)) {
|
|
6175
|
+
const actualParamName = prefix ? `${prefix}_${paramName}` : paramName;
|
|
6176
|
+
const value = urlParams.get(actualParamName);
|
|
6177
|
+
if (value !== undefined)
|
|
6178
|
+
return value;
|
|
6179
|
+
}
|
|
6180
|
+
return defaultValue;
|
|
6181
|
+
}
|
|
6182
|
+
function toParamNames(paramNames) {
|
|
6183
|
+
return typeof paramNames === "string" ? [paramNames] : paramNames;
|
|
5970
6184
|
}
|
|
5971
6185
|
|
|
5972
6186
|
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/resolve.ts
|
|
@@ -5977,13 +6191,16 @@ function resolveQuery(requirement, urlParams) {
|
|
|
5977
6191
|
const rawValue = rawAttributes[field.attr];
|
|
5978
6192
|
if (!rawValue)
|
|
5979
6193
|
continue;
|
|
5980
|
-
const resolvedValue = resolveUrlValue(rawValue, field
|
|
6194
|
+
const resolvedValue = resolveUrlValue(rawValue, getUrlParamNames(field), urlParams, urlAttrPrefix);
|
|
5981
6195
|
if (resolvedValue === undefined)
|
|
5982
6196
|
continue;
|
|
5983
6197
|
assignResolvedUrlField(resolved, field, resolvedValue);
|
|
5984
6198
|
}
|
|
5985
6199
|
return resolved;
|
|
5986
6200
|
}
|
|
6201
|
+
function getUrlParamNames(field) {
|
|
6202
|
+
return field.urlAttrs ? [field.attr, ...field.urlAttrs] : [field.attr];
|
|
6203
|
+
}
|
|
5987
6204
|
function resolveAndNormalizeQuery(requirement, urlParams) {
|
|
5988
6205
|
const resolved = resolveQuery(requirement, urlParams);
|
|
5989
6206
|
return normalizeQuery(resolved);
|
|
@@ -6676,6 +6893,16 @@ async function buildListUsersDataMap(dataProvider, requirements) {
|
|
|
6676
6893
|
}
|
|
6677
6894
|
return dataMap;
|
|
6678
6895
|
}
|
|
6896
|
+
async function buildTagCloudDataMap(dataProvider, requirements) {
|
|
6897
|
+
const dataMap = new Map;
|
|
6898
|
+
for (const req of requirements) {
|
|
6899
|
+
const data = await dataProvider.fetchTagCloud?.(req);
|
|
6900
|
+
if (data) {
|
|
6901
|
+
dataMap.set(req.id, data);
|
|
6902
|
+
}
|
|
6903
|
+
}
|
|
6904
|
+
return dataMap;
|
|
6905
|
+
}
|
|
6679
6906
|
|
|
6680
6907
|
// packages/parser/src/parser/rules/block/module/resolution/contexts.ts
|
|
6681
6908
|
async function buildListPagesContext(dataProvider, requirements, compiledTemplates, parse, urlPath) {
|
|
@@ -6692,6 +6919,16 @@ async function buildListPagesContext(dataProvider, requirements, compiledTemplat
|
|
|
6692
6919
|
parse
|
|
6693
6920
|
};
|
|
6694
6921
|
}
|
|
6922
|
+
async function buildTagCloudContext(dataProvider, requirements) {
|
|
6923
|
+
if (requirements.length === 0 || !dataProvider.fetchTagCloud) {
|
|
6924
|
+
return null;
|
|
6925
|
+
}
|
|
6926
|
+
const dataMap = await buildTagCloudDataMap(dataProvider, requirements);
|
|
6927
|
+
if (dataMap.size === 0) {
|
|
6928
|
+
return null;
|
|
6929
|
+
}
|
|
6930
|
+
return { dataMap };
|
|
6931
|
+
}
|
|
6695
6932
|
async function buildListUsersContext(dataProvider, requirements, compiledTemplates, parse) {
|
|
6696
6933
|
if (requirements.length === 0 || !dataProvider.fetchListUsers) {
|
|
6697
6934
|
return null;
|
|
@@ -6748,10 +6985,27 @@ function resolveDynamicModuleElement(element, ctx, ids) {
|
|
|
6748
6985
|
ids: { ...ids, listUsersId: listUsersId + 1 }
|
|
6749
6986
|
};
|
|
6750
6987
|
}
|
|
6988
|
+
if (isTagCloudModule(element.data)) {
|
|
6989
|
+
const elements = [];
|
|
6990
|
+
const tagCloudId = ids.tagCloudId;
|
|
6991
|
+
if (ctx.tagCloud) {
|
|
6992
|
+
const moduleData = ctx.tagCloud.dataMap.get(tagCloudId);
|
|
6993
|
+
if (moduleData) {
|
|
6994
|
+
elements.push(...resolveTagCloud(element.data, moduleData));
|
|
6995
|
+
}
|
|
6996
|
+
} else if (!ctx.fetchTagCloudProvided) {
|
|
6997
|
+
elements.push(element);
|
|
6998
|
+
}
|
|
6999
|
+
return {
|
|
7000
|
+
handled: true,
|
|
7001
|
+
elements,
|
|
7002
|
+
ids: { ...ids, tagCloudId: tagCloudId + 1 }
|
|
7003
|
+
};
|
|
7004
|
+
}
|
|
6751
7005
|
return { handled: false, elements: [element], ids };
|
|
6752
7006
|
}
|
|
6753
7007
|
function countDynamicModules(elements) {
|
|
6754
|
-
const counts = { listPagesId: 0, listUsersId: 0 };
|
|
7008
|
+
const counts = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
|
|
6755
7009
|
walkElements(elements, (element) => {
|
|
6756
7010
|
if (element.element !== "module")
|
|
6757
7011
|
return;
|
|
@@ -6759,6 +7013,8 @@ function countDynamicModules(elements) {
|
|
|
6759
7013
|
counts.listPagesId++;
|
|
6760
7014
|
} else if (isListUsersModule2(element.data)) {
|
|
6761
7015
|
counts.listUsersId++;
|
|
7016
|
+
} else if (isTagCloudModule(element.data)) {
|
|
7017
|
+
counts.tagCloudId++;
|
|
6762
7018
|
}
|
|
6763
7019
|
});
|
|
6764
7020
|
return counts;
|
|
@@ -6769,12 +7025,18 @@ function walkAndResolve(elements, ctx) {
|
|
|
6769
7025
|
const result = [];
|
|
6770
7026
|
let listPagesId = ctx.listPagesIdCounter;
|
|
6771
7027
|
let listUsersId = ctx.listUsersIdCounter;
|
|
7028
|
+
let tagCloudId = ctx.tagCloudIdCounter;
|
|
6772
7029
|
for (const element of elements) {
|
|
6773
|
-
const dynamicModule = resolveDynamicModuleElement(element, ctx, {
|
|
7030
|
+
const dynamicModule = resolveDynamicModuleElement(element, ctx, {
|
|
7031
|
+
listPagesId,
|
|
7032
|
+
listUsersId,
|
|
7033
|
+
tagCloudId
|
|
7034
|
+
});
|
|
6774
7035
|
if (dynamicModule.handled) {
|
|
6775
7036
|
result.push(...dynamicModule.elements);
|
|
6776
7037
|
listPagesId = dynamicModule.ids.listPagesId;
|
|
6777
7038
|
listUsersId = dynamicModule.ids.listUsersId;
|
|
7039
|
+
tagCloudId = dynamicModule.ids.tagCloudId;
|
|
6778
7040
|
continue;
|
|
6779
7041
|
}
|
|
6780
7042
|
if (isIfTagsElement(element)) {
|
|
@@ -6785,21 +7047,25 @@ function walkAndResolve(elements, ctx) {
|
|
|
6785
7047
|
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
6786
7048
|
...ctx,
|
|
6787
7049
|
listPagesIdCounter: listPagesId,
|
|
6788
|
-
listUsersIdCounter: listUsersId
|
|
7050
|
+
listUsersIdCounter: listUsersId,
|
|
7051
|
+
tagCloudIdCounter: tagCloudId
|
|
6789
7052
|
});
|
|
6790
7053
|
result.push(...childResult.elements);
|
|
6791
7054
|
listPagesId = childResult.nextListPagesId;
|
|
6792
7055
|
listUsersId = childResult.nextListUsersId;
|
|
7056
|
+
tagCloudId = childResult.nextTagCloudId;
|
|
6793
7057
|
} else {
|
|
6794
7058
|
const counts = countDynamicModules(ifTagsData.elements);
|
|
6795
7059
|
listPagesId += counts.listPagesId;
|
|
6796
7060
|
listUsersId += counts.listUsersId;
|
|
7061
|
+
tagCloudId += counts.tagCloudId;
|
|
6797
7062
|
}
|
|
6798
7063
|
} else {
|
|
6799
7064
|
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
6800
7065
|
...ctx,
|
|
6801
7066
|
listPagesIdCounter: listPagesId,
|
|
6802
|
-
listUsersIdCounter: listUsersId
|
|
7067
|
+
listUsersIdCounter: listUsersId,
|
|
7068
|
+
tagCloudIdCounter: tagCloudId
|
|
6803
7069
|
});
|
|
6804
7070
|
result.push({
|
|
6805
7071
|
element: "if-tags",
|
|
@@ -6810,28 +7076,37 @@ function walkAndResolve(elements, ctx) {
|
|
|
6810
7076
|
});
|
|
6811
7077
|
listPagesId = childResult.nextListPagesId;
|
|
6812
7078
|
listUsersId = childResult.nextListUsersId;
|
|
7079
|
+
tagCloudId = childResult.nextTagCloudId;
|
|
6813
7080
|
}
|
|
6814
7081
|
continue;
|
|
6815
7082
|
}
|
|
6816
|
-
const mapped = mapElementChildrenWithState(element, { listPagesId, listUsersId }, (children, state) => {
|
|
7083
|
+
const mapped = mapElementChildrenWithState(element, { listPagesId, listUsersId, tagCloudId }, (children, state) => {
|
|
6817
7084
|
const childResult = walkAndResolve(children, {
|
|
6818
7085
|
...ctx,
|
|
6819
7086
|
listPagesIdCounter: state.listPagesId,
|
|
6820
|
-
listUsersIdCounter: state.listUsersId
|
|
7087
|
+
listUsersIdCounter: state.listUsersId,
|
|
7088
|
+
tagCloudIdCounter: state.tagCloudId
|
|
6821
7089
|
});
|
|
6822
7090
|
return {
|
|
6823
7091
|
elements: childResult.elements,
|
|
6824
7092
|
state: {
|
|
6825
7093
|
listPagesId: childResult.nextListPagesId,
|
|
6826
|
-
listUsersId: childResult.nextListUsersId
|
|
7094
|
+
listUsersId: childResult.nextListUsersId,
|
|
7095
|
+
tagCloudId: childResult.nextTagCloudId
|
|
6827
7096
|
}
|
|
6828
7097
|
};
|
|
6829
7098
|
});
|
|
6830
7099
|
result.push(mapped.element);
|
|
6831
7100
|
listPagesId = mapped.state.listPagesId;
|
|
6832
7101
|
listUsersId = mapped.state.listUsersId;
|
|
7102
|
+
tagCloudId = mapped.state.tagCloudId;
|
|
6833
7103
|
}
|
|
6834
|
-
return {
|
|
7104
|
+
return {
|
|
7105
|
+
elements: result,
|
|
7106
|
+
nextListPagesId: listPagesId,
|
|
7107
|
+
nextListUsersId: listUsersId,
|
|
7108
|
+
nextTagCloudId: tagCloudId
|
|
7109
|
+
};
|
|
6835
7110
|
}
|
|
6836
7111
|
|
|
6837
7112
|
// packages/parser/src/parser/rules/block/module/resolution/styles.ts
|
|
@@ -6870,15 +7145,19 @@ async function resolveModules(ast, dataProvider, options) {
|
|
|
6870
7145
|
const parse = createModuleParseFunction(options, dataProvider);
|
|
6871
7146
|
const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
|
|
6872
7147
|
const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
|
|
7148
|
+
const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
|
|
6873
7149
|
const pageTags = dataProvider.getPageTags?.() ?? null;
|
|
6874
7150
|
const resolvedElements = walkAndResolve(ast.elements, {
|
|
6875
7151
|
listPages: listPagesCtx,
|
|
6876
7152
|
listUsers: listUsersCtx,
|
|
7153
|
+
tagCloud: tagCloudCtx,
|
|
6877
7154
|
fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
|
|
6878
7155
|
fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
|
|
7156
|
+
fetchTagCloudProvided: dataProvider.fetchTagCloud !== undefined,
|
|
6879
7157
|
pageTags,
|
|
6880
7158
|
listPagesIdCounter: 0,
|
|
6881
|
-
listUsersIdCounter: 0
|
|
7159
|
+
listUsersIdCounter: 0,
|
|
7160
|
+
tagCloudIdCounter: 0
|
|
6882
7161
|
});
|
|
6883
7162
|
const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
|
|
6884
7163
|
const result = {
|
|
@@ -13022,6 +13301,7 @@ function parse(source, options) {
|
|
|
13022
13301
|
export {
|
|
13023
13302
|
tokenize,
|
|
13024
13303
|
text,
|
|
13304
|
+
resolveTagCloud,
|
|
13025
13305
|
resolveModules,
|
|
13026
13306
|
resolveListUsers,
|
|
13027
13307
|
resolveIncludesWithTrace,
|
|
@@ -13043,6 +13323,7 @@ export {
|
|
|
13043
13323
|
link,
|
|
13044
13324
|
lineBreak,
|
|
13045
13325
|
italics,
|
|
13326
|
+
isTagCloudModule,
|
|
13046
13327
|
isListUsersModule2 as isListUsersModule,
|
|
13047
13328
|
horizontalRule,
|
|
13048
13329
|
heading,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdprlib/parser",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Parser for Wikidot markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ast",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@braintree/sanitize-url": "^7.1.1",
|
|
44
|
-
"@wdprlib/ast": "2.
|
|
44
|
+
"@wdprlib/ast": "2.2.0"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -133,6 +133,12 @@ export type {
|
|
|
133
133
|
ListUsersDataFetcher,
|
|
134
134
|
ListUsersVariableContext,
|
|
135
135
|
ListUsersCompiledTemplate,
|
|
136
|
+
// TagCloud types
|
|
137
|
+
TagCloudDataRequirement,
|
|
138
|
+
TagCloudTagData,
|
|
139
|
+
TagCloudExternalData,
|
|
140
|
+
TagCloudDataFetcher,
|
|
141
|
+
TagCloudModuleData,
|
|
136
142
|
// Normalized query types
|
|
137
143
|
NormalizedListPagesQuery,
|
|
138
144
|
NormalizedTags,
|
|
@@ -167,4 +173,7 @@ export {
|
|
|
167
173
|
compileListUsersTemplate,
|
|
168
174
|
isListUsersModule,
|
|
169
175
|
resolveListUsers,
|
|
176
|
+
// TagCloud
|
|
177
|
+
isTagCloudModule,
|
|
178
|
+
resolveTagCloud,
|
|
170
179
|
} from "./parser/rules/block/module/index";
|
|
@@ -128,6 +128,16 @@ export {
|
|
|
128
128
|
resolveListUsers,
|
|
129
129
|
} from "./listusers";
|
|
130
130
|
|
|
131
|
+
// TagCloud module
|
|
132
|
+
export type {
|
|
133
|
+
TagCloudDataRequirement,
|
|
134
|
+
TagCloudTagData,
|
|
135
|
+
TagCloudExternalData,
|
|
136
|
+
TagCloudDataFetcher,
|
|
137
|
+
TagCloudModuleData,
|
|
138
|
+
} from "./tagcloud";
|
|
139
|
+
export { tagCloudModuleRule as tagCloudRule, isTagCloudModule, resolveTagCloud } from "./tagcloud";
|
|
140
|
+
|
|
131
141
|
// Module resolver
|
|
132
142
|
export type { ModuleSourceTransform, ResolveOptions } from "./resolve";
|
|
133
143
|
export { resolveModules } from "./resolve";
|
|
@@ -32,6 +32,11 @@ import {
|
|
|
32
32
|
isListUsersModule,
|
|
33
33
|
type ListUsersExtractionState,
|
|
34
34
|
} from "./extraction/listusers";
|
|
35
|
+
import {
|
|
36
|
+
extractTagCloudModule,
|
|
37
|
+
isTagCloudModule,
|
|
38
|
+
type TagCloudExtractionState,
|
|
39
|
+
} from "./extraction/tagcloud";
|
|
35
40
|
import type { ExtractionResult } from "./extraction/result";
|
|
36
41
|
export type { ExtractionResult } from "./extraction/result";
|
|
37
42
|
|
|
@@ -54,6 +59,7 @@ export function extractDataRequirements(ast: SyntaxTree): ExtractionResult {
|
|
|
54
59
|
requirements: {
|
|
55
60
|
listPages: [],
|
|
56
61
|
listUsers: [],
|
|
62
|
+
tagCloud: [],
|
|
57
63
|
},
|
|
58
64
|
compiledListPagesTemplates: new Map(),
|
|
59
65
|
compiledListUsersTemplates: new Map(),
|
|
@@ -61,6 +67,7 @@ export function extractDataRequirements(ast: SyntaxTree): ExtractionResult {
|
|
|
61
67
|
|
|
62
68
|
const listPagesState: ListPagesExtractionState = { nextId: 0 };
|
|
63
69
|
const listUsersState: ListUsersExtractionState = { nextId: 0 };
|
|
70
|
+
const tagCloudState: TagCloudExtractionState = { nextId: 0 };
|
|
64
71
|
|
|
65
72
|
walkElements(ast.elements, (element) => {
|
|
66
73
|
if (element.element !== "module") return;
|
|
@@ -69,6 +76,8 @@ export function extractDataRequirements(ast: SyntaxTree): ExtractionResult {
|
|
|
69
76
|
extractListPagesModule(element.data, listPagesState, result);
|
|
70
77
|
} else if (isListUsersModule(element.data)) {
|
|
71
78
|
extractListUsersModule(element.data, listUsersState, result);
|
|
79
|
+
} else if (isTagCloudModule(element.data)) {
|
|
80
|
+
extractTagCloudModule(element.data, tagCloudState, result);
|
|
72
81
|
}
|
|
73
82
|
});
|
|
74
83
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Module } from "@wdprlib/ast";
|
|
2
|
+
import { isTagCloudModule } from "../../tagcloud/resolve";
|
|
3
|
+
import type { ExtractionResult } from "./result";
|
|
4
|
+
|
|
5
|
+
export type TagCloudModuleForExtraction = Extract<Module, { module: "tag-cloud" }>;
|
|
6
|
+
|
|
7
|
+
export interface TagCloudExtractionState {
|
|
8
|
+
nextId: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { isTagCloudModule };
|
|
12
|
+
|
|
13
|
+
export function extractTagCloudModule(
|
|
14
|
+
tagCloud: TagCloudModuleForExtraction,
|
|
15
|
+
state: TagCloudExtractionState,
|
|
16
|
+
result: ExtractionResult,
|
|
17
|
+
): void {
|
|
18
|
+
const id = state.nextId++;
|
|
19
|
+
|
|
20
|
+
result.requirements.tagCloud.push({
|
|
21
|
+
id,
|
|
22
|
+
category: tagCloud.category,
|
|
23
|
+
limit: tagCloud.limit,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ListUsersDataRequirement } from "../../listusers/types";
|
|
2
|
+
import type { TagCloudDataRequirement } from "../../tagcloud/types";
|
|
2
3
|
import type { ListPagesQuery } from "./query";
|
|
3
4
|
import type { ListPagesVariable } from "./variables";
|
|
4
5
|
|
|
@@ -49,4 +50,5 @@ export interface ListPagesDataRequirement {
|
|
|
49
50
|
export interface DataRequirements {
|
|
50
51
|
listPages: ListPagesDataRequirement[];
|
|
51
52
|
listUsers: ListUsersDataRequirement[];
|
|
53
|
+
tagCloud: TagCloudDataRequirement[];
|
|
52
54
|
}
|