@wdprlib/parser 4.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -38
- package/dist/index.cjs +1035 -249
- package/dist/index.d.cts +203 -158
- package/dist/index.d.ts +203 -158
- package/dist/index.js +930 -139
- package/package.json +2 -2
- package/src/index.ts +13 -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/preprocess/expr/index.ts +26 -0
- package/src/parser/preprocess/utils/raw-regions.ts +16 -7
- 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 +4 -1
- package/src/parser/rules/block/module/listpages/index.ts +2 -0
- 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/listpages/selectors.ts +64 -0
- package/src/parser/rules/block/module/listpages/types/external-data.ts +22 -0
- 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 +172 -0
- package/src/pipeline/types.ts +63 -0
package/dist/index.cjs
CHANGED
|
@@ -31,13 +31,15 @@ var __export = (target, all) => {
|
|
|
31
31
|
var exports_src = {};
|
|
32
32
|
__export(exports_src, {
|
|
33
33
|
tokenize: () => tokenize,
|
|
34
|
-
text: () =>
|
|
34
|
+
text: () => import_ast8.text,
|
|
35
35
|
resolveTagCloud: () => resolveTagCloud,
|
|
36
36
|
resolveModules: () => resolveModules,
|
|
37
37
|
resolveListUsers: () => resolveListUsers,
|
|
38
38
|
resolveIncludesWithTrace: () => resolveIncludesWithTrace,
|
|
39
|
+
resolveIncludesAsyncWithTrace: () => resolveIncludesAsyncWithTrace,
|
|
39
40
|
resolveIncludesAsync: () => resolveIncludesAsync,
|
|
40
41
|
resolveIncludes: () => resolveIncludes,
|
|
42
|
+
processWikitext: () => processWikitext,
|
|
41
43
|
preprocessIftags: () => preprocessIftags,
|
|
42
44
|
parseTags: () => parseTags,
|
|
43
45
|
parseParent: () => parseParent,
|
|
@@ -46,37 +48,39 @@ __export(exports_src, {
|
|
|
46
48
|
parseDateSelector: () => parseDateSelector,
|
|
47
49
|
parseCategory: () => parseCategory,
|
|
48
50
|
parse: () => parse,
|
|
49
|
-
paragraph: () =>
|
|
51
|
+
paragraph: () => import_ast8.paragraph,
|
|
50
52
|
normalizeQuery: () => normalizeQuery,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
matchesListPagesSelectors: () => matchesListPagesSelectors,
|
|
54
|
+
listItemSubList: () => import_ast8.listItemSubList,
|
|
55
|
+
listItemElements: () => import_ast8.listItemElements,
|
|
56
|
+
list: () => import_ast8.list,
|
|
57
|
+
link: () => import_ast8.link,
|
|
58
|
+
lineBreak: () => import_ast8.lineBreak,
|
|
59
|
+
italics: () => import_ast8.italics,
|
|
57
60
|
isTagCloudModule: () => isTagCloudModule,
|
|
58
61
|
isListUsersModule: () => isListUsersModule2,
|
|
59
|
-
horizontalRule: () =>
|
|
60
|
-
heading: () =>
|
|
62
|
+
horizontalRule: () => import_ast8.horizontalRule,
|
|
63
|
+
heading: () => import_ast8.heading,
|
|
61
64
|
extractListUsersVariables: () => extractListUsersVariables,
|
|
62
65
|
extractIncludeReferences: () => extractIncludeReferences,
|
|
63
66
|
extractDataRequirements: () => extractDataRequirements,
|
|
67
|
+
definePageData: () => definePageData,
|
|
64
68
|
createToken: () => createToken,
|
|
65
|
-
createSettings: () =>
|
|
66
|
-
createPosition: () =>
|
|
67
|
-
createPoint: () =>
|
|
68
|
-
container: () =>
|
|
69
|
+
createSettings: () => import_ast9.createSettings,
|
|
70
|
+
createPosition: () => import_ast8.createPosition,
|
|
71
|
+
createPoint: () => import_ast8.createPoint,
|
|
72
|
+
container: () => import_ast8.container,
|
|
69
73
|
compileTemplate: () => compileTemplate,
|
|
70
74
|
compileListUsersTemplate: () => compileListUsersTemplate,
|
|
71
|
-
bold: () =>
|
|
72
|
-
STYLE_SLOT_PREFIX: () =>
|
|
75
|
+
bold: () => import_ast8.bold,
|
|
76
|
+
STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
|
|
73
77
|
Parser: () => Parser,
|
|
74
78
|
Lexer: () => Lexer,
|
|
75
|
-
DEFAULT_SETTINGS: () =>
|
|
79
|
+
DEFAULT_SETTINGS: () => import_ast9.DEFAULT_SETTINGS
|
|
76
80
|
});
|
|
77
81
|
module.exports = __toCommonJS(exports_src);
|
|
78
|
-
var
|
|
79
|
-
var
|
|
82
|
+
var import_ast8 = require("@wdprlib/ast");
|
|
83
|
+
var import_ast9 = require("@wdprlib/ast");
|
|
80
84
|
|
|
81
85
|
// packages/parser/src/lexer/tokens.ts
|
|
82
86
|
function createToken(type, value, position, lineStart = false) {
|
|
@@ -1443,7 +1447,7 @@ function parseNextBlock(ctx, skipWhitespace2, isAtEnd2) {
|
|
|
1443
1447
|
}
|
|
1444
1448
|
|
|
1445
1449
|
// packages/parser/src/parser/parse/context.ts
|
|
1446
|
-
var
|
|
1450
|
+
var import_ast5 = require("@wdprlib/ast");
|
|
1447
1451
|
|
|
1448
1452
|
// packages/parser/src/parser/rules/tokens.ts
|
|
1449
1453
|
function currentToken(ctx) {
|
|
@@ -5843,6 +5847,11 @@ function extractDataRequirements(ast) {
|
|
|
5843
5847
|
});
|
|
5844
5848
|
return result;
|
|
5845
5849
|
}
|
|
5850
|
+
// packages/parser/src/parser/rules/block/module/types.ts
|
|
5851
|
+
function getModuleParseAst(result) {
|
|
5852
|
+
return "ast" in result ? result.ast : result;
|
|
5853
|
+
}
|
|
5854
|
+
|
|
5846
5855
|
// packages/parser/src/parser/rules/block/module/listpages/resolution/items.ts
|
|
5847
5856
|
function renderListPagesItems(module2, data, compiledTemplate, parse) {
|
|
5848
5857
|
const items = [];
|
|
@@ -5857,7 +5866,7 @@ function renderListPagesItems(module2, data, compiledTemplate, parse) {
|
|
|
5857
5866
|
limit: module2.limit,
|
|
5858
5867
|
site: data.site
|
|
5859
5868
|
};
|
|
5860
|
-
const itemAst = parse(compiledTemplate(ctx));
|
|
5869
|
+
const itemAst = getModuleParseAst(parse(compiledTemplate(ctx)));
|
|
5861
5870
|
if (module2.separate) {
|
|
5862
5871
|
items.push({
|
|
5863
5872
|
element: "container",
|
|
@@ -5881,12 +5890,12 @@ function wrapListPagesResult(module2, items, parse) {
|
|
|
5881
5890
|
}
|
|
5882
5891
|
const result = [];
|
|
5883
5892
|
if (module2["prepend-line"] && !module2.separate) {
|
|
5884
|
-
const prependAst = parse(module2["prepend-line"]);
|
|
5893
|
+
const prependAst = getModuleParseAst(parse(module2["prepend-line"]));
|
|
5885
5894
|
result.push(...prependAst.elements);
|
|
5886
5895
|
}
|
|
5887
5896
|
result.push(...items);
|
|
5888
5897
|
if (module2["append-line"] && !module2.separate) {
|
|
5889
|
-
const appendAst = parse(module2["append-line"]);
|
|
5898
|
+
const appendAst = getModuleParseAst(parse(module2["append-line"]));
|
|
5890
5899
|
result.push(...appendAst.elements);
|
|
5891
5900
|
}
|
|
5892
5901
|
if (module2.wrapper) {
|
|
@@ -5912,6 +5921,60 @@ function resolveListPages(module2, data, compiledTemplate, parse) {
|
|
|
5912
5921
|
const items = renderListPagesItems(module2, data, compiledTemplate, parse);
|
|
5913
5922
|
return wrapListPagesResult(module2, items, parse);
|
|
5914
5923
|
}
|
|
5924
|
+
// packages/parser/src/parser/rules/block/module/listpages/types/external-data.ts
|
|
5925
|
+
function definePageData(input) {
|
|
5926
|
+
const separator = input.fullname.indexOf(":");
|
|
5927
|
+
const category = separator === -1 ? "_default" : input.fullname.slice(0, separator);
|
|
5928
|
+
const name = separator === -1 ? input.fullname : input.fullname.slice(separator + 1);
|
|
5929
|
+
return {
|
|
5930
|
+
...input,
|
|
5931
|
+
name: input.name ?? name,
|
|
5932
|
+
category: input.category ?? category,
|
|
5933
|
+
hiddenTags: input.hiddenTags ?? [],
|
|
5934
|
+
children: input.children ?? 0,
|
|
5935
|
+
comments: input.comments ?? 0,
|
|
5936
|
+
size: input.size ?? 0,
|
|
5937
|
+
rating: input.rating ?? 0,
|
|
5938
|
+
ratingVotes: input.ratingVotes ?? 0,
|
|
5939
|
+
revisions: input.revisions ?? 0
|
|
5940
|
+
};
|
|
5941
|
+
}
|
|
5942
|
+
// packages/parser/src/parser/rules/block/module/listpages/selectors.ts
|
|
5943
|
+
function matchesListPagesSelectors(page, query, currentPage) {
|
|
5944
|
+
return matchesCategory(page.category, query.category, currentPage.category) && matchesTags(page, query.tags, currentPage);
|
|
5945
|
+
}
|
|
5946
|
+
function matchesCategory(category, selector, currentCategory) {
|
|
5947
|
+
if (!selector)
|
|
5948
|
+
return category === currentCategory;
|
|
5949
|
+
if (selector.exclude.includes(category))
|
|
5950
|
+
return false;
|
|
5951
|
+
const hasPositiveSelector = selector.all || selector.current || selector.include.length > 0;
|
|
5952
|
+
return !hasPositiveSelector || selector.all || selector.current && category === currentCategory || selector.include.includes(category);
|
|
5953
|
+
}
|
|
5954
|
+
function matchesTags(page, selector, currentPage) {
|
|
5955
|
+
if (!selector)
|
|
5956
|
+
return true;
|
|
5957
|
+
const allTags = new Set([...page.tags, ...page.hiddenTags]);
|
|
5958
|
+
if (selector.all.some((tag) => !allTags.has(tag)))
|
|
5959
|
+
return false;
|
|
5960
|
+
if (selector.any.length > 0 && !selector.any.some((tag) => allTags.has(tag)))
|
|
5961
|
+
return false;
|
|
5962
|
+
if (selector.none.some((tag) => allTags.has(tag)))
|
|
5963
|
+
return false;
|
|
5964
|
+
if (selector.special === "none")
|
|
5965
|
+
return allTags.size === 0;
|
|
5966
|
+
const currentTags = new Set(currentPage.tags.filter((tag) => !tag.startsWith("_")));
|
|
5967
|
+
if (selector.special === "same-visible") {
|
|
5968
|
+
return page.tags.some((tag) => currentTags.has(tag));
|
|
5969
|
+
}
|
|
5970
|
+
if (selector.special === "same-all") {
|
|
5971
|
+
return setsEqual(new Set(page.tags), currentTags);
|
|
5972
|
+
}
|
|
5973
|
+
return true;
|
|
5974
|
+
}
|
|
5975
|
+
function setsEqual(left, right) {
|
|
5976
|
+
return left.size === right.size && [...left].every((value) => right.has(value));
|
|
5977
|
+
}
|
|
5915
5978
|
// packages/parser/src/parser/rules/block/module/listpages/url-resolution/fields.ts
|
|
5916
5979
|
var URL_RESOLVABLE_FIELDS = [
|
|
5917
5980
|
{ attr: "offset", queryKey: "offset", type: "number" },
|
|
@@ -6341,13 +6404,20 @@ var BASE_PLACEHOLDER_OPEN = "";
|
|
|
6341
6404
|
var BASE_PLACEHOLDER_CLOSE = "";
|
|
6342
6405
|
var RAW_BLOCK_OPEN_PATTERN = /\[\[\s*(code|html)\b[^\]]*\]\]/iy;
|
|
6343
6406
|
function makeUniqueSentinels(source) {
|
|
6344
|
-
let
|
|
6345
|
-
let
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6407
|
+
let openRun = 0;
|
|
6408
|
+
let closeRun = 0;
|
|
6409
|
+
let longestOpenRun = 0;
|
|
6410
|
+
let longestCloseRun = 0;
|
|
6411
|
+
for (const char of source) {
|
|
6412
|
+
openRun = char === BASE_PLACEHOLDER_OPEN ? openRun + 1 : 0;
|
|
6413
|
+
closeRun = char === BASE_PLACEHOLDER_CLOSE ? closeRun + 1 : 0;
|
|
6414
|
+
longestOpenRun = Math.max(longestOpenRun, openRun);
|
|
6415
|
+
longestCloseRun = Math.max(longestCloseRun, closeRun);
|
|
6349
6416
|
}
|
|
6350
|
-
return {
|
|
6417
|
+
return {
|
|
6418
|
+
open: BASE_PLACEHOLDER_OPEN.repeat(longestOpenRun + 1),
|
|
6419
|
+
close: BASE_PLACEHOLDER_CLOSE.repeat(longestCloseRun + 1)
|
|
6420
|
+
};
|
|
6351
6421
|
}
|
|
6352
6422
|
function maskRawRegions(source, sentinels) {
|
|
6353
6423
|
const placeholders = [];
|
|
@@ -6805,16 +6875,31 @@ function expandIterativeWithTrace(source, fetcher, maxIterations) {
|
|
|
6805
6875
|
reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
|
|
6806
6876
|
};
|
|
6807
6877
|
}
|
|
6808
|
-
async function
|
|
6878
|
+
async function expandIterativeAsyncWithTrace(source, fetcher, maxIterations) {
|
|
6809
6879
|
let current2 = source;
|
|
6810
6880
|
const replacementCache = new Map;
|
|
6881
|
+
const dependencies = [];
|
|
6882
|
+
const iterations = [];
|
|
6811
6883
|
for (let i = 0;i < maxIterations; i++) {
|
|
6812
|
-
const expanded = await
|
|
6813
|
-
if (expanded === null
|
|
6884
|
+
const expanded = await expandOneIterationAsyncWithTrace(current2, fetcher, replacementCache, i);
|
|
6885
|
+
if (expanded === null)
|
|
6814
6886
|
break;
|
|
6815
|
-
|
|
6887
|
+
dependencies.push(...expanded.dependencies);
|
|
6888
|
+
iterations.push({
|
|
6889
|
+
iteration: i,
|
|
6890
|
+
directives: expanded.references,
|
|
6891
|
+
changed: expanded.source !== current2
|
|
6892
|
+
});
|
|
6893
|
+
if (expanded.source === current2)
|
|
6894
|
+
break;
|
|
6895
|
+
current2 = expanded.source;
|
|
6816
6896
|
}
|
|
6817
|
-
return
|
|
6897
|
+
return {
|
|
6898
|
+
source: current2,
|
|
6899
|
+
dependencies,
|
|
6900
|
+
iterations,
|
|
6901
|
+
reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
|
|
6902
|
+
};
|
|
6818
6903
|
}
|
|
6819
6904
|
function expandOneIteration(source, fetcher, replacementCache) {
|
|
6820
6905
|
if (!MAYBE_INCLUDE_PATTERN.test(source))
|
|
@@ -6852,12 +6937,13 @@ function expandOneIterationWithTrace(source, fetcher, replacementCache, iteratio
|
|
|
6852
6937
|
dependencies
|
|
6853
6938
|
};
|
|
6854
6939
|
}
|
|
6855
|
-
async function
|
|
6940
|
+
async function expandOneIterationAsyncWithTrace(source, fetcher, replacementCache, iteration) {
|
|
6856
6941
|
if (!MAYBE_INCLUDE_PATTERN.test(source))
|
|
6857
6942
|
return null;
|
|
6858
6943
|
const directives = scanIncludeDirectives(source);
|
|
6859
6944
|
if (directives.length === 0)
|
|
6860
6945
|
return null;
|
|
6946
|
+
const references = directives.map(createIncludeReference);
|
|
6861
6947
|
const replacements = await Promise.all(directives.map(({ inner }) => replaceCachedAsync(inner, fetcher, replacementCache)));
|
|
6862
6948
|
const parts = [];
|
|
6863
6949
|
let lastPos = 0;
|
|
@@ -6867,7 +6953,11 @@ async function expandOneIterationAsync(source, fetcher, replacementCache) {
|
|
|
6867
6953
|
lastPos = end;
|
|
6868
6954
|
}
|
|
6869
6955
|
parts.push(source.slice(lastPos));
|
|
6870
|
-
return
|
|
6956
|
+
return {
|
|
6957
|
+
source: parts.join(""),
|
|
6958
|
+
references,
|
|
6959
|
+
dependencies: references.map((reference) => ({ ...reference, iteration }))
|
|
6960
|
+
};
|
|
6871
6961
|
}
|
|
6872
6962
|
function replaceCached(inner, fetcher, cache) {
|
|
6873
6963
|
const cached = cache.get(inner);
|
|
@@ -6909,12 +6999,20 @@ function resolveIncludesWithTrace(source, fetcher, options) {
|
|
|
6909
6999
|
return expandIterativeWithTrace(source, cachedFetcher, maxIterations);
|
|
6910
7000
|
}
|
|
6911
7001
|
async function resolveIncludesAsync(source, fetcher, options) {
|
|
7002
|
+
return (await resolveIncludesAsyncWithTrace(source, fetcher, options)).source;
|
|
7003
|
+
}
|
|
7004
|
+
async function resolveIncludesAsyncWithTrace(source, fetcher, options) {
|
|
6912
7005
|
if (options?.settings && !options.settings.enablePageSyntax) {
|
|
6913
|
-
return
|
|
7006
|
+
return {
|
|
7007
|
+
source,
|
|
7008
|
+
dependencies: [],
|
|
7009
|
+
iterations: [],
|
|
7010
|
+
reachedMaxIterations: false
|
|
7011
|
+
};
|
|
6914
7012
|
}
|
|
6915
7013
|
const maxIterations = options?.maxIterations ?? 10;
|
|
6916
7014
|
const cachedFetcher = createCachedAsyncIncludeFetcher(fetcher, normalizePageKey);
|
|
6917
|
-
return
|
|
7015
|
+
return expandIterativeAsyncWithTrace(source, cachedFetcher, maxIterations);
|
|
6918
7016
|
}
|
|
6919
7017
|
function normalizePageKey(location) {
|
|
6920
7018
|
const site = location.site ?? "";
|
|
@@ -6928,7 +7026,7 @@ function isListUsersModule2(module2) {
|
|
|
6928
7026
|
function resolveListUsers(_module, data, compiledTemplate, parse) {
|
|
6929
7027
|
const ctx = { user: data.user };
|
|
6930
7028
|
const substituted = compiledTemplate(ctx);
|
|
6931
|
-
const itemAst = parse(substituted);
|
|
7029
|
+
const itemAst = getModuleParseAst(parse(substituted));
|
|
6932
7030
|
return itemAst.elements;
|
|
6933
7031
|
}
|
|
6934
7032
|
// packages/parser/src/parser/rules/block/module/resolution/data-maps.ts
|
|
@@ -7081,6 +7179,117 @@ function countDynamicModules(elements) {
|
|
|
7081
7179
|
return counts;
|
|
7082
7180
|
}
|
|
7083
7181
|
|
|
7182
|
+
// packages/parser/src/parser/rules/block/module/resolution/styles.ts
|
|
7183
|
+
var import_ast2 = require("@wdprlib/ast");
|
|
7184
|
+
function collectStyles(elements, ignoredAnchors = new WeakSet) {
|
|
7185
|
+
const styles = [];
|
|
7186
|
+
const anchoredStyles = [];
|
|
7187
|
+
const anchors = [];
|
|
7188
|
+
const usedSlots = collectExistingStyleSlots(elements);
|
|
7189
|
+
const ctx = { nextSlotId: 0, usedSlots };
|
|
7190
|
+
const filtered = collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx);
|
|
7191
|
+
return { elements: filtered, styles, anchoredStyles, anchors };
|
|
7192
|
+
}
|
|
7193
|
+
function mergeCollectedStyles(existing, collected, resolvedSlots = new Map, anchoredStyles = []) {
|
|
7194
|
+
const unanchoredPrevious = [...existing ?? []];
|
|
7195
|
+
for (const style of anchoredStyles)
|
|
7196
|
+
removeFirst(unanchoredPrevious, style);
|
|
7197
|
+
for (const style of collected) {
|
|
7198
|
+
if (isStyleSlotMarker(style))
|
|
7199
|
+
removeFirst(unanchoredPrevious, style);
|
|
7200
|
+
}
|
|
7201
|
+
const merged = unanchoredPrevious.filter((style) => !isStyleSlotMarker(style));
|
|
7202
|
+
for (const style of collected) {
|
|
7203
|
+
if (isStyleSlotMarker(style))
|
|
7204
|
+
appendStyleSlot(merged, style, resolvedSlots);
|
|
7205
|
+
else
|
|
7206
|
+
merged.push(style);
|
|
7207
|
+
}
|
|
7208
|
+
return merged;
|
|
7209
|
+
}
|
|
7210
|
+
function isStyleSlotMarker(style) {
|
|
7211
|
+
return style.startsWith(import_ast2.STYLE_SLOT_PREFIX);
|
|
7212
|
+
}
|
|
7213
|
+
function createStyleSlotMarker(slotId) {
|
|
7214
|
+
return `${import_ast2.STYLE_SLOT_PREFIX}${slotId}`;
|
|
7215
|
+
}
|
|
7216
|
+
function getStyleSlotId(data) {
|
|
7217
|
+
const slotId = data._styleSlot;
|
|
7218
|
+
return Number.isSafeInteger(slotId) && slotId >= 0 ? slotId : undefined;
|
|
7219
|
+
}
|
|
7220
|
+
function removeFirst(values, value) {
|
|
7221
|
+
const index = values.indexOf(value);
|
|
7222
|
+
if (index >= 0)
|
|
7223
|
+
values.splice(index, 1);
|
|
7224
|
+
}
|
|
7225
|
+
function appendStyleSlot(target, marker, resolvedSlots) {
|
|
7226
|
+
const slotId = Number(marker.slice(import_ast2.STYLE_SLOT_PREFIX.length));
|
|
7227
|
+
const replacement = resolvedSlots.get(slotId);
|
|
7228
|
+
if (replacement)
|
|
7229
|
+
target.push(...replacement);
|
|
7230
|
+
else
|
|
7231
|
+
target.push(marker);
|
|
7232
|
+
}
|
|
7233
|
+
function collectExistingStyleSlots(elements) {
|
|
7234
|
+
const slots = new Set;
|
|
7235
|
+
walkElements(elements, (element) => {
|
|
7236
|
+
if (element.element !== "if-tags")
|
|
7237
|
+
return;
|
|
7238
|
+
const slotId = getStyleSlotId(element.data);
|
|
7239
|
+
if (slotId !== undefined)
|
|
7240
|
+
slots.add(slotId);
|
|
7241
|
+
});
|
|
7242
|
+
return slots;
|
|
7243
|
+
}
|
|
7244
|
+
function allocateStyleSlot(ctx) {
|
|
7245
|
+
while (ctx.usedSlots.has(ctx.nextSlotId))
|
|
7246
|
+
ctx.nextSlotId++;
|
|
7247
|
+
const slotId = ctx.nextSlotId++;
|
|
7248
|
+
ctx.usedSlots.add(slotId);
|
|
7249
|
+
return slotId;
|
|
7250
|
+
}
|
|
7251
|
+
function collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx) {
|
|
7252
|
+
const result = [];
|
|
7253
|
+
for (const element of elements) {
|
|
7254
|
+
if (element.element === "style") {
|
|
7255
|
+
const css = element.data;
|
|
7256
|
+
if (css.startsWith(import_ast2.STYLE_SLOT_PREFIX)) {
|
|
7257
|
+
styles.push(css);
|
|
7258
|
+
continue;
|
|
7259
|
+
}
|
|
7260
|
+
if (css.startsWith(import_ast2.STYLE_ANCHOR_PREFIX)) {
|
|
7261
|
+
anchors.push(element);
|
|
7262
|
+
if (ignoredAnchors.has(element)) {
|
|
7263
|
+
result.push(element);
|
|
7264
|
+
continue;
|
|
7265
|
+
}
|
|
7266
|
+
const anchoredCss = css.slice(import_ast2.STYLE_ANCHOR_PREFIX.length);
|
|
7267
|
+
styles.push(anchoredCss);
|
|
7268
|
+
anchoredStyles.push(anchoredCss);
|
|
7269
|
+
result.push(element);
|
|
7270
|
+
continue;
|
|
7271
|
+
}
|
|
7272
|
+
styles.push(css);
|
|
7273
|
+
const anchor = { element: "style", data: `${import_ast2.STYLE_ANCHOR_PREFIX}${css}` };
|
|
7274
|
+
anchors.push(anchor);
|
|
7275
|
+
result.push(anchor);
|
|
7276
|
+
continue;
|
|
7277
|
+
}
|
|
7278
|
+
if (element.element === "if-tags") {
|
|
7279
|
+
const slotId = getStyleSlotId(element.data) ?? allocateStyleSlot(ctx);
|
|
7280
|
+
styles.push(createStyleSlotMarker(slotId));
|
|
7281
|
+
const data = { ...element.data, _styleSlot: slotId };
|
|
7282
|
+
result.push({
|
|
7283
|
+
element: "if-tags",
|
|
7284
|
+
data
|
|
7285
|
+
});
|
|
7286
|
+
continue;
|
|
7287
|
+
}
|
|
7288
|
+
result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, anchoredStyles, anchors, ignoredAnchors, ctx)));
|
|
7289
|
+
}
|
|
7290
|
+
return result;
|
|
7291
|
+
}
|
|
7292
|
+
|
|
7084
7293
|
// packages/parser/src/parser/rules/block/module/resolution/walk-resolve.ts
|
|
7085
7294
|
function walkAndResolve(elements, ctx) {
|
|
7086
7295
|
const result = [];
|
|
@@ -7103,6 +7312,7 @@ function walkAndResolve(elements, ctx) {
|
|
|
7103
7312
|
if (isIfTagsElement(element)) {
|
|
7104
7313
|
const ifTagsData = element.data;
|
|
7105
7314
|
const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
|
|
7315
|
+
const styleSlotId = getStyleSlotId(ifTagsData);
|
|
7106
7316
|
if (resolveResult.evaluated) {
|
|
7107
7317
|
if (resolveResult.matched) {
|
|
7108
7318
|
const childResult = walkAndResolve(ifTagsData.elements, {
|
|
@@ -7111,11 +7321,23 @@ function walkAndResolve(elements, ctx) {
|
|
|
7111
7321
|
listUsersIdCounter: listUsersId,
|
|
7112
7322
|
tagCloudIdCounter: tagCloudId
|
|
7113
7323
|
});
|
|
7114
|
-
|
|
7324
|
+
if (styleSlotId === undefined) {
|
|
7325
|
+
result.push(...childResult.elements);
|
|
7326
|
+
} else {
|
|
7327
|
+
const collected = collectStyles(childResult.elements);
|
|
7328
|
+
ctx.resolvedStyleSlots.set(styleSlotId, collected.styles);
|
|
7329
|
+
for (const anchor of collected.anchors)
|
|
7330
|
+
ctx.routedStyleAnchors.add(anchor);
|
|
7331
|
+
result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) }, ...collected.elements);
|
|
7332
|
+
}
|
|
7115
7333
|
listPagesId = childResult.nextListPagesId;
|
|
7116
7334
|
listUsersId = childResult.nextListUsersId;
|
|
7117
7335
|
tagCloudId = childResult.nextTagCloudId;
|
|
7118
7336
|
} else {
|
|
7337
|
+
if (styleSlotId !== undefined) {
|
|
7338
|
+
ctx.resolvedStyleSlots.set(styleSlotId, []);
|
|
7339
|
+
result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) });
|
|
7340
|
+
}
|
|
7119
7341
|
const counts = countDynamicModules(ifTagsData.elements);
|
|
7120
7342
|
listPagesId += counts.listPagesId;
|
|
7121
7343
|
listUsersId += counts.listUsersId;
|
|
@@ -7170,143 +7392,463 @@ function walkAndResolve(elements, ctx) {
|
|
|
7170
7392
|
};
|
|
7171
7393
|
}
|
|
7172
7394
|
|
|
7173
|
-
// packages/parser/src/parser/rules/block/module/resolution/
|
|
7174
|
-
var
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
function collectStylesFromElements(elements, styles, ctx) {
|
|
7182
|
-
const result = [];
|
|
7183
|
-
for (const element of elements) {
|
|
7184
|
-
if (element.element === "style") {
|
|
7185
|
-
styles.push(element.data);
|
|
7186
|
-
continue;
|
|
7187
|
-
}
|
|
7188
|
-
if (element.element === "if-tags") {
|
|
7189
|
-
const slotId = ctx.nextSlotId++;
|
|
7190
|
-
styles.push(`${import_ast2.STYLE_SLOT_PREFIX}${slotId}`);
|
|
7191
|
-
const data = { ...element.data, _styleSlot: slotId };
|
|
7192
|
-
result.push({
|
|
7193
|
-
element: "if-tags",
|
|
7194
|
-
data
|
|
7195
|
-
});
|
|
7196
|
-
continue;
|
|
7197
|
-
}
|
|
7198
|
-
result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx)));
|
|
7395
|
+
// packages/parser/src/parser/rules/block/module/resolution/document.ts
|
|
7396
|
+
var import_ast3 = require("@wdprlib/ast");
|
|
7397
|
+
|
|
7398
|
+
// packages/parser/src/parser/toc.ts
|
|
7399
|
+
class TocIndexer {
|
|
7400
|
+
index = 0;
|
|
7401
|
+
next() {
|
|
7402
|
+
return this.index++;
|
|
7199
7403
|
}
|
|
7200
|
-
return result;
|
|
7201
7404
|
}
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
const resolvedElements = walkAndResolve(ast.elements, {
|
|
7212
|
-
listPages: listPagesCtx,
|
|
7213
|
-
listUsers: listUsersCtx,
|
|
7214
|
-
tagCloud: tagCloudCtx,
|
|
7215
|
-
fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
|
|
7216
|
-
fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
|
|
7217
|
-
fetchTagCloudProvided: dataProvider.fetchTagCloud !== undefined,
|
|
7218
|
-
pageTags,
|
|
7219
|
-
listPagesIdCounter: 0,
|
|
7220
|
-
listUsersIdCounter: 0,
|
|
7221
|
-
tagCloudIdCounter: 0
|
|
7222
|
-
});
|
|
7223
|
-
const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
|
|
7224
|
-
const result = {
|
|
7225
|
-
...ast,
|
|
7226
|
-
elements: finalElements
|
|
7405
|
+
function buildTocList(indexer, items) {
|
|
7406
|
+
const listItems = items.map((item) => buildTocListItem(indexer, item));
|
|
7407
|
+
return {
|
|
7408
|
+
element: "list",
|
|
7409
|
+
data: {
|
|
7410
|
+
type: "bullet",
|
|
7411
|
+
attributes: {},
|
|
7412
|
+
items: listItems
|
|
7413
|
+
}
|
|
7227
7414
|
};
|
|
7228
|
-
if (styles.length > 0) {
|
|
7229
|
-
result.styles = styles;
|
|
7230
|
-
}
|
|
7231
|
-
return result;
|
|
7232
7415
|
}
|
|
7233
|
-
function
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7416
|
+
function buildTocListItem(indexer, item) {
|
|
7417
|
+
if (item.kind === "list") {
|
|
7418
|
+
return {
|
|
7419
|
+
"item-type": "sub-list",
|
|
7420
|
+
element: "list",
|
|
7421
|
+
data: {
|
|
7422
|
+
type: "bullet",
|
|
7423
|
+
attributes: {},
|
|
7424
|
+
items: item.children.map((child) => buildTocListItem(indexer, child))
|
|
7425
|
+
}
|
|
7426
|
+
};
|
|
7237
7427
|
}
|
|
7238
|
-
|
|
7428
|
+
const anchor = `#toc${indexer.next()}`;
|
|
7429
|
+
const linkElement = {
|
|
7430
|
+
element: "link",
|
|
7431
|
+
data: {
|
|
7432
|
+
type: "table-of-contents",
|
|
7433
|
+
link: anchor,
|
|
7434
|
+
extra: null,
|
|
7435
|
+
label: { text: item.value },
|
|
7436
|
+
target: null
|
|
7437
|
+
}
|
|
7438
|
+
};
|
|
7439
|
+
return {
|
|
7440
|
+
"item-type": "elements",
|
|
7441
|
+
attributes: {},
|
|
7442
|
+
elements: [linkElement]
|
|
7443
|
+
};
|
|
7239
7444
|
}
|
|
7240
|
-
function
|
|
7241
|
-
if (
|
|
7242
|
-
return
|
|
7243
|
-
}
|
|
7244
|
-
if (!dataProvider.fetchInclude) {
|
|
7245
|
-
return null;
|
|
7445
|
+
function buildTableOfContents(entries) {
|
|
7446
|
+
if (entries.length === 0) {
|
|
7447
|
+
return [];
|
|
7246
7448
|
}
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7449
|
+
const depthItems = entries.map((entry) => ({
|
|
7450
|
+
depth: entry.level - 1,
|
|
7451
|
+
ltype: null,
|
|
7452
|
+
value: entry.text
|
|
7453
|
+
}));
|
|
7454
|
+
const trees = processDepths(null, depthItems);
|
|
7455
|
+
const indexer = new TocIndexer;
|
|
7456
|
+
return trees.map((tree) => buildTocList(indexer, tree.list));
|
|
7250
7457
|
}
|
|
7251
7458
|
|
|
7252
|
-
// packages/parser/src/parser/rules/block/module/
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
}
|
|
7288
|
-
} else {
|
|
7289
|
-
attrs[name] = "true";
|
|
7459
|
+
// packages/parser/src/parser/rules/block/module/resolution/document.ts
|
|
7460
|
+
class ModuleDocumentRegistry {
|
|
7461
|
+
footnotesByElement = new WeakMap;
|
|
7462
|
+
diagnostics = [];
|
|
7463
|
+
register(result, options = {}) {
|
|
7464
|
+
const parseResult = isParseResult(result) ? result : null;
|
|
7465
|
+
const ast = parseResult ? parseResult.ast : result;
|
|
7466
|
+
const elements = options.stripLegacyImplicitFootnoteBlock ? stripTrailingDefaultFootnoteBlock(ast.elements) : ast.elements;
|
|
7467
|
+
const registeredAst = elements === ast.elements ? ast : { ...ast, elements };
|
|
7468
|
+
if (parseResult) {
|
|
7469
|
+
this.diagnostics.push(...parseResult.diagnostics);
|
|
7470
|
+
}
|
|
7471
|
+
this.registerFootnotes(registeredAst);
|
|
7472
|
+
return registeredAst;
|
|
7473
|
+
}
|
|
7474
|
+
finalize(ast, elements, pageTags, ensureFootnoteBlock = true) {
|
|
7475
|
+
const normalizedElements = normalizeFootnoteBlocks(elements, ensureFootnoteBlock);
|
|
7476
|
+
const footnotes = [];
|
|
7477
|
+
const htmlBlocks = [];
|
|
7478
|
+
const codeBlocks = [];
|
|
7479
|
+
const tocEntries = [];
|
|
7480
|
+
const collectElement = (element) => {
|
|
7481
|
+
if (element.element === "footnote") {
|
|
7482
|
+
const content = this.footnotesByElement.get(element);
|
|
7483
|
+
if (content)
|
|
7484
|
+
footnotes.push(content);
|
|
7485
|
+
} else if (element.element === "html") {
|
|
7486
|
+
htmlBlocks.push(element.data.contents);
|
|
7487
|
+
} else if (element.element === "code") {
|
|
7488
|
+
codeBlocks.push(element.data);
|
|
7489
|
+
} else if (isTocHeading(element)) {
|
|
7490
|
+
tocEntries.push({
|
|
7491
|
+
level: element.data.type.header.level,
|
|
7492
|
+
text: extractHeadingText(element.data.elements)
|
|
7493
|
+
});
|
|
7290
7494
|
}
|
|
7291
|
-
}
|
|
7292
|
-
|
|
7293
|
-
|
|
7495
|
+
};
|
|
7496
|
+
walkRenderOrder(normalizedElements, pageTags, collectElement);
|
|
7497
|
+
const result = { ...ast, elements: normalizedElements };
|
|
7498
|
+
setOptionalArray(result, "footnotes", footnotes);
|
|
7499
|
+
setOptionalArray(result, "html-blocks", htmlBlocks);
|
|
7500
|
+
setOptionalArray(result, "code-blocks", codeBlocks);
|
|
7501
|
+
setOptionalArray(result, "table-of-contents", buildTableOfContents(tocEntries));
|
|
7502
|
+
return result;
|
|
7503
|
+
}
|
|
7504
|
+
registerFootnotes(ast) {
|
|
7505
|
+
const footnoteElements = [];
|
|
7506
|
+
walkSyntaxOrder(ast.elements, (element) => {
|
|
7507
|
+
if (element.element === "footnote")
|
|
7508
|
+
footnoteElements.push(element);
|
|
7509
|
+
});
|
|
7510
|
+
for (let i = 0;i < footnoteElements.length; i++) {
|
|
7511
|
+
const content = ast.footnotes?.[i];
|
|
7512
|
+
if (content)
|
|
7513
|
+
this.footnotesByElement.set(footnoteElements[i], content);
|
|
7294
7514
|
}
|
|
7295
7515
|
}
|
|
7296
|
-
return { attrs, consumed };
|
|
7297
7516
|
}
|
|
7298
|
-
function
|
|
7299
|
-
return
|
|
7517
|
+
function isParseResult(result) {
|
|
7518
|
+
return "ast" in result && "diagnostics" in result;
|
|
7300
7519
|
}
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7520
|
+
function setOptionalArray(tree, key, value) {
|
|
7521
|
+
if (value.length > 0) {
|
|
7522
|
+
tree[key] = value;
|
|
7523
|
+
} else {
|
|
7524
|
+
delete tree[key];
|
|
7306
7525
|
}
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7526
|
+
}
|
|
7527
|
+
function stripTrailingDefaultFootnoteBlock(elements) {
|
|
7528
|
+
const last = elements.at(-1);
|
|
7529
|
+
if (last?.element !== "footnote-block" || last.data.title !== null || last.data.hide === true) {
|
|
7530
|
+
return elements;
|
|
7531
|
+
}
|
|
7532
|
+
return elements.slice(0, -1);
|
|
7533
|
+
}
|
|
7534
|
+
function normalizeFootnoteBlocks(elements, ensureFootnoteBlock) {
|
|
7535
|
+
const state = { found: false };
|
|
7536
|
+
const normalized = mapSyntaxElements(elements, (element) => {
|
|
7537
|
+
if (element.element !== "footnote-block")
|
|
7538
|
+
return element;
|
|
7539
|
+
if (state.found)
|
|
7540
|
+
return null;
|
|
7541
|
+
state.found = true;
|
|
7542
|
+
return element;
|
|
7543
|
+
});
|
|
7544
|
+
if (!state.found && ensureFootnoteBlock) {
|
|
7545
|
+
normalized.push({
|
|
7546
|
+
element: "footnote-block",
|
|
7547
|
+
data: { title: null, hide: false }
|
|
7548
|
+
});
|
|
7549
|
+
}
|
|
7550
|
+
return normalized;
|
|
7551
|
+
}
|
|
7552
|
+
function containsSyntaxFootnoteBlock(elements) {
|
|
7553
|
+
let found = false;
|
|
7554
|
+
walkSyntaxOrder(elements, (element) => {
|
|
7555
|
+
if (element.element === "footnote-block")
|
|
7556
|
+
found = true;
|
|
7557
|
+
});
|
|
7558
|
+
return found;
|
|
7559
|
+
}
|
|
7560
|
+
function mapSyntaxElements(elements, transform) {
|
|
7561
|
+
const result = [];
|
|
7562
|
+
for (const original of elements) {
|
|
7563
|
+
const element = transform(original);
|
|
7564
|
+
if (!element)
|
|
7565
|
+
continue;
|
|
7566
|
+
result.push(mapSyntaxChildren(element, (children) => mapSyntaxElements(children, transform)));
|
|
7567
|
+
}
|
|
7568
|
+
return result;
|
|
7569
|
+
}
|
|
7570
|
+
function mapSyntaxChildren(element, transform) {
|
|
7571
|
+
if (element.element === "if") {
|
|
7572
|
+
return {
|
|
7573
|
+
...element,
|
|
7574
|
+
data: {
|
|
7575
|
+
...element.data,
|
|
7576
|
+
then: transform(element.data.then),
|
|
7577
|
+
else: transform(element.data.else)
|
|
7578
|
+
}
|
|
7579
|
+
};
|
|
7580
|
+
}
|
|
7581
|
+
if (element.element === "ifexpr") {
|
|
7582
|
+
return {
|
|
7583
|
+
...element,
|
|
7584
|
+
data: {
|
|
7585
|
+
...element.data,
|
|
7586
|
+
then: transform(element.data.then),
|
|
7587
|
+
else: transform(element.data.else)
|
|
7588
|
+
}
|
|
7589
|
+
};
|
|
7590
|
+
}
|
|
7591
|
+
if (element.element === "bibliography-block") {
|
|
7592
|
+
return {
|
|
7593
|
+
...element,
|
|
7594
|
+
data: {
|
|
7595
|
+
...element.data,
|
|
7596
|
+
entries: element.data.entries.map((entry) => ({
|
|
7597
|
+
...entry,
|
|
7598
|
+
key: transform(entry.key),
|
|
7599
|
+
value: transform(entry.value)
|
|
7600
|
+
}))
|
|
7601
|
+
}
|
|
7602
|
+
};
|
|
7603
|
+
}
|
|
7604
|
+
if (element.element === "list") {
|
|
7605
|
+
return {
|
|
7606
|
+
...element,
|
|
7607
|
+
data: {
|
|
7608
|
+
...element.data,
|
|
7609
|
+
items: element.data.items.map((item) => item["item-type"] === "elements" ? { ...item, elements: transform(item.elements) } : mapSubList(item, transform))
|
|
7610
|
+
}
|
|
7611
|
+
};
|
|
7612
|
+
}
|
|
7613
|
+
if (element.element === "table") {
|
|
7614
|
+
return {
|
|
7615
|
+
...element,
|
|
7616
|
+
data: {
|
|
7617
|
+
...element.data,
|
|
7618
|
+
rows: element.data.rows.map((row) => ({
|
|
7619
|
+
...row,
|
|
7620
|
+
cells: row.cells.map((cell) => ({ ...cell, elements: transform(cell.elements) }))
|
|
7621
|
+
}))
|
|
7622
|
+
}
|
|
7623
|
+
};
|
|
7624
|
+
}
|
|
7625
|
+
if (element.element === "definition-list") {
|
|
7626
|
+
return {
|
|
7627
|
+
...element,
|
|
7628
|
+
data: element.data.map((entry) => ({
|
|
7629
|
+
...entry,
|
|
7630
|
+
key: transform(entry.key),
|
|
7631
|
+
value: transform(entry.value)
|
|
7632
|
+
}))
|
|
7633
|
+
};
|
|
7634
|
+
}
|
|
7635
|
+
if (element.element === "tab-view") {
|
|
7636
|
+
return {
|
|
7637
|
+
...element,
|
|
7638
|
+
data: element.data.map((tab) => ({ ...tab, elements: transform(tab.elements) }))
|
|
7639
|
+
};
|
|
7640
|
+
}
|
|
7641
|
+
const children = getGenericElementChildren(element);
|
|
7642
|
+
return children === null ? element : withGenericElementChildren(element, transform(children));
|
|
7643
|
+
}
|
|
7644
|
+
function mapSubList(item, transform) {
|
|
7645
|
+
const transformed = transform([listElement(item.data)])[0];
|
|
7646
|
+
return transformed?.element === "list" ? { ...item, data: transformed.data } : item;
|
|
7647
|
+
}
|
|
7648
|
+
function walkSyntaxOrder(elements, callback) {
|
|
7649
|
+
for (const element of elements) {
|
|
7650
|
+
callback(element);
|
|
7651
|
+
walkAllSyntaxChildren(element, (children) => walkSyntaxOrder(children, callback));
|
|
7652
|
+
}
|
|
7653
|
+
}
|
|
7654
|
+
function walkRenderOrder(elements, pageTags, callback) {
|
|
7655
|
+
for (const element of elements) {
|
|
7656
|
+
callback(element);
|
|
7657
|
+
if (element.element === "if") {
|
|
7658
|
+
walkRenderOrder(import_ast3.isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
|
|
7659
|
+
continue;
|
|
7660
|
+
}
|
|
7661
|
+
if (element.element === "ifexpr") {
|
|
7662
|
+
const evaluated = import_ast3.evaluateExpression(element.data.expression);
|
|
7663
|
+
if (evaluated.success) {
|
|
7664
|
+
walkRenderOrder(evaluated.value !== 0 ? element.data.then : element.data.else, pageTags, callback);
|
|
7665
|
+
}
|
|
7666
|
+
continue;
|
|
7667
|
+
}
|
|
7668
|
+
if (element.element === "if-tags") {
|
|
7669
|
+
const resolved = resolveIfTags(element.data, pageTags);
|
|
7670
|
+
if (!resolved.evaluated || resolved.matched) {
|
|
7671
|
+
walkRenderOrder(element.data.elements, pageTags, callback);
|
|
7672
|
+
}
|
|
7673
|
+
continue;
|
|
7674
|
+
}
|
|
7675
|
+
if (element.element === "bibliography-block") {
|
|
7676
|
+
if (!element.data.hide) {
|
|
7677
|
+
for (const entry of element.data.entries) {
|
|
7678
|
+
walkRenderOrder(entry.value, pageTags, callback);
|
|
7679
|
+
}
|
|
7680
|
+
}
|
|
7681
|
+
continue;
|
|
7682
|
+
}
|
|
7683
|
+
walkBasicChildren(element, (children) => walkRenderOrder(children, pageTags, callback));
|
|
7684
|
+
}
|
|
7685
|
+
}
|
|
7686
|
+
function walkAllSyntaxChildren(element, callback) {
|
|
7687
|
+
if (element.element === "if" || element.element === "ifexpr") {
|
|
7688
|
+
callback(element.data.then);
|
|
7689
|
+
callback(element.data.else);
|
|
7690
|
+
return;
|
|
7691
|
+
}
|
|
7692
|
+
if (element.element === "bibliography-block") {
|
|
7693
|
+
for (const entry of element.data.entries) {
|
|
7694
|
+
callback(entry.key);
|
|
7695
|
+
callback(entry.value);
|
|
7696
|
+
}
|
|
7697
|
+
return;
|
|
7698
|
+
}
|
|
7699
|
+
walkBasicChildren(element, callback);
|
|
7700
|
+
}
|
|
7701
|
+
function walkBasicChildren(element, callback) {
|
|
7702
|
+
if (element.element === "list") {
|
|
7703
|
+
for (const item of element.data.items) {
|
|
7704
|
+
callback(item["item-type"] === "elements" ? item.elements : [listElement(item.data)]);
|
|
7705
|
+
}
|
|
7706
|
+
return;
|
|
7707
|
+
}
|
|
7708
|
+
if (element.element === "table") {
|
|
7709
|
+
for (const row of element.data.rows) {
|
|
7710
|
+
for (const cell of row.cells)
|
|
7711
|
+
callback(cell.elements);
|
|
7712
|
+
}
|
|
7713
|
+
return;
|
|
7714
|
+
}
|
|
7715
|
+
if (element.element === "definition-list") {
|
|
7716
|
+
for (const entry of element.data) {
|
|
7717
|
+
callback(entry.key);
|
|
7718
|
+
callback(entry.value);
|
|
7719
|
+
}
|
|
7720
|
+
return;
|
|
7721
|
+
}
|
|
7722
|
+
if (element.element === "tab-view") {
|
|
7723
|
+
for (const tab of element.data)
|
|
7724
|
+
callback(tab.elements);
|
|
7725
|
+
return;
|
|
7726
|
+
}
|
|
7727
|
+
const children = getGenericElementChildren(element);
|
|
7728
|
+
if (children !== null)
|
|
7729
|
+
callback(children);
|
|
7730
|
+
}
|
|
7731
|
+
function isTocHeading(element) {
|
|
7732
|
+
return element.element === "container" && typeof element.data.type === "object" && "header" in element.data.type && element.data.type.header["has-toc"];
|
|
7733
|
+
}
|
|
7734
|
+
|
|
7735
|
+
// packages/parser/src/parser/rules/block/module/resolve.ts
|
|
7736
|
+
var MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
|
|
7737
|
+
async function resolveModules(ast, dataProvider, options) {
|
|
7738
|
+
const registry = new ModuleDocumentRegistry;
|
|
7739
|
+
registry.register(ast);
|
|
7740
|
+
const parse = createModuleParseFunction(options, dataProvider, registry);
|
|
7741
|
+
const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
|
|
7742
|
+
const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
|
|
7743
|
+
const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
|
|
7744
|
+
const pageTags = dataProvider.getPageTags?.() ?? null;
|
|
7745
|
+
const resolvedStyleSlots = new Map;
|
|
7746
|
+
const routedStyleAnchors = new WeakSet;
|
|
7747
|
+
const resolvedElements = walkAndResolve(ast.elements, {
|
|
7748
|
+
listPages: listPagesCtx,
|
|
7749
|
+
listUsers: listUsersCtx,
|
|
7750
|
+
tagCloud: tagCloudCtx,
|
|
7751
|
+
fetchListPagesProvided: dataProvider.fetchListPages !== undefined,
|
|
7752
|
+
fetchListUsersProvided: dataProvider.fetchListUsers !== undefined,
|
|
7753
|
+
fetchTagCloudProvided: dataProvider.fetchTagCloud !== undefined,
|
|
7754
|
+
pageTags,
|
|
7755
|
+
listPagesIdCounter: 0,
|
|
7756
|
+
listUsersIdCounter: 0,
|
|
7757
|
+
tagCloudIdCounter: 0,
|
|
7758
|
+
resolvedStyleSlots,
|
|
7759
|
+
routedStyleAnchors
|
|
7760
|
+
});
|
|
7761
|
+
const {
|
|
7762
|
+
elements: finalElements,
|
|
7763
|
+
styles,
|
|
7764
|
+
anchoredStyles
|
|
7765
|
+
} = collectStyles(resolvedElements.elements, routedStyleAnchors);
|
|
7766
|
+
const result = {
|
|
7767
|
+
...ast,
|
|
7768
|
+
elements: finalElements
|
|
7769
|
+
};
|
|
7770
|
+
const mergedStyles = mergeCollectedStyles(ast.styles, styles, resolvedStyleSlots, anchoredStyles);
|
|
7771
|
+
if (mergedStyles.length > 0)
|
|
7772
|
+
result.styles = mergedStyles;
|
|
7773
|
+
options.onDiagnostics?.(registry.diagnostics);
|
|
7774
|
+
return registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements));
|
|
7775
|
+
}
|
|
7776
|
+
function createModuleParseFunction(options, dataProvider, registry) {
|
|
7777
|
+
const transform = createModuleSourceTransform(options, dataProvider);
|
|
7778
|
+
return (source) => registry.register(options.parse(transform ? transform(source) : source), {
|
|
7779
|
+
stripLegacyImplicitFootnoteBlock: true
|
|
7780
|
+
});
|
|
7781
|
+
}
|
|
7782
|
+
function createModuleSourceTransform(options, dataProvider) {
|
|
7783
|
+
if (options.transformModuleSource) {
|
|
7784
|
+
return options.transformModuleSource;
|
|
7785
|
+
}
|
|
7786
|
+
if (!dataProvider.fetchInclude) {
|
|
7787
|
+
return null;
|
|
7788
|
+
}
|
|
7789
|
+
return (source) => resolveIncludes(source, dataProvider.fetchInclude, {
|
|
7790
|
+
maxIterations: options.includeMaxIterations ?? MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS
|
|
7791
|
+
});
|
|
7792
|
+
}
|
|
7793
|
+
|
|
7794
|
+
// packages/parser/src/parser/rules/block/module/index.ts
|
|
7795
|
+
var import_ast4 = require("@wdprlib/ast");
|
|
7796
|
+
|
|
7797
|
+
// packages/parser/src/parser/rules/block/footnoteblock/attributes.ts
|
|
7798
|
+
function parseFootnoteBlockAttributes(ctx, startPos) {
|
|
7799
|
+
const attrs = {};
|
|
7800
|
+
let pos = startPos;
|
|
7801
|
+
let consumed = 0;
|
|
7802
|
+
while (pos < ctx.tokens.length) {
|
|
7803
|
+
const token5 = ctx.tokens[pos];
|
|
7804
|
+
if (!token5 || token5.type === "BLOCK_CLOSE" || token5.type === "NEWLINE" || token5.type === "EOF") {
|
|
7805
|
+
break;
|
|
7806
|
+
}
|
|
7807
|
+
if (token5.type === "WHITESPACE") {
|
|
7808
|
+
pos++;
|
|
7809
|
+
consumed++;
|
|
7810
|
+
continue;
|
|
7811
|
+
}
|
|
7812
|
+
if (token5.type === "TEXT" || token5.type === "IDENTIFIER") {
|
|
7813
|
+
const name = token5.value.toLowerCase();
|
|
7814
|
+
pos++;
|
|
7815
|
+
consumed++;
|
|
7816
|
+
const eqToken = ctx.tokens[pos];
|
|
7817
|
+
if (eqToken?.type === "EQUALS") {
|
|
7818
|
+
pos++;
|
|
7819
|
+
consumed++;
|
|
7820
|
+
const valueToken = ctx.tokens[pos];
|
|
7821
|
+
if (valueToken?.type === "QUOTED_STRING") {
|
|
7822
|
+
attrs[name] = stripQuotes2(valueToken.value);
|
|
7823
|
+
pos++;
|
|
7824
|
+
consumed++;
|
|
7825
|
+
} else if (valueToken?.type === "TEXT" || valueToken?.type === "IDENTIFIER") {
|
|
7826
|
+
attrs[name] = valueToken.value;
|
|
7827
|
+
pos++;
|
|
7828
|
+
consumed++;
|
|
7829
|
+
}
|
|
7830
|
+
} else {
|
|
7831
|
+
attrs[name] = "true";
|
|
7832
|
+
}
|
|
7833
|
+
} else {
|
|
7834
|
+
pos++;
|
|
7835
|
+
consumed++;
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
return { attrs, consumed };
|
|
7839
|
+
}
|
|
7840
|
+
function stripQuotes2(value) {
|
|
7841
|
+
return value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
|
|
7842
|
+
}
|
|
7843
|
+
|
|
7844
|
+
// packages/parser/src/parser/rules/block/footnoteblock/open.ts
|
|
7845
|
+
function parseFootnoteBlockOpen(ctx, startPos) {
|
|
7846
|
+
if (ctx.tokens[startPos]?.type !== "BLOCK_OPEN") {
|
|
7847
|
+
return null;
|
|
7848
|
+
}
|
|
7849
|
+
let pos = startPos + 1;
|
|
7850
|
+
let consumed = 1;
|
|
7851
|
+
while (ctx.tokens[pos]?.type === "WHITESPACE") {
|
|
7310
7852
|
pos++;
|
|
7311
7853
|
consumed++;
|
|
7312
7854
|
}
|
|
@@ -12369,7 +12911,8 @@ function createParseContext(tokens, options = {}) {
|
|
|
12369
12911
|
pos: 0,
|
|
12370
12912
|
version: options.version ?? "wikidot",
|
|
12371
12913
|
trackPositions: options.trackPositions ?? true,
|
|
12372
|
-
settings: options.settings ??
|
|
12914
|
+
settings: options.settings ?? import_ast5.DEFAULT_SETTINGS,
|
|
12915
|
+
appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
|
|
12373
12916
|
footnotes: [],
|
|
12374
12917
|
tocEntries: [],
|
|
12375
12918
|
codeBlocks: [],
|
|
@@ -12887,67 +13430,6 @@ function suppressAtLevel(elements) {
|
|
|
12887
13430
|
function suppressDivAdjacentParagraphs(elements) {
|
|
12888
13431
|
return suppressAtLevel(elements);
|
|
12889
13432
|
}
|
|
12890
|
-
// packages/parser/src/parser/toc.ts
|
|
12891
|
-
class TocIndexer {
|
|
12892
|
-
index = 0;
|
|
12893
|
-
next() {
|
|
12894
|
-
return this.index++;
|
|
12895
|
-
}
|
|
12896
|
-
}
|
|
12897
|
-
function buildTocList(indexer, items) {
|
|
12898
|
-
const listItems = items.map((item) => buildTocListItem(indexer, item));
|
|
12899
|
-
return {
|
|
12900
|
-
element: "list",
|
|
12901
|
-
data: {
|
|
12902
|
-
type: "bullet",
|
|
12903
|
-
attributes: {},
|
|
12904
|
-
items: listItems
|
|
12905
|
-
}
|
|
12906
|
-
};
|
|
12907
|
-
}
|
|
12908
|
-
function buildTocListItem(indexer, item) {
|
|
12909
|
-
if (item.kind === "list") {
|
|
12910
|
-
return {
|
|
12911
|
-
"item-type": "sub-list",
|
|
12912
|
-
element: "list",
|
|
12913
|
-
data: {
|
|
12914
|
-
type: "bullet",
|
|
12915
|
-
attributes: {},
|
|
12916
|
-
items: item.children.map((child) => buildTocListItem(indexer, child))
|
|
12917
|
-
}
|
|
12918
|
-
};
|
|
12919
|
-
}
|
|
12920
|
-
const anchor = `#toc${indexer.next()}`;
|
|
12921
|
-
const linkElement = {
|
|
12922
|
-
element: "link",
|
|
12923
|
-
data: {
|
|
12924
|
-
type: "table-of-contents",
|
|
12925
|
-
link: anchor,
|
|
12926
|
-
extra: null,
|
|
12927
|
-
label: { text: item.value },
|
|
12928
|
-
target: null
|
|
12929
|
-
}
|
|
12930
|
-
};
|
|
12931
|
-
return {
|
|
12932
|
-
"item-type": "elements",
|
|
12933
|
-
attributes: {},
|
|
12934
|
-
elements: [linkElement]
|
|
12935
|
-
};
|
|
12936
|
-
}
|
|
12937
|
-
function buildTableOfContents(entries) {
|
|
12938
|
-
if (entries.length === 0) {
|
|
12939
|
-
return [];
|
|
12940
|
-
}
|
|
12941
|
-
const depthItems = entries.map((entry) => ({
|
|
12942
|
-
depth: entry.level - 1,
|
|
12943
|
-
ltype: null,
|
|
12944
|
-
value: entry.text
|
|
12945
|
-
}));
|
|
12946
|
-
const trees = processDepths(null, depthItems);
|
|
12947
|
-
const indexer = new TocIndexer;
|
|
12948
|
-
return trees.map((tree) => buildTocList(indexer, tree.list));
|
|
12949
|
-
}
|
|
12950
|
-
|
|
12951
13433
|
// packages/parser/src/parser/parse/footnotes.ts
|
|
12952
13434
|
function containsFootnoteBlock(elements) {
|
|
12953
13435
|
let found = false;
|
|
@@ -12961,7 +13443,9 @@ function containsFootnoteBlock(elements) {
|
|
|
12961
13443
|
// packages/parser/src/parser/parse/result.ts
|
|
12962
13444
|
function finalizeParseResult(ctx, children) {
|
|
12963
13445
|
const cleanedChildren = postprocessChildren(children);
|
|
12964
|
-
appendImplicitFootnoteBlock
|
|
13446
|
+
if (ctx.appendImplicitFootnoteBlock) {
|
|
13447
|
+
appendImplicitFootnoteBlock(cleanedChildren);
|
|
13448
|
+
}
|
|
12965
13449
|
return {
|
|
12966
13450
|
ast: buildSyntaxTree(ctx, cleanedChildren),
|
|
12967
13451
|
diagnostics: ctx.diagnostics
|
|
@@ -13333,30 +13817,6 @@ function preprocess(text) {
|
|
|
13333
13817
|
return result;
|
|
13334
13818
|
}
|
|
13335
13819
|
|
|
13336
|
-
// packages/parser/src/parser/preprocess/expr/evaluate.ts
|
|
13337
|
-
var import_ast5 = require("@wdprlib/ast");
|
|
13338
|
-
function evaluateDirective(kind, match) {
|
|
13339
|
-
if (kind === "expr") {
|
|
13340
|
-
const result2 = import_ast5.evaluateExpression(match.head);
|
|
13341
|
-
if (result2.success)
|
|
13342
|
-
return import_ast5.formatExprValue(result2.value);
|
|
13343
|
-
if (result2.error === "empty expression")
|
|
13344
|
-
return "";
|
|
13345
|
-
return "ERROR";
|
|
13346
|
-
}
|
|
13347
|
-
if (kind === "if") {
|
|
13348
|
-
if (!match.hasPipe)
|
|
13349
|
-
return "";
|
|
13350
|
-
return import_ast5.isTruthy(match.head) ? match.thenText : match.elseText;
|
|
13351
|
-
}
|
|
13352
|
-
if (!match.hasPipe)
|
|
13353
|
-
return "";
|
|
13354
|
-
const result = import_ast5.evaluateExpression(match.head);
|
|
13355
|
-
if (!result.success)
|
|
13356
|
-
return "ERROR";
|
|
13357
|
-
return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
|
|
13358
|
-
}
|
|
13359
|
-
|
|
13360
13820
|
// packages/parser/src/parser/preprocess/expr/chars.ts
|
|
13361
13821
|
function isWhitespace(ch) {
|
|
13362
13822
|
return ch === " " || ch === "\t" || ch === `
|
|
@@ -13385,6 +13845,30 @@ function matchDirectiveKind(source, i) {
|
|
|
13385
13845
|
return null;
|
|
13386
13846
|
}
|
|
13387
13847
|
|
|
13848
|
+
// packages/parser/src/parser/preprocess/expr/evaluate.ts
|
|
13849
|
+
var import_ast6 = require("@wdprlib/ast");
|
|
13850
|
+
function evaluateDirective(kind, match) {
|
|
13851
|
+
if (kind === "expr") {
|
|
13852
|
+
const result2 = import_ast6.evaluateExpression(match.head);
|
|
13853
|
+
if (result2.success)
|
|
13854
|
+
return import_ast6.formatExprValue(result2.value);
|
|
13855
|
+
if (result2.error === "empty expression")
|
|
13856
|
+
return "";
|
|
13857
|
+
return "ERROR";
|
|
13858
|
+
}
|
|
13859
|
+
if (kind === "if") {
|
|
13860
|
+
if (!match.hasPipe)
|
|
13861
|
+
return "";
|
|
13862
|
+
return import_ast6.isTruthy(match.head) ? match.thenText : match.elseText;
|
|
13863
|
+
}
|
|
13864
|
+
if (!match.hasPipe)
|
|
13865
|
+
return "";
|
|
13866
|
+
const result = import_ast6.evaluateExpression(match.head);
|
|
13867
|
+
if (!result.success)
|
|
13868
|
+
return "ERROR";
|
|
13869
|
+
return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
|
|
13870
|
+
}
|
|
13871
|
+
|
|
13388
13872
|
// packages/parser/src/parser/preprocess/expr/parse.ts
|
|
13389
13873
|
function tryParseInnermostDirective(source, start, kind) {
|
|
13390
13874
|
const keywordLen = kind === "ifexpr" ? 6 : kind === "expr" ? 4 : 2;
|
|
@@ -13486,11 +13970,14 @@ function expandInnermost(source) {
|
|
|
13486
13970
|
}
|
|
13487
13971
|
|
|
13488
13972
|
// packages/parser/src/parser/preprocess/expr/index.ts
|
|
13973
|
+
var MAX_EXPR_NESTING = 64;
|
|
13489
13974
|
function preprocessExpr(source) {
|
|
13490
13975
|
if (!source.includes("[[#"))
|
|
13491
13976
|
return source;
|
|
13492
13977
|
const sentinels = makeUniqueSentinels(source);
|
|
13493
13978
|
const { masked, placeholders } = maskRawRegions(source, sentinels);
|
|
13979
|
+
if (exceedsExprNestingLimit(masked))
|
|
13980
|
+
return source;
|
|
13494
13981
|
const reduced = reduceExpr(masked);
|
|
13495
13982
|
return restorePlaceholders(reduced, placeholders, sentinels);
|
|
13496
13983
|
}
|
|
@@ -13505,6 +13992,26 @@ function reduceExpr(source) {
|
|
|
13505
13992
|
}
|
|
13506
13993
|
return current2;
|
|
13507
13994
|
}
|
|
13995
|
+
function exceedsExprNestingLimit(source) {
|
|
13996
|
+
const expressionStack = [];
|
|
13997
|
+
let expressionDepth = 0;
|
|
13998
|
+
for (let i = 0;i < source.length; i++) {
|
|
13999
|
+
if (source.startsWith("[[", i)) {
|
|
14000
|
+
const isExpression = matchDirectiveKind(source, i) !== null;
|
|
14001
|
+
expressionStack.push(isExpression);
|
|
14002
|
+
if (isExpression && ++expressionDepth > MAX_EXPR_NESTING)
|
|
14003
|
+
return true;
|
|
14004
|
+
i++;
|
|
14005
|
+
continue;
|
|
14006
|
+
}
|
|
14007
|
+
if (source.startsWith("]]", i)) {
|
|
14008
|
+
if (expressionStack.pop())
|
|
14009
|
+
expressionDepth--;
|
|
14010
|
+
i++;
|
|
14011
|
+
}
|
|
14012
|
+
}
|
|
14013
|
+
return false;
|
|
14014
|
+
}
|
|
13508
14015
|
|
|
13509
14016
|
// packages/parser/src/parser/parse/source.ts
|
|
13510
14017
|
function prepareSourceForParse(source, options) {
|
|
@@ -13531,3 +14038,282 @@ function parse(source, options) {
|
|
|
13531
14038
|
});
|
|
13532
14039
|
return new Parser(tokens, options).parse();
|
|
13533
14040
|
}
|
|
14041
|
+
// packages/parser/src/pipeline/process.ts
|
|
14042
|
+
var import_ast7 = require("@wdprlib/ast");
|
|
14043
|
+
|
|
14044
|
+
// packages/parser/src/parser/rules/block/module/resolution/resolve-async.ts
|
|
14045
|
+
async function resolveModulesWithAsyncParse(ast, dataProvider, options) {
|
|
14046
|
+
const registry = new ModuleDocumentRegistry;
|
|
14047
|
+
registry.register(ast);
|
|
14048
|
+
const parse2 = async (source) => registry.register(await options.parse(source));
|
|
14049
|
+
const [listPagesData, listUsersData, tagCloudData] = await Promise.all([
|
|
14050
|
+
buildListPagesDataMap(dataProvider, options.requirements.listPages ?? [], options.urlPath),
|
|
14051
|
+
buildListUsersDataMap(dataProvider, options.requirements.listUsers ?? []),
|
|
14052
|
+
buildTagCloudDataMap(dataProvider, options.requirements.tagCloud ?? [])
|
|
14053
|
+
]);
|
|
14054
|
+
const context = {
|
|
14055
|
+
dataProvider,
|
|
14056
|
+
listPagesData,
|
|
14057
|
+
listUsersData,
|
|
14058
|
+
tagCloudData,
|
|
14059
|
+
options,
|
|
14060
|
+
parse: parse2
|
|
14061
|
+
};
|
|
14062
|
+
const state = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
|
|
14063
|
+
const resolvedElements = await resolveElements(ast.elements, context, state);
|
|
14064
|
+
const { elements, styles, anchoredStyles } = collectStyles(resolvedElements);
|
|
14065
|
+
const intermediate = { ...ast, elements };
|
|
14066
|
+
const mergedStyles = mergeCollectedStyles(ast.styles, styles, new Map, anchoredStyles);
|
|
14067
|
+
if (mergedStyles.length > 0)
|
|
14068
|
+
intermediate.styles = mergedStyles;
|
|
14069
|
+
else
|
|
14070
|
+
delete intermediate.styles;
|
|
14071
|
+
return {
|
|
14072
|
+
ast: registry.finalize(intermediate, elements, options.pageTags),
|
|
14073
|
+
diagnostics: registry.diagnostics
|
|
14074
|
+
};
|
|
14075
|
+
}
|
|
14076
|
+
async function resolveElements(elements, context, state) {
|
|
14077
|
+
const result = [];
|
|
14078
|
+
for (const element of elements) {
|
|
14079
|
+
if (element.element === "module") {
|
|
14080
|
+
const resolved = await resolveModuleElement(element, context, state);
|
|
14081
|
+
if (resolved !== null) {
|
|
14082
|
+
result.push(...resolved);
|
|
14083
|
+
continue;
|
|
14084
|
+
}
|
|
14085
|
+
}
|
|
14086
|
+
if (element.element === "if-tags") {
|
|
14087
|
+
const resolution = resolveIfTags(element.data, context.options.pageTags);
|
|
14088
|
+
if (resolution.matched) {
|
|
14089
|
+
result.push(...await resolveElements(element.data.elements, context, state));
|
|
14090
|
+
}
|
|
14091
|
+
continue;
|
|
14092
|
+
}
|
|
14093
|
+
result.push(await resolveElementChildren(element, context, state));
|
|
14094
|
+
}
|
|
14095
|
+
return result;
|
|
14096
|
+
}
|
|
14097
|
+
async function resolveModuleElement(element, context, state) {
|
|
14098
|
+
if (isListPagesModule2(element.data)) {
|
|
14099
|
+
const id = state.listPagesId++;
|
|
14100
|
+
const data = context.listPagesData.get(id);
|
|
14101
|
+
const template = context.options.compiledListPagesTemplates.get(id);
|
|
14102
|
+
if (data && template)
|
|
14103
|
+
return resolveListPagesAsync(element.data, data, template, context.parse);
|
|
14104
|
+
return context.dataProvider.fetchListPages ? [] : [element];
|
|
14105
|
+
}
|
|
14106
|
+
if (isListUsersModule2(element.data)) {
|
|
14107
|
+
const id = state.listUsersId++;
|
|
14108
|
+
const data = context.listUsersData.get(id);
|
|
14109
|
+
const template = context.options.compiledListUsersTemplates?.get(id);
|
|
14110
|
+
if (data && template) {
|
|
14111
|
+
const variableContext = { user: data.user };
|
|
14112
|
+
return (await context.parse(template(variableContext))).elements;
|
|
14113
|
+
}
|
|
14114
|
+
return context.dataProvider.fetchListUsers ? [] : [element];
|
|
14115
|
+
}
|
|
14116
|
+
if (isTagCloudModule(element.data)) {
|
|
14117
|
+
const id = state.tagCloudId++;
|
|
14118
|
+
const data = context.tagCloudData.get(id);
|
|
14119
|
+
if (data)
|
|
14120
|
+
return resolveTagCloud(element.data, data);
|
|
14121
|
+
return context.dataProvider.fetchTagCloud ? [] : [element];
|
|
14122
|
+
}
|
|
14123
|
+
return null;
|
|
14124
|
+
}
|
|
14125
|
+
async function resolveListPagesAsync(module2, data, template, parse2) {
|
|
14126
|
+
if (data.pages.length === 0)
|
|
14127
|
+
return [];
|
|
14128
|
+
const result = [];
|
|
14129
|
+
if (module2["prepend-line"] && !module2.separate) {
|
|
14130
|
+
result.push(...(await parse2(module2["prepend-line"])).elements);
|
|
14131
|
+
}
|
|
14132
|
+
for (let i = 0;i < data.pages.length; i++) {
|
|
14133
|
+
const page = data.pages[i];
|
|
14134
|
+
if (!page)
|
|
14135
|
+
continue;
|
|
14136
|
+
const variableContext = {
|
|
14137
|
+
page,
|
|
14138
|
+
index: i + 1,
|
|
14139
|
+
total: data.totalCount,
|
|
14140
|
+
limit: module2.limit,
|
|
14141
|
+
site: data.site
|
|
14142
|
+
};
|
|
14143
|
+
const parsed = await parse2(template(variableContext));
|
|
14144
|
+
if (module2.separate) {
|
|
14145
|
+
result.push({
|
|
14146
|
+
element: "container",
|
|
14147
|
+
data: {
|
|
14148
|
+
type: "div",
|
|
14149
|
+
attributes: { class: "list-pages-item" },
|
|
14150
|
+
elements: parsed.elements
|
|
14151
|
+
}
|
|
14152
|
+
});
|
|
14153
|
+
} else {
|
|
14154
|
+
result.push(...parsed.elements);
|
|
14155
|
+
}
|
|
14156
|
+
}
|
|
14157
|
+
if (module2["append-line"] && !module2.separate) {
|
|
14158
|
+
result.push(...(await parse2(module2["append-line"])).elements);
|
|
14159
|
+
}
|
|
14160
|
+
return module2.wrapper ? [
|
|
14161
|
+
{
|
|
14162
|
+
element: "container",
|
|
14163
|
+
data: {
|
|
14164
|
+
type: "div",
|
|
14165
|
+
attributes: { class: "list-pages-box" },
|
|
14166
|
+
elements: result
|
|
14167
|
+
}
|
|
14168
|
+
}
|
|
14169
|
+
] : result;
|
|
14170
|
+
}
|
|
14171
|
+
async function resolveElementChildren(element, context, state) {
|
|
14172
|
+
if (element.element === "list") {
|
|
14173
|
+
const items = [];
|
|
14174
|
+
for (const item of element.data.items) {
|
|
14175
|
+
if (item["item-type"] === "elements") {
|
|
14176
|
+
items.push({ ...item, elements: await resolveElements(item.elements, context, state) });
|
|
14177
|
+
} else {
|
|
14178
|
+
const resolved = (await resolveElements([listElement(item.data)], context, state))[0];
|
|
14179
|
+
items.push(resolved?.element === "list" ? { ...item, data: resolved.data } : item);
|
|
14180
|
+
}
|
|
14181
|
+
}
|
|
14182
|
+
return { ...element, data: { ...element.data, items } };
|
|
14183
|
+
}
|
|
14184
|
+
if (element.element === "table") {
|
|
14185
|
+
const rows = [];
|
|
14186
|
+
for (const row of element.data.rows) {
|
|
14187
|
+
const cells = [];
|
|
14188
|
+
for (const cell of row.cells) {
|
|
14189
|
+
cells.push({ ...cell, elements: await resolveElements(cell.elements, context, state) });
|
|
14190
|
+
}
|
|
14191
|
+
rows.push({ ...row, cells });
|
|
14192
|
+
}
|
|
14193
|
+
return { ...element, data: { ...element.data, rows } };
|
|
14194
|
+
}
|
|
14195
|
+
if (element.element === "definition-list") {
|
|
14196
|
+
const entries = [];
|
|
14197
|
+
for (const entry of element.data) {
|
|
14198
|
+
entries.push({
|
|
14199
|
+
...entry,
|
|
14200
|
+
key: await resolveElements(entry.key, context, state),
|
|
14201
|
+
value: await resolveElements(entry.value, context, state)
|
|
14202
|
+
});
|
|
14203
|
+
}
|
|
14204
|
+
return { ...element, data: entries };
|
|
14205
|
+
}
|
|
14206
|
+
if (element.element === "tab-view") {
|
|
14207
|
+
const tabs = [];
|
|
14208
|
+
for (const tab of element.data) {
|
|
14209
|
+
tabs.push({ ...tab, elements: await resolveElements(tab.elements, context, state) });
|
|
14210
|
+
}
|
|
14211
|
+
return { ...element, data: tabs };
|
|
14212
|
+
}
|
|
14213
|
+
const children = getGenericElementChildren(element);
|
|
14214
|
+
return children === null ? element : withGenericElementChildren(element, await resolveElements(children, context, state));
|
|
14215
|
+
}
|
|
14216
|
+
|
|
14217
|
+
// packages/parser/src/pipeline/process.ts
|
|
14218
|
+
var DEFAULT_MODULE_MAX_PASSES = 5;
|
|
14219
|
+
var PIPELINE_DIAGNOSTIC_POSITION = {
|
|
14220
|
+
start: { line: 1, column: 1, offset: 0 },
|
|
14221
|
+
end: { line: 1, column: 1, offset: 0 }
|
|
14222
|
+
};
|
|
14223
|
+
async function processWikitext(source, options) {
|
|
14224
|
+
const settings = options.settings ?? import_ast7.DEFAULT_SETTINGS;
|
|
14225
|
+
const callbackContext = {
|
|
14226
|
+
page: options.page,
|
|
14227
|
+
settings
|
|
14228
|
+
};
|
|
14229
|
+
const dependencies = [];
|
|
14230
|
+
const diagnostics = [];
|
|
14231
|
+
const fetchInclude = createRequestIncludeFetcher(options.dataProvider?.fetchInclude ? (pageRef) => options.dataProvider.fetchInclude(pageRef, callbackContext) : undefined);
|
|
14232
|
+
const resolveSource = async (input) => {
|
|
14233
|
+
if (!fetchInclude)
|
|
14234
|
+
return input;
|
|
14235
|
+
const resolution = await resolveIncludesAsyncWithTrace(input, fetchInclude, {
|
|
14236
|
+
maxIterations: options.includeMaxIterations,
|
|
14237
|
+
settings
|
|
14238
|
+
});
|
|
14239
|
+
dependencies.push(...resolution.dependencies);
|
|
14240
|
+
if (resolution.reachedMaxIterations) {
|
|
14241
|
+
diagnostics.push(createLimitDiagnostic("include-resolution-limit", `Include expansion stopped after ${options.includeMaxIterations ?? 10} iterations.`));
|
|
14242
|
+
}
|
|
14243
|
+
return resolution.source;
|
|
14244
|
+
};
|
|
14245
|
+
const expandedSource = await resolveSource(source);
|
|
14246
|
+
const initial = parse(expandedSource, {
|
|
14247
|
+
settings,
|
|
14248
|
+
pageTags: options.page.tags,
|
|
14249
|
+
appendImplicitFootnoteBlock: false
|
|
14250
|
+
});
|
|
14251
|
+
diagnostics.push(...initial.diagnostics);
|
|
14252
|
+
const dataProvider = createModuleDataProvider(options, callbackContext);
|
|
14253
|
+
const parseFragment = async (fragmentSource) => parse(await resolveSource(fragmentSource), {
|
|
14254
|
+
settings,
|
|
14255
|
+
pageTags: options.page.tags,
|
|
14256
|
+
appendImplicitFootnoteBlock: false
|
|
14257
|
+
});
|
|
14258
|
+
let ast = initial.ast;
|
|
14259
|
+
for (let pass = 0;pass < DEFAULT_MODULE_MAX_PASSES; pass++) {
|
|
14260
|
+
const extraction = extractDataRequirements(ast);
|
|
14261
|
+
if (pass > 0 && !hasResolvableRequirements(extraction.requirements, options.dataProvider)) {
|
|
14262
|
+
break;
|
|
14263
|
+
}
|
|
14264
|
+
const resolved = await resolveModulesWithAsyncParse(ast, dataProvider, {
|
|
14265
|
+
parse: parseFragment,
|
|
14266
|
+
compiledListPagesTemplates: extraction.compiledListPagesTemplates,
|
|
14267
|
+
compiledListUsersTemplates: extraction.compiledListUsersTemplates,
|
|
14268
|
+
requirements: extraction.requirements,
|
|
14269
|
+
urlPath: options.page.urlPath,
|
|
14270
|
+
pageTags: options.page.tags
|
|
14271
|
+
});
|
|
14272
|
+
ast = resolved.ast;
|
|
14273
|
+
diagnostics.push(...resolved.diagnostics);
|
|
14274
|
+
}
|
|
14275
|
+
if (hasResolvableRequirements(extractDataRequirements(ast).requirements, options.dataProvider)) {
|
|
14276
|
+
diagnostics.push(createLimitDiagnostic("module-resolution-limit", `Module resolution stopped after ${DEFAULT_MODULE_MAX_PASSES} passes.`));
|
|
14277
|
+
}
|
|
14278
|
+
return {
|
|
14279
|
+
ast,
|
|
14280
|
+
page: options.page,
|
|
14281
|
+
settings,
|
|
14282
|
+
diagnostics,
|
|
14283
|
+
dependencies
|
|
14284
|
+
};
|
|
14285
|
+
}
|
|
14286
|
+
function hasResolvableRequirements(requirements, provider) {
|
|
14287
|
+
return Boolean(provider?.fetchListPages && requirements.listPages.length > 0 || provider?.fetchListUsers && requirements.listUsers.length > 0 || provider?.fetchTagCloud && requirements.tagCloud.length > 0);
|
|
14288
|
+
}
|
|
14289
|
+
function createLimitDiagnostic(code, message) {
|
|
14290
|
+
return {
|
|
14291
|
+
severity: "warning",
|
|
14292
|
+
code,
|
|
14293
|
+
message,
|
|
14294
|
+
position: PIPELINE_DIAGNOSTIC_POSITION
|
|
14295
|
+
};
|
|
14296
|
+
}
|
|
14297
|
+
function createModuleDataProvider(options, context) {
|
|
14298
|
+
const provider = options.dataProvider;
|
|
14299
|
+
return {
|
|
14300
|
+
fetchListPages: provider?.fetchListPages ? (query, requirement) => provider.fetchListPages(query, requirement, context) : undefined,
|
|
14301
|
+
fetchListUsers: provider?.fetchListUsers ? (requirement) => provider.fetchListUsers(requirement, context) : undefined,
|
|
14302
|
+
fetchTagCloud: provider?.fetchTagCloud ? (requirement) => provider.fetchTagCloud(requirement, context) : undefined,
|
|
14303
|
+
getPageTags: () => options.page.tags
|
|
14304
|
+
};
|
|
14305
|
+
}
|
|
14306
|
+
function createRequestIncludeFetcher(fetcher) {
|
|
14307
|
+
if (!fetcher)
|
|
14308
|
+
return;
|
|
14309
|
+
const cache = new Map;
|
|
14310
|
+
return (pageRef) => {
|
|
14311
|
+
const key = `${pageRef.site ?? ""}:${pageRef.page.toLowerCase()}`;
|
|
14312
|
+
const cached = cache.get(key);
|
|
14313
|
+
if (cached)
|
|
14314
|
+
return cached;
|
|
14315
|
+
const result = fetcher(pageRef).catch(() => null);
|
|
14316
|
+
cache.set(key, result);
|
|
14317
|
+
return result;
|
|
14318
|
+
};
|
|
14319
|
+
}
|