@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/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: () => import_ast6.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,37 @@ __export(exports_src, {
46
48
  parseDateSelector: () => parseDateSelector,
47
49
  parseCategory: () => parseCategory,
48
50
  parse: () => parse,
49
- paragraph: () => import_ast6.paragraph,
51
+ paragraph: () => import_ast8.paragraph,
50
52
  normalizeQuery: () => normalizeQuery,
51
- listItemSubList: () => import_ast6.listItemSubList,
52
- listItemElements: () => import_ast6.listItemElements,
53
- list: () => import_ast6.list,
54
- link: () => import_ast6.link,
55
- lineBreak: () => import_ast6.lineBreak,
56
- italics: () => import_ast6.italics,
53
+ listItemSubList: () => import_ast8.listItemSubList,
54
+ listItemElements: () => import_ast8.listItemElements,
55
+ list: () => import_ast8.list,
56
+ link: () => import_ast8.link,
57
+ lineBreak: () => import_ast8.lineBreak,
58
+ italics: () => import_ast8.italics,
57
59
  isTagCloudModule: () => isTagCloudModule,
58
60
  isListUsersModule: () => isListUsersModule2,
59
- horizontalRule: () => import_ast6.horizontalRule,
60
- heading: () => import_ast6.heading,
61
+ horizontalRule: () => import_ast8.horizontalRule,
62
+ heading: () => import_ast8.heading,
61
63
  extractListUsersVariables: () => extractListUsersVariables,
62
64
  extractIncludeReferences: () => extractIncludeReferences,
63
65
  extractDataRequirements: () => extractDataRequirements,
64
66
  createToken: () => createToken,
65
- createSettings: () => import_ast7.createSettings,
66
- createPosition: () => import_ast6.createPosition,
67
- createPoint: () => import_ast6.createPoint,
68
- container: () => import_ast6.container,
67
+ createSettings: () => import_ast9.createSettings,
68
+ createPosition: () => import_ast8.createPosition,
69
+ createPoint: () => import_ast8.createPoint,
70
+ container: () => import_ast8.container,
69
71
  compileTemplate: () => compileTemplate,
70
72
  compileListUsersTemplate: () => compileListUsersTemplate,
71
- bold: () => import_ast6.bold,
72
- STYLE_SLOT_PREFIX: () => import_ast3.STYLE_SLOT_PREFIX,
73
+ bold: () => import_ast8.bold,
74
+ STYLE_SLOT_PREFIX: () => import_ast4.STYLE_SLOT_PREFIX,
73
75
  Parser: () => Parser,
74
76
  Lexer: () => Lexer,
75
- DEFAULT_SETTINGS: () => import_ast7.DEFAULT_SETTINGS
77
+ DEFAULT_SETTINGS: () => import_ast9.DEFAULT_SETTINGS
76
78
  });
77
79
  module.exports = __toCommonJS(exports_src);
78
- var import_ast6 = require("@wdprlib/ast");
79
- var import_ast7 = require("@wdprlib/ast");
80
+ var import_ast8 = require("@wdprlib/ast");
81
+ var import_ast9 = require("@wdprlib/ast");
80
82
 
81
83
  // packages/parser/src/lexer/tokens.ts
82
84
  function createToken(type, value, position, lineStart = false) {
@@ -1443,7 +1445,7 @@ function parseNextBlock(ctx, skipWhitespace2, isAtEnd2) {
1443
1445
  }
1444
1446
 
1445
1447
  // packages/parser/src/parser/parse/context.ts
1446
- var import_ast4 = require("@wdprlib/ast");
1448
+ var import_ast5 = require("@wdprlib/ast");
1447
1449
 
1448
1450
  // packages/parser/src/parser/rules/tokens.ts
1449
1451
  function currentToken(ctx) {
@@ -5843,6 +5845,11 @@ function extractDataRequirements(ast) {
5843
5845
  });
5844
5846
  return result;
5845
5847
  }
5848
+ // packages/parser/src/parser/rules/block/module/types.ts
5849
+ function getModuleParseAst(result) {
5850
+ return "ast" in result ? result.ast : result;
5851
+ }
5852
+
5846
5853
  // packages/parser/src/parser/rules/block/module/listpages/resolution/items.ts
5847
5854
  function renderListPagesItems(module2, data, compiledTemplate, parse) {
5848
5855
  const items = [];
@@ -5857,7 +5864,7 @@ function renderListPagesItems(module2, data, compiledTemplate, parse) {
5857
5864
  limit: module2.limit,
5858
5865
  site: data.site
5859
5866
  };
5860
- const itemAst = parse(compiledTemplate(ctx));
5867
+ const itemAst = getModuleParseAst(parse(compiledTemplate(ctx)));
5861
5868
  if (module2.separate) {
5862
5869
  items.push({
5863
5870
  element: "container",
@@ -5881,12 +5888,12 @@ function wrapListPagesResult(module2, items, parse) {
5881
5888
  }
5882
5889
  const result = [];
5883
5890
  if (module2["prepend-line"] && !module2.separate) {
5884
- const prependAst = parse(module2["prepend-line"]);
5891
+ const prependAst = getModuleParseAst(parse(module2["prepend-line"]));
5885
5892
  result.push(...prependAst.elements);
5886
5893
  }
5887
5894
  result.push(...items);
5888
5895
  if (module2["append-line"] && !module2.separate) {
5889
- const appendAst = parse(module2["append-line"]);
5896
+ const appendAst = getModuleParseAst(parse(module2["append-line"]));
5890
5897
  result.push(...appendAst.elements);
5891
5898
  }
5892
5899
  if (module2.wrapper) {
@@ -6805,16 +6812,31 @@ function expandIterativeWithTrace(source, fetcher, maxIterations) {
6805
6812
  reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
6806
6813
  };
6807
6814
  }
6808
- async function expandIterativeAsync(source, fetcher, maxIterations) {
6815
+ async function expandIterativeAsyncWithTrace(source, fetcher, maxIterations) {
6809
6816
  let current2 = source;
6810
6817
  const replacementCache = new Map;
6818
+ const dependencies = [];
6819
+ const iterations = [];
6811
6820
  for (let i = 0;i < maxIterations; i++) {
6812
- const expanded = await expandOneIterationAsync(current2, fetcher, replacementCache);
6813
- if (expanded === null || expanded === current2)
6821
+ const expanded = await expandOneIterationAsyncWithTrace(current2, fetcher, replacementCache, i);
6822
+ if (expanded === null)
6814
6823
  break;
6815
- current2 = expanded;
6824
+ dependencies.push(...expanded.dependencies);
6825
+ iterations.push({
6826
+ iteration: i,
6827
+ directives: expanded.references,
6828
+ changed: expanded.source !== current2
6829
+ });
6830
+ if (expanded.source === current2)
6831
+ break;
6832
+ current2 = expanded.source;
6816
6833
  }
6817
- return current2;
6834
+ return {
6835
+ source: current2,
6836
+ dependencies,
6837
+ iterations,
6838
+ reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
6839
+ };
6818
6840
  }
6819
6841
  function expandOneIteration(source, fetcher, replacementCache) {
6820
6842
  if (!MAYBE_INCLUDE_PATTERN.test(source))
@@ -6852,12 +6874,13 @@ function expandOneIterationWithTrace(source, fetcher, replacementCache, iteratio
6852
6874
  dependencies
6853
6875
  };
6854
6876
  }
6855
- async function expandOneIterationAsync(source, fetcher, replacementCache) {
6877
+ async function expandOneIterationAsyncWithTrace(source, fetcher, replacementCache, iteration) {
6856
6878
  if (!MAYBE_INCLUDE_PATTERN.test(source))
6857
6879
  return null;
6858
6880
  const directives = scanIncludeDirectives(source);
6859
6881
  if (directives.length === 0)
6860
6882
  return null;
6883
+ const references = directives.map(createIncludeReference);
6861
6884
  const replacements = await Promise.all(directives.map(({ inner }) => replaceCachedAsync(inner, fetcher, replacementCache)));
6862
6885
  const parts = [];
6863
6886
  let lastPos = 0;
@@ -6867,7 +6890,11 @@ async function expandOneIterationAsync(source, fetcher, replacementCache) {
6867
6890
  lastPos = end;
6868
6891
  }
6869
6892
  parts.push(source.slice(lastPos));
6870
- return parts.join("");
6893
+ return {
6894
+ source: parts.join(""),
6895
+ references,
6896
+ dependencies: references.map((reference) => ({ ...reference, iteration }))
6897
+ };
6871
6898
  }
6872
6899
  function replaceCached(inner, fetcher, cache) {
6873
6900
  const cached = cache.get(inner);
@@ -6909,12 +6936,20 @@ function resolveIncludesWithTrace(source, fetcher, options) {
6909
6936
  return expandIterativeWithTrace(source, cachedFetcher, maxIterations);
6910
6937
  }
6911
6938
  async function resolveIncludesAsync(source, fetcher, options) {
6939
+ return (await resolveIncludesAsyncWithTrace(source, fetcher, options)).source;
6940
+ }
6941
+ async function resolveIncludesAsyncWithTrace(source, fetcher, options) {
6912
6942
  if (options?.settings && !options.settings.enablePageSyntax) {
6913
- return source;
6943
+ return {
6944
+ source,
6945
+ dependencies: [],
6946
+ iterations: [],
6947
+ reachedMaxIterations: false
6948
+ };
6914
6949
  }
6915
6950
  const maxIterations = options?.maxIterations ?? 10;
6916
6951
  const cachedFetcher = createCachedAsyncIncludeFetcher(fetcher, normalizePageKey);
6917
- return expandIterativeAsync(source, cachedFetcher, maxIterations);
6952
+ return expandIterativeAsyncWithTrace(source, cachedFetcher, maxIterations);
6918
6953
  }
6919
6954
  function normalizePageKey(location) {
6920
6955
  const site = location.site ?? "";
@@ -6928,7 +6963,7 @@ function isListUsersModule2(module2) {
6928
6963
  function resolveListUsers(_module, data, compiledTemplate, parse) {
6929
6964
  const ctx = { user: data.user };
6930
6965
  const substituted = compiledTemplate(ctx);
6931
- const itemAst = parse(substituted);
6966
+ const itemAst = getModuleParseAst(parse(substituted));
6932
6967
  return itemAst.elements;
6933
6968
  }
6934
6969
  // packages/parser/src/parser/rules/block/module/resolution/data-maps.ts
@@ -7081,6 +7116,117 @@ function countDynamicModules(elements) {
7081
7116
  return counts;
7082
7117
  }
7083
7118
 
7119
+ // packages/parser/src/parser/rules/block/module/resolution/styles.ts
7120
+ var import_ast2 = require("@wdprlib/ast");
7121
+ function collectStyles(elements, ignoredAnchors = new WeakSet) {
7122
+ const styles = [];
7123
+ const anchoredStyles = [];
7124
+ const anchors = [];
7125
+ const usedSlots = collectExistingStyleSlots(elements);
7126
+ const ctx = { nextSlotId: 0, usedSlots };
7127
+ const filtered = collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx);
7128
+ return { elements: filtered, styles, anchoredStyles, anchors };
7129
+ }
7130
+ function mergeCollectedStyles(existing, collected, resolvedSlots = new Map, anchoredStyles = []) {
7131
+ const unanchoredPrevious = [...existing ?? []];
7132
+ for (const style of anchoredStyles)
7133
+ removeFirst(unanchoredPrevious, style);
7134
+ for (const style of collected) {
7135
+ if (isStyleSlotMarker(style))
7136
+ removeFirst(unanchoredPrevious, style);
7137
+ }
7138
+ const merged = unanchoredPrevious.filter((style) => !isStyleSlotMarker(style));
7139
+ for (const style of collected) {
7140
+ if (isStyleSlotMarker(style))
7141
+ appendStyleSlot(merged, style, resolvedSlots);
7142
+ else
7143
+ merged.push(style);
7144
+ }
7145
+ return merged;
7146
+ }
7147
+ function isStyleSlotMarker(style) {
7148
+ return style.startsWith(import_ast2.STYLE_SLOT_PREFIX);
7149
+ }
7150
+ function createStyleSlotMarker(slotId) {
7151
+ return `${import_ast2.STYLE_SLOT_PREFIX}${slotId}`;
7152
+ }
7153
+ function getStyleSlotId(data) {
7154
+ const slotId = data._styleSlot;
7155
+ return Number.isSafeInteger(slotId) && slotId >= 0 ? slotId : undefined;
7156
+ }
7157
+ function removeFirst(values, value) {
7158
+ const index = values.indexOf(value);
7159
+ if (index >= 0)
7160
+ values.splice(index, 1);
7161
+ }
7162
+ function appendStyleSlot(target, marker, resolvedSlots) {
7163
+ const slotId = Number(marker.slice(import_ast2.STYLE_SLOT_PREFIX.length));
7164
+ const replacement = resolvedSlots.get(slotId);
7165
+ if (replacement)
7166
+ target.push(...replacement);
7167
+ else
7168
+ target.push(marker);
7169
+ }
7170
+ function collectExistingStyleSlots(elements) {
7171
+ const slots = new Set;
7172
+ walkElements(elements, (element) => {
7173
+ if (element.element !== "if-tags")
7174
+ return;
7175
+ const slotId = getStyleSlotId(element.data);
7176
+ if (slotId !== undefined)
7177
+ slots.add(slotId);
7178
+ });
7179
+ return slots;
7180
+ }
7181
+ function allocateStyleSlot(ctx) {
7182
+ while (ctx.usedSlots.has(ctx.nextSlotId))
7183
+ ctx.nextSlotId++;
7184
+ const slotId = ctx.nextSlotId++;
7185
+ ctx.usedSlots.add(slotId);
7186
+ return slotId;
7187
+ }
7188
+ function collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx) {
7189
+ const result = [];
7190
+ for (const element of elements) {
7191
+ if (element.element === "style") {
7192
+ const css = element.data;
7193
+ if (css.startsWith(import_ast2.STYLE_SLOT_PREFIX)) {
7194
+ styles.push(css);
7195
+ continue;
7196
+ }
7197
+ if (css.startsWith(import_ast2.STYLE_ANCHOR_PREFIX)) {
7198
+ anchors.push(element);
7199
+ if (ignoredAnchors.has(element)) {
7200
+ result.push(element);
7201
+ continue;
7202
+ }
7203
+ const anchoredCss = css.slice(import_ast2.STYLE_ANCHOR_PREFIX.length);
7204
+ styles.push(anchoredCss);
7205
+ anchoredStyles.push(anchoredCss);
7206
+ result.push(element);
7207
+ continue;
7208
+ }
7209
+ styles.push(css);
7210
+ const anchor = { element: "style", data: `${import_ast2.STYLE_ANCHOR_PREFIX}${css}` };
7211
+ anchors.push(anchor);
7212
+ result.push(anchor);
7213
+ continue;
7214
+ }
7215
+ if (element.element === "if-tags") {
7216
+ const slotId = getStyleSlotId(element.data) ?? allocateStyleSlot(ctx);
7217
+ styles.push(createStyleSlotMarker(slotId));
7218
+ const data = { ...element.data, _styleSlot: slotId };
7219
+ result.push({
7220
+ element: "if-tags",
7221
+ data
7222
+ });
7223
+ continue;
7224
+ }
7225
+ result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, anchoredStyles, anchors, ignoredAnchors, ctx)));
7226
+ }
7227
+ return result;
7228
+ }
7229
+
7084
7230
  // packages/parser/src/parser/rules/block/module/resolution/walk-resolve.ts
7085
7231
  function walkAndResolve(elements, ctx) {
7086
7232
  const result = [];
@@ -7103,6 +7249,7 @@ function walkAndResolve(elements, ctx) {
7103
7249
  if (isIfTagsElement(element)) {
7104
7250
  const ifTagsData = element.data;
7105
7251
  const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
7252
+ const styleSlotId = getStyleSlotId(ifTagsData);
7106
7253
  if (resolveResult.evaluated) {
7107
7254
  if (resolveResult.matched) {
7108
7255
  const childResult = walkAndResolve(ifTagsData.elements, {
@@ -7111,11 +7258,23 @@ function walkAndResolve(elements, ctx) {
7111
7258
  listUsersIdCounter: listUsersId,
7112
7259
  tagCloudIdCounter: tagCloudId
7113
7260
  });
7114
- result.push(...childResult.elements);
7261
+ if (styleSlotId === undefined) {
7262
+ result.push(...childResult.elements);
7263
+ } else {
7264
+ const collected = collectStyles(childResult.elements);
7265
+ ctx.resolvedStyleSlots.set(styleSlotId, collected.styles);
7266
+ for (const anchor of collected.anchors)
7267
+ ctx.routedStyleAnchors.add(anchor);
7268
+ result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) }, ...collected.elements);
7269
+ }
7115
7270
  listPagesId = childResult.nextListPagesId;
7116
7271
  listUsersId = childResult.nextListUsersId;
7117
7272
  tagCloudId = childResult.nextTagCloudId;
7118
7273
  } else {
7274
+ if (styleSlotId !== undefined) {
7275
+ ctx.resolvedStyleSlots.set(styleSlotId, []);
7276
+ result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) });
7277
+ }
7119
7278
  const counts = countDynamicModules(ifTagsData.elements);
7120
7279
  listPagesId += counts.listPagesId;
7121
7280
  listUsersId += counts.listUsersId;
@@ -7170,44 +7329,358 @@ function walkAndResolve(elements, ctx) {
7170
7329
  };
7171
7330
  }
7172
7331
 
7173
- // packages/parser/src/parser/rules/block/module/resolution/styles.ts
7174
- var import_ast2 = require("@wdprlib/ast");
7175
- function collectStyles(elements) {
7176
- const styles = [];
7177
- const ctx = { nextSlotId: 0 };
7178
- const filtered = collectStylesFromElements(elements, styles, ctx);
7179
- return { elements: filtered, styles };
7332
+ // packages/parser/src/parser/rules/block/module/resolution/document.ts
7333
+ var import_ast3 = require("@wdprlib/ast");
7334
+
7335
+ // packages/parser/src/parser/toc.ts
7336
+ class TocIndexer {
7337
+ index = 0;
7338
+ next() {
7339
+ return this.index++;
7340
+ }
7341
+ }
7342
+ function buildTocList(indexer, items) {
7343
+ const listItems = items.map((item) => buildTocListItem(indexer, item));
7344
+ return {
7345
+ element: "list",
7346
+ data: {
7347
+ type: "bullet",
7348
+ attributes: {},
7349
+ items: listItems
7350
+ }
7351
+ };
7352
+ }
7353
+ function buildTocListItem(indexer, item) {
7354
+ if (item.kind === "list") {
7355
+ return {
7356
+ "item-type": "sub-list",
7357
+ element: "list",
7358
+ data: {
7359
+ type: "bullet",
7360
+ attributes: {},
7361
+ items: item.children.map((child) => buildTocListItem(indexer, child))
7362
+ }
7363
+ };
7364
+ }
7365
+ const anchor = `#toc${indexer.next()}`;
7366
+ const linkElement = {
7367
+ element: "link",
7368
+ data: {
7369
+ type: "table-of-contents",
7370
+ link: anchor,
7371
+ extra: null,
7372
+ label: { text: item.value },
7373
+ target: null
7374
+ }
7375
+ };
7376
+ return {
7377
+ "item-type": "elements",
7378
+ attributes: {},
7379
+ elements: [linkElement]
7380
+ };
7381
+ }
7382
+ function buildTableOfContents(entries) {
7383
+ if (entries.length === 0) {
7384
+ return [];
7385
+ }
7386
+ const depthItems = entries.map((entry) => ({
7387
+ depth: entry.level - 1,
7388
+ ltype: null,
7389
+ value: entry.text
7390
+ }));
7391
+ const trees = processDepths(null, depthItems);
7392
+ const indexer = new TocIndexer;
7393
+ return trees.map((tree) => buildTocList(indexer, tree.list));
7394
+ }
7395
+
7396
+ // packages/parser/src/parser/rules/block/module/resolution/document.ts
7397
+ class ModuleDocumentRegistry {
7398
+ footnotesByElement = new WeakMap;
7399
+ diagnostics = [];
7400
+ register(result, options = {}) {
7401
+ const parseResult = isParseResult(result) ? result : null;
7402
+ const ast = parseResult ? parseResult.ast : result;
7403
+ const elements = options.stripLegacyImplicitFootnoteBlock ? stripTrailingDefaultFootnoteBlock(ast.elements) : ast.elements;
7404
+ const registeredAst = elements === ast.elements ? ast : { ...ast, elements };
7405
+ if (parseResult) {
7406
+ this.diagnostics.push(...parseResult.diagnostics);
7407
+ }
7408
+ this.registerFootnotes(registeredAst);
7409
+ return registeredAst;
7410
+ }
7411
+ finalize(ast, elements, pageTags, ensureFootnoteBlock = true) {
7412
+ const normalizedElements = normalizeFootnoteBlocks(elements, ensureFootnoteBlock);
7413
+ const footnotes = [];
7414
+ const htmlBlocks = [];
7415
+ const codeBlocks = [];
7416
+ const tocEntries = [];
7417
+ const collectElement = (element) => {
7418
+ if (element.element === "footnote") {
7419
+ const content = this.footnotesByElement.get(element);
7420
+ if (content)
7421
+ footnotes.push(content);
7422
+ } else if (element.element === "html") {
7423
+ htmlBlocks.push(element.data.contents);
7424
+ } else if (element.element === "code") {
7425
+ codeBlocks.push(element.data);
7426
+ } else if (isTocHeading(element)) {
7427
+ tocEntries.push({
7428
+ level: element.data.type.header.level,
7429
+ text: extractHeadingText(element.data.elements)
7430
+ });
7431
+ }
7432
+ };
7433
+ walkRenderOrder(normalizedElements, pageTags, collectElement);
7434
+ const result = { ...ast, elements: normalizedElements };
7435
+ setOptionalArray(result, "footnotes", footnotes);
7436
+ setOptionalArray(result, "html-blocks", htmlBlocks);
7437
+ setOptionalArray(result, "code-blocks", codeBlocks);
7438
+ setOptionalArray(result, "table-of-contents", buildTableOfContents(tocEntries));
7439
+ return result;
7440
+ }
7441
+ registerFootnotes(ast) {
7442
+ const footnoteElements = [];
7443
+ walkSyntaxOrder(ast.elements, (element) => {
7444
+ if (element.element === "footnote")
7445
+ footnoteElements.push(element);
7446
+ });
7447
+ for (let i = 0;i < footnoteElements.length; i++) {
7448
+ const content = ast.footnotes?.[i];
7449
+ if (content)
7450
+ this.footnotesByElement.set(footnoteElements[i], content);
7451
+ }
7452
+ }
7453
+ }
7454
+ function isParseResult(result) {
7455
+ return "ast" in result && "diagnostics" in result;
7456
+ }
7457
+ function setOptionalArray(tree, key, value) {
7458
+ if (value.length > 0) {
7459
+ tree[key] = value;
7460
+ } else {
7461
+ delete tree[key];
7462
+ }
7463
+ }
7464
+ function stripTrailingDefaultFootnoteBlock(elements) {
7465
+ const last = elements.at(-1);
7466
+ if (last?.element !== "footnote-block" || last.data.title !== null || last.data.hide === true) {
7467
+ return elements;
7468
+ }
7469
+ return elements.slice(0, -1);
7470
+ }
7471
+ function normalizeFootnoteBlocks(elements, ensureFootnoteBlock) {
7472
+ const state = { found: false };
7473
+ const normalized = mapSyntaxElements(elements, (element) => {
7474
+ if (element.element !== "footnote-block")
7475
+ return element;
7476
+ if (state.found)
7477
+ return null;
7478
+ state.found = true;
7479
+ return element;
7480
+ });
7481
+ if (!state.found && ensureFootnoteBlock) {
7482
+ normalized.push({
7483
+ element: "footnote-block",
7484
+ data: { title: null, hide: false }
7485
+ });
7486
+ }
7487
+ return normalized;
7488
+ }
7489
+ function containsSyntaxFootnoteBlock(elements) {
7490
+ let found = false;
7491
+ walkSyntaxOrder(elements, (element) => {
7492
+ if (element.element === "footnote-block")
7493
+ found = true;
7494
+ });
7495
+ return found;
7180
7496
  }
7181
- function collectStylesFromElements(elements, styles, ctx) {
7497
+ function mapSyntaxElements(elements, transform) {
7182
7498
  const result = [];
7499
+ for (const original of elements) {
7500
+ const element = transform(original);
7501
+ if (!element)
7502
+ continue;
7503
+ result.push(mapSyntaxChildren(element, (children) => mapSyntaxElements(children, transform)));
7504
+ }
7505
+ return result;
7506
+ }
7507
+ function mapSyntaxChildren(element, transform) {
7508
+ if (element.element === "if") {
7509
+ return {
7510
+ ...element,
7511
+ data: {
7512
+ ...element.data,
7513
+ then: transform(element.data.then),
7514
+ else: transform(element.data.else)
7515
+ }
7516
+ };
7517
+ }
7518
+ if (element.element === "ifexpr") {
7519
+ return {
7520
+ ...element,
7521
+ data: {
7522
+ ...element.data,
7523
+ then: transform(element.data.then),
7524
+ else: transform(element.data.else)
7525
+ }
7526
+ };
7527
+ }
7528
+ if (element.element === "bibliography-block") {
7529
+ return {
7530
+ ...element,
7531
+ data: {
7532
+ ...element.data,
7533
+ entries: element.data.entries.map((entry) => ({
7534
+ ...entry,
7535
+ key: transform(entry.key),
7536
+ value: transform(entry.value)
7537
+ }))
7538
+ }
7539
+ };
7540
+ }
7541
+ if (element.element === "list") {
7542
+ return {
7543
+ ...element,
7544
+ data: {
7545
+ ...element.data,
7546
+ items: element.data.items.map((item) => item["item-type"] === "elements" ? { ...item, elements: transform(item.elements) } : mapSubList(item, transform))
7547
+ }
7548
+ };
7549
+ }
7550
+ if (element.element === "table") {
7551
+ return {
7552
+ ...element,
7553
+ data: {
7554
+ ...element.data,
7555
+ rows: element.data.rows.map((row) => ({
7556
+ ...row,
7557
+ cells: row.cells.map((cell) => ({ ...cell, elements: transform(cell.elements) }))
7558
+ }))
7559
+ }
7560
+ };
7561
+ }
7562
+ if (element.element === "definition-list") {
7563
+ return {
7564
+ ...element,
7565
+ data: element.data.map((entry) => ({
7566
+ ...entry,
7567
+ key: transform(entry.key),
7568
+ value: transform(entry.value)
7569
+ }))
7570
+ };
7571
+ }
7572
+ if (element.element === "tab-view") {
7573
+ return {
7574
+ ...element,
7575
+ data: element.data.map((tab) => ({ ...tab, elements: transform(tab.elements) }))
7576
+ };
7577
+ }
7578
+ const children = getGenericElementChildren(element);
7579
+ return children === null ? element : withGenericElementChildren(element, transform(children));
7580
+ }
7581
+ function mapSubList(item, transform) {
7582
+ const transformed = transform([listElement(item.data)])[0];
7583
+ return transformed?.element === "list" ? { ...item, data: transformed.data } : item;
7584
+ }
7585
+ function walkSyntaxOrder(elements, callback) {
7183
7586
  for (const element of elements) {
7184
- if (element.element === "style") {
7185
- styles.push(element.data);
7587
+ callback(element);
7588
+ walkAllSyntaxChildren(element, (children) => walkSyntaxOrder(children, callback));
7589
+ }
7590
+ }
7591
+ function walkRenderOrder(elements, pageTags, callback) {
7592
+ for (const element of elements) {
7593
+ callback(element);
7594
+ if (element.element === "if") {
7595
+ walkRenderOrder(import_ast3.isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
7596
+ continue;
7597
+ }
7598
+ if (element.element === "ifexpr") {
7599
+ const evaluated = import_ast3.evaluateExpression(element.data.expression);
7600
+ if (evaluated.success) {
7601
+ walkRenderOrder(evaluated.value !== 0 ? element.data.then : element.data.else, pageTags, callback);
7602
+ }
7186
7603
  continue;
7187
7604
  }
7188
7605
  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
- });
7606
+ const resolved = resolveIfTags(element.data, pageTags);
7607
+ if (!resolved.evaluated || resolved.matched) {
7608
+ walkRenderOrder(element.data.elements, pageTags, callback);
7609
+ }
7610
+ continue;
7611
+ }
7612
+ if (element.element === "bibliography-block") {
7613
+ if (!element.data.hide) {
7614
+ for (const entry of element.data.entries) {
7615
+ walkRenderOrder(entry.value, pageTags, callback);
7616
+ }
7617
+ }
7196
7618
  continue;
7197
7619
  }
7198
- result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx)));
7620
+ walkBasicChildren(element, (children) => walkRenderOrder(children, pageTags, callback));
7199
7621
  }
7200
- return result;
7622
+ }
7623
+ function walkAllSyntaxChildren(element, callback) {
7624
+ if (element.element === "if" || element.element === "ifexpr") {
7625
+ callback(element.data.then);
7626
+ callback(element.data.else);
7627
+ return;
7628
+ }
7629
+ if (element.element === "bibliography-block") {
7630
+ for (const entry of element.data.entries) {
7631
+ callback(entry.key);
7632
+ callback(entry.value);
7633
+ }
7634
+ return;
7635
+ }
7636
+ walkBasicChildren(element, callback);
7637
+ }
7638
+ function walkBasicChildren(element, callback) {
7639
+ if (element.element === "list") {
7640
+ for (const item of element.data.items) {
7641
+ callback(item["item-type"] === "elements" ? item.elements : [listElement(item.data)]);
7642
+ }
7643
+ return;
7644
+ }
7645
+ if (element.element === "table") {
7646
+ for (const row of element.data.rows) {
7647
+ for (const cell of row.cells)
7648
+ callback(cell.elements);
7649
+ }
7650
+ return;
7651
+ }
7652
+ if (element.element === "definition-list") {
7653
+ for (const entry of element.data) {
7654
+ callback(entry.key);
7655
+ callback(entry.value);
7656
+ }
7657
+ return;
7658
+ }
7659
+ if (element.element === "tab-view") {
7660
+ for (const tab of element.data)
7661
+ callback(tab.elements);
7662
+ return;
7663
+ }
7664
+ const children = getGenericElementChildren(element);
7665
+ if (children !== null)
7666
+ callback(children);
7667
+ }
7668
+ function isTocHeading(element) {
7669
+ return element.element === "container" && typeof element.data.type === "object" && "header" in element.data.type && element.data.type.header["has-toc"];
7201
7670
  }
7202
7671
 
7203
7672
  // packages/parser/src/parser/rules/block/module/resolve.ts
7204
7673
  var MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
7205
7674
  async function resolveModules(ast, dataProvider, options) {
7206
- const parse = createModuleParseFunction(options, dataProvider);
7675
+ const registry = new ModuleDocumentRegistry;
7676
+ registry.register(ast);
7677
+ const parse = createModuleParseFunction(options, dataProvider, registry);
7207
7678
  const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
7208
7679
  const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
7209
7680
  const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
7210
7681
  const pageTags = dataProvider.getPageTags?.() ?? null;
7682
+ const resolvedStyleSlots = new Map;
7683
+ const routedStyleAnchors = new WeakSet;
7211
7684
  const resolvedElements = walkAndResolve(ast.elements, {
7212
7685
  listPages: listPagesCtx,
7213
7686
  listUsers: listUsersCtx,
@@ -7218,24 +7691,30 @@ async function resolveModules(ast, dataProvider, options) {
7218
7691
  pageTags,
7219
7692
  listPagesIdCounter: 0,
7220
7693
  listUsersIdCounter: 0,
7221
- tagCloudIdCounter: 0
7694
+ tagCloudIdCounter: 0,
7695
+ resolvedStyleSlots,
7696
+ routedStyleAnchors
7222
7697
  });
7223
- const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
7698
+ const {
7699
+ elements: finalElements,
7700
+ styles,
7701
+ anchoredStyles
7702
+ } = collectStyles(resolvedElements.elements, routedStyleAnchors);
7224
7703
  const result = {
7225
7704
  ...ast,
7226
7705
  elements: finalElements
7227
7706
  };
7228
- if (styles.length > 0) {
7229
- result.styles = styles;
7230
- }
7231
- return result;
7707
+ const mergedStyles = mergeCollectedStyles(ast.styles, styles, resolvedStyleSlots, anchoredStyles);
7708
+ if (mergedStyles.length > 0)
7709
+ result.styles = mergedStyles;
7710
+ options.onDiagnostics?.(registry.diagnostics);
7711
+ return registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements));
7232
7712
  }
7233
- function createModuleParseFunction(options, dataProvider) {
7713
+ function createModuleParseFunction(options, dataProvider, registry) {
7234
7714
  const transform = createModuleSourceTransform(options, dataProvider);
7235
- if (!transform) {
7236
- return options.parse;
7237
- }
7238
- return (source) => options.parse(transform(source));
7715
+ return (source) => registry.register(options.parse(transform ? transform(source) : source), {
7716
+ stripLegacyImplicitFootnoteBlock: true
7717
+ });
7239
7718
  }
7240
7719
  function createModuleSourceTransform(options, dataProvider) {
7241
7720
  if (options.transformModuleSource) {
@@ -7250,7 +7729,7 @@ function createModuleSourceTransform(options, dataProvider) {
7250
7729
  }
7251
7730
 
7252
7731
  // packages/parser/src/parser/rules/block/module/index.ts
7253
- var import_ast3 = require("@wdprlib/ast");
7732
+ var import_ast4 = require("@wdprlib/ast");
7254
7733
 
7255
7734
  // packages/parser/src/parser/rules/block/footnoteblock/attributes.ts
7256
7735
  function parseFootnoteBlockAttributes(ctx, startPos) {
@@ -12369,7 +12848,8 @@ function createParseContext(tokens, options = {}) {
12369
12848
  pos: 0,
12370
12849
  version: options.version ?? "wikidot",
12371
12850
  trackPositions: options.trackPositions ?? true,
12372
- settings: options.settings ?? import_ast4.DEFAULT_SETTINGS,
12851
+ settings: options.settings ?? import_ast5.DEFAULT_SETTINGS,
12852
+ appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
12373
12853
  footnotes: [],
12374
12854
  tocEntries: [],
12375
12855
  codeBlocks: [],
@@ -12887,67 +13367,6 @@ function suppressAtLevel(elements) {
12887
13367
  function suppressDivAdjacentParagraphs(elements) {
12888
13368
  return suppressAtLevel(elements);
12889
13369
  }
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
13370
  // packages/parser/src/parser/parse/footnotes.ts
12952
13371
  function containsFootnoteBlock(elements) {
12953
13372
  let found = false;
@@ -12961,7 +13380,9 @@ function containsFootnoteBlock(elements) {
12961
13380
  // packages/parser/src/parser/parse/result.ts
12962
13381
  function finalizeParseResult(ctx, children) {
12963
13382
  const cleanedChildren = postprocessChildren(children);
12964
- appendImplicitFootnoteBlock(cleanedChildren);
13383
+ if (ctx.appendImplicitFootnoteBlock) {
13384
+ appendImplicitFootnoteBlock(cleanedChildren);
13385
+ }
12965
13386
  return {
12966
13387
  ast: buildSyntaxTree(ctx, cleanedChildren),
12967
13388
  diagnostics: ctx.diagnostics
@@ -13334,12 +13755,12 @@ function preprocess(text) {
13334
13755
  }
13335
13756
 
13336
13757
  // packages/parser/src/parser/preprocess/expr/evaluate.ts
13337
- var import_ast5 = require("@wdprlib/ast");
13758
+ var import_ast6 = require("@wdprlib/ast");
13338
13759
  function evaluateDirective(kind, match) {
13339
13760
  if (kind === "expr") {
13340
- const result2 = import_ast5.evaluateExpression(match.head);
13761
+ const result2 = import_ast6.evaluateExpression(match.head);
13341
13762
  if (result2.success)
13342
- return import_ast5.formatExprValue(result2.value);
13763
+ return import_ast6.formatExprValue(result2.value);
13343
13764
  if (result2.error === "empty expression")
13344
13765
  return "";
13345
13766
  return "ERROR";
@@ -13347,11 +13768,11 @@ function evaluateDirective(kind, match) {
13347
13768
  if (kind === "if") {
13348
13769
  if (!match.hasPipe)
13349
13770
  return "";
13350
- return import_ast5.isTruthy(match.head) ? match.thenText : match.elseText;
13771
+ return import_ast6.isTruthy(match.head) ? match.thenText : match.elseText;
13351
13772
  }
13352
13773
  if (!match.hasPipe)
13353
13774
  return "";
13354
- const result = import_ast5.evaluateExpression(match.head);
13775
+ const result = import_ast6.evaluateExpression(match.head);
13355
13776
  if (!result.success)
13356
13777
  return "ERROR";
13357
13778
  return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
@@ -13531,3 +13952,249 @@ function parse(source, options) {
13531
13952
  });
13532
13953
  return new Parser(tokens, options).parse();
13533
13954
  }
13955
+ // packages/parser/src/pipeline/process.ts
13956
+ var import_ast7 = require("@wdprlib/ast");
13957
+
13958
+ // packages/parser/src/parser/rules/block/module/resolution/resolve-async.ts
13959
+ async function resolveModulesWithAsyncParse(ast, dataProvider, options) {
13960
+ const registry = new ModuleDocumentRegistry;
13961
+ registry.register(ast);
13962
+ const parse2 = async (source) => registry.register(await options.parse(source));
13963
+ const [listPagesData, listUsersData, tagCloudData] = await Promise.all([
13964
+ buildListPagesDataMap(dataProvider, options.requirements.listPages ?? [], options.urlPath),
13965
+ buildListUsersDataMap(dataProvider, options.requirements.listUsers ?? []),
13966
+ buildTagCloudDataMap(dataProvider, options.requirements.tagCloud ?? [])
13967
+ ]);
13968
+ const context = {
13969
+ dataProvider,
13970
+ listPagesData,
13971
+ listUsersData,
13972
+ tagCloudData,
13973
+ options,
13974
+ parse: parse2
13975
+ };
13976
+ const state = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
13977
+ const resolvedElements = await resolveElements(ast.elements, context, state);
13978
+ const { elements, styles, anchoredStyles } = collectStyles(resolvedElements);
13979
+ const intermediate = { ...ast, elements };
13980
+ const mergedStyles = mergeCollectedStyles(ast.styles, styles, new Map, anchoredStyles);
13981
+ if (mergedStyles.length > 0)
13982
+ intermediate.styles = mergedStyles;
13983
+ else
13984
+ delete intermediate.styles;
13985
+ return {
13986
+ ast: registry.finalize(intermediate, elements, options.pageTags),
13987
+ diagnostics: registry.diagnostics
13988
+ };
13989
+ }
13990
+ async function resolveElements(elements, context, state) {
13991
+ const result = [];
13992
+ for (const element of elements) {
13993
+ if (element.element === "module") {
13994
+ const resolved = await resolveModuleElement(element, context, state);
13995
+ if (resolved !== null) {
13996
+ result.push(...resolved);
13997
+ continue;
13998
+ }
13999
+ }
14000
+ if (element.element === "if-tags") {
14001
+ const resolution = resolveIfTags(element.data, context.options.pageTags);
14002
+ if (resolution.matched) {
14003
+ result.push(...await resolveElements(element.data.elements, context, state));
14004
+ }
14005
+ continue;
14006
+ }
14007
+ result.push(await resolveElementChildren(element, context, state));
14008
+ }
14009
+ return result;
14010
+ }
14011
+ async function resolveModuleElement(element, context, state) {
14012
+ if (isListPagesModule2(element.data)) {
14013
+ const id = state.listPagesId++;
14014
+ const data = context.listPagesData.get(id);
14015
+ const template = context.options.compiledListPagesTemplates.get(id);
14016
+ if (data && template)
14017
+ return resolveListPagesAsync(element.data, data, template, context.parse);
14018
+ return context.dataProvider.fetchListPages ? [] : [element];
14019
+ }
14020
+ if (isListUsersModule2(element.data)) {
14021
+ const id = state.listUsersId++;
14022
+ const data = context.listUsersData.get(id);
14023
+ const template = context.options.compiledListUsersTemplates?.get(id);
14024
+ if (data && template) {
14025
+ const variableContext = { user: data.user };
14026
+ return (await context.parse(template(variableContext))).elements;
14027
+ }
14028
+ return context.dataProvider.fetchListUsers ? [] : [element];
14029
+ }
14030
+ if (isTagCloudModule(element.data)) {
14031
+ const id = state.tagCloudId++;
14032
+ const data = context.tagCloudData.get(id);
14033
+ if (data)
14034
+ return resolveTagCloud(element.data, data);
14035
+ return context.dataProvider.fetchTagCloud ? [] : [element];
14036
+ }
14037
+ return null;
14038
+ }
14039
+ async function resolveListPagesAsync(module2, data, template, parse2) {
14040
+ if (data.pages.length === 0)
14041
+ return [];
14042
+ const result = [];
14043
+ if (module2["prepend-line"] && !module2.separate) {
14044
+ result.push(...(await parse2(module2["prepend-line"])).elements);
14045
+ }
14046
+ for (let i = 0;i < data.pages.length; i++) {
14047
+ const page = data.pages[i];
14048
+ if (!page)
14049
+ continue;
14050
+ const variableContext = {
14051
+ page,
14052
+ index: i + 1,
14053
+ total: data.totalCount,
14054
+ limit: module2.limit,
14055
+ site: data.site
14056
+ };
14057
+ const parsed = await parse2(template(variableContext));
14058
+ if (module2.separate) {
14059
+ result.push({
14060
+ element: "container",
14061
+ data: {
14062
+ type: "div",
14063
+ attributes: { class: "list-pages-item" },
14064
+ elements: parsed.elements
14065
+ }
14066
+ });
14067
+ } else {
14068
+ result.push(...parsed.elements);
14069
+ }
14070
+ }
14071
+ if (module2["append-line"] && !module2.separate) {
14072
+ result.push(...(await parse2(module2["append-line"])).elements);
14073
+ }
14074
+ return module2.wrapper ? [
14075
+ {
14076
+ element: "container",
14077
+ data: {
14078
+ type: "div",
14079
+ attributes: { class: "list-pages-box" },
14080
+ elements: result
14081
+ }
14082
+ }
14083
+ ] : result;
14084
+ }
14085
+ async function resolveElementChildren(element, context, state) {
14086
+ if (element.element === "list") {
14087
+ const items = [];
14088
+ for (const item of element.data.items) {
14089
+ if (item["item-type"] === "elements") {
14090
+ items.push({ ...item, elements: await resolveElements(item.elements, context, state) });
14091
+ } else {
14092
+ const resolved = (await resolveElements([listElement(item.data)], context, state))[0];
14093
+ items.push(resolved?.element === "list" ? { ...item, data: resolved.data } : item);
14094
+ }
14095
+ }
14096
+ return { ...element, data: { ...element.data, items } };
14097
+ }
14098
+ if (element.element === "table") {
14099
+ const rows = [];
14100
+ for (const row of element.data.rows) {
14101
+ const cells = [];
14102
+ for (const cell of row.cells) {
14103
+ cells.push({ ...cell, elements: await resolveElements(cell.elements, context, state) });
14104
+ }
14105
+ rows.push({ ...row, cells });
14106
+ }
14107
+ return { ...element, data: { ...element.data, rows } };
14108
+ }
14109
+ if (element.element === "definition-list") {
14110
+ const entries = [];
14111
+ for (const entry of element.data) {
14112
+ entries.push({
14113
+ ...entry,
14114
+ key: await resolveElements(entry.key, context, state),
14115
+ value: await resolveElements(entry.value, context, state)
14116
+ });
14117
+ }
14118
+ return { ...element, data: entries };
14119
+ }
14120
+ if (element.element === "tab-view") {
14121
+ const tabs = [];
14122
+ for (const tab of element.data) {
14123
+ tabs.push({ ...tab, elements: await resolveElements(tab.elements, context, state) });
14124
+ }
14125
+ return { ...element, data: tabs };
14126
+ }
14127
+ const children = getGenericElementChildren(element);
14128
+ return children === null ? element : withGenericElementChildren(element, await resolveElements(children, context, state));
14129
+ }
14130
+
14131
+ // packages/parser/src/pipeline/process.ts
14132
+ async function processWikitext(source, options) {
14133
+ const settings = options.settings ?? import_ast7.DEFAULT_SETTINGS;
14134
+ const callbackContext = {
14135
+ page: options.page,
14136
+ settings
14137
+ };
14138
+ const dependencies = [];
14139
+ const fetchInclude = createRequestIncludeFetcher(options.dataProvider?.fetchInclude ? (pageRef) => options.dataProvider.fetchInclude(pageRef, callbackContext) : undefined);
14140
+ const resolveSource = async (input) => {
14141
+ if (!fetchInclude)
14142
+ return input;
14143
+ const resolution = await resolveIncludesAsyncWithTrace(input, fetchInclude, {
14144
+ maxIterations: options.includeMaxIterations,
14145
+ settings
14146
+ });
14147
+ dependencies.push(...resolution.dependencies);
14148
+ return resolution.source;
14149
+ };
14150
+ const expandedSource = await resolveSource(source);
14151
+ const initial = parse(expandedSource, {
14152
+ settings,
14153
+ pageTags: options.page.tags,
14154
+ appendImplicitFootnoteBlock: false
14155
+ });
14156
+ const extraction = extractDataRequirements(initial.ast);
14157
+ const dataProvider = createModuleDataProvider(options, callbackContext);
14158
+ const resolved = await resolveModulesWithAsyncParse(initial.ast, dataProvider, {
14159
+ parse: async (fragmentSource) => parse(await resolveSource(fragmentSource), {
14160
+ settings,
14161
+ pageTags: options.page.tags,
14162
+ appendImplicitFootnoteBlock: false
14163
+ }),
14164
+ compiledListPagesTemplates: extraction.compiledListPagesTemplates,
14165
+ compiledListUsersTemplates: extraction.compiledListUsersTemplates,
14166
+ requirements: extraction.requirements,
14167
+ urlPath: options.page.urlPath,
14168
+ pageTags: options.page.tags
14169
+ });
14170
+ return {
14171
+ ast: resolved.ast,
14172
+ page: options.page,
14173
+ settings,
14174
+ diagnostics: [...initial.diagnostics, ...resolved.diagnostics],
14175
+ dependencies
14176
+ };
14177
+ }
14178
+ function createModuleDataProvider(options, context) {
14179
+ const provider = options.dataProvider;
14180
+ return {
14181
+ fetchListPages: provider?.fetchListPages ? (query, requirement) => provider.fetchListPages(query, requirement, context) : undefined,
14182
+ fetchListUsers: provider?.fetchListUsers ? (requirement) => provider.fetchListUsers(requirement, context) : undefined,
14183
+ fetchTagCloud: provider?.fetchTagCloud ? (requirement) => provider.fetchTagCloud(requirement, context) : undefined,
14184
+ getPageTags: () => options.page.tags
14185
+ };
14186
+ }
14187
+ function createRequestIncludeFetcher(fetcher) {
14188
+ if (!fetcher)
14189
+ return;
14190
+ const cache = new Map;
14191
+ return (pageRef) => {
14192
+ const key = `${pageRef.site ?? ""}:${pageRef.page.toLowerCase()}`;
14193
+ const cached = cache.get(key);
14194
+ if (cached)
14195
+ return cached;
14196
+ const result = fetcher(pageRef).catch(() => null);
14197
+ cache.set(key, result);
14198
+ return result;
14199
+ };
14200
+ }