@wdprlib/parser 4.2.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.
Files changed (30) hide show
  1. package/README.md +28 -38
  2. package/dist/index.cjs +973 -134
  3. package/dist/index.d.cts +195 -158
  4. package/dist/index.d.ts +195 -158
  5. package/dist/index.js +955 -113
  6. package/package.json +2 -2
  7. package/src/index.ts +17 -0
  8. package/src/parser/parse/context.ts +1 -0
  9. package/src/parser/parse/options.ts +6 -0
  10. package/src/parser/parse/result.ts +3 -1
  11. package/src/parser/rules/block/gallery/index.ts +215 -0
  12. package/src/parser/rules/block/gallery/items.ts +62 -0
  13. package/src/parser/rules/block/index.ts +3 -0
  14. package/src/parser/rules/block/module/include/index.ts +6 -1
  15. package/src/parser/rules/block/module/include/resolve/index.ts +23 -3
  16. package/src/parser/rules/block/module/include/resolve/iterate.ts +71 -0
  17. package/src/parser/rules/block/module/index.ts +2 -1
  18. package/src/parser/rules/block/module/listpages/resolution/items.ts +2 -2
  19. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +3 -3
  20. package/src/parser/rules/block/module/listusers/resolve.ts +2 -2
  21. package/src/parser/rules/block/module/resolution/document.ts +357 -0
  22. package/src/parser/rules/block/module/resolution/resolve-async.ts +269 -0
  23. package/src/parser/rules/block/module/resolution/styles.ts +134 -12
  24. package/src/parser/rules/block/module/resolution/walk-resolve.ts +19 -1
  25. package/src/parser/rules/block/module/resolve.ts +32 -13
  26. package/src/parser/rules/block/module/types.ts +7 -2
  27. package/src/parser/rules/contracts/parse-context.ts +1 -0
  28. package/src/pipeline/index.ts +7 -0
  29. package/src/pipeline/process.ts +105 -0
  30. package/src/pipeline/types.ts +63 -0
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  listItemElements,
16
16
  listItemSubList
17
17
  } from "@wdprlib/ast";
18
- import { createSettings, DEFAULT_SETTINGS as DEFAULT_SETTINGS2 } from "@wdprlib/ast";
18
+ import { createSettings, DEFAULT_SETTINGS as DEFAULT_SETTINGS3 } from "@wdprlib/ast";
19
19
 
20
20
  // packages/parser/src/lexer/tokens.ts
21
21
  function createToken(type, value, position, lineStart = false) {
@@ -5782,6 +5782,11 @@ function extractDataRequirements(ast) {
5782
5782
  });
5783
5783
  return result;
5784
5784
  }
5785
+ // packages/parser/src/parser/rules/block/module/types.ts
5786
+ function getModuleParseAst(result) {
5787
+ return "ast" in result ? result.ast : result;
5788
+ }
5789
+
5785
5790
  // packages/parser/src/parser/rules/block/module/listpages/resolution/items.ts
5786
5791
  function renderListPagesItems(module, data, compiledTemplate, parse) {
5787
5792
  const items = [];
@@ -5796,7 +5801,7 @@ function renderListPagesItems(module, data, compiledTemplate, parse) {
5796
5801
  limit: module.limit,
5797
5802
  site: data.site
5798
5803
  };
5799
- const itemAst = parse(compiledTemplate(ctx));
5804
+ const itemAst = getModuleParseAst(parse(compiledTemplate(ctx)));
5800
5805
  if (module.separate) {
5801
5806
  items.push({
5802
5807
  element: "container",
@@ -5820,12 +5825,12 @@ function wrapListPagesResult(module, items, parse) {
5820
5825
  }
5821
5826
  const result = [];
5822
5827
  if (module["prepend-line"] && !module.separate) {
5823
- const prependAst = parse(module["prepend-line"]);
5828
+ const prependAst = getModuleParseAst(parse(module["prepend-line"]));
5824
5829
  result.push(...prependAst.elements);
5825
5830
  }
5826
5831
  result.push(...items);
5827
5832
  if (module["append-line"] && !module.separate) {
5828
- const appendAst = parse(module["append-line"]);
5833
+ const appendAst = getModuleParseAst(parse(module["append-line"]));
5829
5834
  result.push(...appendAst.elements);
5830
5835
  }
5831
5836
  if (module.wrapper) {
@@ -6744,16 +6749,31 @@ function expandIterativeWithTrace(source, fetcher, maxIterations) {
6744
6749
  reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
6745
6750
  };
6746
6751
  }
6747
- async function expandIterativeAsync(source, fetcher, maxIterations) {
6752
+ async function expandIterativeAsyncWithTrace(source, fetcher, maxIterations) {
6748
6753
  let current2 = source;
6749
6754
  const replacementCache = new Map;
6755
+ const dependencies = [];
6756
+ const iterations = [];
6750
6757
  for (let i = 0;i < maxIterations; i++) {
6751
- const expanded = await expandOneIterationAsync(current2, fetcher, replacementCache);
6752
- if (expanded === null || expanded === current2)
6758
+ const expanded = await expandOneIterationAsyncWithTrace(current2, fetcher, replacementCache, i);
6759
+ if (expanded === null)
6753
6760
  break;
6754
- current2 = expanded;
6761
+ dependencies.push(...expanded.dependencies);
6762
+ iterations.push({
6763
+ iteration: i,
6764
+ directives: expanded.references,
6765
+ changed: expanded.source !== current2
6766
+ });
6767
+ if (expanded.source === current2)
6768
+ break;
6769
+ current2 = expanded.source;
6755
6770
  }
6756
- return current2;
6771
+ return {
6772
+ source: current2,
6773
+ dependencies,
6774
+ iterations,
6775
+ reachedMaxIterations: iterations.length === maxIterations && scanIncludeDirectives(current2).length > 0
6776
+ };
6757
6777
  }
6758
6778
  function expandOneIteration(source, fetcher, replacementCache) {
6759
6779
  if (!MAYBE_INCLUDE_PATTERN.test(source))
@@ -6791,12 +6811,13 @@ function expandOneIterationWithTrace(source, fetcher, replacementCache, iteratio
6791
6811
  dependencies
6792
6812
  };
6793
6813
  }
6794
- async function expandOneIterationAsync(source, fetcher, replacementCache) {
6814
+ async function expandOneIterationAsyncWithTrace(source, fetcher, replacementCache, iteration) {
6795
6815
  if (!MAYBE_INCLUDE_PATTERN.test(source))
6796
6816
  return null;
6797
6817
  const directives = scanIncludeDirectives(source);
6798
6818
  if (directives.length === 0)
6799
6819
  return null;
6820
+ const references = directives.map(createIncludeReference);
6800
6821
  const replacements = await Promise.all(directives.map(({ inner }) => replaceCachedAsync(inner, fetcher, replacementCache)));
6801
6822
  const parts = [];
6802
6823
  let lastPos = 0;
@@ -6806,7 +6827,11 @@ async function expandOneIterationAsync(source, fetcher, replacementCache) {
6806
6827
  lastPos = end;
6807
6828
  }
6808
6829
  parts.push(source.slice(lastPos));
6809
- return parts.join("");
6830
+ return {
6831
+ source: parts.join(""),
6832
+ references,
6833
+ dependencies: references.map((reference) => ({ ...reference, iteration }))
6834
+ };
6810
6835
  }
6811
6836
  function replaceCached(inner, fetcher, cache) {
6812
6837
  const cached = cache.get(inner);
@@ -6848,12 +6873,20 @@ function resolveIncludesWithTrace(source, fetcher, options) {
6848
6873
  return expandIterativeWithTrace(source, cachedFetcher, maxIterations);
6849
6874
  }
6850
6875
  async function resolveIncludesAsync(source, fetcher, options) {
6876
+ return (await resolveIncludesAsyncWithTrace(source, fetcher, options)).source;
6877
+ }
6878
+ async function resolveIncludesAsyncWithTrace(source, fetcher, options) {
6851
6879
  if (options?.settings && !options.settings.enablePageSyntax) {
6852
- return source;
6880
+ return {
6881
+ source,
6882
+ dependencies: [],
6883
+ iterations: [],
6884
+ reachedMaxIterations: false
6885
+ };
6853
6886
  }
6854
6887
  const maxIterations = options?.maxIterations ?? 10;
6855
6888
  const cachedFetcher = createCachedAsyncIncludeFetcher(fetcher, normalizePageKey);
6856
- return expandIterativeAsync(source, cachedFetcher, maxIterations);
6889
+ return expandIterativeAsyncWithTrace(source, cachedFetcher, maxIterations);
6857
6890
  }
6858
6891
  function normalizePageKey(location) {
6859
6892
  const site = location.site ?? "";
@@ -6867,7 +6900,7 @@ function isListUsersModule2(module) {
6867
6900
  function resolveListUsers(_module, data, compiledTemplate, parse) {
6868
6901
  const ctx = { user: data.user };
6869
6902
  const substituted = compiledTemplate(ctx);
6870
- const itemAst = parse(substituted);
6903
+ const itemAst = getModuleParseAst(parse(substituted));
6871
6904
  return itemAst.elements;
6872
6905
  }
6873
6906
  // packages/parser/src/parser/rules/block/module/resolution/data-maps.ts
@@ -7020,6 +7053,117 @@ function countDynamicModules(elements) {
7020
7053
  return counts;
7021
7054
  }
7022
7055
 
7056
+ // packages/parser/src/parser/rules/block/module/resolution/styles.ts
7057
+ import { STYLE_ANCHOR_PREFIX, STYLE_SLOT_PREFIX } from "@wdprlib/ast";
7058
+ function collectStyles(elements, ignoredAnchors = new WeakSet) {
7059
+ const styles = [];
7060
+ const anchoredStyles = [];
7061
+ const anchors = [];
7062
+ const usedSlots = collectExistingStyleSlots(elements);
7063
+ const ctx = { nextSlotId: 0, usedSlots };
7064
+ const filtered = collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx);
7065
+ return { elements: filtered, styles, anchoredStyles, anchors };
7066
+ }
7067
+ function mergeCollectedStyles(existing, collected, resolvedSlots = new Map, anchoredStyles = []) {
7068
+ const unanchoredPrevious = [...existing ?? []];
7069
+ for (const style of anchoredStyles)
7070
+ removeFirst(unanchoredPrevious, style);
7071
+ for (const style of collected) {
7072
+ if (isStyleSlotMarker(style))
7073
+ removeFirst(unanchoredPrevious, style);
7074
+ }
7075
+ const merged = unanchoredPrevious.filter((style) => !isStyleSlotMarker(style));
7076
+ for (const style of collected) {
7077
+ if (isStyleSlotMarker(style))
7078
+ appendStyleSlot(merged, style, resolvedSlots);
7079
+ else
7080
+ merged.push(style);
7081
+ }
7082
+ return merged;
7083
+ }
7084
+ function isStyleSlotMarker(style) {
7085
+ return style.startsWith(STYLE_SLOT_PREFIX);
7086
+ }
7087
+ function createStyleSlotMarker(slotId) {
7088
+ return `${STYLE_SLOT_PREFIX}${slotId}`;
7089
+ }
7090
+ function getStyleSlotId(data) {
7091
+ const slotId = data._styleSlot;
7092
+ return Number.isSafeInteger(slotId) && slotId >= 0 ? slotId : undefined;
7093
+ }
7094
+ function removeFirst(values, value) {
7095
+ const index = values.indexOf(value);
7096
+ if (index >= 0)
7097
+ values.splice(index, 1);
7098
+ }
7099
+ function appendStyleSlot(target, marker, resolvedSlots) {
7100
+ const slotId = Number(marker.slice(STYLE_SLOT_PREFIX.length));
7101
+ const replacement = resolvedSlots.get(slotId);
7102
+ if (replacement)
7103
+ target.push(...replacement);
7104
+ else
7105
+ target.push(marker);
7106
+ }
7107
+ function collectExistingStyleSlots(elements) {
7108
+ const slots = new Set;
7109
+ walkElements(elements, (element) => {
7110
+ if (element.element !== "if-tags")
7111
+ return;
7112
+ const slotId = getStyleSlotId(element.data);
7113
+ if (slotId !== undefined)
7114
+ slots.add(slotId);
7115
+ });
7116
+ return slots;
7117
+ }
7118
+ function allocateStyleSlot(ctx) {
7119
+ while (ctx.usedSlots.has(ctx.nextSlotId))
7120
+ ctx.nextSlotId++;
7121
+ const slotId = ctx.nextSlotId++;
7122
+ ctx.usedSlots.add(slotId);
7123
+ return slotId;
7124
+ }
7125
+ function collectStylesFromElements(elements, styles, anchoredStyles, anchors, ignoredAnchors, ctx) {
7126
+ const result = [];
7127
+ for (const element of elements) {
7128
+ if (element.element === "style") {
7129
+ const css = element.data;
7130
+ if (css.startsWith(STYLE_SLOT_PREFIX)) {
7131
+ styles.push(css);
7132
+ continue;
7133
+ }
7134
+ if (css.startsWith(STYLE_ANCHOR_PREFIX)) {
7135
+ anchors.push(element);
7136
+ if (ignoredAnchors.has(element)) {
7137
+ result.push(element);
7138
+ continue;
7139
+ }
7140
+ const anchoredCss = css.slice(STYLE_ANCHOR_PREFIX.length);
7141
+ styles.push(anchoredCss);
7142
+ anchoredStyles.push(anchoredCss);
7143
+ result.push(element);
7144
+ continue;
7145
+ }
7146
+ styles.push(css);
7147
+ const anchor = { element: "style", data: `${STYLE_ANCHOR_PREFIX}${css}` };
7148
+ anchors.push(anchor);
7149
+ result.push(anchor);
7150
+ continue;
7151
+ }
7152
+ if (element.element === "if-tags") {
7153
+ const slotId = getStyleSlotId(element.data) ?? allocateStyleSlot(ctx);
7154
+ styles.push(createStyleSlotMarker(slotId));
7155
+ const data = { ...element.data, _styleSlot: slotId };
7156
+ result.push({
7157
+ element: "if-tags",
7158
+ data
7159
+ });
7160
+ continue;
7161
+ }
7162
+ result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, anchoredStyles, anchors, ignoredAnchors, ctx)));
7163
+ }
7164
+ return result;
7165
+ }
7166
+
7023
7167
  // packages/parser/src/parser/rules/block/module/resolution/walk-resolve.ts
7024
7168
  function walkAndResolve(elements, ctx) {
7025
7169
  const result = [];
@@ -7042,6 +7186,7 @@ function walkAndResolve(elements, ctx) {
7042
7186
  if (isIfTagsElement(element)) {
7043
7187
  const ifTagsData = element.data;
7044
7188
  const resolveResult = resolveIfTags(ifTagsData, ctx.pageTags);
7189
+ const styleSlotId = getStyleSlotId(ifTagsData);
7045
7190
  if (resolveResult.evaluated) {
7046
7191
  if (resolveResult.matched) {
7047
7192
  const childResult = walkAndResolve(ifTagsData.elements, {
@@ -7050,11 +7195,23 @@ function walkAndResolve(elements, ctx) {
7050
7195
  listUsersIdCounter: listUsersId,
7051
7196
  tagCloudIdCounter: tagCloudId
7052
7197
  });
7053
- result.push(...childResult.elements);
7198
+ if (styleSlotId === undefined) {
7199
+ result.push(...childResult.elements);
7200
+ } else {
7201
+ const collected = collectStyles(childResult.elements);
7202
+ ctx.resolvedStyleSlots.set(styleSlotId, collected.styles);
7203
+ for (const anchor of collected.anchors)
7204
+ ctx.routedStyleAnchors.add(anchor);
7205
+ result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) }, ...collected.elements);
7206
+ }
7054
7207
  listPagesId = childResult.nextListPagesId;
7055
7208
  listUsersId = childResult.nextListUsersId;
7056
7209
  tagCloudId = childResult.nextTagCloudId;
7057
7210
  } else {
7211
+ if (styleSlotId !== undefined) {
7212
+ ctx.resolvedStyleSlots.set(styleSlotId, []);
7213
+ result.push({ element: "style", data: createStyleSlotMarker(styleSlotId) });
7214
+ }
7058
7215
  const counts = countDynamicModules(ifTagsData.elements);
7059
7216
  listPagesId += counts.listPagesId;
7060
7217
  listUsersId += counts.listUsersId;
@@ -7109,44 +7266,361 @@ function walkAndResolve(elements, ctx) {
7109
7266
  };
7110
7267
  }
7111
7268
 
7112
- // packages/parser/src/parser/rules/block/module/resolution/styles.ts
7113
- import { STYLE_SLOT_PREFIX } from "@wdprlib/ast";
7114
- function collectStyles(elements) {
7115
- const styles = [];
7116
- const ctx = { nextSlotId: 0 };
7117
- const filtered = collectStylesFromElements(elements, styles, ctx);
7118
- return { elements: filtered, styles };
7269
+ // packages/parser/src/parser/rules/block/module/resolution/document.ts
7270
+ import {
7271
+ evaluateExpression,
7272
+ isTruthy
7273
+ } from "@wdprlib/ast";
7274
+
7275
+ // packages/parser/src/parser/toc.ts
7276
+ class TocIndexer {
7277
+ index = 0;
7278
+ next() {
7279
+ return this.index++;
7280
+ }
7281
+ }
7282
+ function buildTocList(indexer, items) {
7283
+ const listItems = items.map((item) => buildTocListItem(indexer, item));
7284
+ return {
7285
+ element: "list",
7286
+ data: {
7287
+ type: "bullet",
7288
+ attributes: {},
7289
+ items: listItems
7290
+ }
7291
+ };
7292
+ }
7293
+ function buildTocListItem(indexer, item) {
7294
+ if (item.kind === "list") {
7295
+ return {
7296
+ "item-type": "sub-list",
7297
+ element: "list",
7298
+ data: {
7299
+ type: "bullet",
7300
+ attributes: {},
7301
+ items: item.children.map((child) => buildTocListItem(indexer, child))
7302
+ }
7303
+ };
7304
+ }
7305
+ const anchor = `#toc${indexer.next()}`;
7306
+ const linkElement = {
7307
+ element: "link",
7308
+ data: {
7309
+ type: "table-of-contents",
7310
+ link: anchor,
7311
+ extra: null,
7312
+ label: { text: item.value },
7313
+ target: null
7314
+ }
7315
+ };
7316
+ return {
7317
+ "item-type": "elements",
7318
+ attributes: {},
7319
+ elements: [linkElement]
7320
+ };
7321
+ }
7322
+ function buildTableOfContents(entries) {
7323
+ if (entries.length === 0) {
7324
+ return [];
7325
+ }
7326
+ const depthItems = entries.map((entry) => ({
7327
+ depth: entry.level - 1,
7328
+ ltype: null,
7329
+ value: entry.text
7330
+ }));
7331
+ const trees = processDepths(null, depthItems);
7332
+ const indexer = new TocIndexer;
7333
+ return trees.map((tree) => buildTocList(indexer, tree.list));
7334
+ }
7335
+
7336
+ // packages/parser/src/parser/rules/block/module/resolution/document.ts
7337
+ class ModuleDocumentRegistry {
7338
+ footnotesByElement = new WeakMap;
7339
+ diagnostics = [];
7340
+ register(result, options = {}) {
7341
+ const parseResult = isParseResult(result) ? result : null;
7342
+ const ast = parseResult ? parseResult.ast : result;
7343
+ const elements = options.stripLegacyImplicitFootnoteBlock ? stripTrailingDefaultFootnoteBlock(ast.elements) : ast.elements;
7344
+ const registeredAst = elements === ast.elements ? ast : { ...ast, elements };
7345
+ if (parseResult) {
7346
+ this.diagnostics.push(...parseResult.diagnostics);
7347
+ }
7348
+ this.registerFootnotes(registeredAst);
7349
+ return registeredAst;
7350
+ }
7351
+ finalize(ast, elements, pageTags, ensureFootnoteBlock = true) {
7352
+ const normalizedElements = normalizeFootnoteBlocks(elements, ensureFootnoteBlock);
7353
+ const footnotes = [];
7354
+ const htmlBlocks = [];
7355
+ const codeBlocks = [];
7356
+ const tocEntries = [];
7357
+ const collectElement = (element) => {
7358
+ if (element.element === "footnote") {
7359
+ const content = this.footnotesByElement.get(element);
7360
+ if (content)
7361
+ footnotes.push(content);
7362
+ } else if (element.element === "html") {
7363
+ htmlBlocks.push(element.data.contents);
7364
+ } else if (element.element === "code") {
7365
+ codeBlocks.push(element.data);
7366
+ } else if (isTocHeading(element)) {
7367
+ tocEntries.push({
7368
+ level: element.data.type.header.level,
7369
+ text: extractHeadingText(element.data.elements)
7370
+ });
7371
+ }
7372
+ };
7373
+ walkRenderOrder(normalizedElements, pageTags, collectElement);
7374
+ const result = { ...ast, elements: normalizedElements };
7375
+ setOptionalArray(result, "footnotes", footnotes);
7376
+ setOptionalArray(result, "html-blocks", htmlBlocks);
7377
+ setOptionalArray(result, "code-blocks", codeBlocks);
7378
+ setOptionalArray(result, "table-of-contents", buildTableOfContents(tocEntries));
7379
+ return result;
7380
+ }
7381
+ registerFootnotes(ast) {
7382
+ const footnoteElements = [];
7383
+ walkSyntaxOrder(ast.elements, (element) => {
7384
+ if (element.element === "footnote")
7385
+ footnoteElements.push(element);
7386
+ });
7387
+ for (let i = 0;i < footnoteElements.length; i++) {
7388
+ const content = ast.footnotes?.[i];
7389
+ if (content)
7390
+ this.footnotesByElement.set(footnoteElements[i], content);
7391
+ }
7392
+ }
7393
+ }
7394
+ function isParseResult(result) {
7395
+ return "ast" in result && "diagnostics" in result;
7396
+ }
7397
+ function setOptionalArray(tree, key, value) {
7398
+ if (value.length > 0) {
7399
+ tree[key] = value;
7400
+ } else {
7401
+ delete tree[key];
7402
+ }
7403
+ }
7404
+ function stripTrailingDefaultFootnoteBlock(elements) {
7405
+ const last = elements.at(-1);
7406
+ if (last?.element !== "footnote-block" || last.data.title !== null || last.data.hide === true) {
7407
+ return elements;
7408
+ }
7409
+ return elements.slice(0, -1);
7410
+ }
7411
+ function normalizeFootnoteBlocks(elements, ensureFootnoteBlock) {
7412
+ const state = { found: false };
7413
+ const normalized = mapSyntaxElements(elements, (element) => {
7414
+ if (element.element !== "footnote-block")
7415
+ return element;
7416
+ if (state.found)
7417
+ return null;
7418
+ state.found = true;
7419
+ return element;
7420
+ });
7421
+ if (!state.found && ensureFootnoteBlock) {
7422
+ normalized.push({
7423
+ element: "footnote-block",
7424
+ data: { title: null, hide: false }
7425
+ });
7426
+ }
7427
+ return normalized;
7119
7428
  }
7120
- function collectStylesFromElements(elements, styles, ctx) {
7429
+ function containsSyntaxFootnoteBlock(elements) {
7430
+ let found = false;
7431
+ walkSyntaxOrder(elements, (element) => {
7432
+ if (element.element === "footnote-block")
7433
+ found = true;
7434
+ });
7435
+ return found;
7436
+ }
7437
+ function mapSyntaxElements(elements, transform) {
7121
7438
  const result = [];
7439
+ for (const original of elements) {
7440
+ const element = transform(original);
7441
+ if (!element)
7442
+ continue;
7443
+ result.push(mapSyntaxChildren(element, (children) => mapSyntaxElements(children, transform)));
7444
+ }
7445
+ return result;
7446
+ }
7447
+ function mapSyntaxChildren(element, transform) {
7448
+ if (element.element === "if") {
7449
+ return {
7450
+ ...element,
7451
+ data: {
7452
+ ...element.data,
7453
+ then: transform(element.data.then),
7454
+ else: transform(element.data.else)
7455
+ }
7456
+ };
7457
+ }
7458
+ if (element.element === "ifexpr") {
7459
+ return {
7460
+ ...element,
7461
+ data: {
7462
+ ...element.data,
7463
+ then: transform(element.data.then),
7464
+ else: transform(element.data.else)
7465
+ }
7466
+ };
7467
+ }
7468
+ if (element.element === "bibliography-block") {
7469
+ return {
7470
+ ...element,
7471
+ data: {
7472
+ ...element.data,
7473
+ entries: element.data.entries.map((entry) => ({
7474
+ ...entry,
7475
+ key: transform(entry.key),
7476
+ value: transform(entry.value)
7477
+ }))
7478
+ }
7479
+ };
7480
+ }
7481
+ if (element.element === "list") {
7482
+ return {
7483
+ ...element,
7484
+ data: {
7485
+ ...element.data,
7486
+ items: element.data.items.map((item) => item["item-type"] === "elements" ? { ...item, elements: transform(item.elements) } : mapSubList(item, transform))
7487
+ }
7488
+ };
7489
+ }
7490
+ if (element.element === "table") {
7491
+ return {
7492
+ ...element,
7493
+ data: {
7494
+ ...element.data,
7495
+ rows: element.data.rows.map((row) => ({
7496
+ ...row,
7497
+ cells: row.cells.map((cell) => ({ ...cell, elements: transform(cell.elements) }))
7498
+ }))
7499
+ }
7500
+ };
7501
+ }
7502
+ if (element.element === "definition-list") {
7503
+ return {
7504
+ ...element,
7505
+ data: element.data.map((entry) => ({
7506
+ ...entry,
7507
+ key: transform(entry.key),
7508
+ value: transform(entry.value)
7509
+ }))
7510
+ };
7511
+ }
7512
+ if (element.element === "tab-view") {
7513
+ return {
7514
+ ...element,
7515
+ data: element.data.map((tab) => ({ ...tab, elements: transform(tab.elements) }))
7516
+ };
7517
+ }
7518
+ const children = getGenericElementChildren(element);
7519
+ return children === null ? element : withGenericElementChildren(element, transform(children));
7520
+ }
7521
+ function mapSubList(item, transform) {
7522
+ const transformed = transform([listElement(item.data)])[0];
7523
+ return transformed?.element === "list" ? { ...item, data: transformed.data } : item;
7524
+ }
7525
+ function walkSyntaxOrder(elements, callback) {
7122
7526
  for (const element of elements) {
7123
- if (element.element === "style") {
7124
- styles.push(element.data);
7527
+ callback(element);
7528
+ walkAllSyntaxChildren(element, (children) => walkSyntaxOrder(children, callback));
7529
+ }
7530
+ }
7531
+ function walkRenderOrder(elements, pageTags, callback) {
7532
+ for (const element of elements) {
7533
+ callback(element);
7534
+ if (element.element === "if") {
7535
+ walkRenderOrder(isTruthy(element.data.condition) ? element.data.then : element.data.else, pageTags, callback);
7536
+ continue;
7537
+ }
7538
+ if (element.element === "ifexpr") {
7539
+ const evaluated = evaluateExpression(element.data.expression);
7540
+ if (evaluated.success) {
7541
+ walkRenderOrder(evaluated.value !== 0 ? element.data.then : element.data.else, pageTags, callback);
7542
+ }
7125
7543
  continue;
7126
7544
  }
7127
7545
  if (element.element === "if-tags") {
7128
- const slotId = ctx.nextSlotId++;
7129
- styles.push(`${STYLE_SLOT_PREFIX}${slotId}`);
7130
- const data = { ...element.data, _styleSlot: slotId };
7131
- result.push({
7132
- element: "if-tags",
7133
- data
7134
- });
7546
+ const resolved = resolveIfTags(element.data, pageTags);
7547
+ if (!resolved.evaluated || resolved.matched) {
7548
+ walkRenderOrder(element.data.elements, pageTags, callback);
7549
+ }
7550
+ continue;
7551
+ }
7552
+ if (element.element === "bibliography-block") {
7553
+ if (!element.data.hide) {
7554
+ for (const entry of element.data.entries) {
7555
+ walkRenderOrder(entry.value, pageTags, callback);
7556
+ }
7557
+ }
7135
7558
  continue;
7136
7559
  }
7137
- result.push(mapElementChildren(element, (children) => collectStylesFromElements(children, styles, ctx)));
7560
+ walkBasicChildren(element, (children) => walkRenderOrder(children, pageTags, callback));
7138
7561
  }
7139
- return result;
7562
+ }
7563
+ function walkAllSyntaxChildren(element, callback) {
7564
+ if (element.element === "if" || element.element === "ifexpr") {
7565
+ callback(element.data.then);
7566
+ callback(element.data.else);
7567
+ return;
7568
+ }
7569
+ if (element.element === "bibliography-block") {
7570
+ for (const entry of element.data.entries) {
7571
+ callback(entry.key);
7572
+ callback(entry.value);
7573
+ }
7574
+ return;
7575
+ }
7576
+ walkBasicChildren(element, callback);
7577
+ }
7578
+ function walkBasicChildren(element, callback) {
7579
+ if (element.element === "list") {
7580
+ for (const item of element.data.items) {
7581
+ callback(item["item-type"] === "elements" ? item.elements : [listElement(item.data)]);
7582
+ }
7583
+ return;
7584
+ }
7585
+ if (element.element === "table") {
7586
+ for (const row of element.data.rows) {
7587
+ for (const cell of row.cells)
7588
+ callback(cell.elements);
7589
+ }
7590
+ return;
7591
+ }
7592
+ if (element.element === "definition-list") {
7593
+ for (const entry of element.data) {
7594
+ callback(entry.key);
7595
+ callback(entry.value);
7596
+ }
7597
+ return;
7598
+ }
7599
+ if (element.element === "tab-view") {
7600
+ for (const tab of element.data)
7601
+ callback(tab.elements);
7602
+ return;
7603
+ }
7604
+ const children = getGenericElementChildren(element);
7605
+ if (children !== null)
7606
+ callback(children);
7607
+ }
7608
+ function isTocHeading(element) {
7609
+ return element.element === "container" && typeof element.data.type === "object" && "header" in element.data.type && element.data.type.header["has-toc"];
7140
7610
  }
7141
7611
 
7142
7612
  // packages/parser/src/parser/rules/block/module/resolve.ts
7143
7613
  var MODULE_SECONDARY_INCLUDE_MAX_ITERATIONS = 5;
7144
7614
  async function resolveModules(ast, dataProvider, options) {
7145
- const parse = createModuleParseFunction(options, dataProvider);
7615
+ const registry = new ModuleDocumentRegistry;
7616
+ registry.register(ast);
7617
+ const parse = createModuleParseFunction(options, dataProvider, registry);
7146
7618
  const listPagesCtx = await buildListPagesContext(dataProvider, options.requirements.listPages ?? [], options.compiledListPagesTemplates, parse, options.urlPath);
7147
7619
  const listUsersCtx = await buildListUsersContext(dataProvider, options.requirements.listUsers ?? [], options.compiledListUsersTemplates, parse);
7148
7620
  const tagCloudCtx = await buildTagCloudContext(dataProvider, options.requirements.tagCloud ?? []);
7149
7621
  const pageTags = dataProvider.getPageTags?.() ?? null;
7622
+ const resolvedStyleSlots = new Map;
7623
+ const routedStyleAnchors = new WeakSet;
7150
7624
  const resolvedElements = walkAndResolve(ast.elements, {
7151
7625
  listPages: listPagesCtx,
7152
7626
  listUsers: listUsersCtx,
@@ -7157,24 +7631,30 @@ async function resolveModules(ast, dataProvider, options) {
7157
7631
  pageTags,
7158
7632
  listPagesIdCounter: 0,
7159
7633
  listUsersIdCounter: 0,
7160
- tagCloudIdCounter: 0
7634
+ tagCloudIdCounter: 0,
7635
+ resolvedStyleSlots,
7636
+ routedStyleAnchors
7161
7637
  });
7162
- const { elements: finalElements, styles } = collectStyles(resolvedElements.elements);
7638
+ const {
7639
+ elements: finalElements,
7640
+ styles,
7641
+ anchoredStyles
7642
+ } = collectStyles(resolvedElements.elements, routedStyleAnchors);
7163
7643
  const result = {
7164
7644
  ...ast,
7165
7645
  elements: finalElements
7166
7646
  };
7167
- if (styles.length > 0) {
7168
- result.styles = styles;
7169
- }
7170
- return result;
7647
+ const mergedStyles = mergeCollectedStyles(ast.styles, styles, resolvedStyleSlots, anchoredStyles);
7648
+ if (mergedStyles.length > 0)
7649
+ result.styles = mergedStyles;
7650
+ options.onDiagnostics?.(registry.diagnostics);
7651
+ return registry.finalize(result, finalElements, pageTags, containsSyntaxFootnoteBlock(ast.elements));
7171
7652
  }
7172
- function createModuleParseFunction(options, dataProvider) {
7653
+ function createModuleParseFunction(options, dataProvider, registry) {
7173
7654
  const transform = createModuleSourceTransform(options, dataProvider);
7174
- if (!transform) {
7175
- return options.parse;
7176
- }
7177
- return (source) => options.parse(transform(source));
7655
+ return (source) => registry.register(options.parse(transform ? transform(source) : source), {
7656
+ stripLegacyImplicitFootnoteBlock: true
7657
+ });
7178
7658
  }
7179
7659
  function createModuleSourceTransform(options, dataProvider) {
7180
7660
  if (options.transformModuleSource) {
@@ -9257,6 +9737,177 @@ var bibliographyRule = {
9257
9737
  }
9258
9738
  };
9259
9739
 
9740
+ // packages/parser/src/parser/rules/block/gallery/items.ts
9741
+ function parseGalleryItemLine(content) {
9742
+ const spacePos = content.indexOf(" ");
9743
+ let source = spacePos < 0 ? content : content.slice(0, spacePos);
9744
+ const attrText = spacePos < 0 ? "" : content.slice(spacePos + 1);
9745
+ let newWindow = false;
9746
+ if (source.startsWith("*")) {
9747
+ source = source.slice(1);
9748
+ newWindow = true;
9749
+ }
9750
+ const attrs = parseItemAttrs(attrText);
9751
+ let link = attrs.get("link") ?? null;
9752
+ if (link !== null && link.startsWith("*")) {
9753
+ newWindow = true;
9754
+ link = link.slice(1);
9755
+ }
9756
+ const alt = attrs.get("alt") ?? null;
9757
+ return { source, link, alt, newWindow };
9758
+ }
9759
+ function parseItemAttrs(text) {
9760
+ const attrs = new Map;
9761
+ const parts = text.trim().split('="');
9762
+ let key = parts[0]?.trim() ?? "";
9763
+ for (let i = 1;i < parts.length; i++) {
9764
+ const val = parts[i] ?? "";
9765
+ const quotePos = val.lastIndexOf('"');
9766
+ if (quotePos < 0) {
9767
+ attrs.set(key, "");
9768
+ key = val.slice(1).trim();
9769
+ } else {
9770
+ attrs.set(key, stripslashes(val.slice(0, quotePos)));
9771
+ key = val.slice(quotePos + 1).trim();
9772
+ }
9773
+ }
9774
+ return attrs;
9775
+ }
9776
+ function stripslashes(value) {
9777
+ return value.replace(/\\(.)/gs, "$1").replace(/\\$/, "");
9778
+ }
9779
+
9780
+ // packages/parser/src/parser/rules/block/gallery/index.ts
9781
+ var GALLERY_SIZES = ["small", "medium", "thumbnail", "square", "original"];
9782
+ function normalizeSize(value) {
9783
+ return value !== undefined && GALLERY_SIZES.includes(value) ? value : "thumbnail";
9784
+ }
9785
+ function normalizeViewer(value) {
9786
+ return value !== "no" && value !== "false";
9787
+ }
9788
+ function normalizeOrder(value) {
9789
+ switch (value) {
9790
+ case "name":
9791
+ case "name desc":
9792
+ case "created_at":
9793
+ case "created_at desc":
9794
+ return value;
9795
+ case "nameDesc":
9796
+ return "name desc";
9797
+ case "dateAdded":
9798
+ return "created_at";
9799
+ case "dateAddedDesc":
9800
+ return "created_at desc";
9801
+ case "name desc desc":
9802
+ return "name";
9803
+ case "created_at desc desc":
9804
+ return "created_at";
9805
+ default:
9806
+ return "name";
9807
+ }
9808
+ }
9809
+ function tryParseGalleryContent(ctx, pos) {
9810
+ const start = pos;
9811
+ if (ctx.tokens[pos]?.type !== "NEWLINE") {
9812
+ return null;
9813
+ }
9814
+ const lines = [];
9815
+ let p = pos + 1;
9816
+ for (;; ) {
9817
+ const colon = ctx.tokens[p];
9818
+ if (colon?.type !== "COLON" || !colon.lineStart) {
9819
+ break;
9820
+ }
9821
+ const space = ctx.tokens[p + 1];
9822
+ if (space?.type !== "WHITESPACE" || !space.value.startsWith(" ")) {
9823
+ break;
9824
+ }
9825
+ let content = "";
9826
+ let q = p + 1;
9827
+ while (q < ctx.tokens.length) {
9828
+ const token5 = ctx.tokens[q];
9829
+ if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
9830
+ break;
9831
+ }
9832
+ content += token5.value;
9833
+ q++;
9834
+ }
9835
+ if (content === " ") {
9836
+ return null;
9837
+ }
9838
+ if (ctx.tokens[q]?.type !== "NEWLINE") {
9839
+ return null;
9840
+ }
9841
+ lines.push(content.trim());
9842
+ p = q + 1;
9843
+ }
9844
+ if (lines.length === 0) {
9845
+ return null;
9846
+ }
9847
+ if (ctx.tokens[p]?.type !== "BLOCK_END_OPEN") {
9848
+ return null;
9849
+ }
9850
+ const nameResult = parseBlockName(ctx, p + 1);
9851
+ if (!nameResult || nameResult.name !== "gallery") {
9852
+ return null;
9853
+ }
9854
+ const closePos = p + 1 + nameResult.consumed;
9855
+ if (ctx.tokens[closePos]?.type !== "BLOCK_CLOSE") {
9856
+ return null;
9857
+ }
9858
+ return { lines, consumed: closePos + 1 - start };
9859
+ }
9860
+ var galleryRule = {
9861
+ name: "gallery",
9862
+ startTokens: ["BLOCK_OPEN"],
9863
+ requiresLineStart: true,
9864
+ parse(ctx) {
9865
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
9866
+ return { success: false };
9867
+ }
9868
+ let pos = ctx.pos + 1;
9869
+ const nameResult = parseBlockName(ctx, pos);
9870
+ if (!nameResult || nameResult.name !== "gallery") {
9871
+ return { success: false };
9872
+ }
9873
+ pos += nameResult.consumed;
9874
+ const attrResult = parseAttributesRaw(ctx, pos);
9875
+ pos += attrResult.consumed;
9876
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
9877
+ return { success: false };
9878
+ }
9879
+ pos++;
9880
+ const size = normalizeSize(attrResult.attrs.size);
9881
+ const viewer = normalizeViewer(attrResult.attrs.viewer);
9882
+ const order = normalizeOrder(attrResult.attrs.order);
9883
+ const openConsumed = pos - ctx.pos;
9884
+ const content = tryParseGalleryContent(ctx, pos);
9885
+ if (!content) {
9886
+ return {
9887
+ success: true,
9888
+ elements: [
9889
+ {
9890
+ element: "gallery",
9891
+ data: { size, order, viewer, content: { type: "auto", files: null } }
9892
+ }
9893
+ ],
9894
+ consumed: openConsumed
9895
+ };
9896
+ }
9897
+ const items = content.lines.map(parseGalleryItemLine);
9898
+ return {
9899
+ success: true,
9900
+ elements: [
9901
+ {
9902
+ element: "gallery",
9903
+ data: { size, order, viewer, content: { type: "items", items } }
9904
+ }
9905
+ ],
9906
+ consumed: openConsumed + content.consumed
9907
+ };
9908
+ }
9909
+ };
9910
+
9260
9911
  // packages/parser/src/parser/rules/block/index.ts
9261
9912
  var blockRules = [
9262
9913
  blockCommentRule,
@@ -9286,6 +9937,7 @@ var blockRules = [
9286
9937
  iframeRule,
9287
9938
  iftagsRule,
9288
9939
  bibliographyRule,
9940
+ galleryRule,
9289
9941
  divRule
9290
9942
  ];
9291
9943
  // packages/parser/src/parser/rules/inline/formatting/container.ts
@@ -12137,6 +12789,7 @@ function createParseContext(tokens, options = {}) {
12137
12789
  version: options.version ?? "wikidot",
12138
12790
  trackPositions: options.trackPositions ?? true,
12139
12791
  settings: options.settings ?? DEFAULT_SETTINGS,
12792
+ appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
12140
12793
  footnotes: [],
12141
12794
  tocEntries: [],
12142
12795
  codeBlocks: [],
@@ -12654,67 +13307,6 @@ function suppressAtLevel(elements) {
12654
13307
  function suppressDivAdjacentParagraphs(elements) {
12655
13308
  return suppressAtLevel(elements);
12656
13309
  }
12657
- // packages/parser/src/parser/toc.ts
12658
- class TocIndexer {
12659
- index = 0;
12660
- next() {
12661
- return this.index++;
12662
- }
12663
- }
12664
- function buildTocList(indexer, items) {
12665
- const listItems = items.map((item) => buildTocListItem(indexer, item));
12666
- return {
12667
- element: "list",
12668
- data: {
12669
- type: "bullet",
12670
- attributes: {},
12671
- items: listItems
12672
- }
12673
- };
12674
- }
12675
- function buildTocListItem(indexer, item) {
12676
- if (item.kind === "list") {
12677
- return {
12678
- "item-type": "sub-list",
12679
- element: "list",
12680
- data: {
12681
- type: "bullet",
12682
- attributes: {},
12683
- items: item.children.map((child) => buildTocListItem(indexer, child))
12684
- }
12685
- };
12686
- }
12687
- const anchor = `#toc${indexer.next()}`;
12688
- const linkElement = {
12689
- element: "link",
12690
- data: {
12691
- type: "table-of-contents",
12692
- link: anchor,
12693
- extra: null,
12694
- label: { text: item.value },
12695
- target: null
12696
- }
12697
- };
12698
- return {
12699
- "item-type": "elements",
12700
- attributes: {},
12701
- elements: [linkElement]
12702
- };
12703
- }
12704
- function buildTableOfContents(entries) {
12705
- if (entries.length === 0) {
12706
- return [];
12707
- }
12708
- const depthItems = entries.map((entry) => ({
12709
- depth: entry.level - 1,
12710
- ltype: null,
12711
- value: entry.text
12712
- }));
12713
- const trees = processDepths(null, depthItems);
12714
- const indexer = new TocIndexer;
12715
- return trees.map((tree) => buildTocList(indexer, tree.list));
12716
- }
12717
-
12718
13310
  // packages/parser/src/parser/parse/footnotes.ts
12719
13311
  function containsFootnoteBlock(elements) {
12720
13312
  let found = false;
@@ -12728,7 +13320,9 @@ function containsFootnoteBlock(elements) {
12728
13320
  // packages/parser/src/parser/parse/result.ts
12729
13321
  function finalizeParseResult(ctx, children) {
12730
13322
  const cleanedChildren = postprocessChildren(children);
12731
- appendImplicitFootnoteBlock(cleanedChildren);
13323
+ if (ctx.appendImplicitFootnoteBlock) {
13324
+ appendImplicitFootnoteBlock(cleanedChildren);
13325
+ }
12732
13326
  return {
12733
13327
  ast: buildSyntaxTree(ctx, cleanedChildren),
12734
13328
  diagnostics: ctx.diagnostics
@@ -13101,10 +13695,10 @@ function preprocess(text) {
13101
13695
  }
13102
13696
 
13103
13697
  // packages/parser/src/parser/preprocess/expr/evaluate.ts
13104
- import { evaluateExpression, formatExprValue, isTruthy } from "@wdprlib/ast";
13698
+ import { evaluateExpression as evaluateExpression2, formatExprValue, isTruthy as isTruthy2 } from "@wdprlib/ast";
13105
13699
  function evaluateDirective(kind, match) {
13106
13700
  if (kind === "expr") {
13107
- const result2 = evaluateExpression(match.head);
13701
+ const result2 = evaluateExpression2(match.head);
13108
13702
  if (result2.success)
13109
13703
  return formatExprValue(result2.value);
13110
13704
  if (result2.error === "empty expression")
@@ -13114,11 +13708,11 @@ function evaluateDirective(kind, match) {
13114
13708
  if (kind === "if") {
13115
13709
  if (!match.hasPipe)
13116
13710
  return "";
13117
- return isTruthy(match.head) ? match.thenText : match.elseText;
13711
+ return isTruthy2(match.head) ? match.thenText : match.elseText;
13118
13712
  }
13119
13713
  if (!match.hasPipe)
13120
13714
  return "";
13121
- const result = evaluateExpression(match.head);
13715
+ const result = evaluateExpression2(match.head);
13122
13716
  if (!result.success)
13123
13717
  return "ERROR";
13124
13718
  return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
@@ -13298,6 +13892,252 @@ function parse(source, options) {
13298
13892
  });
13299
13893
  return new Parser(tokens, options).parse();
13300
13894
  }
13895
+ // packages/parser/src/pipeline/process.ts
13896
+ import { DEFAULT_SETTINGS as DEFAULT_SETTINGS2 } from "@wdprlib/ast";
13897
+
13898
+ // packages/parser/src/parser/rules/block/module/resolution/resolve-async.ts
13899
+ async function resolveModulesWithAsyncParse(ast, dataProvider, options) {
13900
+ const registry = new ModuleDocumentRegistry;
13901
+ registry.register(ast);
13902
+ const parse2 = async (source) => registry.register(await options.parse(source));
13903
+ const [listPagesData, listUsersData, tagCloudData] = await Promise.all([
13904
+ buildListPagesDataMap(dataProvider, options.requirements.listPages ?? [], options.urlPath),
13905
+ buildListUsersDataMap(dataProvider, options.requirements.listUsers ?? []),
13906
+ buildTagCloudDataMap(dataProvider, options.requirements.tagCloud ?? [])
13907
+ ]);
13908
+ const context = {
13909
+ dataProvider,
13910
+ listPagesData,
13911
+ listUsersData,
13912
+ tagCloudData,
13913
+ options,
13914
+ parse: parse2
13915
+ };
13916
+ const state = { listPagesId: 0, listUsersId: 0, tagCloudId: 0 };
13917
+ const resolvedElements = await resolveElements(ast.elements, context, state);
13918
+ const { elements, styles, anchoredStyles } = collectStyles(resolvedElements);
13919
+ const intermediate = { ...ast, elements };
13920
+ const mergedStyles = mergeCollectedStyles(ast.styles, styles, new Map, anchoredStyles);
13921
+ if (mergedStyles.length > 0)
13922
+ intermediate.styles = mergedStyles;
13923
+ else
13924
+ delete intermediate.styles;
13925
+ return {
13926
+ ast: registry.finalize(intermediate, elements, options.pageTags),
13927
+ diagnostics: registry.diagnostics
13928
+ };
13929
+ }
13930
+ async function resolveElements(elements, context, state) {
13931
+ const result = [];
13932
+ for (const element of elements) {
13933
+ if (element.element === "module") {
13934
+ const resolved = await resolveModuleElement(element, context, state);
13935
+ if (resolved !== null) {
13936
+ result.push(...resolved);
13937
+ continue;
13938
+ }
13939
+ }
13940
+ if (element.element === "if-tags") {
13941
+ const resolution = resolveIfTags(element.data, context.options.pageTags);
13942
+ if (resolution.matched) {
13943
+ result.push(...await resolveElements(element.data.elements, context, state));
13944
+ }
13945
+ continue;
13946
+ }
13947
+ result.push(await resolveElementChildren(element, context, state));
13948
+ }
13949
+ return result;
13950
+ }
13951
+ async function resolveModuleElement(element, context, state) {
13952
+ if (isListPagesModule2(element.data)) {
13953
+ const id = state.listPagesId++;
13954
+ const data = context.listPagesData.get(id);
13955
+ const template = context.options.compiledListPagesTemplates.get(id);
13956
+ if (data && template)
13957
+ return resolveListPagesAsync(element.data, data, template, context.parse);
13958
+ return context.dataProvider.fetchListPages ? [] : [element];
13959
+ }
13960
+ if (isListUsersModule2(element.data)) {
13961
+ const id = state.listUsersId++;
13962
+ const data = context.listUsersData.get(id);
13963
+ const template = context.options.compiledListUsersTemplates?.get(id);
13964
+ if (data && template) {
13965
+ const variableContext = { user: data.user };
13966
+ return (await context.parse(template(variableContext))).elements;
13967
+ }
13968
+ return context.dataProvider.fetchListUsers ? [] : [element];
13969
+ }
13970
+ if (isTagCloudModule(element.data)) {
13971
+ const id = state.tagCloudId++;
13972
+ const data = context.tagCloudData.get(id);
13973
+ if (data)
13974
+ return resolveTagCloud(element.data, data);
13975
+ return context.dataProvider.fetchTagCloud ? [] : [element];
13976
+ }
13977
+ return null;
13978
+ }
13979
+ async function resolveListPagesAsync(module, data, template, parse2) {
13980
+ if (data.pages.length === 0)
13981
+ return [];
13982
+ const result = [];
13983
+ if (module["prepend-line"] && !module.separate) {
13984
+ result.push(...(await parse2(module["prepend-line"])).elements);
13985
+ }
13986
+ for (let i = 0;i < data.pages.length; i++) {
13987
+ const page = data.pages[i];
13988
+ if (!page)
13989
+ continue;
13990
+ const variableContext = {
13991
+ page,
13992
+ index: i + 1,
13993
+ total: data.totalCount,
13994
+ limit: module.limit,
13995
+ site: data.site
13996
+ };
13997
+ const parsed = await parse2(template(variableContext));
13998
+ if (module.separate) {
13999
+ result.push({
14000
+ element: "container",
14001
+ data: {
14002
+ type: "div",
14003
+ attributes: { class: "list-pages-item" },
14004
+ elements: parsed.elements
14005
+ }
14006
+ });
14007
+ } else {
14008
+ result.push(...parsed.elements);
14009
+ }
14010
+ }
14011
+ if (module["append-line"] && !module.separate) {
14012
+ result.push(...(await parse2(module["append-line"])).elements);
14013
+ }
14014
+ return module.wrapper ? [
14015
+ {
14016
+ element: "container",
14017
+ data: {
14018
+ type: "div",
14019
+ attributes: { class: "list-pages-box" },
14020
+ elements: result
14021
+ }
14022
+ }
14023
+ ] : result;
14024
+ }
14025
+ async function resolveElementChildren(element, context, state) {
14026
+ if (element.element === "list") {
14027
+ const items = [];
14028
+ for (const item of element.data.items) {
14029
+ if (item["item-type"] === "elements") {
14030
+ items.push({ ...item, elements: await resolveElements(item.elements, context, state) });
14031
+ } else {
14032
+ const resolved = (await resolveElements([listElement(item.data)], context, state))[0];
14033
+ items.push(resolved?.element === "list" ? { ...item, data: resolved.data } : item);
14034
+ }
14035
+ }
14036
+ return { ...element, data: { ...element.data, items } };
14037
+ }
14038
+ if (element.element === "table") {
14039
+ const rows = [];
14040
+ for (const row of element.data.rows) {
14041
+ const cells = [];
14042
+ for (const cell of row.cells) {
14043
+ cells.push({ ...cell, elements: await resolveElements(cell.elements, context, state) });
14044
+ }
14045
+ rows.push({ ...row, cells });
14046
+ }
14047
+ return { ...element, data: { ...element.data, rows } };
14048
+ }
14049
+ if (element.element === "definition-list") {
14050
+ const entries = [];
14051
+ for (const entry of element.data) {
14052
+ entries.push({
14053
+ ...entry,
14054
+ key: await resolveElements(entry.key, context, state),
14055
+ value: await resolveElements(entry.value, context, state)
14056
+ });
14057
+ }
14058
+ return { ...element, data: entries };
14059
+ }
14060
+ if (element.element === "tab-view") {
14061
+ const tabs = [];
14062
+ for (const tab of element.data) {
14063
+ tabs.push({ ...tab, elements: await resolveElements(tab.elements, context, state) });
14064
+ }
14065
+ return { ...element, data: tabs };
14066
+ }
14067
+ const children = getGenericElementChildren(element);
14068
+ return children === null ? element : withGenericElementChildren(element, await resolveElements(children, context, state));
14069
+ }
14070
+
14071
+ // packages/parser/src/pipeline/process.ts
14072
+ async function processWikitext(source, options) {
14073
+ const settings = options.settings ?? DEFAULT_SETTINGS2;
14074
+ const callbackContext = {
14075
+ page: options.page,
14076
+ settings
14077
+ };
14078
+ const dependencies = [];
14079
+ const fetchInclude = createRequestIncludeFetcher(options.dataProvider?.fetchInclude ? (pageRef) => options.dataProvider.fetchInclude(pageRef, callbackContext) : undefined);
14080
+ const resolveSource = async (input) => {
14081
+ if (!fetchInclude)
14082
+ return input;
14083
+ const resolution = await resolveIncludesAsyncWithTrace(input, fetchInclude, {
14084
+ maxIterations: options.includeMaxIterations,
14085
+ settings
14086
+ });
14087
+ dependencies.push(...resolution.dependencies);
14088
+ return resolution.source;
14089
+ };
14090
+ const expandedSource = await resolveSource(source);
14091
+ const initial = parse(expandedSource, {
14092
+ settings,
14093
+ pageTags: options.page.tags,
14094
+ appendImplicitFootnoteBlock: false
14095
+ });
14096
+ const extraction = extractDataRequirements(initial.ast);
14097
+ const dataProvider = createModuleDataProvider(options, callbackContext);
14098
+ const resolved = await resolveModulesWithAsyncParse(initial.ast, dataProvider, {
14099
+ parse: async (fragmentSource) => parse(await resolveSource(fragmentSource), {
14100
+ settings,
14101
+ pageTags: options.page.tags,
14102
+ appendImplicitFootnoteBlock: false
14103
+ }),
14104
+ compiledListPagesTemplates: extraction.compiledListPagesTemplates,
14105
+ compiledListUsersTemplates: extraction.compiledListUsersTemplates,
14106
+ requirements: extraction.requirements,
14107
+ urlPath: options.page.urlPath,
14108
+ pageTags: options.page.tags
14109
+ });
14110
+ return {
14111
+ ast: resolved.ast,
14112
+ page: options.page,
14113
+ settings,
14114
+ diagnostics: [...initial.diagnostics, ...resolved.diagnostics],
14115
+ dependencies
14116
+ };
14117
+ }
14118
+ function createModuleDataProvider(options, context) {
14119
+ const provider = options.dataProvider;
14120
+ return {
14121
+ fetchListPages: provider?.fetchListPages ? (query, requirement) => provider.fetchListPages(query, requirement, context) : undefined,
14122
+ fetchListUsers: provider?.fetchListUsers ? (requirement) => provider.fetchListUsers(requirement, context) : undefined,
14123
+ fetchTagCloud: provider?.fetchTagCloud ? (requirement) => provider.fetchTagCloud(requirement, context) : undefined,
14124
+ getPageTags: () => options.page.tags
14125
+ };
14126
+ }
14127
+ function createRequestIncludeFetcher(fetcher) {
14128
+ if (!fetcher)
14129
+ return;
14130
+ const cache = new Map;
14131
+ return (pageRef) => {
14132
+ const key = `${pageRef.site ?? ""}:${pageRef.page.toLowerCase()}`;
14133
+ const cached = cache.get(key);
14134
+ if (cached)
14135
+ return cached;
14136
+ const result = fetcher(pageRef).catch(() => null);
14137
+ cache.set(key, result);
14138
+ return result;
14139
+ };
14140
+ }
13301
14141
  export {
13302
14142
  tokenize,
13303
14143
  text,
@@ -13305,8 +14145,10 @@ export {
13305
14145
  resolveModules,
13306
14146
  resolveListUsers,
13307
14147
  resolveIncludesWithTrace,
14148
+ resolveIncludesAsyncWithTrace,
13308
14149
  resolveIncludesAsync,
13309
14150
  resolveIncludes,
14151
+ processWikitext,
13310
14152
  preprocessIftags,
13311
14153
  parseTags,
13312
14154
  parseParent,
@@ -13341,5 +14183,5 @@ export {
13341
14183
  STYLE_SLOT_PREFIX2 as STYLE_SLOT_PREFIX,
13342
14184
  Parser,
13343
14185
  Lexer,
13344
- DEFAULT_SETTINGS2 as DEFAULT_SETTINGS
14186
+ DEFAULT_SETTINGS3 as DEFAULT_SETTINGS
13345
14187
  };