@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.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) {
@@ -9318,6 +9797,177 @@ var bibliographyRule = {
9318
9797
  }
9319
9798
  };
9320
9799
 
9800
+ // packages/parser/src/parser/rules/block/gallery/items.ts
9801
+ function parseGalleryItemLine(content) {
9802
+ const spacePos = content.indexOf(" ");
9803
+ let source = spacePos < 0 ? content : content.slice(0, spacePos);
9804
+ const attrText = spacePos < 0 ? "" : content.slice(spacePos + 1);
9805
+ let newWindow = false;
9806
+ if (source.startsWith("*")) {
9807
+ source = source.slice(1);
9808
+ newWindow = true;
9809
+ }
9810
+ const attrs = parseItemAttrs(attrText);
9811
+ let link = attrs.get("link") ?? null;
9812
+ if (link !== null && link.startsWith("*")) {
9813
+ newWindow = true;
9814
+ link = link.slice(1);
9815
+ }
9816
+ const alt = attrs.get("alt") ?? null;
9817
+ return { source, link, alt, newWindow };
9818
+ }
9819
+ function parseItemAttrs(text) {
9820
+ const attrs = new Map;
9821
+ const parts = text.trim().split('="');
9822
+ let key = parts[0]?.trim() ?? "";
9823
+ for (let i = 1;i < parts.length; i++) {
9824
+ const val = parts[i] ?? "";
9825
+ const quotePos = val.lastIndexOf('"');
9826
+ if (quotePos < 0) {
9827
+ attrs.set(key, "");
9828
+ key = val.slice(1).trim();
9829
+ } else {
9830
+ attrs.set(key, stripslashes(val.slice(0, quotePos)));
9831
+ key = val.slice(quotePos + 1).trim();
9832
+ }
9833
+ }
9834
+ return attrs;
9835
+ }
9836
+ function stripslashes(value) {
9837
+ return value.replace(/\\(.)/gs, "$1").replace(/\\$/, "");
9838
+ }
9839
+
9840
+ // packages/parser/src/parser/rules/block/gallery/index.ts
9841
+ var GALLERY_SIZES = ["small", "medium", "thumbnail", "square", "original"];
9842
+ function normalizeSize(value) {
9843
+ return value !== undefined && GALLERY_SIZES.includes(value) ? value : "thumbnail";
9844
+ }
9845
+ function normalizeViewer(value) {
9846
+ return value !== "no" && value !== "false";
9847
+ }
9848
+ function normalizeOrder(value) {
9849
+ switch (value) {
9850
+ case "name":
9851
+ case "name desc":
9852
+ case "created_at":
9853
+ case "created_at desc":
9854
+ return value;
9855
+ case "nameDesc":
9856
+ return "name desc";
9857
+ case "dateAdded":
9858
+ return "created_at";
9859
+ case "dateAddedDesc":
9860
+ return "created_at desc";
9861
+ case "name desc desc":
9862
+ return "name";
9863
+ case "created_at desc desc":
9864
+ return "created_at";
9865
+ default:
9866
+ return "name";
9867
+ }
9868
+ }
9869
+ function tryParseGalleryContent(ctx, pos) {
9870
+ const start = pos;
9871
+ if (ctx.tokens[pos]?.type !== "NEWLINE") {
9872
+ return null;
9873
+ }
9874
+ const lines = [];
9875
+ let p = pos + 1;
9876
+ for (;; ) {
9877
+ const colon = ctx.tokens[p];
9878
+ if (colon?.type !== "COLON" || !colon.lineStart) {
9879
+ break;
9880
+ }
9881
+ const space = ctx.tokens[p + 1];
9882
+ if (space?.type !== "WHITESPACE" || !space.value.startsWith(" ")) {
9883
+ break;
9884
+ }
9885
+ let content = "";
9886
+ let q = p + 1;
9887
+ while (q < ctx.tokens.length) {
9888
+ const token5 = ctx.tokens[q];
9889
+ if (!token5 || token5.type === "NEWLINE" || token5.type === "EOF") {
9890
+ break;
9891
+ }
9892
+ content += token5.value;
9893
+ q++;
9894
+ }
9895
+ if (content === " ") {
9896
+ return null;
9897
+ }
9898
+ if (ctx.tokens[q]?.type !== "NEWLINE") {
9899
+ return null;
9900
+ }
9901
+ lines.push(content.trim());
9902
+ p = q + 1;
9903
+ }
9904
+ if (lines.length === 0) {
9905
+ return null;
9906
+ }
9907
+ if (ctx.tokens[p]?.type !== "BLOCK_END_OPEN") {
9908
+ return null;
9909
+ }
9910
+ const nameResult = parseBlockName(ctx, p + 1);
9911
+ if (!nameResult || nameResult.name !== "gallery") {
9912
+ return null;
9913
+ }
9914
+ const closePos = p + 1 + nameResult.consumed;
9915
+ if (ctx.tokens[closePos]?.type !== "BLOCK_CLOSE") {
9916
+ return null;
9917
+ }
9918
+ return { lines, consumed: closePos + 1 - start };
9919
+ }
9920
+ var galleryRule = {
9921
+ name: "gallery",
9922
+ startTokens: ["BLOCK_OPEN"],
9923
+ requiresLineStart: true,
9924
+ parse(ctx) {
9925
+ if (ctx.tokens[ctx.pos]?.type !== "BLOCK_OPEN") {
9926
+ return { success: false };
9927
+ }
9928
+ let pos = ctx.pos + 1;
9929
+ const nameResult = parseBlockName(ctx, pos);
9930
+ if (!nameResult || nameResult.name !== "gallery") {
9931
+ return { success: false };
9932
+ }
9933
+ pos += nameResult.consumed;
9934
+ const attrResult = parseAttributesRaw(ctx, pos);
9935
+ pos += attrResult.consumed;
9936
+ if (ctx.tokens[pos]?.type !== "BLOCK_CLOSE") {
9937
+ return { success: false };
9938
+ }
9939
+ pos++;
9940
+ const size = normalizeSize(attrResult.attrs.size);
9941
+ const viewer = normalizeViewer(attrResult.attrs.viewer);
9942
+ const order = normalizeOrder(attrResult.attrs.order);
9943
+ const openConsumed = pos - ctx.pos;
9944
+ const content = tryParseGalleryContent(ctx, pos);
9945
+ if (!content) {
9946
+ return {
9947
+ success: true,
9948
+ elements: [
9949
+ {
9950
+ element: "gallery",
9951
+ data: { size, order, viewer, content: { type: "auto", files: null } }
9952
+ }
9953
+ ],
9954
+ consumed: openConsumed
9955
+ };
9956
+ }
9957
+ const items = content.lines.map(parseGalleryItemLine);
9958
+ return {
9959
+ success: true,
9960
+ elements: [
9961
+ {
9962
+ element: "gallery",
9963
+ data: { size, order, viewer, content: { type: "items", items } }
9964
+ }
9965
+ ],
9966
+ consumed: openConsumed + content.consumed
9967
+ };
9968
+ }
9969
+ };
9970
+
9321
9971
  // packages/parser/src/parser/rules/block/index.ts
9322
9972
  var blockRules = [
9323
9973
  blockCommentRule,
@@ -9347,6 +9997,7 @@ var blockRules = [
9347
9997
  iframeRule,
9348
9998
  iftagsRule,
9349
9999
  bibliographyRule,
10000
+ galleryRule,
9350
10001
  divRule
9351
10002
  ];
9352
10003
  // packages/parser/src/parser/rules/inline/formatting/container.ts
@@ -12197,7 +12848,8 @@ function createParseContext(tokens, options = {}) {
12197
12848
  pos: 0,
12198
12849
  version: options.version ?? "wikidot",
12199
12850
  trackPositions: options.trackPositions ?? true,
12200
- settings: options.settings ?? import_ast4.DEFAULT_SETTINGS,
12851
+ settings: options.settings ?? import_ast5.DEFAULT_SETTINGS,
12852
+ appendImplicitFootnoteBlock: options.appendImplicitFootnoteBlock ?? true,
12201
12853
  footnotes: [],
12202
12854
  tocEntries: [],
12203
12855
  codeBlocks: [],
@@ -12715,67 +13367,6 @@ function suppressAtLevel(elements) {
12715
13367
  function suppressDivAdjacentParagraphs(elements) {
12716
13368
  return suppressAtLevel(elements);
12717
13369
  }
12718
- // packages/parser/src/parser/toc.ts
12719
- class TocIndexer {
12720
- index = 0;
12721
- next() {
12722
- return this.index++;
12723
- }
12724
- }
12725
- function buildTocList(indexer, items) {
12726
- const listItems = items.map((item) => buildTocListItem(indexer, item));
12727
- return {
12728
- element: "list",
12729
- data: {
12730
- type: "bullet",
12731
- attributes: {},
12732
- items: listItems
12733
- }
12734
- };
12735
- }
12736
- function buildTocListItem(indexer, item) {
12737
- if (item.kind === "list") {
12738
- return {
12739
- "item-type": "sub-list",
12740
- element: "list",
12741
- data: {
12742
- type: "bullet",
12743
- attributes: {},
12744
- items: item.children.map((child) => buildTocListItem(indexer, child))
12745
- }
12746
- };
12747
- }
12748
- const anchor = `#toc${indexer.next()}`;
12749
- const linkElement = {
12750
- element: "link",
12751
- data: {
12752
- type: "table-of-contents",
12753
- link: anchor,
12754
- extra: null,
12755
- label: { text: item.value },
12756
- target: null
12757
- }
12758
- };
12759
- return {
12760
- "item-type": "elements",
12761
- attributes: {},
12762
- elements: [linkElement]
12763
- };
12764
- }
12765
- function buildTableOfContents(entries) {
12766
- if (entries.length === 0) {
12767
- return [];
12768
- }
12769
- const depthItems = entries.map((entry) => ({
12770
- depth: entry.level - 1,
12771
- ltype: null,
12772
- value: entry.text
12773
- }));
12774
- const trees = processDepths(null, depthItems);
12775
- const indexer = new TocIndexer;
12776
- return trees.map((tree) => buildTocList(indexer, tree.list));
12777
- }
12778
-
12779
13370
  // packages/parser/src/parser/parse/footnotes.ts
12780
13371
  function containsFootnoteBlock(elements) {
12781
13372
  let found = false;
@@ -12789,7 +13380,9 @@ function containsFootnoteBlock(elements) {
12789
13380
  // packages/parser/src/parser/parse/result.ts
12790
13381
  function finalizeParseResult(ctx, children) {
12791
13382
  const cleanedChildren = postprocessChildren(children);
12792
- appendImplicitFootnoteBlock(cleanedChildren);
13383
+ if (ctx.appendImplicitFootnoteBlock) {
13384
+ appendImplicitFootnoteBlock(cleanedChildren);
13385
+ }
12793
13386
  return {
12794
13387
  ast: buildSyntaxTree(ctx, cleanedChildren),
12795
13388
  diagnostics: ctx.diagnostics
@@ -13162,12 +13755,12 @@ function preprocess(text) {
13162
13755
  }
13163
13756
 
13164
13757
  // packages/parser/src/parser/preprocess/expr/evaluate.ts
13165
- var import_ast5 = require("@wdprlib/ast");
13758
+ var import_ast6 = require("@wdprlib/ast");
13166
13759
  function evaluateDirective(kind, match) {
13167
13760
  if (kind === "expr") {
13168
- const result2 = import_ast5.evaluateExpression(match.head);
13761
+ const result2 = import_ast6.evaluateExpression(match.head);
13169
13762
  if (result2.success)
13170
- return import_ast5.formatExprValue(result2.value);
13763
+ return import_ast6.formatExprValue(result2.value);
13171
13764
  if (result2.error === "empty expression")
13172
13765
  return "";
13173
13766
  return "ERROR";
@@ -13175,11 +13768,11 @@ function evaluateDirective(kind, match) {
13175
13768
  if (kind === "if") {
13176
13769
  if (!match.hasPipe)
13177
13770
  return "";
13178
- return import_ast5.isTruthy(match.head) ? match.thenText : match.elseText;
13771
+ return import_ast6.isTruthy(match.head) ? match.thenText : match.elseText;
13179
13772
  }
13180
13773
  if (!match.hasPipe)
13181
13774
  return "";
13182
- const result = import_ast5.evaluateExpression(match.head);
13775
+ const result = import_ast6.evaluateExpression(match.head);
13183
13776
  if (!result.success)
13184
13777
  return "ERROR";
13185
13778
  return result.value !== 0 && !Number.isNaN(result.value) ? match.thenText : match.elseText;
@@ -13359,3 +13952,249 @@ function parse(source, options) {
13359
13952
  });
13360
13953
  return new Parser(tokens, options).parse();
13361
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
+ }