@wdprlib/parser 4.3.0 → 4.4.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 +26 -38
- package/dist/index.cjs +801 -134
- package/dist/index.d.cts +195 -158
- package/dist/index.d.ts +195 -158
- package/dist/index.js +783 -113
- package/package.json +2 -2
- package/src/index.ts +11 -0
- package/src/parser/parse/context.ts +1 -0
- package/src/parser/parse/options.ts +6 -0
- package/src/parser/parse/result.ts +3 -1
- package/src/parser/rules/block/module/include/index.ts +6 -1
- package/src/parser/rules/block/module/include/resolve/index.ts +23 -3
- package/src/parser/rules/block/module/include/resolve/iterate.ts +71 -0
- package/src/parser/rules/block/module/index.ts +2 -1
- package/src/parser/rules/block/module/listpages/resolution/items.ts +2 -2
- package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +3 -3
- package/src/parser/rules/block/module/listusers/resolve.ts +2 -2
- package/src/parser/rules/block/module/resolution/document.ts +357 -0
- package/src/parser/rules/block/module/resolution/resolve-async.ts +269 -0
- package/src/parser/rules/block/module/resolution/styles.ts +134 -12
- package/src/parser/rules/block/module/resolution/walk-resolve.ts +19 -1
- package/src/parser/rules/block/module/resolve.ts +32 -13
- package/src/parser/rules/block/module/types.ts +7 -2
- package/src/parser/rules/contracts/parse-context.ts +1 -0
- package/src/pipeline/index.ts +7 -0
- package/src/pipeline/process.ts +105 -0
- package/src/pipeline/types.ts +63 -0
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
listItemElements,
|
|
16
16
|
listItemSubList
|
|
17
17
|
} from "@wdprlib/ast";
|
|
18
|
-
import { createSettings, DEFAULT_SETTINGS as
|
|
18
|
+
import { createSettings, DEFAULT_SETTINGS as DEFAULT_SETTINGS3 } from "@wdprlib/ast";
|
|
19
19
|
|
|
20
20
|
// packages/parser/src/lexer/tokens.ts
|
|
21
21
|
function createToken(type, value, position, lineStart = false) {
|
|
@@ -5782,6 +5782,11 @@ function extractDataRequirements(ast) {
|
|
|
5782
5782
|
});
|
|
5783
5783
|
return result;
|
|
5784
5784
|
}
|
|
5785
|
+
// packages/parser/src/parser/rules/block/module/types.ts
|
|
5786
|
+
function getModuleParseAst(result) {
|
|
5787
|
+
return "ast" in result ? result.ast : result;
|
|
5788
|
+
}
|
|
5789
|
+
|
|
5785
5790
|
// packages/parser/src/parser/rules/block/module/listpages/resolution/items.ts
|
|
5786
5791
|
function renderListPagesItems(module, data, compiledTemplate, parse) {
|
|
5787
5792
|
const items = [];
|
|
@@ -5796,7 +5801,7 @@ function renderListPagesItems(module, data, compiledTemplate, parse) {
|
|
|
5796
5801
|
limit: module.limit,
|
|
5797
5802
|
site: data.site
|
|
5798
5803
|
};
|
|
5799
|
-
const itemAst = parse(compiledTemplate(ctx));
|
|
5804
|
+
const itemAst = getModuleParseAst(parse(compiledTemplate(ctx)));
|
|
5800
5805
|
if (module.separate) {
|
|
5801
5806
|
items.push({
|
|
5802
5807
|
element: "container",
|
|
@@ -5820,12 +5825,12 @@ function wrapListPagesResult(module, items, parse) {
|
|
|
5820
5825
|
}
|
|
5821
5826
|
const result = [];
|
|
5822
5827
|
if (module["prepend-line"] && !module.separate) {
|
|
5823
|
-
const prependAst = parse(module["prepend-line"]);
|
|
5828
|
+
const prependAst = getModuleParseAst(parse(module["prepend-line"]));
|
|
5824
5829
|
result.push(...prependAst.elements);
|
|
5825
5830
|
}
|
|
5826
5831
|
result.push(...items);
|
|
5827
5832
|
if (module["append-line"] && !module.separate) {
|
|
5828
|
-
const appendAst = parse(module["append-line"]);
|
|
5833
|
+
const appendAst = getModuleParseAst(parse(module["append-line"]));
|
|
5829
5834
|
result.push(...appendAst.elements);
|
|
5830
5835
|
}
|
|
5831
5836
|
if (module.wrapper) {
|
|
@@ -6744,16 +6749,31 @@ function expandIterativeWithTrace(source, fetcher, maxIterations) {
|
|
|
6744
6749
|
reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
|
|
6745
6750
|
};
|
|
6746
6751
|
}
|
|
6747
|
-
async function
|
|
6752
|
+
async function expandIterativeAsyncWithTrace(source, fetcher, maxIterations) {
|
|
6748
6753
|
let current2 = source;
|
|
6749
6754
|
const replacementCache = new Map;
|
|
6755
|
+
const dependencies = [];
|
|
6756
|
+
const iterations = [];
|
|
6750
6757
|
for (let i = 0;i < maxIterations; i++) {
|
|
6751
|
-
const expanded = await
|
|
6752
|
-
if (expanded === null
|
|
6758
|
+
const expanded = await expandOneIterationAsyncWithTrace(current2, fetcher, replacementCache, i);
|
|
6759
|
+
if (expanded === null)
|
|
6753
6760
|
break;
|
|
6754
|
-
|
|
6761
|
+
dependencies.push(...expanded.dependencies);
|
|
6762
|
+
iterations.push({
|
|
6763
|
+
iteration: i,
|
|
6764
|
+
directives: expanded.references,
|
|
6765
|
+
changed: expanded.source !== current2
|
|
6766
|
+
});
|
|
6767
|
+
if (expanded.source === current2)
|
|
6768
|
+
break;
|
|
6769
|
+
current2 = expanded.source;
|
|
6755
6770
|
}
|
|
6756
|
-
return
|
|
6771
|
+
return {
|
|
6772
|
+
source: current2,
|
|
6773
|
+
dependencies,
|
|
6774
|
+
iterations,
|
|
6775
|
+
reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
|
|
6776
|
+
};
|
|
6757
6777
|
}
|
|
6758
6778
|
function expandOneIteration(source, fetcher, replacementCache) {
|
|
6759
6779
|
if (!MAYBE_INCLUDE_PATTERN.test(source))
|
|
@@ -6791,12 +6811,13 @@ function expandOneIterationWithTrace(source, fetcher, replacementCache, iteratio
|
|
|
6791
6811
|
dependencies
|
|
6792
6812
|
};
|
|
6793
6813
|
}
|
|
6794
|
-
async function
|
|
6814
|
+
async function expandOneIterationAsyncWithTrace(source, fetcher, replacementCache, iteration) {
|
|
6795
6815
|
if (!MAYBE_INCLUDE_PATTERN.test(source))
|
|
6796
6816
|
return null;
|
|
6797
6817
|
const directives = scanIncludeDirectives(source);
|
|
6798
6818
|
if (directives.length === 0)
|
|
6799
6819
|
return null;
|
|
6820
|
+
const references = directives.map(createIncludeReference);
|
|
6800
6821
|
const replacements = await Promise.all(directives.map(({ inner }) => replaceCachedAsync(inner, fetcher, replacementCache)));
|
|
6801
6822
|
const parts = [];
|
|
6802
6823
|
let lastPos = 0;
|
|
@@ -6806,7 +6827,11 @@ async function expandOneIterationAsync(source, fetcher, replacementCache) {
|
|
|
6806
6827
|
lastPos = end;
|
|
6807
6828
|
}
|
|
6808
6829
|
parts.push(source.slice(lastPos));
|
|
6809
|
-
return
|
|
6830
|
+
return {
|
|
6831
|
+
source: parts.join(""),
|
|
6832
|
+
references,
|
|
6833
|
+
dependencies: references.map((reference) => ({ ...reference, iteration }))
|
|
6834
|
+
};
|
|
6810
6835
|
}
|
|
6811
6836
|
function replaceCached(inner, fetcher, cache) {
|
|
6812
6837
|
const cached = cache.get(inner);
|
|
@@ -6848,12 +6873,20 @@ function resolveIncludesWithTrace(source, fetcher, options) {
|
|
|
6848
6873
|
return expandIterativeWithTrace(source, cachedFetcher, maxIterations);
|
|
6849
6874
|
}
|
|
6850
6875
|
async function resolveIncludesAsync(source, fetcher, options) {
|
|
6876
|
+
return (await resolveIncludesAsyncWithTrace(source, fetcher, options)).source;
|
|
6877
|
+
}
|
|
6878
|
+
async function resolveIncludesAsyncWithTrace(source, fetcher, options) {
|
|
6851
6879
|
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
6852
|
-
return
|
|
6880
|
+
return {
|
|
6881
|
+
source,
|
|
6882
|
+
dependencies: [],
|
|
6883
|
+
iterations: [],
|
|
6884
|
+
reachedMaxIterations: false
|
|
6885
|
+
};
|
|
6853
6886
|
}
|
|
6854
6887
|
const maxIterations = options?.maxIterations ?? 10;
|
|
6855
6888
|
const cachedFetcher = createCachedAsyncIncludeFetcher(fetcher, normalizePageKey);
|
|
6856
|
-
return
|
|
6889
|
+
return expandIterativeAsyncWithTrace(source, cachedFetcher, maxIterations);
|
|
6857
6890
|
}
|
|
6858
6891
|
function normalizePageKey(location) {
|
|
6859
6892
|
const site = location.site ?? "";
|
|
@@ -6867,7 +6900,7 @@ function isListUsersModule2(module) {
|
|
|
6867
6900
|
function resolveListUsers(_module, data, compiledTemplate, parse) {
|
|
6868
6901
|
const ctx = { user: data.user };
|
|
6869
6902
|
const substituted = compiledTemplate(ctx);
|
|
6870
|
-
const itemAst = parse(substituted);
|
|
6903
|
+
const itemAst = getModuleParseAst(parse(substituted));
|
|
6871
6904
|
return itemAst.elements;
|
|
6872
6905
|
}
|
|
6873
6906
|
// packages/parser/src/parser/rules/block/module/resolution/data-maps.ts
|
|
@@ -7020,6 +7053,117 @@ function countDynamicModules(elements) {
|
|
|
7020
7053
|
return counts;
|
|
7021
7054
|
}
|
|
7022
7055
|
|
|
7056
|
+
// packages/parser/src/parser/rules/block/module/resolution/styles.ts
|
|
7057
|
+
import { STYLE_ANCHOR_PREFIX, STYLE_SLOT_PREFIX } from "@wdprlib/ast";
|
|
7058
|
+
function collectStyles(elements, ignoredAnchors = new WeakSet) {
|
|
7059
|
+
const styles = [];
|
|
7060
|
+
const anchoredStyles = [];
|
|
7061
|
+
const anchors = [];
|
|
7062
|
+
const usedSlots = collectExistingStyleSlots(elements);
|
|
7063
|
+
const ctx = { nextSlotId: 0, usedSlots };
|
|
7064
|
+
const filtered = collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx);
|
|
7065
|
+
return { elements: filtered, styles, anchoredStyles, anchors };
|
|
7066
|
+
}
|
|
7067
|
+
function mergeCollectedStyles(existing, collected, resolvedSlots = new Map, anchoredStyles = []) {
|
|
7068
|
+
const unanchoredPrevious = [...existing ?? []];
|
|
7069
|
+
for (const style of anchoredStyles)
|
|
7070
|
+
removeFirst(unanchoredPrevious, style);
|
|
7071
|
+
for (const style of collected) {
|
|
7072
|
+
if (isStyleSlotMarker(style))
|
|
7073
|
+
removeFirst(unanchoredPrevious, style);
|
|
7074
|
+
}
|
|
7075
|
+
const merged = unanchoredPrevious.filter((style) => !isStyleSlotMarker(style));
|
|
7076
|
+
for (const style of collected) {
|
|
7077
|
+
if (isStyleSlotMarker(style))
|
|
7078
|
+
appendStyleSlot(merged, style, resolvedSlots);
|
|
7079
|
+
else
|
|
7080
|
+
merged.push(style);
|
|
7081
|
+
}
|
|
7082
|
+
return merged;
|
|
7083
|
+
}
|
|
7084
|
+
function isStyleSlotMarker(style) {
|
|
7085
|
+
return style.startsWith(STYLE_SLOT_PREFIX);
|
|
7086
|
+
}
|
|
7087
|
+
function createStyleSlotMarker(slotId) {
|
|
7088
|
+
return `${STYLE_SLOT_PREFIX}${slotId}`;
|
|
7089
|
+
}
|
|
7090
|
+
function getStyleSlotId(data) {
|
|
7091
|
+
const slotId = data._styleSlot;
|
|
7092
|
+
return Number.isSafeInteger(slotId) && slotId >= 0 ? slotId : undefined;
|
|
7093
|
+
}
|
|
7094
|
+
function removeFirst(values, value) {
|
|
7095
|
+
const index = values.indexOf(value);
|
|
7096
|
+
if (index >= 0)
|
|
7097
|
+
values.splice(index, 1);
|
|
7098
|
+
}
|
|
7099
|
+
function appendStyleSlot(target, marker, resolvedSlots) {
|
|
7100
|
+
const slotId = Number(marker.slice(STYLE_SLOT_PREFIX.length));
|
|
7101
|
+
const replacement = resolvedSlots.get(slotId);
|
|
7102
|
+
if (replacement)
|
|
7103
|
+
target.push(...replacement);
|
|
7104
|
+
else
|
|
7105
|
+
target.push(marker);
|
|
7106
|
+
}
|
|
7107
|
+
function collectExistingStyleSlots(elements) {
|
|
7108
|
+
const slots = new Set;
|
|
7109
|
+
walkElements(elements, (element) => {
|
|
7110
|
+
if (element.element !== "if-tags")
|
|
7111
|
+
return;
|
|
7112
|
+
const slotId = getStyleSlotId(element.data);
|
|
7113
|
+
if (slotId !== undefined)
|
|
7114
|
+
slots.add(slotId);
|
|
7115
|
+
});
|
|
7116
|
+
return slots;
|
|
7117
|
+
}
|
|
7118
|
+
function allocateStyleSlot(ctx) {
|
|
7119
|
+
while (ctx.usedSlots.has(ctx.nextSlotId))
|
|
7120
|
+
ctx.nextSlotId++;
|
|
7121
|
+
const slotId = ctx.nextSlotId++;
|
|
7122
|
+
ctx.usedSlots.add(slotId);
|
|
7123
|
+
return slotId;
|
|
7124
|
+
}
|
|
7125
|
+
function collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx) {
|
|
7126
|
+
const result = [];
|
|
7127
|
+
for (const element of elements) {
|
|
7128
|
+
if (element.element === "style") {
|
|
7129
|
+
const css = element.data;
|
|
7130
|
+
if (css.startsWith(STYLE_SLOT_PREFIX)) {
|
|
7131
|
+
styles.push(css);
|
|
7132
|
+
continue;
|
|
7133
|
+
}
|
|
7134
|
+
if (css.startsWith(STYLE_ANCHOR_PREFIX)) {
|
|
7135
|
+
anchors.push(element);
|
|
7136
|
+
if (ignoredAnchors.has(element)) {
|
|
7137
|
+
result.push(element);
|
|
7138
|
+
continue;
|
|
7139
|
+
}
|
|
7140
|
+
const anchoredCss = css.slice(STYLE_ANCHOR_PREFIX.length);
|
|
7141
|
+
styles.push(anchoredCss);
|
|
7142
|
+
anchoredStyles.push(anchoredCss);
|
|
7143
|
+
result.push(element);
|
|
7144
|
+
continue;
|
|
7145
|
+
}
|
|
7146
|
+
styles.push(css);
|
|
7147
|
+
const anchor = { element: "style", data: `${STYLE_ANCHOR_PREFIX}${css}` };
|
|
7148
|
+
anchors.push(anchor);
|
|
7149
|
+
result.push(anchor);
|
|
7150
|
+
continue;
|
|
7151
|
+
}
|
|
7152
|
+
if (element.element === "if-tags") {
|
|
7153
|
+
const slotId = getStyleSlotId(element.data) ?? allocateStyleSlot(ctx);
|
|
7154
|
+
styles.push(createStyleSlotMarker(slotId));
|
|
7155
|
+
const data = { ...element.data, _styleSlot: slotId };
|
|
7156
|
+
result.push({
|
|
7157
|
+
element: "if-tags",
|
|
7158
|
+
data
|
|
7159
|
+
});
|
|
7160
|
+
continue;
|
|
7161
|
+
}
|
|
7162
|
+
result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, anchoredStyles, anchors, ignoredAnchors, ctx)));
|
|
7163
|
+
}
|
|
7164
|
+
return result;
|
|
7165
|
+
}
|
|
7166
|
+
|
|
7023
7167
|
// packages/parser/src/parser/rules/block/module/resolution/walk-resolve.ts
|
|
7024
7168
|
function walkAndResolve(elements, ctx) {
|
|
7025
7169
|
const result = [];
|
|
@@ -7042,6 +7186,7 @@ function walkAndResolve(elements, ctx) {
|
|
|
7042
7186
|
if (isIfTagsElement(element)) {
|
|
7043
7187
|
const ifTagsData = element.data;
|
|
7044
7188
|
const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
|
|
7189
|
+
const styleSlotId = getStyleSlotId(ifTagsData);
|
|
7045
7190
|
if (resolveResult.evaluated) {
|
|
7046
7191
|
if (resolveResult.matched) {
|
|
7047
7192
|
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
@@ -7050,11 +7195,23 @@ function walkAndResolve(elements, ctx) {
|
|
|
7050
7195
|
listUsersIdCounter: listUsersId,
|
|
7051
7196
|
tagCloudIdCounter: tagCloudId
|
|
7052
7197
|
});
|
|
7053
|
-
|
|
7198
|
+
if (styleSlotId === undefined) {
|
|
7199
|
+
result.push(...childResult.elements);
|
|
7200
|
+
} else {
|
|
7201
|
+
const collected = collectStyles(childResult.elements);
|
|
7202
|
+
ctx.resolvedStyleSlots.set(styleSlotId, collected.styles);
|
|
7203
|
+
for (const anchor of collected.anchors)
|
|
7204
|
+
ctx.routedStyleAnchors.add(anchor);
|
|
7205
|
+
result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) }, ...collected.elements);
|
|
7206
|
+
}
|
|
7054
7207
|
listPagesId = childResult.nextListPagesId;
|
|
7055
7208
|
listUsersId = childResult.nextListUsersId;
|
|
7056
7209
|
tagCloudId = childResult.nextTagCloudId;
|
|
7057
7210
|
} else {
|
|
7211
|
+
if (styleSlotId !== undefined) {
|
|
7212
|
+
ctx.resolvedStyleSlots.set(styleSlotId, []);
|
|
7213
|
+
result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) });
|
|
7214
|
+
}
|
|
7058
7215
|
const counts = countDynamicModules(ifTagsData.elements);
|
|
7059
7216
|
listPagesId += counts.listPagesId;
|
|
7060
7217
|
listUsersId += counts.listUsersId;
|
|
@@ -7109,44 +7266,361 @@ function walkAndResolve(elements, ctx) {
|
|
|
7109
7266
|
};
|
|
7110
7267
|
}
|
|
7111
7268
|
|
|
7112
|
-
// packages/parser/src/parser/rules/block/module/resolution/
|
|
7113
|
-
import {
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7269
|
+
// packages/parser/src/parser/rules/block/module/resolution/document.ts
|
|
7270
|
+
import {
|
|
7271
|
+
evaluateExpression,
|
|
7272
|
+
isTruthy
|
|
7273
|
+
} from "@wdprlib/ast";
|
|
7274
|
+
|
|
7275
|
+
// packages/parser/src/parser/toc.ts
|
|
7276
|
+
class TocIndexer {
|
|
7277
|
+
index = 0;
|
|
7278
|
+
next() {
|
|
7279
|
+
return this.index++;
|
|
7280
|
+
}
|
|
7119
7281
|
}
|
|
7120
|
-
function
|
|
7282
|
+
function buildTocList(indexer, items) {
|
|
7283
|
+
const listItems = items.map((item) => buildTocListItem(indexer, item));
|
|
7284
|
+
return {
|
|
7285
|
+
element: "list",
|
|
7286
|
+
data: {
|
|
7287
|
+
type: "bullet",
|
|
7288
|
+
attributes: {},
|
|
7289
|
+
items: listItems
|
|
7290
|
+
}
|
|
7291
|
+
};
|
|
7292
|
+
}
|
|
7293
|
+
function buildTocListItem(indexer, item) {
|
|
7294
|
+
if (item.kind === "list") {
|
|
7295
|
+
return {
|
|
7296
|
+
"item-type": "sub-list",
|
|
7297
|
+
element: "list",
|
|
7298
|
+
data: {
|
|
7299
|
+
type: "bullet",
|
|
7300
|
+
attributes: {},
|
|
7301
|
+
items: item.children.map((child) => buildTocListItem(indexer, child))
|
|
7302
|
+
}
|
|
7303
|
+
};
|
|
7304
|
+
}
|
|
7305
|
+
const anchor = `#toc${indexer.next()}`;
|
|
7306
|
+
const linkElement = {
|
|
7307
|
+
element: "link",
|
|
7308
|
+
data: {
|
|
7309
|
+
type: "table-of-contents",
|
|
7310
|
+
link: anchor,
|
|
7311
|
+
extra: null,
|
|
7312
|
+
label: { text: item.value },
|
|
7313
|
+
target: null
|
|
7314
|
+
}
|
|
7315
|
+
};
|
|
7316
|
+
return {
|
|
7317
|
+
"item-type": "elements",
|
|
7318
|
+
attributes: {},
|
|
7319
|
+
elements: [linkElement]
|
|
7320
|
+
};
|
|
7321
|
+
}
|
|
7322
|
+
function buildTableOfContents(entries) {
|
|
7323
|
+
if (entries.length === 0) {
|
|
7324
|
+
return [];
|
|
7325
|
+
}
|
|
7326
|
+
const depthItems = entries.map((entry) => ({
|
|
7327
|
+
depth: entry.level - 1,
|
|
7328
|
+
ltype: null,
|
|
7329
|
+
value: entry.text
|
|
7330
|
+
}));
|
|
7331
|
+
const trees = processDepths(null, depthItems);
|
|
7332
|
+
const indexer = new TocIndexer;
|
|
7333
|
+
return trees.map((tree) => buildTocList(indexer, tree.list));
|
|
7334
|
+
}
|
|
7335
|
+
|
|
7336
|
+
// packages/parser/src/parser/rules/block/module/resolution/document.ts
|
|
7337
|
+
class ModuleDocumentRegistry {
|
|
7338
|
+
footnotesByElement = new WeakMap;
|
|
7339
|
+
diagnostics = [];
|
|
7340
|
+
register(result, options = {}) {
|
|
7341
|
+
const parseResult = isParseResult(result) ? result : null;
|
|
7342
|
+
const ast = parseResult ? parseResult.ast : result;
|
|
7343
|
+
const elements = options.stripLegacyImplicitFootnoteBlock ? stripTrailingDefaultFootnoteBlock(ast.elements) : ast.elements;
|
|
7344
|
+
const registeredAst = elements === ast.elements ? ast : { ...ast, elements };
|
|
7345
|
+
if (parseResult) {
|
|
7346
|
+
this.diagnostics.push(...parseResult.diagnostics);
|
|
7347
|
+
}
|
|
7348
|
+
this.registerFootnotes(registeredAst);
|
|
7349
|
+
return registeredAst;
|
|
7350
|
+
}
|
|
7351
|
+
finalize(ast, elements, pageTags, ensureFootnoteBlock = true) {
|
|
7352
|
+
const normalizedElements = normalizeFootnoteBlocks(elements, ensureFootnoteBlock);
|
|
7353
|
+
const footnotes = [];
|
|
7354
|
+
const htmlBlocks = [];
|
|
7355
|
+
const codeBlocks = [];
|
|
7356
|
+
const tocEntries = [];
|
|
7357
|
+
const collectElement = (element) => {
|
|
7358
|
+
if (element.element === "footnote") {
|
|
7359
|
+
const content = this.footnotesByElement.get(element);
|
|
7360
|
+
if (content)
|
|
7361
|
+
footnotes.push(content);
|
|
7362
|
+
} else if (element.element === "html") {
|
|
7363
|
+
htmlBlocks.push(element.data.contents);
|
|
7364
|
+
} else if (element.element === "code") {
|
|
7365
|
+
codeBlocks.push(element.data);
|
|
7366
|
+
} else if (isTocHeading(element)) {
|
|
7367
|
+
tocEntries.push({
|
|
7368
|
+
level: element.data.type.header.level,
|
|
7369
|
+
text: extractHeadingText(element.data.elements)
|
|
7370
|
+
});
|
|
7371
|
+
}
|
|
7372
|
+
};
|
|
7373
|
+
walkRenderOrder(normalizedElements, pageTags, collectElement);
|
|
7374
|
+
const result = { ...ast, elements: normalizedElements };
|
|
7375
|
+
setOptionalArray(result, "footnotes", footnotes);
|
|
7376
|
+
setOptionalArray(result, "html-blocks", htmlBlocks);
|
|
7377
|
+
setOptionalArray(result, "code-blocks", codeBlocks);
|
|
7378
|
+
setOptionalArray(result, "table-of-contents", buildTableOfContents(tocEntries));
|
|
7379
|
+
return result;
|
|
7380
|
+
}
|
|
7381
|
+
registerFootnotes(ast) {
|
|
7382
|
+
const footnoteElements = [];
|
|
7383
|
+
walkSyntaxOrder(ast.elements, (element) => {
|
|
7384
|
+
if (element.element === "footnote")
|
|
7385
|
+
footnoteElements.push(element);
|
|
7386
|
+
});
|
|
7387
|
+
for (let i = 0;i < footnoteElements.length; i++) {
|
|
7388
|
+
const content = ast.footnotes?.[i];
|
|
7389
|
+
if (content)
|
|
7390
|
+
this.footnotesByElement.set(footnoteElements[i], content);
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7393
|
+
}
|
|
7394
|
+
function isParseResult(result) {
|
|
7395
|
+
return "ast" in result && "diagnostics" in result;
|
|
7396
|
+
}
|
|
7397
|
+
function setOptionalArray(tree, key, value) {
|
|
7398
|
+
if (value.length > 0) {
|
|
7399
|
+
tree[key] = value;
|
|
7400
|
+
} else {
|
|
7401
|
+
delete tree[key];
|
|
7402
|
+
}
|
|
7403
|
+
}
|
|
7404
|
+
function stripTrailingDefaultFootnoteBlock(elements) {
|
|
7405
|
+
const last = elements.at(-1);
|
|
7406
|
+
if (last?.element !== "footnote-block" || last.data.title !== null || last.data.hide === true) {
|
|
7407
|
+
return elements;
|
|
7408
|
+
}
|
|
7409
|
+
return elements.slice(0, -1);
|
|
7410
|
+
}
|
|
7411
|
+
function normalizeFootnoteBlocks(elements, ensureFootnoteBlock) {
|
|
7412
|
+
const state = { found: false };
|
|
7413
|
+
const normalized = mapSyntaxElements(elements, (element) => {
|
|
7414
|
+
if (element.element !== "footnote-block")
|
|
7415
|
+
return element;
|
|
7416
|
+
if (state.found)
|
|
7417
|
+
return null;
|
|
7418
|
+
state.found = true;
|
|
7419
|
+
return element;
|
|
7420
|
+
});
|
|
7421
|
+
if (!state.found && ensureFootnoteBlock) {
|
|
7422
|
+
normalized.push({
|
|
7423
|
+
element: "footnote-block",
|
|
7424
|
+
data: { title: null, hide: false }
|
|
7425
|
+
});
|
|
7426
|
+
}
|
|
7427
|
+
return normalized;
|
|
7428
|
+
}
|
|
7429
|
+
function containsSyntaxFootnoteBlock(elements) {
|
|
7430
|
+
let found = false;
|
|
7431
|
+
walkSyntaxOrder(elements, (element) => {
|
|
7432
|
+
if (element.element === "footnote-block")
|
|
7433
|
+
found = true;
|
|
7434
|
+
});
|
|
7435
|
+
return found;
|
|
7436
|
+
}
|
|
7437
|
+
function mapSyntaxElements(elements, transform) {
|
|
7121
7438
|
const result = [];
|
|
7439
|
+
for (const original of elements) {
|
|
7440
|
+
const element = transform(original);
|
|
7441
|
+
if (!element)
|
|
7442
|
+
continue;
|
|
7443
|
+
result.push(mapSyntaxChildren(element, (children) => mapSyntaxElements(children, transform)));
|
|
7444
|
+
}
|
|
7445
|
+
return result;
|
|
7446
|
+
}
|
|
7447
|
+
function mapSyntaxChildren(element, transform) {
|
|
7448
|
+
if (element.element === "if") {
|
|
7449
|
+
return {
|
|
7450
|
+
...element,
|
|
7451
|
+
data: {
|
|
7452
|
+
...element.data,
|
|
7453
|
+
then: transform(element.data.then),
|
|
7454
|
+
else: transform(element.data.else)
|
|
7455
|
+
}
|
|
7456
|
+
};
|
|
7457
|
+
}
|
|
7458
|
+
if (element.element === "ifexpr") {
|
|
7459
|
+
return {
|
|
7460
|
+
...element,
|
|
7461
|
+
data: {
|
|
7462
|
+
...element.data,
|
|
7463
|
+
then: transform(element.data.then),
|
|
7464
|
+
else: transform(element.data.else)
|
|
7465
|
+
}
|
|
7466
|
+
};
|
|
7467
|
+
}
|
|
7468
|
+
if (element.element === "bibliography-block") {
|
|
7469
|
+
return {
|
|
7470
|
+
...element,
|
|
7471
|
+
data: {
|
|
7472
|
+
...element.data,
|
|
7473
|
+
entries: element.data.entries.map((entry) => ({
|
|
7474
|
+
...entry,
|
|
7475
|
+
key: transform(entry.key),
|
|
7476
|
+
value: transform(entry.value)
|
|
7477
|
+
}))
|
|
7478
|
+
}
|
|
7479
|
+
};
|
|
7480
|
+
}
|
|
7481
|
+
if (element.element === "list") {
|
|
7482
|
+
return {
|
|
7483
|
+
...element,
|
|
7484
|
+
data: {
|
|
7485
|
+
...element.data,
|
|
7486
|
+
items: element.data.items.map((item) => item["item-type"] === "elements" ? { ...item, elements: transform(item.elements) } : mapSubList(item, transform))
|
|
7487
|
+
}
|
|
7488
|
+
};
|
|
7489
|
+
}
|
|
7490
|
+
if (element.element === "table") {
|
|
7491
|
+
return {
|
|
7492
|
+
...element,
|
|
7493
|
+
data: {
|
|
7494
|
+
...element.data,
|
|
7495
|
+
rows: element.data.rows.map((row) => ({
|
|
7496
|
+
...row,
|
|
7497
|
+
cells: row.cells.map((cell) => ({ ...cell, elements: transform(cell.elements) }))
|
|
7498
|
+
}))
|
|
7499
|
+
}
|
|
7500
|
+
};
|
|
7501
|
+
}
|
|
7502
|
+
if (element.element === "definition-list") {
|
|
7503
|
+
return {
|
|
7504
|
+
...element,
|
|
7505
|
+
data: element.data.map((entry) => ({
|
|
7506
|
+
...entry,
|
|
7507
|
+
key: transform(entry.key),
|
|
7508
|
+
value: transform(entry.value)
|
|
7509
|
+
}))
|
|
7510
|
+
};
|
|
7511
|
+
}
|
|
7512
|
+
if (element.element === "tab-view") {
|
|
7513
|
+
return {
|
|
7514
|
+
...element,
|
|
7515
|
+
data: element.data.map((tab) => ({ ...tab, elements: transform(tab.elements) }))
|
|
7516
|
+
};
|
|
7517
|
+
}
|
|
7518
|
+
const children = getGenericElementChildren(element);
|
|
7519
|
+
return children === null ? element : withGenericElementChildren(element, transform(children));
|
|
7520
|
+
}
|
|
7521
|
+
function mapSubList(item, transform) {
|
|
7522
|
+
const transformed = transform([listElement(item.data)])[0];
|
|
7523
|
+
return transformed?.element === "list" ? { ...item, data: transformed.data } : item;
|
|
7524
|
+
}
|
|
7525
|
+
function walkSyntaxOrder(elements, callback) {
|
|
7122
7526
|
for (const element of elements) {
|
|
7123
|
-
|
|
7124
|
-
|
|
7527
|
+
callback(element);
|
|
7528
|
+
walkAllSyntaxChildren(element, (children) => walkSyntaxOrder(children, callback));
|
|
7529
|
+
}
|
|
7530
|
+
}
|
|
7531
|
+
function walkRenderOrder(elements, pageTags, callback) {
|
|
7532
|
+
for (const element of elements) {
|
|
7533
|
+
callback(element);
|
|
7534
|
+
if (element.element === "if") {
|
|
7535
|
+
walkRenderOrder(isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
|
|
7536
|
+
continue;
|
|
7537
|
+
}
|
|
7538
|
+
if (element.element === "ifexpr") {
|
|
7539
|
+
const evaluated = evaluateExpression(element.data.expression);
|
|
7540
|
+
if (evaluated.success) {
|
|
7541
|
+
walkRenderOrder(evaluated.value !== 0 ? element.data.then : element.data.else, pageTags, callback);
|
|
7542
|
+
}
|
|
7125
7543
|
continue;
|
|
7126
7544
|
}
|
|
7127
7545
|
if (element.element === "if-tags") {
|
|
7128
|
-
const
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
element: "if-tags",
|
|
7133
|
-
data
|
|
7134
|
-
});
|
|
7546
|
+
const resolved = resolveIfTags(element.data, pageTags);
|
|
7547
|
+
if (!resolved.evaluated || resolved.matched) {
|
|
7548
|
+
walkRenderOrder(element.data.elements, pageTags, callback);
|
|
7549
|
+
}
|
|
7135
7550
|
continue;
|
|
7136
7551
|
}
|
|
7137
|
-
|
|
7552
|
+
if (element.element === "bibliography-block") {
|
|
7553
|
+
if (!element.data.hide) {
|
|
7554
|
+
for (const entry of element.data.entries) {
|
|
7555
|
+
walkRenderOrder(entry.value, pageTags, callback);
|
|
7556
|
+
}
|
|
7557
|
+
}
|
|
7558
|
+
continue;
|
|
7559
|
+
}
|
|
7560
|
+
walkBasicChildren(element, (children) => walkRenderOrder(children, pageTags, callback));
|
|
7138
7561
|
}
|
|
7139
|
-
|
|
7562
|
+
}
|
|
7563
|
+
function walkAllSyntaxChildren(element, callback) {
|
|
7564
|
+
if (element.element === "if" || element.element === "ifexpr") {
|
|
7565
|
+
callback(element.data.then);
|
|
7566
|
+
callback(element.data.else);
|
|
7567
|
+
return;
|
|
7568
|
+
}
|
|
7569
|
+
if (element.element === "bibliography-block") {
|
|
7570
|
+
for (const entry of element.data.entries) {
|
|
7571
|
+
callback(entry.key);
|
|
7572
|
+
callback(entry.value);
|
|
7573
|
+
}
|
|
7574
|
+
return;
|
|
7575
|
+
}
|
|
7576
|
+
walkBasicChildren(element, callback);
|
|
7577
|
+
}
|
|
7578
|
+
function walkBasicChildren(element, callback) {
|
|
7579
|
+
if (element.element === "list") {
|
|
7580
|
+
for (const item of element.data.items) {
|
|
7581
|
+
callback(item["item-type"] === "elements" ? item.elements : [listElement(item.data)]);
|
|
7582
|
+
}
|
|
7583
|
+
return;
|
|
7584
|
+
}
|
|
7585
|
+
if (element.element === "table") {
|
|
7586
|
+
for (const row of element.data.rows) {
|
|
7587
|
+
for (const cell of row.cells)
|
|
7588
|
+
callback(cell.elements);
|
|
7589
|
+
}
|
|
7590
|
+
return;
|
|
7591
|
+
}
|
|
7592
|
+
if (element.element === "definition-list") {
|
|
7593
|
+
for (const entry of element.data) {
|
|
7594
|
+
callback(entry.key);
|
|
7595
|
+
callback(entry.value);
|
|
7596
|
+
}
|
|
7597
|
+
return;
|
|
7598
|
+
}
|
|
7599
|
+
if (element.element === "tab-view") {
|
|
7600
|
+
for (const tab of element.data)
|
|
7601
|
+
callback(tab.elements);
|
|
7602
|
+
return;
|
|
7603
|
+
}
|
|
7604
|
+
const children = getGenericElementChildren(element);
|
|
7605
|
+
if (children !== null)
|
|
7606
|
+
callback(children);
|
|
7607
|
+
}
|
|
7608
|
+
function isTocHeading(element) {
|
|
7609
|
+
return element.element === "container" && typeof element.data.type === "object" && "header" in element.data.type && element.data.type.header["has-toc"];
|
|
7140
7610
|
}
|
|
7141
7611
|
|
|
7142
7612
|
// packages/parser/src/parser/rules/block/module/resolve.ts
|
|
7143
7613
|
var MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
|
|
7144
7614
|
async function resolveModules(ast, dataProvider, options) {
|
|
7145
|
-
const
|
|
7615
|
+
const registry = new ModuleDocumentRegistry;
|
|
7616
|
+
registry.register(ast);
|
|
7617
|
+
const parse = createModuleParseFunction(options, dataProvider, registry);
|
|
7146
7618
|
const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
|
|
7147
7619
|
const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
|
|
7148
7620
|
const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
|
|
7149
7621
|
const pageTags = dataProvider.getPageTags?.() ?? null;
|
|
7622
|
+
const resolvedStyleSlots = new Map;
|
|
7623
|
+
const routedStyleAnchors = new WeakSet;
|
|
7150
7624
|
const resolvedElements = walkAndResolve(ast.elements, {
|
|
7151
7625
|
listPages: listPagesCtx,
|
|
7152
7626
|
listUsers: listUsersCtx,
|
|
@@ -7157,24 +7631,30 @@ async function resolveModules(ast, dataProvider, options) {
|
|
|
7157
7631
|
pageTags,
|
|
7158
7632
|
listPagesIdCounter: 0,
|
|
7159
7633
|
listUsersIdCounter: 0,
|
|
7160
|
-
tagCloudIdCounter: 0
|
|
7634
|
+
tagCloudIdCounter: 0,
|
|
7635
|
+
resolvedStyleSlots,
|
|
7636
|
+
routedStyleAnchors
|
|
7161
7637
|
});
|
|
7162
|
-
const {
|
|
7638
|
+
const {
|
|
7639
|
+
elements: finalElements,
|
|
7640
|
+
styles,
|
|
7641
|
+
anchoredStyles
|
|
7642
|
+
} = collectStyles(resolvedElements.elements, routedStyleAnchors);
|
|
7163
7643
|
const result = {
|
|
7164
7644
|
...ast,
|
|
7165
7645
|
elements: finalElements
|
|
7166
7646
|
};
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7647
|
+
const mergedStyles = mergeCollectedStyles(ast.styles, styles, resolvedStyleSlots, anchoredStyles);
|
|
7648
|
+
if (mergedStyles.length > 0)
|
|
7649
|
+
result.styles = mergedStyles;
|
|
7650
|
+
options.onDiagnostics?.(registry.diagnostics);
|
|
7651
|
+
return registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements));
|
|
7171
7652
|
}
|
|
7172
|
-
function createModuleParseFunction(options, dataProvider) {
|
|
7653
|
+
function createModuleParseFunction(options, dataProvider, registry) {
|
|
7173
7654
|
const transform = createModuleSourceTransform(options, dataProvider);
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
}
|
|
7177
|
-
return (source) => options.parse(transform(source));
|
|
7655
|
+
return (source) => registry.register(options.parse(transform ? transform(source) : source), {
|
|
7656
|
+
stripLegacyImplicitFootnoteBlock: true
|
|
7657
|
+
});
|
|
7178
7658
|
}
|
|
7179
7659
|
function createModuleSourceTransform(options, dataProvider) {
|
|
7180
7660
|
if (options.transformModuleSource) {
|
|
@@ -12309,6 +12789,7 @@ function createParseContext(tokens, options = {}) {
|
|
|
12309
12789
|
version: options.version ?? "wikidot",
|
|
12310
12790
|
trackPositions: options.trackPositions ?? true,
|
|
12311
12791
|
settings: options.settings ?? DEFAULT_SETTINGS,
|
|
12792
|
+
appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
|
|
12312
12793
|
footnotes: [],
|
|
12313
12794
|
tocEntries: [],
|
|
12314
12795
|
codeBlocks: [],
|
|
@@ -12826,67 +13307,6 @@ function suppressAtLevel(elements) {
|
|
|
12826
13307
|
function suppressDivAdjacentParagraphs(elements) {
|
|
12827
13308
|
return suppressAtLevel(elements);
|
|
12828
13309
|
}
|
|
12829
|
-
// packages/parser/src/parser/toc.ts
|
|
12830
|
-
class TocIndexer {
|
|
12831
|
-
index = 0;
|
|
12832
|
-
next() {
|
|
12833
|
-
return this.index++;
|
|
12834
|
-
}
|
|
12835
|
-
}
|
|
12836
|
-
function buildTocList(indexer, items) {
|
|
12837
|
-
const listItems = items.map((item) => buildTocListItem(indexer, item));
|
|
12838
|
-
return {
|
|
12839
|
-
element: "list",
|
|
12840
|
-
data: {
|
|
12841
|
-
type: "bullet",
|
|
12842
|
-
attributes: {},
|
|
12843
|
-
items: listItems
|
|
12844
|
-
}
|
|
12845
|
-
};
|
|
12846
|
-
}
|
|
12847
|
-
function buildTocListItem(indexer, item) {
|
|
12848
|
-
if (item.kind === "list") {
|
|
12849
|
-
return {
|
|
12850
|
-
"item-type": "sub-list",
|
|
12851
|
-
element: "list",
|
|
12852
|
-
data: {
|
|
12853
|
-
type: "bullet",
|
|
12854
|
-
attributes: {},
|
|
12855
|
-
items: item.children.map((child) => buildTocListItem(indexer, child))
|
|
12856
|
-
}
|
|
12857
|
-
};
|
|
12858
|
-
}
|
|
12859
|
-
const anchor = `#toc${indexer.next()}`;
|
|
12860
|
-
const linkElement = {
|
|
12861
|
-
element: "link",
|
|
12862
|
-
data: {
|
|
12863
|
-
type: "table-of-contents",
|
|
12864
|
-
link: anchor,
|
|
12865
|
-
extra: null,
|
|
12866
|
-
label: { text: item.value },
|
|
12867
|
-
target: null
|
|
12868
|
-
}
|
|
12869
|
-
};
|
|
12870
|
-
return {
|
|
12871
|
-
"item-type": "elements",
|
|
12872
|
-
attributes: {},
|
|
12873
|
-
elements: [linkElement]
|
|
12874
|
-
};
|
|
12875
|
-
}
|
|
12876
|
-
function buildTableOfContents(entries) {
|
|
12877
|
-
if (entries.length === 0) {
|
|
12878
|
-
return [];
|
|
12879
|
-
}
|
|
12880
|
-
const depthItems = entries.map((entry) => ({
|
|
12881
|
-
depth: entry.level - 1,
|
|
12882
|
-
ltype: null,
|
|
12883
|
-
value: entry.text
|
|
12884
|
-
}));
|
|
12885
|
-
const trees = processDepths(null, depthItems);
|
|
12886
|
-
const indexer = new TocIndexer;
|
|
12887
|
-
return trees.map((tree) => buildTocList(indexer, tree.list));
|
|
12888
|
-
}
|
|
12889
|
-
|
|
12890
13310
|
// packages/parser/src/parser/parse/footnotes.ts
|
|
12891
13311
|
function containsFootnoteBlock(elements) {
|
|
12892
13312
|
let found = false;
|
|
@@ -12900,7 +13320,9 @@ function containsFootnoteBlock(elements) {
|
|
|
12900
13320
|
// packages/parser/src/parser/parse/result.ts
|
|
12901
13321
|
function finalizeParseResult(ctx, children) {
|
|
12902
13322
|
const cleanedChildren = postprocessChildren(children);
|
|
12903
|
-
appendImplicitFootnoteBlock
|
|
13323
|
+
if (ctx.appendImplicitFootnoteBlock) {
|
|
13324
|
+
appendImplicitFootnoteBlock(cleanedChildren);
|
|
13325
|
+
}
|
|
12904
13326
|
return {
|
|
12905
13327
|
ast: buildSyntaxTree(ctx, cleanedChildren),
|
|
12906
13328
|
diagnostics: ctx.diagnostics
|
|
@@ -13273,10 +13695,10 @@ function preprocess(text) {
|
|
|
13273
13695
|
}
|
|
13274
13696
|
|
|
13275
13697
|
// packages/parser/src/parser/preprocess/expr/evaluate.ts
|
|
13276
|
-
import { evaluateExpression, formatExprValue, isTruthy } from "@wdprlib/ast";
|
|
13698
|
+
import { evaluateExpression as evaluateExpression2, formatExprValue, isTruthy as isTruthy2 } from "@wdprlib/ast";
|
|
13277
13699
|
function evaluateDirective(kind, match) {
|
|
13278
13700
|
if (kind === "expr") {
|
|
13279
|
-
const result2 =
|
|
13701
|
+
const result2 = evaluateExpression2(match.head);
|
|
13280
13702
|
if (result2.success)
|
|
13281
13703
|
return formatExprValue(result2.value);
|
|
13282
13704
|
if (result2.error === "empty expression")
|
|
@@ -13286,11 +13708,11 @@ function evaluateDirective(kind, match) {
|
|
|
13286
13708
|
if (kind === "if") {
|
|
13287
13709
|
if (!match.hasPipe)
|
|
13288
13710
|
return "";
|
|
13289
|
-
return
|
|
13711
|
+
return isTruthy2(match.head) ? match.thenText : match.elseText;
|
|
13290
13712
|
}
|
|
13291
13713
|
if (!match.hasPipe)
|
|
13292
13714
|
return "";
|
|
13293
|
-
const result =
|
|
13715
|
+
const result = evaluateExpression2(match.head);
|
|
13294
13716
|
if (!result.success)
|
|
13295
13717
|
return "ERROR";
|
|
13296
13718
|
return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
|
|
@@ -13470,6 +13892,252 @@ function parse(source, options) {
|
|
|
13470
13892
|
});
|
|
13471
13893
|
return new Parser(tokens, options).parse();
|
|
13472
13894
|
}
|
|
13895
|
+
// packages/parser/src/pipeline/process.ts
|
|
13896
|
+
import { DEFAULT_SETTINGS as DEFAULT_SETTINGS2 } from "@wdprlib/ast";
|
|
13897
|
+
|
|
13898
|
+
// packages/parser/src/parser/rules/block/module/resolution/resolve-async.ts
|
|
13899
|
+
async function resolveModulesWithAsyncParse(ast, dataProvider, options) {
|
|
13900
|
+
const registry = new ModuleDocumentRegistry;
|
|
13901
|
+
registry.register(ast);
|
|
13902
|
+
const parse2 = async (source) => registry.register(await options.parse(source));
|
|
13903
|
+
const [listPagesData, listUsersData, tagCloudData] = await Promise.all([
|
|
13904
|
+
buildListPagesDataMap(dataProvider, options.requirements.listPages ?? [], options.urlPath),
|
|
13905
|
+
buildListUsersDataMap(dataProvider, options.requirements.listUsers ?? []),
|
|
13906
|
+
buildTagCloudDataMap(dataProvider, options.requirements.tagCloud ?? [])
|
|
13907
|
+
]);
|
|
13908
|
+
const context = {
|
|
13909
|
+
dataProvider,
|
|
13910
|
+
listPagesData,
|
|
13911
|
+
listUsersData,
|
|
13912
|
+
tagCloudData,
|
|
13913
|
+
options,
|
|
13914
|
+
parse: parse2
|
|
13915
|
+
};
|
|
13916
|
+
const state = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
|
|
13917
|
+
const resolvedElements = await resolveElements(ast.elements, context, state);
|
|
13918
|
+
const { elements, styles, anchoredStyles } = collectStyles(resolvedElements);
|
|
13919
|
+
const intermediate = { ...ast, elements };
|
|
13920
|
+
const mergedStyles = mergeCollectedStyles(ast.styles, styles, new Map, anchoredStyles);
|
|
13921
|
+
if (mergedStyles.length > 0)
|
|
13922
|
+
intermediate.styles = mergedStyles;
|
|
13923
|
+
else
|
|
13924
|
+
delete intermediate.styles;
|
|
13925
|
+
return {
|
|
13926
|
+
ast: registry.finalize(intermediate, elements, options.pageTags),
|
|
13927
|
+
diagnostics: registry.diagnostics
|
|
13928
|
+
};
|
|
13929
|
+
}
|
|
13930
|
+
async function resolveElements(elements, context, state) {
|
|
13931
|
+
const result = [];
|
|
13932
|
+
for (const element of elements) {
|
|
13933
|
+
if (element.element === "module") {
|
|
13934
|
+
const resolved = await resolveModuleElement(element, context, state);
|
|
13935
|
+
if (resolved !== null) {
|
|
13936
|
+
result.push(...resolved);
|
|
13937
|
+
continue;
|
|
13938
|
+
}
|
|
13939
|
+
}
|
|
13940
|
+
if (element.element === "if-tags") {
|
|
13941
|
+
const resolution = resolveIfTags(element.data, context.options.pageTags);
|
|
13942
|
+
if (resolution.matched) {
|
|
13943
|
+
result.push(...await resolveElements(element.data.elements, context, state));
|
|
13944
|
+
}
|
|
13945
|
+
continue;
|
|
13946
|
+
}
|
|
13947
|
+
result.push(await resolveElementChildren(element, context, state));
|
|
13948
|
+
}
|
|
13949
|
+
return result;
|
|
13950
|
+
}
|
|
13951
|
+
async function resolveModuleElement(element, context, state) {
|
|
13952
|
+
if (isListPagesModule2(element.data)) {
|
|
13953
|
+
const id = state.listPagesId++;
|
|
13954
|
+
const data = context.listPagesData.get(id);
|
|
13955
|
+
const template = context.options.compiledListPagesTemplates.get(id);
|
|
13956
|
+
if (data && template)
|
|
13957
|
+
return resolveListPagesAsync(element.data, data, template, context.parse);
|
|
13958
|
+
return context.dataProvider.fetchListPages ? [] : [element];
|
|
13959
|
+
}
|
|
13960
|
+
if (isListUsersModule2(element.data)) {
|
|
13961
|
+
const id = state.listUsersId++;
|
|
13962
|
+
const data = context.listUsersData.get(id);
|
|
13963
|
+
const template = context.options.compiledListUsersTemplates?.get(id);
|
|
13964
|
+
if (data && template) {
|
|
13965
|
+
const variableContext = { user: data.user };
|
|
13966
|
+
return (await context.parse(template(variableContext))).elements;
|
|
13967
|
+
}
|
|
13968
|
+
return context.dataProvider.fetchListUsers ? [] : [element];
|
|
13969
|
+
}
|
|
13970
|
+
if (isTagCloudModule(element.data)) {
|
|
13971
|
+
const id = state.tagCloudId++;
|
|
13972
|
+
const data = context.tagCloudData.get(id);
|
|
13973
|
+
if (data)
|
|
13974
|
+
return resolveTagCloud(element.data, data);
|
|
13975
|
+
return context.dataProvider.fetchTagCloud ? [] : [element];
|
|
13976
|
+
}
|
|
13977
|
+
return null;
|
|
13978
|
+
}
|
|
13979
|
+
async function resolveListPagesAsync(module, data, template, parse2) {
|
|
13980
|
+
if (data.pages.length === 0)
|
|
13981
|
+
return [];
|
|
13982
|
+
const result = [];
|
|
13983
|
+
if (module["prepend-line"] && !module.separate) {
|
|
13984
|
+
result.push(...(await parse2(module["prepend-line"])).elements);
|
|
13985
|
+
}
|
|
13986
|
+
for (let i = 0;i < data.pages.length; i++) {
|
|
13987
|
+
const page = data.pages[i];
|
|
13988
|
+
if (!page)
|
|
13989
|
+
continue;
|
|
13990
|
+
const variableContext = {
|
|
13991
|
+
page,
|
|
13992
|
+
index: i + 1,
|
|
13993
|
+
total: data.totalCount,
|
|
13994
|
+
limit: module.limit,
|
|
13995
|
+
site: data.site
|
|
13996
|
+
};
|
|
13997
|
+
const parsed = await parse2(template(variableContext));
|
|
13998
|
+
if (module.separate) {
|
|
13999
|
+
result.push({
|
|
14000
|
+
element: "container",
|
|
14001
|
+
data: {
|
|
14002
|
+
type: "div",
|
|
14003
|
+
attributes: { class: "list-pages-item" },
|
|
14004
|
+
elements: parsed.elements
|
|
14005
|
+
}
|
|
14006
|
+
});
|
|
14007
|
+
} else {
|
|
14008
|
+
result.push(...parsed.elements);
|
|
14009
|
+
}
|
|
14010
|
+
}
|
|
14011
|
+
if (module["append-line"] && !module.separate) {
|
|
14012
|
+
result.push(...(await parse2(module["append-line"])).elements);
|
|
14013
|
+
}
|
|
14014
|
+
return module.wrapper ? [
|
|
14015
|
+
{
|
|
14016
|
+
element: "container",
|
|
14017
|
+
data: {
|
|
14018
|
+
type: "div",
|
|
14019
|
+
attributes: { class: "list-pages-box" },
|
|
14020
|
+
elements: result
|
|
14021
|
+
}
|
|
14022
|
+
}
|
|
14023
|
+
] : result;
|
|
14024
|
+
}
|
|
14025
|
+
async function resolveElementChildren(element, context, state) {
|
|
14026
|
+
if (element.element === "list") {
|
|
14027
|
+
const items = [];
|
|
14028
|
+
for (const item of element.data.items) {
|
|
14029
|
+
if (item["item-type"] === "elements") {
|
|
14030
|
+
items.push({ ...item, elements: await resolveElements(item.elements, context, state) });
|
|
14031
|
+
} else {
|
|
14032
|
+
const resolved = (await resolveElements([listElement(item.data)], context, state))[0];
|
|
14033
|
+
items.push(resolved?.element === "list" ? { ...item, data: resolved.data } : item);
|
|
14034
|
+
}
|
|
14035
|
+
}
|
|
14036
|
+
return { ...element, data: { ...element.data, items } };
|
|
14037
|
+
}
|
|
14038
|
+
if (element.element === "table") {
|
|
14039
|
+
const rows = [];
|
|
14040
|
+
for (const row of element.data.rows) {
|
|
14041
|
+
const cells = [];
|
|
14042
|
+
for (const cell of row.cells) {
|
|
14043
|
+
cells.push({ ...cell, elements: await resolveElements(cell.elements, context, state) });
|
|
14044
|
+
}
|
|
14045
|
+
rows.push({ ...row, cells });
|
|
14046
|
+
}
|
|
14047
|
+
return { ...element, data: { ...element.data, rows } };
|
|
14048
|
+
}
|
|
14049
|
+
if (element.element === "definition-list") {
|
|
14050
|
+
const entries = [];
|
|
14051
|
+
for (const entry of element.data) {
|
|
14052
|
+
entries.push({
|
|
14053
|
+
...entry,
|
|
14054
|
+
key: await resolveElements(entry.key, context, state),
|
|
14055
|
+
value: await resolveElements(entry.value, context, state)
|
|
14056
|
+
});
|
|
14057
|
+
}
|
|
14058
|
+
return { ...element, data: entries };
|
|
14059
|
+
}
|
|
14060
|
+
if (element.element === "tab-view") {
|
|
14061
|
+
const tabs = [];
|
|
14062
|
+
for (const tab of element.data) {
|
|
14063
|
+
tabs.push({ ...tab, elements: await resolveElements(tab.elements, context, state) });
|
|
14064
|
+
}
|
|
14065
|
+
return { ...element, data: tabs };
|
|
14066
|
+
}
|
|
14067
|
+
const children = getGenericElementChildren(element);
|
|
14068
|
+
return children === null ? element : withGenericElementChildren(element, await resolveElements(children, context, state));
|
|
14069
|
+
}
|
|
14070
|
+
|
|
14071
|
+
// packages/parser/src/pipeline/process.ts
|
|
14072
|
+
async function processWikitext(source, options) {
|
|
14073
|
+
const settings = options.settings ?? DEFAULT_SETTINGS2;
|
|
14074
|
+
const callbackContext = {
|
|
14075
|
+
page: options.page,
|
|
14076
|
+
settings
|
|
14077
|
+
};
|
|
14078
|
+
const dependencies = [];
|
|
14079
|
+
const fetchInclude = createRequestIncludeFetcher(options.dataProvider?.fetchInclude ? (pageRef) => options.dataProvider.fetchInclude(pageRef, callbackContext) : undefined);
|
|
14080
|
+
const resolveSource = async (input) => {
|
|
14081
|
+
if (!fetchInclude)
|
|
14082
|
+
return input;
|
|
14083
|
+
const resolution = await resolveIncludesAsyncWithTrace(input, fetchInclude, {
|
|
14084
|
+
maxIterations: options.includeMaxIterations,
|
|
14085
|
+
settings
|
|
14086
|
+
});
|
|
14087
|
+
dependencies.push(...resolution.dependencies);
|
|
14088
|
+
return resolution.source;
|
|
14089
|
+
};
|
|
14090
|
+
const expandedSource = await resolveSource(source);
|
|
14091
|
+
const initial = parse(expandedSource, {
|
|
14092
|
+
settings,
|
|
14093
|
+
pageTags: options.page.tags,
|
|
14094
|
+
appendImplicitFootnoteBlock: false
|
|
14095
|
+
});
|
|
14096
|
+
const extraction = extractDataRequirements(initial.ast);
|
|
14097
|
+
const dataProvider = createModuleDataProvider(options, callbackContext);
|
|
14098
|
+
const resolved = await resolveModulesWithAsyncParse(initial.ast, dataProvider, {
|
|
14099
|
+
parse: async (fragmentSource) => parse(await resolveSource(fragmentSource), {
|
|
14100
|
+
settings,
|
|
14101
|
+
pageTags: options.page.tags,
|
|
14102
|
+
appendImplicitFootnoteBlock: false
|
|
14103
|
+
}),
|
|
14104
|
+
compiledListPagesTemplates: extraction.compiledListPagesTemplates,
|
|
14105
|
+
compiledListUsersTemplates: extraction.compiledListUsersTemplates,
|
|
14106
|
+
requirements: extraction.requirements,
|
|
14107
|
+
urlPath: options.page.urlPath,
|
|
14108
|
+
pageTags: options.page.tags
|
|
14109
|
+
});
|
|
14110
|
+
return {
|
|
14111
|
+
ast: resolved.ast,
|
|
14112
|
+
page: options.page,
|
|
14113
|
+
settings,
|
|
14114
|
+
diagnostics: [...initial.diagnostics, ...resolved.diagnostics],
|
|
14115
|
+
dependencies
|
|
14116
|
+
};
|
|
14117
|
+
}
|
|
14118
|
+
function createModuleDataProvider(options, context) {
|
|
14119
|
+
const provider = options.dataProvider;
|
|
14120
|
+
return {
|
|
14121
|
+
fetchListPages: provider?.fetchListPages ? (query, requirement) => provider.fetchListPages(query, requirement, context) : undefined,
|
|
14122
|
+
fetchListUsers: provider?.fetchListUsers ? (requirement) => provider.fetchListUsers(requirement, context) : undefined,
|
|
14123
|
+
fetchTagCloud: provider?.fetchTagCloud ? (requirement) => provider.fetchTagCloud(requirement, context) : undefined,
|
|
14124
|
+
getPageTags: () => options.page.tags
|
|
14125
|
+
};
|
|
14126
|
+
}
|
|
14127
|
+
function createRequestIncludeFetcher(fetcher) {
|
|
14128
|
+
if (!fetcher)
|
|
14129
|
+
return;
|
|
14130
|
+
const cache = new Map;
|
|
14131
|
+
return (pageRef) => {
|
|
14132
|
+
const key = `${pageRef.site ?? ""}:${pageRef.page.toLowerCase()}`;
|
|
14133
|
+
const cached = cache.get(key);
|
|
14134
|
+
if (cached)
|
|
14135
|
+
return cached;
|
|
14136
|
+
const result = fetcher(pageRef).catch(() => null);
|
|
14137
|
+
cache.set(key, result);
|
|
14138
|
+
return result;
|
|
14139
|
+
};
|
|
14140
|
+
}
|
|
13473
14141
|
export {
|
|
13474
14142
|
tokenize,
|
|
13475
14143
|
text,
|
|
@@ -13477,8 +14145,10 @@ export {
|
|
|
13477
14145
|
resolveModules,
|
|
13478
14146
|
resolveListUsers,
|
|
13479
14147
|
resolveIncludesWithTrace,
|
|
14148
|
+
resolveIncludesAsyncWithTrace,
|
|
13480
14149
|
resolveIncludesAsync,
|
|
13481
14150
|
resolveIncludes,
|
|
14151
|
+
processWikitext,
|
|
13482
14152
|
preprocessIftags,
|
|
13483
14153
|
parseTags,
|
|
13484
14154
|
parseParent,
|
|
@@ -13513,5 +14183,5 @@ export {
|
|
|
13513
14183
|
STYLE_SLOT_PREFIX2 as STYLE_SLOT_PREFIX,
|
|
13514
14184
|
Parser,
|
|
13515
14185
|
Lexer,
|
|
13516
|
-
|
|
14186
|
+
DEFAULT_SETTINGS3 as DEFAULT_SETTINGS
|
|
13517
14187
|
};
|