@pixerate/editor 0.135.0 → 0.136.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 (99) hide show
  1. package/dist/animation-editor/index.cjs +58 -55
  2. package/dist/animation-editor/index.cjs.map +1 -1
  3. package/dist/animation-editor/index.d.cts +8 -5
  4. package/dist/animation-editor/index.d.ts +8 -5
  5. package/dist/animation-editor/index.js +5 -2
  6. package/dist/animation-editor/index.js.map +1 -1
  7. package/dist/{bezier-J8i4uqSH.d.cts → bezier-CdccFsF8.d.cts} +1 -1
  8. package/dist/{bezier-lNEOp0Jx.d.ts → bezier-DG9qNZQV.d.ts} +1 -1
  9. package/dist/canvas/index.d.cts +10 -7
  10. package/dist/canvas/index.d.ts +10 -7
  11. package/dist/{chunk-Z2H7KECK.cjs → chunk-2R3UW57U.cjs} +13 -2
  12. package/dist/chunk-2R3UW57U.cjs.map +1 -0
  13. package/dist/{chunk-ESIWZMMK.js → chunk-6QQR4LKE.js} +2 -2
  14. package/dist/chunk-A3BVTI3G.js +150 -0
  15. package/dist/chunk-A3BVTI3G.js.map +1 -0
  16. package/dist/{chunk-T6TV6HY6.cjs → chunk-B2CUCM7Y.cjs} +36 -36
  17. package/dist/{chunk-T6TV6HY6.cjs.map → chunk-B2CUCM7Y.cjs.map} +1 -1
  18. package/dist/chunk-ECCXGELC.cjs +727 -0
  19. package/dist/chunk-ECCXGELC.cjs.map +1 -0
  20. package/dist/{chunk-OXSV64JX.js → chunk-G6IKY6PL.js} +4 -4
  21. package/dist/chunk-I52DRGGJ.js +727 -0
  22. package/dist/chunk-I52DRGGJ.js.map +1 -0
  23. package/dist/{chunk-YAFS2QFZ.cjs → chunk-JLGNZMUV.cjs} +82 -82
  24. package/dist/{chunk-YAFS2QFZ.cjs.map → chunk-JLGNZMUV.cjs.map} +1 -1
  25. package/dist/{chunk-7RJ6P7MI.js → chunk-KZXLZCQ7.js} +2 -2
  26. package/dist/{chunk-HHTCDFZC.js → chunk-MAHQC3SK.js} +13 -2
  27. package/dist/chunk-MAHQC3SK.js.map +1 -0
  28. package/dist/{chunk-FWEO3HSL.js → chunk-PQQF5KOW.js} +8 -8
  29. package/dist/chunk-Q6OUXEK3.cjs +150 -0
  30. package/dist/chunk-Q6OUXEK3.cjs.map +1 -0
  31. package/dist/{chunk-P3RQ5UJE.cjs → chunk-UTQKC66X.cjs} +4 -4
  32. package/dist/{chunk-P3RQ5UJE.cjs.map → chunk-UTQKC66X.cjs.map} +1 -1
  33. package/dist/{chunk-J3B45HTA.cjs → chunk-XB25WOC2.cjs} +6 -6
  34. package/dist/{chunk-J3B45HTA.cjs.map → chunk-XB25WOC2.cjs.map} +1 -1
  35. package/dist/effects/index.d.cts +7 -4
  36. package/dist/effects/index.d.ts +7 -4
  37. package/dist/{export-AZSwX087.d.cts → export-BOheWw2R.d.cts} +3 -3
  38. package/dist/{export-BDkyDNM8.d.ts → export-ByKKIA2S.d.ts} +3 -3
  39. package/dist/{export-KzubBKo7.d.cts → export-CEYeRQXH.d.cts} +1 -1
  40. package/dist/{export-DMeG6E06.d.ts → export-Ds7zgGD8.d.ts} +1 -1
  41. package/dist/extensions/index.cjs +3 -3
  42. package/dist/extensions/index.cjs.map +1 -1
  43. package/dist/extensions/index.js +2 -2
  44. package/dist/generation/index.cjs +150 -945
  45. package/dist/generation/index.cjs.map +1 -1
  46. package/dist/generation/index.d.cts +3 -423
  47. package/dist/generation/index.d.ts +3 -423
  48. package/dist/generation/index.js +59 -854
  49. package/dist/generation/index.js.map +1 -1
  50. package/dist/grammar/index.cjs +3 -3
  51. package/dist/grammar/index.cjs.map +1 -1
  52. package/dist/grammar/index.js +2 -2
  53. package/dist/{helpers-Coa4e2j_.d.ts → helpers--ns3W2D7.d.ts} +7 -1
  54. package/dist/{helpers-DHl28yLO.d.cts → helpers-BVkU4oUi.d.cts} +7 -1
  55. package/dist/image-editor/index.cjs +617 -614
  56. package/dist/image-editor/index.cjs.map +1 -1
  57. package/dist/image-editor/index.d.cts +11 -8
  58. package/dist/image-editor/index.d.ts +11 -8
  59. package/dist/image-editor/index.js +5 -2
  60. package/dist/image-editor/index.js.map +1 -1
  61. package/dist/index.cjs +28 -28
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.js +36 -36
  64. package/dist/{opentype-Dfcx6wFx.d.ts → opentype-DfoVYgmG.d.ts} +1 -1
  65. package/dist/{opentype-BWR7Qv8W.d.cts → opentype-yi-Kz4ND.d.cts} +1 -1
  66. package/dist/paint-editor/index.cjs +10 -7
  67. package/dist/paint-editor/index.cjs.map +1 -1
  68. package/dist/paint-editor/index.d.cts +8 -5
  69. package/dist/paint-editor/index.d.ts +8 -5
  70. package/dist/paint-editor/index.js +5 -2
  71. package/dist/paint-editor/index.js.map +1 -1
  72. package/dist/{pathfinder-D8KQ6blQ.d.cts → pathfinder-7JkMwYvC.d.cts} +1 -1
  73. package/dist/{pathfinder-Celbi3e6.d.ts → pathfinder-GM3UWdBZ.d.ts} +1 -1
  74. package/dist/{pool-BfuxBKTd.d.cts → pool-04qp8iW4.d.cts} +1 -1
  75. package/dist/{pool-8JZGWHvR.d.ts → pool-CkTxlLMC.d.ts} +1 -1
  76. package/dist/provenance-DmlcgdzT.d.cts +426 -0
  77. package/dist/provenance-uh5r2TQ8.d.ts +426 -0
  78. package/dist/{svg-pwXWq6s2.d.cts → svg-BDDKvWWY.d.cts} +2 -2
  79. package/dist/{svg-CxxqG3_W.d.ts → svg-rV6_HPmn.d.ts} +2 -2
  80. package/dist/{tools-3EBjR91b.d.cts → tools-BAjSbTdY.d.cts} +1 -1
  81. package/dist/{tools-y1M6O3UT.d.ts → tools-DPYerqeR.d.ts} +1 -1
  82. package/dist/vector/index.cjs +2684 -1860
  83. package/dist/vector/index.cjs.map +1 -1
  84. package/dist/vector/index.d.cts +313 -71
  85. package/dist/vector/index.d.ts +313 -71
  86. package/dist/vector/index.js +4700 -3876
  87. package/dist/vector/index.js.map +1 -1
  88. package/dist/video-editor/index.d.cts +7 -4
  89. package/dist/video-editor/index.d.ts +7 -4
  90. package/dist/{warp-Ceqdz7kj.d.cts → warp-DQh9R7Ie.d.cts} +1 -1
  91. package/dist/{warp-C1gwu2G_.d.ts → warp-XVL6SpSh.d.ts} +1 -1
  92. package/package.json +1 -1
  93. package/skills/pixerate-vector/SKILL.md +14 -0
  94. package/dist/chunk-HHTCDFZC.js.map +0 -1
  95. package/dist/chunk-Z2H7KECK.cjs.map +0 -1
  96. /package/dist/{chunk-ESIWZMMK.js.map → chunk-6QQR4LKE.js.map} +0 -0
  97. /package/dist/{chunk-OXSV64JX.js.map → chunk-G6IKY6PL.js.map} +0 -0
  98. /package/dist/{chunk-7RJ6P7MI.js.map → chunk-KZXLZCQ7.js.map} +0 -0
  99. /package/dist/{chunk-FWEO3HSL.js.map → chunk-PQQF5KOW.js.map} +0 -0
@@ -38,13 +38,6 @@ import {
38
38
  import {
39
39
  chartDataToTable
40
40
  } from "./chunk-633QC34G.js";
41
- import {
42
- INSTRUCTION_REGEX,
43
- TEMPLATE_REGEX,
44
- VARIABLE_REGEX,
45
- matchConditionalTags,
46
- parseVariableBody
47
- } from "./chunk-P6ODPZ4W.js";
48
41
  import {
49
42
  PIXERATE_DOCUMENT_MIME,
50
43
  getClipboardData,
@@ -70,6 +63,13 @@ import {
70
63
  import {
71
64
  readZip
72
65
  } from "./chunk-33AHNSEB.js";
66
+ import {
67
+ INSTRUCTION_REGEX,
68
+ TEMPLATE_REGEX,
69
+ VARIABLE_REGEX,
70
+ matchConditionalTags,
71
+ parseVariableBody
72
+ } from "./chunk-P6ODPZ4W.js";
73
73
 
74
74
  // src/extensions/gradient-text.ts
75
75
  import { Mark } from "@tiptap/core";
@@ -6755,4 +6755,4 @@ export {
6755
6755
  validateFindPattern,
6756
6756
  createTableCommands
6757
6757
  };
6758
- //# sourceMappingURL=chunk-FWEO3HSL.js.map
6758
+ //# sourceMappingURL=chunk-PQQF5KOW.js.map
@@ -0,0 +1,150 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+ var _chunkFD4LPFAEcjs = require('./chunk-FD4LPFAE.cjs');
7
+
8
+ // src/generation/provenance.ts
9
+ var PROVENANCE_FORMAT = "pixerate.generation-provenance";
10
+ var PROVENANCE_VERSION = 1;
11
+ var ProvenanceParseError = class extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "ProvenanceParseError";
15
+ }
16
+ };
17
+ var toIso = (value) => new Date(value).toISOString();
18
+ var clone = (value) => value === void 0 ? value : JSON.parse(JSON.stringify(value));
19
+ function pinTemplates(rawPrompt, templates, bindings, maxDepth) {
20
+ const byName = new Map(templates.map((t) => [t.name, t]));
21
+ const pinned = /* @__PURE__ */ new Map();
22
+ const visit = (text, depth) => {
23
+ if (depth > maxDepth) return;
24
+ for (const token of _chunkFD4LPFAEcjs.tokenizePrompt.call(void 0, text)) {
25
+ if (token.type !== "template" || pinned.has(token.value)) continue;
26
+ const template = byName.get(token.value);
27
+ if (!template) continue;
28
+ const body = _chunkFD4LPFAEcjs.getTemplateBody.call(void 0, template, bindings);
29
+ if (body === void 0) continue;
30
+ const bound = bindings[template.name];
31
+ const version = bound && template.versions ? template.versions.find((v) => v.id === bound || v.version === bound) : _chunkFD4LPFAEcjs.getLatestVersion.call(void 0, template);
32
+ const isVersioned = !!_optionalChain([template, 'access', _ => _.versions, 'optionalAccess', _2 => _2.length]) && !!version;
33
+ pinned.set(template.name, {
34
+ name: template.name,
35
+ ...template.id !== void 0 ? { templateId: template.id } : {},
36
+ ...isVersioned ? { versionId: version.id, version: version.version } : {},
37
+ body
38
+ });
39
+ visit(body, depth + 1);
40
+ }
41
+ };
42
+ visit(rawPrompt, 0);
43
+ return [...pinned.values()];
44
+ }
45
+ function pinnedTemplatesToTemplates(pinned) {
46
+ return pinned.map(
47
+ (p) => p.versionId !== void 0 ? {
48
+ ...p.templateId !== void 0 ? { id: p.templateId } : {},
49
+ name: p.name,
50
+ latestVersion: p.version,
51
+ versions: [{ id: p.versionId, version: _nullishCoalesce(p.version, () => ( p.versionId)), body: p.body }]
52
+ } : { ...p.templateId !== void 0 ? { id: p.templateId } : {}, name: p.name, body: p.body }
53
+ );
54
+ }
55
+ function createProvenance(options) {
56
+ const templates = _nullishCoalesce(options.templates, () => ( []));
57
+ const maxDepth = _nullishCoalesce(options.maxDepth, () => ( 10));
58
+ const resolved = _chunkFD4LPFAEcjs.resolvePrompt.call(void 0, options.rawPrompt, templates, {
59
+ bindings: options.bindings,
60
+ values: options.values,
61
+ maxDepth
62
+ });
63
+ const pinned = pinTemplates(options.rawPrompt, templates, _nullishCoalesce(options.bindings, () => ( {})), maxDepth);
64
+ const bindings = {};
65
+ for (const p of pinned) if (p.versionId !== void 0) bindings[p.name] = p.versionId;
66
+ const modelId = typeof options.model === "string" ? options.model : options.model.id;
67
+ const request = clone(_nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'access', _3 => _3.plan, 'optionalAccess', _4 => _4.request]), () => ( options.request)), () => ( {})));
68
+ request.model = modelId;
69
+ if (request.prompt === void 0) request.prompt = resolved.text;
70
+ const adjustments = clone(_nullishCoalesce(_nullishCoalesce(options.adjustments, () => ( _optionalChain([options, 'access', _5 => _5.plan, 'optionalAccess', _6 => _6.adjustments]))), () => ( [])));
71
+ return {
72
+ format: PROVENANCE_FORMAT,
73
+ version: PROVENANCE_VERSION,
74
+ rawPrompt: options.rawPrompt,
75
+ templates: pinned,
76
+ bindings,
77
+ values: options.values ? clone(options.values) : null,
78
+ resolvedPrompt: resolved.text,
79
+ sourceMap: resolved.map.map((segment) => {
80
+ const { locked: _locked, ...rest } = segment;
81
+ return rest;
82
+ }),
83
+ modelId,
84
+ request,
85
+ adjustments,
86
+ references: (_nullishCoalesce(request.references, () => ( []))).map(({ id, role }) => ({ id, role })),
87
+ createdAt: toIso(_nullishCoalesce(options.createdAt, () => ( Date.now()))),
88
+ ...options.startedAt !== void 0 ? { startedAt: toIso(options.startedAt) } : {},
89
+ ...options.completedAt !== void 0 ? { completedAt: toIso(options.completedAt) } : {},
90
+ ...options.outputIds ? { outputIds: [...options.outputIds] } : {},
91
+ ...options.meta ? { meta: clone(options.meta) } : {}
92
+ };
93
+ }
94
+ function serializeProvenance(provenance) {
95
+ return JSON.stringify(provenance);
96
+ }
97
+ var isRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
98
+ function parseProvenance(input) {
99
+ let data = input;
100
+ if (typeof input === "string") {
101
+ try {
102
+ data = JSON.parse(input);
103
+ } catch (e) {
104
+ throw new ProvenanceParseError("Provenance is not valid JSON.");
105
+ }
106
+ }
107
+ if (!isRecord(data) || data.format !== PROVENANCE_FORMAT) {
108
+ throw new ProvenanceParseError("Not a generation provenance record.");
109
+ }
110
+ if (typeof data.version !== "number" || data.version > PROVENANCE_VERSION) {
111
+ throw new ProvenanceParseError(`Unsupported provenance version ${JSON.stringify(data.version)}.`);
112
+ }
113
+ const checks = [
114
+ ["rawPrompt", typeof data.rawPrompt === "string"],
115
+ ["resolvedPrompt", typeof data.resolvedPrompt === "string"],
116
+ ["modelId", typeof data.modelId === "string"],
117
+ ["createdAt", typeof data.createdAt === "string"],
118
+ ["request", isRecord(data.request)],
119
+ ["templates", Array.isArray(data.templates) && data.templates.every((t) => isRecord(t) && typeof t.name === "string" && typeof t.body === "string")],
120
+ ["sourceMap", Array.isArray(data.sourceMap)],
121
+ ["adjustments", Array.isArray(data.adjustments)],
122
+ ["references", Array.isArray(data.references)]
123
+ ];
124
+ const bad = checks.find(([, ok]) => !ok);
125
+ if (bad) throw new ProvenanceParseError(`Invalid provenance field "${bad[0]}".`);
126
+ return {
127
+ ...data,
128
+ bindings: isRecord(data.bindings) ? data.bindings : {},
129
+ values: isRecord(data.values) ? data.values : null
130
+ };
131
+ }
132
+ function replayProvenancePrompt(provenance) {
133
+ const result = _chunkFD4LPFAEcjs.resolvePrompt.call(void 0, provenance.rawPrompt, pinnedTemplatesToTemplates(provenance.templates), {
134
+ bindings: provenance.bindings,
135
+ ...provenance.values ? { values: provenance.values } : {}
136
+ });
137
+ return { text: result.text, map: result.map, matches: result.text === provenance.resolvedPrompt };
138
+ }
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+ exports.PROVENANCE_FORMAT = PROVENANCE_FORMAT; exports.PROVENANCE_VERSION = PROVENANCE_VERSION; exports.ProvenanceParseError = ProvenanceParseError; exports.pinnedTemplatesToTemplates = pinnedTemplatesToTemplates; exports.createProvenance = createProvenance; exports.serializeProvenance = serializeProvenance; exports.parseProvenance = parseProvenance; exports.replayProvenancePrompt = replayProvenancePrompt;
150
+ //# sourceMappingURL=chunk-Q6OUXEK3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-Q6OUXEK3.cjs","../src/generation/provenance.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-Q6OUXEK3.cjs","sourcesContent":[null,"import { getLatestVersion, getTemplateBody, resolvePrompt } from '../grammar/engine.js';\nimport type { SourceMapSegment } from '../grammar/sourcemap.js';\nimport { tokenizePrompt } from '../grammar/tokenizer.js';\nimport type { PromptValues, Template } from '../grammar/tokens.js';\nimport type { GenerationRequest, ModelCapabilities, ReferenceRole } from './capabilities.js';\nimport type { GenerationPlan, PlanAdjustment } from './plan.js';\n\nexport const PROVENANCE_FORMAT = 'pixerate.generation-provenance';\nexport const PROVENANCE_VERSION = 1;\n\n/** The exact template body a generation used. */\nexport interface PinnedTemplate {\n\tname: string;\n\ttemplateId?: string;\n\t/** Version id or version label the body came from (absent for unversioned templates). */\n\tversionId?: string;\n\tversion?: string | number;\n\tbody: string;\n}\n\n/** Everything needed to explain and reproduce one generation. */\nexport interface GenerationProvenance {\n\tformat: typeof PROVENANCE_FORMAT;\n\tversion: typeof PROVENANCE_VERSION;\n\t/** Raw prompt as typed, with `{{templates}}` and `{variables}`. */\n\trawPrompt: string;\n\t/** Every template the prompt reached (recursively), pinned to the body used. */\n\ttemplates: PinnedTemplate[];\n\t/** Version bindings in effect (`{ templateName: versionId }`) for every pinned versioned template. */\n\tbindings: Record<string, string>;\n\t/** Variable values, or `null` when variables were left unresolved. */\n\tvalues: PromptValues | null;\n\tresolvedPrompt: string;\n\tsourceMap: SourceMapSegment[];\n\tmodelId: string;\n\t/** The planned (adjusted) request that was sent. */\n\trequest: GenerationRequest;\n\tadjustments: PlanAdjustment[];\n\treferences: { id: string; role: ReferenceRole }[];\n\t/** ISO timestamps. */\n\tcreatedAt: string;\n\tstartedAt?: string;\n\tcompletedAt?: string;\n\t/** Ids of the outputs this generation produced. */\n\toutputIds?: string[];\n\tmeta?: Record<string, unknown>;\n}\n\nexport interface CreateProvenanceOptions {\n\trawPrompt: string;\n\ttemplates?: Template[];\n\t/** Template version bindings (`{ templateName: versionIdOrVersion }`). */\n\tbindings?: Record<string, string>;\n\tvalues?: PromptValues;\n\tmodel: string | ModelCapabilities;\n\t/** The plan the request came from (its request and adjustments are recorded) … */\n\tplan?: GenerationPlan;\n\t/** … or the request that was sent. */\n\trequest?: GenerationRequest;\n\tadjustments?: PlanAdjustment[];\n\t/** Creation time (default `Date.now()`). */\n\tcreatedAt?: Date | number | string;\n\tstartedAt?: Date | number | string;\n\tcompletedAt?: Date | number | string;\n\toutputIds?: string[];\n\tmeta?: Record<string, unknown>;\n\tmaxDepth?: number;\n}\n\nexport class ProvenanceParseError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'ProvenanceParseError';\n\t}\n}\n\nconst toIso = (value: Date | number | string) => new Date(value).toISOString();\nconst clone = <T>(value: T): T => (value === undefined ? value : JSON.parse(JSON.stringify(value)));\n\n/** Collects the templates a prompt reaches, with the body each one resolves to. */\nfunction pinTemplates(\n\trawPrompt: string,\n\ttemplates: Template[],\n\tbindings: Record<string, string>,\n\tmaxDepth: number\n): PinnedTemplate[] {\n\tconst byName = new Map(templates.map((t) => [t.name, t]));\n\tconst pinned = new Map<string, PinnedTemplate>();\n\tconst visit = (text: string, depth: number) => {\n\t\tif (depth > maxDepth) return;\n\t\tfor (const token of tokenizePrompt(text)) {\n\t\t\tif (token.type !== 'template' || pinned.has(token.value)) continue;\n\t\t\tconst template = byName.get(token.value);\n\t\t\tif (!template) continue;\n\t\t\t// Mirror `getTemplateBody` so the pinned body is the one `resolvePrompt` used.\n\t\t\tconst body = getTemplateBody(template, bindings);\n\t\t\tif (body === undefined) continue;\n\t\t\tconst bound = bindings[template.name];\n\t\t\tconst version =\n\t\t\t\tbound && template.versions\n\t\t\t\t\t? template.versions.find((v) => v.id === bound || v.version === bound)\n\t\t\t\t\t: getLatestVersion(template);\n\t\t\tconst isVersioned = !!template.versions?.length && !!version;\n\t\t\tpinned.set(template.name, {\n\t\t\t\tname: template.name,\n\t\t\t\t...(template.id !== undefined ? { templateId: template.id } : {}),\n\t\t\t\t...(isVersioned ? { versionId: version!.id, version: version!.version } : {}),\n\t\t\t\tbody\n\t\t\t});\n\t\t\tvisit(body, depth + 1);\n\t\t}\n\t};\n\tvisit(rawPrompt, 0);\n\treturn [...pinned.values()];\n}\n\n/** Templates that reproduce the pinned bodies exactly (one single-version template each). */\nexport function pinnedTemplatesToTemplates(pinned: readonly PinnedTemplate[]): Template[] {\n\treturn pinned.map((p) =>\n\t\tp.versionId !== undefined\n\t\t\t? {\n\t\t\t\t\t...(p.templateId !== undefined ? { id: p.templateId } : {}),\n\t\t\t\t\tname: p.name,\n\t\t\t\t\tlatestVersion: p.version,\n\t\t\t\t\tversions: [{ id: p.versionId, version: p.version ?? p.versionId, body: p.body }]\n\t\t\t\t}\n\t\t\t: { ...(p.templateId !== undefined ? { id: p.templateId } : {}), name: p.name, body: p.body }\n\t);\n}\n\n/**\n * Records what produced an output: the raw prompt, the exact template bodies\n * and versions it reached, variable values, the resolved prompt and its\n * source map, the model, the planned settings and adjustments, and the\n * references by role.\n */\nexport function createProvenance(options: CreateProvenanceOptions): GenerationProvenance {\n\tconst templates = options.templates ?? [];\n\tconst maxDepth = options.maxDepth ?? 10;\n\tconst resolved = resolvePrompt(options.rawPrompt, templates, {\n\t\tbindings: options.bindings,\n\t\tvalues: options.values,\n\t\tmaxDepth\n\t});\n\tconst pinned = pinTemplates(options.rawPrompt, templates, options.bindings ?? {}, maxDepth);\n\tconst bindings: Record<string, string> = {};\n\tfor (const p of pinned) if (p.versionId !== undefined) bindings[p.name] = p.versionId;\n\n\tconst modelId = typeof options.model === 'string' ? options.model : options.model.id;\n\tconst request: GenerationRequest = clone(options.plan?.request ?? options.request ?? {});\n\trequest.model = modelId;\n\tif (request.prompt === undefined) request.prompt = resolved.text;\n\tconst adjustments = clone(options.adjustments ?? options.plan?.adjustments ?? []);\n\n\treturn {\n\t\tformat: PROVENANCE_FORMAT,\n\t\tversion: PROVENANCE_VERSION,\n\t\trawPrompt: options.rawPrompt,\n\t\ttemplates: pinned,\n\t\tbindings,\n\t\tvalues: options.values ? clone(options.values) : null,\n\t\tresolvedPrompt: resolved.text,\n\t\tsourceMap: resolved.map.map((segment) => {\n\t\t\tconst { locked: _locked, ...rest } = segment as SourceMapSegment & { locked?: boolean };\n\t\t\treturn rest;\n\t\t}),\n\t\tmodelId,\n\t\trequest,\n\t\tadjustments,\n\t\treferences: (request.references ?? []).map(({ id, role }) => ({ id, role })),\n\t\tcreatedAt: toIso(options.createdAt ?? Date.now()),\n\t\t...(options.startedAt !== undefined ? { startedAt: toIso(options.startedAt) } : {}),\n\t\t...(options.completedAt !== undefined ? { completedAt: toIso(options.completedAt) } : {}),\n\t\t...(options.outputIds ? { outputIds: [...options.outputIds] } : {}),\n\t\t...(options.meta ? { meta: clone(options.meta) } : {})\n\t};\n}\n\n/** Versioned JSON for storage next to an output. */\nexport function serializeProvenance(provenance: GenerationProvenance): string {\n\treturn JSON.stringify(provenance);\n}\n\nconst isRecord = (value: unknown): value is Record<string, any> =>\n\t!!value && typeof value === 'object' && !Array.isArray(value);\n\n/** Parses and checks serialized provenance. Throws {@link ProvenanceParseError}. */\nexport function parseProvenance(input: string | unknown): GenerationProvenance {\n\tlet data: unknown = input;\n\tif (typeof input === 'string') {\n\t\ttry {\n\t\t\tdata = JSON.parse(input);\n\t\t} catch {\n\t\t\tthrow new ProvenanceParseError('Provenance is not valid JSON.');\n\t\t}\n\t}\n\tif (!isRecord(data) || data.format !== PROVENANCE_FORMAT) {\n\t\tthrow new ProvenanceParseError('Not a generation provenance record.');\n\t}\n\tif (typeof data.version !== 'number' || data.version > PROVENANCE_VERSION) {\n\t\tthrow new ProvenanceParseError(`Unsupported provenance version ${JSON.stringify(data.version)}.`);\n\t}\n\tconst checks: [string, boolean][] = [\n\t\t['rawPrompt', typeof data.rawPrompt === 'string'],\n\t\t['resolvedPrompt', typeof data.resolvedPrompt === 'string'],\n\t\t['modelId', typeof data.modelId === 'string'],\n\t\t['createdAt', typeof data.createdAt === 'string'],\n\t\t['request', isRecord(data.request)],\n\t\t['templates', Array.isArray(data.templates) && data.templates.every((t: any) => isRecord(t) && typeof t.name === 'string' && typeof t.body === 'string')],\n\t\t['sourceMap', Array.isArray(data.sourceMap)],\n\t\t['adjustments', Array.isArray(data.adjustments)],\n\t\t['references', Array.isArray(data.references)]\n\t];\n\tconst bad = checks.find(([, ok]) => !ok);\n\tif (bad) throw new ProvenanceParseError(`Invalid provenance field \"${bad[0]}\".`);\n\treturn {\n\t\t...(data as GenerationProvenance),\n\t\tbindings: isRecord(data.bindings) ? data.bindings : {},\n\t\tvalues: isRecord(data.values) ? data.values : null\n\t};\n}\n\n/**\n * Re-resolves the raw prompt against the pinned template bodies and values,\n * e.g. to check a record or to open it in an editor with its source map.\n */\nexport function replayProvenancePrompt(provenance: GenerationProvenance): {\n\ttext: string;\n\tmap: SourceMapSegment[];\n\tmatches: boolean;\n} {\n\tconst result = resolvePrompt(provenance.rawPrompt, pinnedTemplatesToTemplates(provenance.templates), {\n\t\tbindings: provenance.bindings,\n\t\t...(provenance.values ? { values: provenance.values } : {})\n\t});\n\treturn { text: result.text, map: result.map, matches: result.text === provenance.resolvedPrompt };\n}\n"]}
@@ -1,21 +1,21 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
+ var _chunkTNNJXF46cjs = require('./chunk-TNNJXF46.cjs');
3
4
 
4
5
 
5
6
 
6
- var _chunkFD4LPFAEcjs = require('./chunk-FD4LPFAE.cjs');
7
7
 
8
8
 
9
+ var _chunkFD4LPFAEcjs = require('./chunk-FD4LPFAE.cjs');
9
10
 
10
11
 
11
12
 
12
13
 
13
14
 
14
15
 
15
- var _chunkMKA3AHLVcjs = require('./chunk-MKA3AHLV.cjs');
16
16
 
17
17
 
18
- var _chunkTNNJXF46cjs = require('./chunk-TNNJXF46.cjs');
18
+ var _chunkMKA3AHLVcjs = require('./chunk-MKA3AHLV.cjs');
19
19
 
20
20
  // src/grammar/resolver.ts
21
21
  function resolveTemplates(text, templates = [], options) {
@@ -686,4 +686,4 @@ function serializeMergeOutputs(outputs, format = "text", separator = "\n\n") {
686
686
 
687
687
 
688
688
  exports.resolveTemplates = resolveTemplates; exports.resolveVariables = resolveVariables; exports.extractTemplateNames = extractTemplateNames; exports.extractVariableNames = extractVariableNames; exports.extractInstructionNames = extractInstructionNames; exports.resolveTemplatesWithMapping = resolveTemplatesWithMapping; exports.mapResolvedOffsetToRaw = mapResolvedOffsetToRaw; exports.mapRawOffsetToResolved = mapRawOffsetToResolved; exports.extractVariables = extractVariables; exports.getVariableFormFields = getVariableFormFields; exports.compactVariableValues = compactVariableValues; exports.MAX_DATA_SOURCE_RECORDS = MAX_DATA_SOURCE_RECORDS; exports.MAX_DATA_SOURCE_FIELDS = MAX_DATA_SOURCE_FIELDS; exports.detectDelimiter = detectDelimiter; exports.normalizeFieldNames = normalizeFieldNames; exports.parseDataSource = parseDataSource; exports.normalizeFieldKey = normalizeFieldKey; exports.FIELD_ALIASES = FIELD_ALIASES; exports.matchFields = matchFields; exports.recordToValues = recordToValues; exports.MAX_MERGE_OUTPUTS = MAX_MERGE_OUTPUTS; exports.MAX_MERGE_LENGTH = MAX_MERGE_LENGTH; exports.mergeRecords = mergeRecords; exports.serializeMergeOutputs = serializeMergeOutputs;
689
- //# sourceMappingURL=chunk-P3RQ5UJE.cjs.map
689
+ //# sourceMappingURL=chunk-UTQKC66X.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-P3RQ5UJE.cjs","../src/grammar/resolver.ts","../src/grammar/sourcemap.ts","../src/grammar/fields.ts","../src/grammar/data-source.ts","../src/grammar/merge.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-P3RQ5UJE.cjs","sourcesContent":[null,"import {\n TEMPLATE_REGEX,\n VARIABLE_REGEX,\n INSTRUCTION_REGEX,\n Template,\n PromptValues,\n} from \"./tokens\";\nimport { resolvePrompt } from \"./engine\";\nimport { conditionSubject, parseVariableBody } from \"./variables\";\nimport { tokenizePrompt } from \"./tokenizer\";\n\nexport interface ResolveTemplatesOptions {\n bindings?: Record<string, string>;\n maxDepth?: number;\n /**\n * Values for `{variable}` slots and `{?variable}` sections. When omitted,\n * variables, defaults and section tags are left exactly as written.\n */\n values?: PromptValues;\n}\n\n/**\n * Recursively resolves template tags `{{template_name}}` in a given text.\n * A tag that would recurse into itself is replaced with `TEMPLATE_LOOP_ERROR`,\n * and a tag nested deeper than `maxDepth` with `TEMPLATE_DEPTH_ERROR`; the rest\n * of the text still resolves normally.\n *\n * Pass `options.values` to also fill variables (falling back to their\n * `{name|default}`) and evaluate `{?name}…{/name}` / `{!name}…{/name}`\n * sections, including those inside template bodies. See `resolvePrompt` for\n * the source map and diagnostics.\n */\nexport function resolveTemplates(\n text: string,\n templates: Template[] = [],\n options?: ResolveTemplatesOptions,\n): string {\n return resolvePrompt(text, templates, options).text;\n}\n\n/**\n * Replaces `{variableName}` with values from a dictionary, falling back to a\n * `{variableName|default}` when no value is supplied, and evaluates\n * `{?name}…{/name}` / `{!name}…{/name}` sections. Variables with neither a\n * value nor a default are left as written. Templates are not expanded.\n */\nexport function resolveVariables(\n text: string,\n values: PromptValues,\n): string {\n if (!text) return \"\";\n return resolvePrompt(text, [], { values }).text;\n}\n\n/**\n * Extracts unique template names referenced in text.\n */\nexport function extractTemplateNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(TEMPLATE_REGEX.source, TEMPLATE_REGEX.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n set.add(match[1].trim());\n }\n return Array.from(set);\n}\n\n/**\n * Extracts unique variable names referenced in text, including names used by\n * conditional section tags (`amount` for `{?amount>100}…{/amount}`).\n * Defaults and descriptions are stripped.\n */\nexport function extractVariableNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(VARIABLE_REGEX.source, VARIABLE_REGEX.flags);\n let comparisonStarts: Set<number> | undefined;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n const parsed = parseVariableBody(match[1]);\n let name = parsed.name;\n if (parsed.kind === \"conditional\" && parsed.conditional !== \"end\") {\n const subject = conditionSubject(name);\n if (subject) {\n // Only a tag closed by `{/subject}` is a comparison on `subject`.\n comparisonStarts ??= new Set(\n tokenizePrompt(text)\n .filter((token) => token.comparison)\n .map((token) => token.start),\n );\n if (comparisonStarts.has(match.index)) name = subject;\n }\n }\n set.add(name);\n }\n return Array.from(set);\n}\n\n/**\n * Extracts unique instruction names referenced in text.\n */\nexport function extractInstructionNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(INSTRUCTION_REGEX.source, INSTRUCTION_REGEX.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n set.add(match[1].trim());\n }\n return Array.from(set);\n}\n","import type { PromptDiagnostic, Template } from \"./tokens\";\nimport type { ResolveTemplatesOptions } from \"./resolver\";\nimport { resolvePrompt } from \"./engine\";\nimport { getPromptDiagnostics } from \"./tokenizer\";\n\n/**\n * One contiguous piece of resolved output and the raw range it came from.\n *\n * - `raw`: copied verbatim; offsets map character by character.\n * - `template`: the expansion of a `{{template}}` tag.\n * - `variable`: a substituted value or `|default` for a `{variable}` tag.\n * - `conditional`: a section tag, or a whole removed section. These segments\n * are empty in the resolved text (`resolvedStart === resolvedEnd`).\n *\n * Offsets inside non-raw segments map to the start of their raw range.\n */\nexport interface SourceMapSegment {\n resolvedStart: number;\n resolvedEnd: number;\n source: \"raw\" | \"template\" | \"variable\" | \"conditional\";\n rawStart: number;\n rawEnd: number;\n templateName?: string;\n /** Variable substituted (`variable`) or tested (`conditional`). */\n variableName?: string;\n /** For `variable` segments: whether a supplied value or the default was used. */\n valueSource?: \"value\" | \"default\";\n}\n\n/**\n * Resolves templates in text while tracking character offset mapping\n * between the raw input and the fully resolved output.\n *\n * Pass `options.values` to also substitute variables and evaluate conditional\n * sections (see `resolvePrompt`); without it the output is unchanged from the\n * template-only behavior.\n */\nexport function resolveTemplatesWithMapping(\n text: string,\n templates: Template[] = [],\n templateBindings?: Record<string, string>,\n options?: Pick<ResolveTemplatesOptions, \"maxDepth\" | \"values\">,\n): { text: string; map: SourceMapSegment[]; diagnostics: PromptDiagnostic[] } {\n if (\n options?.values === undefined &&\n (!templates || templates.length === 0 || !text.includes(\"{{\"))\n ) {\n return {\n diagnostics: getPromptDiagnostics(text),\n text,\n map: [\n {\n resolvedStart: 0,\n resolvedEnd: text.length,\n source: \"raw\",\n rawStart: 0,\n rawEnd: text.length,\n },\n ],\n };\n }\n\n return resolvePrompt(text, templates, {\n bindings: templateBindings,\n maxDepth: options?.maxDepth,\n values: options?.values,\n });\n}\n\n/**\n * Maps an offset in resolved text back to the corresponding offset in raw text.\n */\nexport function mapResolvedOffsetToRaw(\n resolvedOffset: number,\n map: SourceMapSegment[],\n): number {\n for (let i = 0; i < map.length; i++) {\n const seg = map[i];\n const isLast = i === map.length - 1;\n const inRange = isLast\n ? resolvedOffset >= seg.resolvedStart && resolvedOffset <= seg.resolvedEnd\n : resolvedOffset >= seg.resolvedStart && resolvedOffset < seg.resolvedEnd;\n\n if (inRange) {\n if (seg.source === \"raw\") {\n return seg.rawStart + (resolvedOffset - seg.resolvedStart);\n }\n // The end of the text maps to the end of the tag; anywhere inside a\n // resolved template maps to the start of its tag.\n if (resolvedOffset === seg.resolvedEnd) {\n return seg.rawEnd;\n }\n return seg.rawStart;\n }\n }\n return resolvedOffset;\n}\n\n/**\n * Maps an offset in raw text to the corresponding offset in resolved text.\n */\nexport function mapRawOffsetToResolved(\n rawOffset: number,\n map: SourceMapSegment[],\n): number {\n for (let i = 0; i < map.length; i++) {\n const seg = map[i];\n const isLast = i === map.length - 1;\n const inRange = isLast\n ? rawOffset >= seg.rawStart && rawOffset <= seg.rawEnd\n : rawOffset >= seg.rawStart && rawOffset < seg.rawEnd;\n\n if (inRange) {\n if (seg.source === \"raw\") {\n return seg.resolvedStart + (rawOffset - seg.rawStart);\n }\n if (rawOffset === seg.rawEnd) {\n return seg.resolvedEnd;\n }\n return seg.resolvedStart;\n }\n }\n return rawOffset;\n}\n","import type { PromptValues, Template } from \"./tokens\";\nimport { tokenizePrompt } from \"./tokenizer\";\nimport { getTemplateBody } from \"./engine\";\n\n/** Everything a prompt (and, optionally, its templates) says about one variable. */\nexport interface VariableDescriptor {\n name: string;\n /** First `{name|default}` found. */\n defaultValue?: string;\n /** First `{name|default|description}` found. */\n description?: string;\n /** Appears as a `{name}` slot. */\n usedAsValue: boolean;\n /** Appears in a `{?name}` / `{!name}` condition (including comparisons). */\n usedInCondition: boolean;\n /**\n * Present (and `true`) when the variable is compared in a condition such as\n * `{?amount>100}`, so a form should ask for its text, not a checkbox.\n */\n usedInComparison?: true;\n /** Number of `{name…}` slots and condition tags (closing tags excluded). */\n occurrences: number;\n /** Templates whose bodies mention the variable, in discovery order. */\n templates: string[];\n}\n\nexport interface ExtractVariablesOptions {\n /** Templates to search recursively for further variables. */\n templates?: Template[];\n bindings?: Record<string, string>;\n /** Maximum template nesting depth to search (default 10). */\n maxDepth?: number;\n}\n\n/**\n * Lists every variable a prompt uses, in order of first appearance, with its\n * default and description. Templates referenced by the prompt are searched\n * recursively when `options.templates` is given (loops are skipped). All\n * sections are searched, whatever their condition would evaluate to.\n */\nexport function extractVariables(\n text: string,\n options: ExtractVariablesOptions = {},\n): VariableDescriptor[] {\n const descriptors = new Map<string, VariableDescriptor>();\n const templateMap = new Map(\n (options.templates ?? []).map((t) => [t.name, t] as const),\n );\n const maxDepth = options.maxDepth ?? 10;\n\n const describe = (name: string, templateName?: string) => {\n let descriptor = descriptors.get(name);\n if (!descriptor) {\n descriptor = {\n name,\n usedAsValue: false,\n usedInCondition: false,\n occurrences: 0,\n templates: [],\n };\n descriptors.set(name, descriptor);\n }\n descriptor.occurrences++;\n if (templateName && !descriptor.templates.includes(templateName)) {\n descriptor.templates.push(templateName);\n }\n return descriptor;\n };\n\n const visit = (\n source: string,\n visited: Set<string>,\n depth: number,\n templateName?: string,\n ) => {\n for (const token of tokenizePrompt(source)) {\n if (token.type === \"variable\") {\n const descriptor = describe(token.value, templateName);\n descriptor.usedAsValue = true;\n if (descriptor.defaultValue === undefined && token.defaultValue !== undefined) {\n descriptor.defaultValue = token.defaultValue;\n }\n if (descriptor.description === undefined && token.description !== undefined) {\n descriptor.description = token.description;\n }\n } else if (token.type === \"conditional\" && token.conditional !== \"end\") {\n const descriptor = describe(token.value, templateName);\n descriptor.usedInCondition = true;\n if (token.comparison) descriptor.usedInComparison = true;\n } else if (token.type === \"template\") {\n const template = templateMap.get(token.value);\n if (!template || visited.has(token.value) || depth + 1 > maxDepth) {\n continue;\n }\n const body = getTemplateBody(template, options.bindings);\n if (body === undefined) continue;\n visit(body, new Set(visited).add(token.value), depth + 1, token.value);\n }\n }\n };\n\n if (text) visit(text, new Set(), 0);\n return Array.from(descriptors.values());\n}\n\n/** A headless description of one input in a variable fill-in form. */\nexport interface VariableFormField {\n name: string;\n /** The variable's description, or its name. */\n label: string;\n /** The variable's default, or an empty string. */\n placeholder: string;\n defaultValue?: string;\n description?: string;\n /**\n * The variable is used as a slot and has no default, so leaving it blank\n * leaves the `{name}` placeholder in the resolved prompt.\n */\n required: boolean;\n /**\n * Only used by `{?name}` / `{!name}` presence conditions, never substituted\n * or compared (a form can show a checkbox).\n */\n conditionOnly: boolean;\n}\n\n/**\n * Builds field descriptors for a fill-in form (Word's FILLIN analogue): one\n * per variable, labelled with its description and using its default as the\n * placeholder. Feed the entered text through `compactVariableValues` before\n * resolving so blank inputs fall back to defaults.\n */\nexport function getVariableFormFields(\n text: string,\n options: ExtractVariablesOptions = {},\n): VariableFormField[] {\n return extractVariables(text, options).map((variable) => ({\n name: variable.name,\n label: variable.description || variable.name,\n placeholder: variable.defaultValue ?? \"\",\n ...(variable.defaultValue !== undefined\n ? { defaultValue: variable.defaultValue }\n : {}),\n ...(variable.description !== undefined\n ? { description: variable.description }\n : {}),\n required: variable.usedAsValue && variable.defaultValue === undefined,\n conditionOnly: !variable.usedAsValue && !variable.usedInComparison,\n }));\n}\n\n/**\n * Drops blank entries from form input so the resolver falls back to each\n * variable's default (an explicit `\"\"` value would otherwise render as empty).\n */\nexport function compactVariableValues(\n input: Record<string, string | null | undefined>,\n): PromptValues {\n const values: PromptValues = {};\n for (const [name, value] of Object.entries(input)) {\n if (value !== null && value !== undefined && value.trim() !== \"\") {\n values[name] = value;\n }\n }\n return values;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/mailings.rs and\n// wordcraft/crates/formats/src/sheet.rs (MIT OR Apache-2.0, © ArtCraft Team\n// and contributors). See THIRD_PARTY_NOTICES.md.\n\n/**\n * Mail-merge data sources: CSV / TSV text, JSON, rows or objects normalised\n * into named fields and string records, plus fuzzy matching of prompt\n * variables to those fields.\n *\n * Imports only the self-contained CSV module, never the spreadsheet entry, so\n * the grammar entry stays light.\n */\nimport { parseCsv } from \"../spreadsheet/csv\";\nimport type { PromptValues } from \"./tokens\";\n\n/** Most records a data source keeps by default. */\nexport const MAX_DATA_SOURCE_RECORDS = 100_000;\n/** Most fields a data source keeps by default. */\nexport const MAX_DATA_SOURCE_FIELDS = 1_000;\n\n/** One record: field name → cell text. */\nexport type MergeRecord = Record<string, string>;\n\n/** Anything `parseDataSource` accepts. */\nexport type DataSourceInput =\n | string\n | ReadonlyArray<ReadonlyArray<unknown>>\n | ReadonlyArray<Readonly<Record<string, unknown>>>;\n\nexport interface ParseDataSourceOptions {\n /**\n * Field separator for delimited text. `\"auto\"` (the default) picks whichever\n * of `,` `;` and tab occurs most often in the first line (outside quotes),\n * preferring `,` on a tie.\n */\n delimiter?: \"auto\" | string;\n /**\n * Whether the first row names the fields (default `true`). Without a header\n * the fields are `Column 1`…`Column N`. Ignored for arrays of objects.\n */\n hasHeader?: boolean;\n /**\n * How to read a string: `\"auto\"` (default) parses text starting with `[` as\n * JSON and falls back to delimited text when that fails.\n */\n format?: \"auto\" | \"csv\" | \"json\";\n /** Record cap (default `MAX_DATA_SOURCE_RECORDS`). */\n maxRecords?: number;\n /** Field cap (default `MAX_DATA_SOURCE_FIELDS`). */\n maxFields?: number;\n}\n\nexport type DataSourceWarningCode =\n | \"empty\"\n | \"invalid-json\"\n | \"unsupported-json\"\n | \"blank-header\"\n | \"duplicate-header\"\n | \"ragged-rows\"\n | \"records-truncated\"\n | \"fields-truncated\";\n\nexport interface DataSourceWarning {\n code: DataSourceWarningCode;\n message: string;\n /** For `ragged-rows`: how many records were padded or cut. */\n count?: number;\n}\n\nexport interface MergeDataSource {\n /** Field names: trimmed, unique (case-insensitively), never blank. */\n fields: string[];\n /** One entry per record, with every field present. */\n records: MergeRecord[];\n warnings: DataSourceWarning[];\n /** How the input was read. */\n format: \"csv\" | \"json\" | \"rows\" | \"objects\";\n /** The delimiter used for delimited text. */\n delimiter?: string;\n}\n\nconst AUTO_DELIMITERS = [\",\", \";\", \"\\t\"];\n\n/** Counts the auto-detect candidates in the first line, ignoring quoted text. */\nexport function detectDelimiter(text: string): string {\n const counts = new Map<string, number>(AUTO_DELIMITERS.map((d) => [d, 0]));\n let quoted = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (ch === '\"') {\n quoted = !quoted;\n continue;\n }\n if (quoted) continue;\n if (ch === \"\\n\" || ch === \"\\r\") break;\n if (counts.has(ch)) counts.set(ch, counts.get(ch)! + 1);\n }\n let best = \",\";\n for (const d of AUTO_DELIMITERS) {\n if (counts.get(d)! > counts.get(best)!) best = d;\n }\n return best;\n}\n\n/**\n * Field names from a header row: names are trimmed, a blank name becomes\n * `Column N` (its 1-based position), and repeats (compared case-insensitively)\n * are numbered `Name 2`, `Name 3`, ….\n */\nexport function normalizeFieldNames(row: ReadonlyArray<unknown>): string[] {\n const out: string[] = [];\n const taken = new Set<string>();\n row.forEach((cell, i) => {\n const trimmed = cellText(cell).trim();\n const base = trimmed === \"\" ? `Column ${i + 1}` : trimmed;\n let name = base;\n for (let k = 2; taken.has(name.toLowerCase()); k++) name = `${base} ${k}`;\n taken.add(name.toLowerCase());\n out.push(name);\n });\n return out;\n}\n\nfunction cellText(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"object\") {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n/** Sets an own property, even for names such as `__proto__`. */\nfunction setField(record: MergeRecord, name: string, value: string): void {\n Object.defineProperty(record, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n}\n\nfunction isBlankRow(row: ReadonlyArray<unknown>): boolean {\n return row.every((cell) => cellText(cell).trim() === \"\");\n}\n\n/**\n * Reads a mail-merge data source.\n *\n * - **Text**: CSV / TSV (RFC 4180 quoting, doubled quotes, CRLF / LF / CR,\n * a leading BOM ignored) with the delimiter auto-detected, or JSON (an\n * array of objects or of arrays).\n * - **Rows** (`unknown[][]`): the first row is the header unless\n * `hasHeader: false`.\n * - **Objects**: the fields are the union of keys in first-seen order.\n *\n * Blank rows are skipped, header names are normalised (`normalizeFieldNames`),\n * records are padded or cut to the header width, and records and fields are\n * capped. Cells become strings (`null` → `\"\"`, nested values → JSON). Problems\n * are reported in `warnings`; this never throws.\n */\nexport function parseDataSource(\n input: DataSourceInput,\n options: ParseDataSourceOptions = {},\n): MergeDataSource {\n const warnings: DataSourceWarning[] = [];\n if (typeof input === \"string\") {\n const format = options.format ?? \"auto\";\n const trimmed = input.trim();\n if (format === \"json\" || (format === \"auto\" && /^\\[/.test(trimmed))) {\n let parsed: unknown;\n let ok = true;\n try {\n parsed = JSON.parse(trimmed);\n } catch (error) {\n ok = false;\n if (format === \"json\") {\n warnings.push({\n code: \"invalid-json\",\n message: `Invalid JSON: ${(error as Error).message}`,\n });\n return { fields: [], records: [], warnings, format: \"json\" };\n }\n }\n if (ok) {\n if (!Array.isArray(parsed)) {\n warnings.push({\n code: \"unsupported-json\",\n message: \"JSON data must be an array of objects or of arrays\",\n });\n return { fields: [], records: [], warnings, format: \"json\" };\n }\n const result = fromArray(parsed, options, warnings);\n return { ...result, format: \"json\" };\n }\n }\n const delimiter =\n !options.delimiter || options.delimiter === \"auto\"\n ? detectDelimiter(input)\n : options.delimiter;\n let rows: string[][];\n try {\n rows = parseCsv(input, { delimiter });\n } catch (error) {\n warnings.push({ code: \"empty\", message: (error as Error).message });\n return { fields: [], records: [], warnings, format: \"csv\", delimiter };\n }\n return {\n ...fromRows(rows, options, warnings),\n format: \"csv\",\n delimiter,\n };\n }\n const result = fromArray(input as ReadonlyArray<unknown>, options, warnings);\n return {\n ...result,\n format: result.objects ? \"objects\" : \"rows\",\n };\n}\n\nfunction fromArray(\n items: ReadonlyArray<unknown>,\n options: ParseDataSourceOptions,\n warnings: DataSourceWarning[],\n): { fields: string[]; records: MergeRecord[]; warnings: DataSourceWarning[]; objects: boolean } {\n const objects = items.some(\n (item) => item !== null && typeof item === \"object\" && !Array.isArray(item),\n );\n if (!objects) {\n const rows = items.filter((item): item is unknown[] => Array.isArray(item));\n return { ...fromRows(rows, options, warnings), objects: false };\n }\n const maxFields = options.maxFields ?? MAX_DATA_SOURCE_FIELDS;\n const maxRecords = options.maxRecords ?? MAX_DATA_SOURCE_RECORDS;\n const fields: string[] = [];\n const seen = new Set<string>();\n let fieldsTruncated = false;\n const rows = items.filter(\n (item): item is Record<string, unknown> =>\n item !== null && typeof item === \"object\" && !Array.isArray(item),\n );\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (seen.has(key)) continue;\n if (fields.length >= maxFields) {\n fieldsTruncated = true;\n continue;\n }\n seen.add(key);\n fields.push(key);\n }\n }\n if (fieldsTruncated) {\n warnings.push({\n code: \"fields-truncated\",\n message: `Only the first ${maxFields} fields were kept`,\n });\n }\n const records: MergeRecord[] = [];\n for (const row of rows) {\n if (fields.every((field) => cellText(row[field]).trim() === \"\")) continue;\n if (records.length >= maxRecords) {\n warnings.push({\n code: \"records-truncated\",\n message: `Only the first ${maxRecords} records were kept`,\n });\n break;\n }\n const record: MergeRecord = {};\n for (const field of fields) {\n const value = Object.prototype.hasOwnProperty.call(row, field)\n ? row[field]\n : undefined;\n setField(record, field, cellText(value));\n }\n records.push(record);\n }\n if (records.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n }\n return { fields, records, warnings, objects: true };\n}\n\nfunction fromRows(\n allRows: ReadonlyArray<ReadonlyArray<unknown>>,\n options: ParseDataSourceOptions,\n warnings: DataSourceWarning[],\n): { fields: string[]; records: MergeRecord[]; warnings: DataSourceWarning[] } {\n const maxFields = options.maxFields ?? MAX_DATA_SOURCE_FIELDS;\n const maxRecords = options.maxRecords ?? MAX_DATA_SOURCE_RECORDS;\n const rows = allRows.filter((row) => !isBlankRow(row));\n if (rows.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n return { fields: [], records: [], warnings };\n }\n const hasHeader = options.hasHeader ?? true;\n let fields: string[];\n let body: ReadonlyArray<ReadonlyArray<unknown>>;\n let widest: number;\n if (hasHeader) {\n const header = rows[0];\n widest = header.length;\n if (header.some((cell) => cellText(cell).trim() === \"\")) {\n warnings.push({\n code: \"blank-header\",\n message: \"Blank column headers were named \\\"Column N\\\"\",\n });\n }\n fields = normalizeFieldNames(header.slice(0, maxFields));\n const lower = header.map((cell) => cellText(cell).trim().toLowerCase());\n if (lower.some((name, i) => name !== \"\" && lower.indexOf(name) !== i)) {\n warnings.push({\n code: \"duplicate-header\",\n message: \"Repeated column headers were numbered\",\n });\n }\n body = rows.slice(1);\n } else {\n widest = Math.max(...rows.map((row) => row.length));\n fields = Array.from(\n { length: Math.min(widest, maxFields) },\n (_, i) => `Column ${i + 1}`,\n );\n body = rows;\n }\n if (widest > maxFields) {\n warnings.push({\n code: \"fields-truncated\",\n message: `Only the first ${maxFields} fields were kept`,\n });\n }\n if (body.length > maxRecords) {\n warnings.push({\n code: \"records-truncated\",\n message: `Only the first ${maxRecords} of ${body.length} records were kept`,\n });\n body = body.slice(0, maxRecords);\n }\n let ragged = 0;\n const records = body.map((row) => {\n if (hasHeader && row.length !== widest) ragged++;\n const record: MergeRecord = {};\n fields.forEach((field, i) => setField(record, field, cellText(row[i])));\n return record;\n });\n if (ragged > 0) {\n warnings.push({\n code: \"ragged-rows\",\n message: `${ragged} record${ragged === 1 ? \" was\" : \"s were\"} padded or cut to ${widest} fields`,\n count: ragged,\n });\n }\n if (records.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n }\n return { fields, records, warnings };\n}\n\n/** Lower-cases and drops spaces, `_`, `-` and `.` so `First Name` matches `first_name`. */\nexport function normalizeFieldKey(name: string): string {\n return name.toLowerCase().replace(/[\\s_.\\-]+/g, \"\");\n}\n\n/**\n * Built-in alias groups for `matchFields`: any name in a group matches any\n * other (after `normalizeFieldKey`). Extended from Word's address-block\n * field detection.\n */\nexport const FIELD_ALIASES: ReadonlyArray<ReadonlyArray<string>> = [\n [\"FirstName\", \"First\", \"GivenName\", \"Forename\", \"FName\"],\n [\"LastName\", \"Last\", \"Surname\", \"FamilyName\", \"LName\"],\n [\"Name\", \"FullName\", \"DisplayName\"],\n [\"Company\", \"CompanyName\", \"Organization\", \"Organisation\", \"Employer\", \"Business\"],\n [\"Address\", \"AddressLine1\", \"Address1\", \"Street\", \"StreetAddress\"],\n [\"City\", \"Town\"],\n [\"State\", \"Province\", \"Region\", \"County\"],\n [\"PostalCode\", \"ZIP\", \"ZipCode\", \"Postcode\"],\n [\"Country\", \"CountryName\", \"Nation\"],\n [\"Title\", \"CourtesyTitle\", \"Salutation\", \"Honorific\"],\n [\"Email\", \"EmailAddress\", \"Mail\", \"EMail\"],\n [\"Phone\", \"PhoneNumber\", \"Telephone\", \"Tel\", \"Mobile\"],\n];\n\nexport type FieldMatchKind = \"exact\" | \"normalized\" | \"alias\";\n\nexport interface FieldMatch {\n variable: string;\n /** The matched field, or `null`. */\n field: string | null;\n kind: FieldMatchKind | null;\n}\n\nexport interface FieldMapping {\n /** Variable → field (or `null` when unmatched), in variable order. */\n mapping: Record<string, string | null>;\n matches: FieldMatch[];\n unmatchedVariables: string[];\n /** Fields no variable maps to. */\n unusedFields: string[];\n}\n\nexport interface MatchFieldsOptions {\n /** Extra alias groups, checked after the built-in ones. */\n aliases?: ReadonlyArray<ReadonlyArray<string>>;\n}\n\n/**\n * Maps prompt variables to data source fields: an exact name first, then a\n * case-, space- and punctuation-insensitive match (`first_name` ↔\n * `First Name`), then an alias (`FirstName` ↔ `First` / `GivenName`, see\n * `FIELD_ALIASES`). Several variables may map to the same field.\n */\nexport function matchFields(\n variables: ReadonlyArray<string | { name: string }>,\n fields: ReadonlyArray<string>,\n options: MatchFieldsOptions = {},\n): FieldMapping {\n const names = Array.from(\n new Set(variables.map((v) => (typeof v === \"string\" ? v : v.name))),\n );\n const byKey = new Map<string, string>();\n for (const field of fields) {\n const key = normalizeFieldKey(field);\n if (!byKey.has(key)) byKey.set(key, field);\n }\n const groups = [...FIELD_ALIASES, ...(options.aliases ?? [])].map((group) =>\n group.map(normalizeFieldKey),\n );\n\n const matches: FieldMatch[] = names.map((variable) => {\n if (fields.includes(variable)) {\n return { variable, field: variable, kind: \"exact\" };\n }\n const key = normalizeFieldKey(variable);\n const normalized = byKey.get(key);\n if (normalized !== undefined) {\n return { variable, field: normalized, kind: \"normalized\" };\n }\n for (const group of groups) {\n if (!group.includes(key)) continue;\n for (const alias of group) {\n const field = byKey.get(alias);\n if (field !== undefined) return { variable, field, kind: \"alias\" };\n }\n }\n return { variable, field: null, kind: null };\n });\n\n const mapping: Record<string, string | null> = {};\n for (const match of matches) {\n Object.defineProperty(mapping, match.variable, {\n value: match.field,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n const used = new Set(matches.map((m) => m.field));\n return {\n mapping,\n matches,\n unmatchedVariables: matches.filter((m) => !m.field).map((m) => m.variable),\n unusedFields: fields.filter((field) => !used.has(field)),\n };\n}\n\nexport interface RecordToValuesOptions {\n /**\n * Treat blank cells as missing so `{name|default}` falls back to its\n * default (default `true`). With `false`, a blank cell renders as empty.\n */\n blankAsMissing?: boolean;\n}\n\n/**\n * The prompt values for one record: every field under its own name, then\n * each mapped variable set from its field (a `null` mapping leaves the\n * variable unset even if a field shares its name).\n */\nexport function recordToValues(\n record: MergeRecord,\n mapping: Readonly<Record<string, string | null | undefined>> = {},\n options: RecordToValuesOptions = {},\n): PromptValues {\n const blankAsMissing = options.blankAsMissing ?? true;\n const values: PromptValues = {};\n const assign = (name: string, value: string | undefined) => {\n if (value === undefined || (blankAsMissing && value.trim() === \"\")) {\n delete values[name];\n return;\n }\n Object.defineProperty(values, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n };\n const own = (name: string) =>\n Object.prototype.hasOwnProperty.call(record, name) ? record[name] : undefined;\n for (const field of Object.keys(record)) assign(field, record[field]);\n for (const variable of Object.keys(mapping)) {\n const field = mapping[variable];\n if (field === undefined) continue;\n assign(variable, field === null ? undefined : own(field));\n }\n return values;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/mailings.rs\n// (MIT OR Apache-2.0, © ArtCraft Team and contributors). See\n// THIRD_PARTY_NOTICES.md.\n\n/**\n * Multi-record merge: resolves one prompt per data source record with\n * `resolvePrompt`, like Word's Finish & Merge.\n */\nimport type { PromptDiagnostic, PromptValues, Template } from \"./tokens\";\nimport type { SourceMapSegment } from \"./sourcemap\";\nimport { resolvePrompt } from \"./engine\";\nimport { extractVariables } from \"./fields\";\nimport {\n evaluateConditionExpression,\n parseConditionExpression,\n} from \"./variables\";\nimport {\n matchFields,\n parseDataSource,\n recordToValues,\n type DataSourceInput,\n type MergeDataSource,\n type MergeRecord,\n type ParseDataSourceOptions,\n} from \"./data-source\";\n\n/** Default cap on merged outputs. */\nexport const MAX_MERGE_OUTPUTS = 10_000;\n/** Default cap on the total length of merged text (characters). */\nexport const MAX_MERGE_LENGTH = 20_000_000;\n\nexport interface MergeRecordsOptions {\n /** Templates for `{{name}}` tags. */\n templates?: Template[];\n /** Template version bindings. */\n bindings?: Record<string, string>;\n /** Maximum template nesting depth (default 10). */\n maxDepth?: number;\n /**\n * Variable → field. Variables left out are matched automatically with\n * `matchFields`; a `null` entry leaves the variable unset.\n */\n mapping?: Record<string, string | null>;\n /**\n * Text placed between outputs in the joined `text`: default `\"\\n\\n\"`.\n * `\"none\"` joins them with nothing in between.\n */\n separator?: string;\n /**\n * Drops a record's output when this holds. Either a function of the record\n * (and its prompt values), or a condition written like the inside of a\n * section tag: `void`, `!email`, `status=cancelled`, `amount<10`. The\n * condition is evaluated against the record's prompt values (mapped\n * variables and raw field names); a name that is neither is matched to a\n * field like a variable (`status` → `Status`).\n */\n skipIf?:\n | string\n | ((record: MergeRecord, values: PromptValues, index: number) => boolean);\n /** Stop after this many outputs (default `MAX_MERGE_OUTPUTS`). */\n maxOutputs?: number;\n /** Stop once the outputs reach this many characters (default `MAX_MERGE_LENGTH`). */\n maxLength?: number;\n /** First record to merge, 1-based (default 1). */\n from?: number;\n /** Last record to merge, 1-based and inclusive (default: the last). */\n to?: number;\n /** See `recordToValues` (default `true`: blank cells use defaults). */\n blankAsMissing?: boolean;\n /** Options for parsing `source` when it is not already parsed. */\n parse?: ParseDataSourceOptions;\n}\n\nexport interface MergeOutput {\n /** 0-based index of the record in the data source. */\n index: number;\n record: MergeRecord;\n /** The values the prompt was resolved with. */\n values: PromptValues;\n text: string;\n map: SourceMapSegment[];\n}\n\nexport interface MergeSkip {\n index: number;\n record: MergeRecord;\n reason: \"skip-if\";\n}\n\nexport type MergeDiagnosticCode =\n | PromptDiagnostic[\"code\"]\n | \"unmapped-variable\"\n | \"invalid-skip-condition\"\n | \"max-outputs\"\n | \"max-length\"\n | \"data-source\";\n\n/** A grammar diagnostic from the template, or a merge-level problem. */\nexport interface MergeDiagnostic {\n code: MergeDiagnosticCode;\n message: string;\n /** Variable, for grammar and `unmapped-variable` diagnostics. */\n name?: string;\n start?: number;\n end?: number;\n templateName?: string;\n}\n\nexport interface MergeRecordsResult {\n outputs: MergeOutput[];\n skipped: MergeSkip[];\n diagnostics: MergeDiagnostic[];\n /** Every output's text joined with the separator. */\n text: string;\n /** The variable → field mapping used. */\n mapping: Record<string, string | null>;\n /** The merge stopped early at `maxOutputs` or `maxLength`. */\n truncated: boolean;\n}\n\nfunction isParsedSource(source: unknown): source is MergeDataSource {\n return (\n !!source &&\n typeof source === \"object\" &&\n !Array.isArray(source) &&\n Array.isArray((source as MergeDataSource).fields) &&\n Array.isArray((source as MergeDataSource).records)\n );\n}\n\n/**\n * Merges a prompt with every record of a data source: one resolved output per\n * record, in order. Fields are matched to the prompt's variables\n * automatically (override with `mapping`), blank cells fall back to the\n * variable's default, `{?field}` / `{?field>3}` sections are evaluated per\n * record, and `skipIf` drops records. Grammar diagnostics in the prompt are\n * reported once. Never throws.\n */\nexport function mergeRecords(\n template: string,\n source: MergeDataSource | DataSourceInput,\n options: MergeRecordsOptions = {},\n): MergeRecordsResult {\n const data = isParsedSource(source)\n ? source\n : parseDataSource(source, options.parse);\n const diagnostics: MergeDiagnostic[] = [];\n if (!isParsedSource(source)) {\n for (const warning of data.warnings) {\n if (warning.code === \"empty\") continue;\n diagnostics.push({ code: \"data-source\", message: warning.message });\n }\n }\n\n const variables = extractVariables(template, {\n templates: options.templates,\n bindings: options.bindings,\n maxDepth: options.maxDepth,\n });\n const auto = matchFields(variables, data.fields).mapping;\n const mapping: Record<string, string | null> = { ...auto };\n for (const [variable, field] of Object.entries(options.mapping ?? {})) {\n Object.defineProperty(mapping, variable, {\n value: field,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n for (const variable of variables) {\n const field = mapping[variable.name];\n if (\n (field === null || field === undefined) &&\n variable.defaultValue === undefined &&\n variable.usedAsValue\n ) {\n diagnostics.push({\n code: \"unmapped-variable\",\n message: `No field is mapped to \"${variable.name}\", so it stays as a placeholder`,\n name: variable.name,\n });\n }\n }\n\n let skip: ((record: MergeRecord, values: PromptValues, index: number) => boolean) | undefined;\n if (typeof options.skipIf === \"function\") {\n skip = options.skipIf;\n } else if (typeof options.skipIf === \"string\" && options.skipIf.trim()) {\n const parsed = parseConditionExpression(options.skipIf);\n if (\"error\" in parsed) {\n diagnostics.push({\n code: \"invalid-skip-condition\",\n message: `Invalid skipIf condition \"${options.skipIf}\": ${parsed.error}`,\n });\n } else {\n // The condition may name a field the template never uses: match it to\n // a field the same way variables are (`status` → `Status`).\n const field =\n mapping[parsed.name] ??\n matchFields([parsed.name], data.fields).mapping[parsed.name];\n skip = (record, values) => {\n if (\n field &&\n !Object.prototype.hasOwnProperty.call(values, parsed.name) &&\n Object.prototype.hasOwnProperty.call(record, field)\n ) {\n return evaluateConditionExpression(parsed, {\n ...values,\n [parsed.name]: record[field],\n });\n }\n return evaluateConditionExpression(parsed, values);\n };\n }\n }\n\n const separator =\n options.separator === undefined\n ? \"\\n\\n\"\n : options.separator === \"none\"\n ? \"\"\n : options.separator;\n const maxOutputs = Math.max(0, options.maxOutputs ?? MAX_MERGE_OUTPUTS);\n const maxLength = Math.max(0, options.maxLength ?? MAX_MERGE_LENGTH);\n const first = Math.max(1, Math.floor(options.from ?? 1)) - 1;\n const last = Math.min(\n data.records.length,\n Math.floor(options.to ?? data.records.length),\n );\n\n const outputs: MergeOutput[] = [];\n const skipped: MergeSkip[] = [];\n let length = 0;\n let truncated = false;\n let reportedGrammar = false;\n\n for (let index = first; index < last; index++) {\n const record = data.records[index];\n const values = recordToValues(record, mapping, {\n blankAsMissing: options.blankAsMissing,\n });\n if (skip?.(record, values, index)) {\n skipped.push({ index, record, reason: \"skip-if\" });\n continue;\n }\n if (outputs.length >= maxOutputs) {\n truncated = true;\n diagnostics.push({\n code: \"max-outputs\",\n message: `Stopped after ${maxOutputs} outputs`,\n });\n break;\n }\n const resolved = resolvePrompt(template, options.templates, {\n bindings: options.bindings,\n maxDepth: options.maxDepth,\n values,\n });\n if (!reportedGrammar) {\n // The template's grammar diagnostics are the same for every record.\n reportedGrammar = true;\n diagnostics.push(...resolved.diagnostics);\n }\n const added = resolved.text.length + (outputs.length > 0 ? separator.length : 0);\n if (length + added > maxLength) {\n truncated = true;\n diagnostics.push({\n code: \"max-length\",\n message: `Stopped at ${outputs.length} outputs: the merged text would exceed ${maxLength} characters`,\n });\n break;\n }\n length += added;\n outputs.push({ index, record, values, text: resolved.text, map: resolved.map });\n }\n\n return {\n outputs,\n skipped,\n diagnostics,\n text: outputs.map((output) => output.text).join(separator),\n mapping,\n truncated,\n };\n}\n\n/**\n * Serializes merge outputs for copying or download: `\"text\"` joins them with\n * `separator` (default `\"\\n\\n\"`), `\"json\"` writes an array of\n * `{ record, text }` objects (`record` is 1-based).\n */\nexport function serializeMergeOutputs(\n outputs: ReadonlyArray<Pick<MergeOutput, \"index\" | \"text\" | \"values\">>,\n format: \"text\" | \"json\" = \"text\",\n separator = \"\\n\\n\",\n): string {\n if (format === \"json\") {\n return JSON.stringify(\n outputs.map((output) => ({ record: output.index + 1, text: output.text })),\n null,\n 2,\n );\n }\n return outputs.map((output) => output.text).join(separator === \"none\" ? \"\" : separator);\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-UTQKC66X.cjs","../src/grammar/resolver.ts","../src/grammar/sourcemap.ts","../src/grammar/fields.ts","../src/grammar/data-source.ts","../src/grammar/merge.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-UTQKC66X.cjs","sourcesContent":[null,"import {\n TEMPLATE_REGEX,\n VARIABLE_REGEX,\n INSTRUCTION_REGEX,\n Template,\n PromptValues,\n} from \"./tokens\";\nimport { resolvePrompt } from \"./engine\";\nimport { conditionSubject, parseVariableBody } from \"./variables\";\nimport { tokenizePrompt } from \"./tokenizer\";\n\nexport interface ResolveTemplatesOptions {\n bindings?: Record<string, string>;\n maxDepth?: number;\n /**\n * Values for `{variable}` slots and `{?variable}` sections. When omitted,\n * variables, defaults and section tags are left exactly as written.\n */\n values?: PromptValues;\n}\n\n/**\n * Recursively resolves template tags `{{template_name}}` in a given text.\n * A tag that would recurse into itself is replaced with `TEMPLATE_LOOP_ERROR`,\n * and a tag nested deeper than `maxDepth` with `TEMPLATE_DEPTH_ERROR`; the rest\n * of the text still resolves normally.\n *\n * Pass `options.values` to also fill variables (falling back to their\n * `{name|default}`) and evaluate `{?name}…{/name}` / `{!name}…{/name}`\n * sections, including those inside template bodies. See `resolvePrompt` for\n * the source map and diagnostics.\n */\nexport function resolveTemplates(\n text: string,\n templates: Template[] = [],\n options?: ResolveTemplatesOptions,\n): string {\n return resolvePrompt(text, templates, options).text;\n}\n\n/**\n * Replaces `{variableName}` with values from a dictionary, falling back to a\n * `{variableName|default}` when no value is supplied, and evaluates\n * `{?name}…{/name}` / `{!name}…{/name}` sections. Variables with neither a\n * value nor a default are left as written. Templates are not expanded.\n */\nexport function resolveVariables(\n text: string,\n values: PromptValues,\n): string {\n if (!text) return \"\";\n return resolvePrompt(text, [], { values }).text;\n}\n\n/**\n * Extracts unique template names referenced in text.\n */\nexport function extractTemplateNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(TEMPLATE_REGEX.source, TEMPLATE_REGEX.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n set.add(match[1].trim());\n }\n return Array.from(set);\n}\n\n/**\n * Extracts unique variable names referenced in text, including names used by\n * conditional section tags (`amount` for `{?amount>100}…{/amount}`).\n * Defaults and descriptions are stripped.\n */\nexport function extractVariableNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(VARIABLE_REGEX.source, VARIABLE_REGEX.flags);\n let comparisonStarts: Set<number> | undefined;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n const parsed = parseVariableBody(match[1]);\n let name = parsed.name;\n if (parsed.kind === \"conditional\" && parsed.conditional !== \"end\") {\n const subject = conditionSubject(name);\n if (subject) {\n // Only a tag closed by `{/subject}` is a comparison on `subject`.\n comparisonStarts ??= new Set(\n tokenizePrompt(text)\n .filter((token) => token.comparison)\n .map((token) => token.start),\n );\n if (comparisonStarts.has(match.index)) name = subject;\n }\n }\n set.add(name);\n }\n return Array.from(set);\n}\n\n/**\n * Extracts unique instruction names referenced in text.\n */\nexport function extractInstructionNames(text: string): string[] {\n if (!text) return [];\n const set = new Set<string>();\n const regex = new RegExp(INSTRUCTION_REGEX.source, INSTRUCTION_REGEX.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n set.add(match[1].trim());\n }\n return Array.from(set);\n}\n","import type { PromptDiagnostic, Template } from \"./tokens\";\nimport type { ResolveTemplatesOptions } from \"./resolver\";\nimport { resolvePrompt } from \"./engine\";\nimport { getPromptDiagnostics } from \"./tokenizer\";\n\n/**\n * One contiguous piece of resolved output and the raw range it came from.\n *\n * - `raw`: copied verbatim; offsets map character by character.\n * - `template`: the expansion of a `{{template}}` tag.\n * - `variable`: a substituted value or `|default` for a `{variable}` tag.\n * - `conditional`: a section tag, or a whole removed section. These segments\n * are empty in the resolved text (`resolvedStart === resolvedEnd`).\n *\n * Offsets inside non-raw segments map to the start of their raw range.\n */\nexport interface SourceMapSegment {\n resolvedStart: number;\n resolvedEnd: number;\n source: \"raw\" | \"template\" | \"variable\" | \"conditional\";\n rawStart: number;\n rawEnd: number;\n templateName?: string;\n /** Variable substituted (`variable`) or tested (`conditional`). */\n variableName?: string;\n /** For `variable` segments: whether a supplied value or the default was used. */\n valueSource?: \"value\" | \"default\";\n}\n\n/**\n * Resolves templates in text while tracking character offset mapping\n * between the raw input and the fully resolved output.\n *\n * Pass `options.values` to also substitute variables and evaluate conditional\n * sections (see `resolvePrompt`); without it the output is unchanged from the\n * template-only behavior.\n */\nexport function resolveTemplatesWithMapping(\n text: string,\n templates: Template[] = [],\n templateBindings?: Record<string, string>,\n options?: Pick<ResolveTemplatesOptions, \"maxDepth\" | \"values\">,\n): { text: string; map: SourceMapSegment[]; diagnostics: PromptDiagnostic[] } {\n if (\n options?.values === undefined &&\n (!templates || templates.length === 0 || !text.includes(\"{{\"))\n ) {\n return {\n diagnostics: getPromptDiagnostics(text),\n text,\n map: [\n {\n resolvedStart: 0,\n resolvedEnd: text.length,\n source: \"raw\",\n rawStart: 0,\n rawEnd: text.length,\n },\n ],\n };\n }\n\n return resolvePrompt(text, templates, {\n bindings: templateBindings,\n maxDepth: options?.maxDepth,\n values: options?.values,\n });\n}\n\n/**\n * Maps an offset in resolved text back to the corresponding offset in raw text.\n */\nexport function mapResolvedOffsetToRaw(\n resolvedOffset: number,\n map: SourceMapSegment[],\n): number {\n for (let i = 0; i < map.length; i++) {\n const seg = map[i];\n const isLast = i === map.length - 1;\n const inRange = isLast\n ? resolvedOffset >= seg.resolvedStart && resolvedOffset <= seg.resolvedEnd\n : resolvedOffset >= seg.resolvedStart && resolvedOffset < seg.resolvedEnd;\n\n if (inRange) {\n if (seg.source === \"raw\") {\n return seg.rawStart + (resolvedOffset - seg.resolvedStart);\n }\n // The end of the text maps to the end of the tag; anywhere inside a\n // resolved template maps to the start of its tag.\n if (resolvedOffset === seg.resolvedEnd) {\n return seg.rawEnd;\n }\n return seg.rawStart;\n }\n }\n return resolvedOffset;\n}\n\n/**\n * Maps an offset in raw text to the corresponding offset in resolved text.\n */\nexport function mapRawOffsetToResolved(\n rawOffset: number,\n map: SourceMapSegment[],\n): number {\n for (let i = 0; i < map.length; i++) {\n const seg = map[i];\n const isLast = i === map.length - 1;\n const inRange = isLast\n ? rawOffset >= seg.rawStart && rawOffset <= seg.rawEnd\n : rawOffset >= seg.rawStart && rawOffset < seg.rawEnd;\n\n if (inRange) {\n if (seg.source === \"raw\") {\n return seg.resolvedStart + (rawOffset - seg.rawStart);\n }\n if (rawOffset === seg.rawEnd) {\n return seg.resolvedEnd;\n }\n return seg.resolvedStart;\n }\n }\n return rawOffset;\n}\n","import type { PromptValues, Template } from \"./tokens\";\nimport { tokenizePrompt } from \"./tokenizer\";\nimport { getTemplateBody } from \"./engine\";\n\n/** Everything a prompt (and, optionally, its templates) says about one variable. */\nexport interface VariableDescriptor {\n name: string;\n /** First `{name|default}` found. */\n defaultValue?: string;\n /** First `{name|default|description}` found. */\n description?: string;\n /** Appears as a `{name}` slot. */\n usedAsValue: boolean;\n /** Appears in a `{?name}` / `{!name}` condition (including comparisons). */\n usedInCondition: boolean;\n /**\n * Present (and `true`) when the variable is compared in a condition such as\n * `{?amount>100}`, so a form should ask for its text, not a checkbox.\n */\n usedInComparison?: true;\n /** Number of `{name…}` slots and condition tags (closing tags excluded). */\n occurrences: number;\n /** Templates whose bodies mention the variable, in discovery order. */\n templates: string[];\n}\n\nexport interface ExtractVariablesOptions {\n /** Templates to search recursively for further variables. */\n templates?: Template[];\n bindings?: Record<string, string>;\n /** Maximum template nesting depth to search (default 10). */\n maxDepth?: number;\n}\n\n/**\n * Lists every variable a prompt uses, in order of first appearance, with its\n * default and description. Templates referenced by the prompt are searched\n * recursively when `options.templates` is given (loops are skipped). All\n * sections are searched, whatever their condition would evaluate to.\n */\nexport function extractVariables(\n text: string,\n options: ExtractVariablesOptions = {},\n): VariableDescriptor[] {\n const descriptors = new Map<string, VariableDescriptor>();\n const templateMap = new Map(\n (options.templates ?? []).map((t) => [t.name, t] as const),\n );\n const maxDepth = options.maxDepth ?? 10;\n\n const describe = (name: string, templateName?: string) => {\n let descriptor = descriptors.get(name);\n if (!descriptor) {\n descriptor = {\n name,\n usedAsValue: false,\n usedInCondition: false,\n occurrences: 0,\n templates: [],\n };\n descriptors.set(name, descriptor);\n }\n descriptor.occurrences++;\n if (templateName && !descriptor.templates.includes(templateName)) {\n descriptor.templates.push(templateName);\n }\n return descriptor;\n };\n\n const visit = (\n source: string,\n visited: Set<string>,\n depth: number,\n templateName?: string,\n ) => {\n for (const token of tokenizePrompt(source)) {\n if (token.type === \"variable\") {\n const descriptor = describe(token.value, templateName);\n descriptor.usedAsValue = true;\n if (descriptor.defaultValue === undefined && token.defaultValue !== undefined) {\n descriptor.defaultValue = token.defaultValue;\n }\n if (descriptor.description === undefined && token.description !== undefined) {\n descriptor.description = token.description;\n }\n } else if (token.type === \"conditional\" && token.conditional !== \"end\") {\n const descriptor = describe(token.value, templateName);\n descriptor.usedInCondition = true;\n if (token.comparison) descriptor.usedInComparison = true;\n } else if (token.type === \"template\") {\n const template = templateMap.get(token.value);\n if (!template || visited.has(token.value) || depth + 1 > maxDepth) {\n continue;\n }\n const body = getTemplateBody(template, options.bindings);\n if (body === undefined) continue;\n visit(body, new Set(visited).add(token.value), depth + 1, token.value);\n }\n }\n };\n\n if (text) visit(text, new Set(), 0);\n return Array.from(descriptors.values());\n}\n\n/** A headless description of one input in a variable fill-in form. */\nexport interface VariableFormField {\n name: string;\n /** The variable's description, or its name. */\n label: string;\n /** The variable's default, or an empty string. */\n placeholder: string;\n defaultValue?: string;\n description?: string;\n /**\n * The variable is used as a slot and has no default, so leaving it blank\n * leaves the `{name}` placeholder in the resolved prompt.\n */\n required: boolean;\n /**\n * Only used by `{?name}` / `{!name}` presence conditions, never substituted\n * or compared (a form can show a checkbox).\n */\n conditionOnly: boolean;\n}\n\n/**\n * Builds field descriptors for a fill-in form (Word's FILLIN analogue): one\n * per variable, labelled with its description and using its default as the\n * placeholder. Feed the entered text through `compactVariableValues` before\n * resolving so blank inputs fall back to defaults.\n */\nexport function getVariableFormFields(\n text: string,\n options: ExtractVariablesOptions = {},\n): VariableFormField[] {\n return extractVariables(text, options).map((variable) => ({\n name: variable.name,\n label: variable.description || variable.name,\n placeholder: variable.defaultValue ?? \"\",\n ...(variable.defaultValue !== undefined\n ? { defaultValue: variable.defaultValue }\n : {}),\n ...(variable.description !== undefined\n ? { description: variable.description }\n : {}),\n required: variable.usedAsValue && variable.defaultValue === undefined,\n conditionOnly: !variable.usedAsValue && !variable.usedInComparison,\n }));\n}\n\n/**\n * Drops blank entries from form input so the resolver falls back to each\n * variable's default (an explicit `\"\"` value would otherwise render as empty).\n */\nexport function compactVariableValues(\n input: Record<string, string | null | undefined>,\n): PromptValues {\n const values: PromptValues = {};\n for (const [name, value] of Object.entries(input)) {\n if (value !== null && value !== undefined && value.trim() !== \"\") {\n values[name] = value;\n }\n }\n return values;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/mailings.rs and\n// wordcraft/crates/formats/src/sheet.rs (MIT OR Apache-2.0, © ArtCraft Team\n// and contributors). See THIRD_PARTY_NOTICES.md.\n\n/**\n * Mail-merge data sources: CSV / TSV text, JSON, rows or objects normalised\n * into named fields and string records, plus fuzzy matching of prompt\n * variables to those fields.\n *\n * Imports only the self-contained CSV module, never the spreadsheet entry, so\n * the grammar entry stays light.\n */\nimport { parseCsv } from \"../spreadsheet/csv\";\nimport type { PromptValues } from \"./tokens\";\n\n/** Most records a data source keeps by default. */\nexport const MAX_DATA_SOURCE_RECORDS = 100_000;\n/** Most fields a data source keeps by default. */\nexport const MAX_DATA_SOURCE_FIELDS = 1_000;\n\n/** One record: field name → cell text. */\nexport type MergeRecord = Record<string, string>;\n\n/** Anything `parseDataSource` accepts. */\nexport type DataSourceInput =\n | string\n | ReadonlyArray<ReadonlyArray<unknown>>\n | ReadonlyArray<Readonly<Record<string, unknown>>>;\n\nexport interface ParseDataSourceOptions {\n /**\n * Field separator for delimited text. `\"auto\"` (the default) picks whichever\n * of `,` `;` and tab occurs most often in the first line (outside quotes),\n * preferring `,` on a tie.\n */\n delimiter?: \"auto\" | string;\n /**\n * Whether the first row names the fields (default `true`). Without a header\n * the fields are `Column 1`…`Column N`. Ignored for arrays of objects.\n */\n hasHeader?: boolean;\n /**\n * How to read a string: `\"auto\"` (default) parses text starting with `[` as\n * JSON and falls back to delimited text when that fails.\n */\n format?: \"auto\" | \"csv\" | \"json\";\n /** Record cap (default `MAX_DATA_SOURCE_RECORDS`). */\n maxRecords?: number;\n /** Field cap (default `MAX_DATA_SOURCE_FIELDS`). */\n maxFields?: number;\n}\n\nexport type DataSourceWarningCode =\n | \"empty\"\n | \"invalid-json\"\n | \"unsupported-json\"\n | \"blank-header\"\n | \"duplicate-header\"\n | \"ragged-rows\"\n | \"records-truncated\"\n | \"fields-truncated\";\n\nexport interface DataSourceWarning {\n code: DataSourceWarningCode;\n message: string;\n /** For `ragged-rows`: how many records were padded or cut. */\n count?: number;\n}\n\nexport interface MergeDataSource {\n /** Field names: trimmed, unique (case-insensitively), never blank. */\n fields: string[];\n /** One entry per record, with every field present. */\n records: MergeRecord[];\n warnings: DataSourceWarning[];\n /** How the input was read. */\n format: \"csv\" | \"json\" | \"rows\" | \"objects\";\n /** The delimiter used for delimited text. */\n delimiter?: string;\n}\n\nconst AUTO_DELIMITERS = [\",\", \";\", \"\\t\"];\n\n/** Counts the auto-detect candidates in the first line, ignoring quoted text. */\nexport function detectDelimiter(text: string): string {\n const counts = new Map<string, number>(AUTO_DELIMITERS.map((d) => [d, 0]));\n let quoted = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (ch === '\"') {\n quoted = !quoted;\n continue;\n }\n if (quoted) continue;\n if (ch === \"\\n\" || ch === \"\\r\") break;\n if (counts.has(ch)) counts.set(ch, counts.get(ch)! + 1);\n }\n let best = \",\";\n for (const d of AUTO_DELIMITERS) {\n if (counts.get(d)! > counts.get(best)!) best = d;\n }\n return best;\n}\n\n/**\n * Field names from a header row: names are trimmed, a blank name becomes\n * `Column N` (its 1-based position), and repeats (compared case-insensitively)\n * are numbered `Name 2`, `Name 3`, ….\n */\nexport function normalizeFieldNames(row: ReadonlyArray<unknown>): string[] {\n const out: string[] = [];\n const taken = new Set<string>();\n row.forEach((cell, i) => {\n const trimmed = cellText(cell).trim();\n const base = trimmed === \"\" ? `Column ${i + 1}` : trimmed;\n let name = base;\n for (let k = 2; taken.has(name.toLowerCase()); k++) name = `${base} ${k}`;\n taken.add(name.toLowerCase());\n out.push(name);\n });\n return out;\n}\n\nfunction cellText(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"object\") {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n/** Sets an own property, even for names such as `__proto__`. */\nfunction setField(record: MergeRecord, name: string, value: string): void {\n Object.defineProperty(record, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n}\n\nfunction isBlankRow(row: ReadonlyArray<unknown>): boolean {\n return row.every((cell) => cellText(cell).trim() === \"\");\n}\n\n/**\n * Reads a mail-merge data source.\n *\n * - **Text**: CSV / TSV (RFC 4180 quoting, doubled quotes, CRLF / LF / CR,\n * a leading BOM ignored) with the delimiter auto-detected, or JSON (an\n * array of objects or of arrays).\n * - **Rows** (`unknown[][]`): the first row is the header unless\n * `hasHeader: false`.\n * - **Objects**: the fields are the union of keys in first-seen order.\n *\n * Blank rows are skipped, header names are normalised (`normalizeFieldNames`),\n * records are padded or cut to the header width, and records and fields are\n * capped. Cells become strings (`null` → `\"\"`, nested values → JSON). Problems\n * are reported in `warnings`; this never throws.\n */\nexport function parseDataSource(\n input: DataSourceInput,\n options: ParseDataSourceOptions = {},\n): MergeDataSource {\n const warnings: DataSourceWarning[] = [];\n if (typeof input === \"string\") {\n const format = options.format ?? \"auto\";\n const trimmed = input.trim();\n if (format === \"json\" || (format === \"auto\" && /^\\[/.test(trimmed))) {\n let parsed: unknown;\n let ok = true;\n try {\n parsed = JSON.parse(trimmed);\n } catch (error) {\n ok = false;\n if (format === \"json\") {\n warnings.push({\n code: \"invalid-json\",\n message: `Invalid JSON: ${(error as Error).message}`,\n });\n return { fields: [], records: [], warnings, format: \"json\" };\n }\n }\n if (ok) {\n if (!Array.isArray(parsed)) {\n warnings.push({\n code: \"unsupported-json\",\n message: \"JSON data must be an array of objects or of arrays\",\n });\n return { fields: [], records: [], warnings, format: \"json\" };\n }\n const result = fromArray(parsed, options, warnings);\n return { ...result, format: \"json\" };\n }\n }\n const delimiter =\n !options.delimiter || options.delimiter === \"auto\"\n ? detectDelimiter(input)\n : options.delimiter;\n let rows: string[][];\n try {\n rows = parseCsv(input, { delimiter });\n } catch (error) {\n warnings.push({ code: \"empty\", message: (error as Error).message });\n return { fields: [], records: [], warnings, format: \"csv\", delimiter };\n }\n return {\n ...fromRows(rows, options, warnings),\n format: \"csv\",\n delimiter,\n };\n }\n const result = fromArray(input as ReadonlyArray<unknown>, options, warnings);\n return {\n ...result,\n format: result.objects ? \"objects\" : \"rows\",\n };\n}\n\nfunction fromArray(\n items: ReadonlyArray<unknown>,\n options: ParseDataSourceOptions,\n warnings: DataSourceWarning[],\n): { fields: string[]; records: MergeRecord[]; warnings: DataSourceWarning[]; objects: boolean } {\n const objects = items.some(\n (item) => item !== null && typeof item === \"object\" && !Array.isArray(item),\n );\n if (!objects) {\n const rows = items.filter((item): item is unknown[] => Array.isArray(item));\n return { ...fromRows(rows, options, warnings), objects: false };\n }\n const maxFields = options.maxFields ?? MAX_DATA_SOURCE_FIELDS;\n const maxRecords = options.maxRecords ?? MAX_DATA_SOURCE_RECORDS;\n const fields: string[] = [];\n const seen = new Set<string>();\n let fieldsTruncated = false;\n const rows = items.filter(\n (item): item is Record<string, unknown> =>\n item !== null && typeof item === \"object\" && !Array.isArray(item),\n );\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (seen.has(key)) continue;\n if (fields.length >= maxFields) {\n fieldsTruncated = true;\n continue;\n }\n seen.add(key);\n fields.push(key);\n }\n }\n if (fieldsTruncated) {\n warnings.push({\n code: \"fields-truncated\",\n message: `Only the first ${maxFields} fields were kept`,\n });\n }\n const records: MergeRecord[] = [];\n for (const row of rows) {\n if (fields.every((field) => cellText(row[field]).trim() === \"\")) continue;\n if (records.length >= maxRecords) {\n warnings.push({\n code: \"records-truncated\",\n message: `Only the first ${maxRecords} records were kept`,\n });\n break;\n }\n const record: MergeRecord = {};\n for (const field of fields) {\n const value = Object.prototype.hasOwnProperty.call(row, field)\n ? row[field]\n : undefined;\n setField(record, field, cellText(value));\n }\n records.push(record);\n }\n if (records.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n }\n return { fields, records, warnings, objects: true };\n}\n\nfunction fromRows(\n allRows: ReadonlyArray<ReadonlyArray<unknown>>,\n options: ParseDataSourceOptions,\n warnings: DataSourceWarning[],\n): { fields: string[]; records: MergeRecord[]; warnings: DataSourceWarning[] } {\n const maxFields = options.maxFields ?? MAX_DATA_SOURCE_FIELDS;\n const maxRecords = options.maxRecords ?? MAX_DATA_SOURCE_RECORDS;\n const rows = allRows.filter((row) => !isBlankRow(row));\n if (rows.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n return { fields: [], records: [], warnings };\n }\n const hasHeader = options.hasHeader ?? true;\n let fields: string[];\n let body: ReadonlyArray<ReadonlyArray<unknown>>;\n let widest: number;\n if (hasHeader) {\n const header = rows[0];\n widest = header.length;\n if (header.some((cell) => cellText(cell).trim() === \"\")) {\n warnings.push({\n code: \"blank-header\",\n message: \"Blank column headers were named \\\"Column N\\\"\",\n });\n }\n fields = normalizeFieldNames(header.slice(0, maxFields));\n const lower = header.map((cell) => cellText(cell).trim().toLowerCase());\n if (lower.some((name, i) => name !== \"\" && lower.indexOf(name) !== i)) {\n warnings.push({\n code: \"duplicate-header\",\n message: \"Repeated column headers were numbered\",\n });\n }\n body = rows.slice(1);\n } else {\n widest = Math.max(...rows.map((row) => row.length));\n fields = Array.from(\n { length: Math.min(widest, maxFields) },\n (_, i) => `Column ${i + 1}`,\n );\n body = rows;\n }\n if (widest > maxFields) {\n warnings.push({\n code: \"fields-truncated\",\n message: `Only the first ${maxFields} fields were kept`,\n });\n }\n if (body.length > maxRecords) {\n warnings.push({\n code: \"records-truncated\",\n message: `Only the first ${maxRecords} of ${body.length} records were kept`,\n });\n body = body.slice(0, maxRecords);\n }\n let ragged = 0;\n const records = body.map((row) => {\n if (hasHeader && row.length !== widest) ragged++;\n const record: MergeRecord = {};\n fields.forEach((field, i) => setField(record, field, cellText(row[i])));\n return record;\n });\n if (ragged > 0) {\n warnings.push({\n code: \"ragged-rows\",\n message: `${ragged} record${ragged === 1 ? \" was\" : \"s were\"} padded or cut to ${widest} fields`,\n count: ragged,\n });\n }\n if (records.length === 0) {\n warnings.push({ code: \"empty\", message: \"The data source has no records\" });\n }\n return { fields, records, warnings };\n}\n\n/** Lower-cases and drops spaces, `_`, `-` and `.` so `First Name` matches `first_name`. */\nexport function normalizeFieldKey(name: string): string {\n return name.toLowerCase().replace(/[\\s_.\\-]+/g, \"\");\n}\n\n/**\n * Built-in alias groups for `matchFields`: any name in a group matches any\n * other (after `normalizeFieldKey`). Extended from Word's address-block\n * field detection.\n */\nexport const FIELD_ALIASES: ReadonlyArray<ReadonlyArray<string>> = [\n [\"FirstName\", \"First\", \"GivenName\", \"Forename\", \"FName\"],\n [\"LastName\", \"Last\", \"Surname\", \"FamilyName\", \"LName\"],\n [\"Name\", \"FullName\", \"DisplayName\"],\n [\"Company\", \"CompanyName\", \"Organization\", \"Organisation\", \"Employer\", \"Business\"],\n [\"Address\", \"AddressLine1\", \"Address1\", \"Street\", \"StreetAddress\"],\n [\"City\", \"Town\"],\n [\"State\", \"Province\", \"Region\", \"County\"],\n [\"PostalCode\", \"ZIP\", \"ZipCode\", \"Postcode\"],\n [\"Country\", \"CountryName\", \"Nation\"],\n [\"Title\", \"CourtesyTitle\", \"Salutation\", \"Honorific\"],\n [\"Email\", \"EmailAddress\", \"Mail\", \"EMail\"],\n [\"Phone\", \"PhoneNumber\", \"Telephone\", \"Tel\", \"Mobile\"],\n];\n\nexport type FieldMatchKind = \"exact\" | \"normalized\" | \"alias\";\n\nexport interface FieldMatch {\n variable: string;\n /** The matched field, or `null`. */\n field: string | null;\n kind: FieldMatchKind | null;\n}\n\nexport interface FieldMapping {\n /** Variable → field (or `null` when unmatched), in variable order. */\n mapping: Record<string, string | null>;\n matches: FieldMatch[];\n unmatchedVariables: string[];\n /** Fields no variable maps to. */\n unusedFields: string[];\n}\n\nexport interface MatchFieldsOptions {\n /** Extra alias groups, checked after the built-in ones. */\n aliases?: ReadonlyArray<ReadonlyArray<string>>;\n}\n\n/**\n * Maps prompt variables to data source fields: an exact name first, then a\n * case-, space- and punctuation-insensitive match (`first_name` ↔\n * `First Name`), then an alias (`FirstName` ↔ `First` / `GivenName`, see\n * `FIELD_ALIASES`). Several variables may map to the same field.\n */\nexport function matchFields(\n variables: ReadonlyArray<string | { name: string }>,\n fields: ReadonlyArray<string>,\n options: MatchFieldsOptions = {},\n): FieldMapping {\n const names = Array.from(\n new Set(variables.map((v) => (typeof v === \"string\" ? v : v.name))),\n );\n const byKey = new Map<string, string>();\n for (const field of fields) {\n const key = normalizeFieldKey(field);\n if (!byKey.has(key)) byKey.set(key, field);\n }\n const groups = [...FIELD_ALIASES, ...(options.aliases ?? [])].map((group) =>\n group.map(normalizeFieldKey),\n );\n\n const matches: FieldMatch[] = names.map((variable) => {\n if (fields.includes(variable)) {\n return { variable, field: variable, kind: \"exact\" };\n }\n const key = normalizeFieldKey(variable);\n const normalized = byKey.get(key);\n if (normalized !== undefined) {\n return { variable, field: normalized, kind: \"normalized\" };\n }\n for (const group of groups) {\n if (!group.includes(key)) continue;\n for (const alias of group) {\n const field = byKey.get(alias);\n if (field !== undefined) return { variable, field, kind: \"alias\" };\n }\n }\n return { variable, field: null, kind: null };\n });\n\n const mapping: Record<string, string | null> = {};\n for (const match of matches) {\n Object.defineProperty(mapping, match.variable, {\n value: match.field,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n const used = new Set(matches.map((m) => m.field));\n return {\n mapping,\n matches,\n unmatchedVariables: matches.filter((m) => !m.field).map((m) => m.variable),\n unusedFields: fields.filter((field) => !used.has(field)),\n };\n}\n\nexport interface RecordToValuesOptions {\n /**\n * Treat blank cells as missing so `{name|default}` falls back to its\n * default (default `true`). With `false`, a blank cell renders as empty.\n */\n blankAsMissing?: boolean;\n}\n\n/**\n * The prompt values for one record: every field under its own name, then\n * each mapped variable set from its field (a `null` mapping leaves the\n * variable unset even if a field shares its name).\n */\nexport function recordToValues(\n record: MergeRecord,\n mapping: Readonly<Record<string, string | null | undefined>> = {},\n options: RecordToValuesOptions = {},\n): PromptValues {\n const blankAsMissing = options.blankAsMissing ?? true;\n const values: PromptValues = {};\n const assign = (name: string, value: string | undefined) => {\n if (value === undefined || (blankAsMissing && value.trim() === \"\")) {\n delete values[name];\n return;\n }\n Object.defineProperty(values, name, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n };\n const own = (name: string) =>\n Object.prototype.hasOwnProperty.call(record, name) ? record[name] : undefined;\n for (const field of Object.keys(record)) assign(field, record[field]);\n for (const variable of Object.keys(mapping)) {\n const field = mapping[variable];\n if (field === undefined) continue;\n assign(variable, field === null ? undefined : own(field));\n }\n return values;\n}\n","// Portions ported from wordcraft/crates/engine/src/cmd/mailings.rs\n// (MIT OR Apache-2.0, © ArtCraft Team and contributors). See\n// THIRD_PARTY_NOTICES.md.\n\n/**\n * Multi-record merge: resolves one prompt per data source record with\n * `resolvePrompt`, like Word's Finish & Merge.\n */\nimport type { PromptDiagnostic, PromptValues, Template } from \"./tokens\";\nimport type { SourceMapSegment } from \"./sourcemap\";\nimport { resolvePrompt } from \"./engine\";\nimport { extractVariables } from \"./fields\";\nimport {\n evaluateConditionExpression,\n parseConditionExpression,\n} from \"./variables\";\nimport {\n matchFields,\n parseDataSource,\n recordToValues,\n type DataSourceInput,\n type MergeDataSource,\n type MergeRecord,\n type ParseDataSourceOptions,\n} from \"./data-source\";\n\n/** Default cap on merged outputs. */\nexport const MAX_MERGE_OUTPUTS = 10_000;\n/** Default cap on the total length of merged text (characters). */\nexport const MAX_MERGE_LENGTH = 20_000_000;\n\nexport interface MergeRecordsOptions {\n /** Templates for `{{name}}` tags. */\n templates?: Template[];\n /** Template version bindings. */\n bindings?: Record<string, string>;\n /** Maximum template nesting depth (default 10). */\n maxDepth?: number;\n /**\n * Variable → field. Variables left out are matched automatically with\n * `matchFields`; a `null` entry leaves the variable unset.\n */\n mapping?: Record<string, string | null>;\n /**\n * Text placed between outputs in the joined `text`: default `\"\\n\\n\"`.\n * `\"none\"` joins them with nothing in between.\n */\n separator?: string;\n /**\n * Drops a record's output when this holds. Either a function of the record\n * (and its prompt values), or a condition written like the inside of a\n * section tag: `void`, `!email`, `status=cancelled`, `amount<10`. The\n * condition is evaluated against the record's prompt values (mapped\n * variables and raw field names); a name that is neither is matched to a\n * field like a variable (`status` → `Status`).\n */\n skipIf?:\n | string\n | ((record: MergeRecord, values: PromptValues, index: number) => boolean);\n /** Stop after this many outputs (default `MAX_MERGE_OUTPUTS`). */\n maxOutputs?: number;\n /** Stop once the outputs reach this many characters (default `MAX_MERGE_LENGTH`). */\n maxLength?: number;\n /** First record to merge, 1-based (default 1). */\n from?: number;\n /** Last record to merge, 1-based and inclusive (default: the last). */\n to?: number;\n /** See `recordToValues` (default `true`: blank cells use defaults). */\n blankAsMissing?: boolean;\n /** Options for parsing `source` when it is not already parsed. */\n parse?: ParseDataSourceOptions;\n}\n\nexport interface MergeOutput {\n /** 0-based index of the record in the data source. */\n index: number;\n record: MergeRecord;\n /** The values the prompt was resolved with. */\n values: PromptValues;\n text: string;\n map: SourceMapSegment[];\n}\n\nexport interface MergeSkip {\n index: number;\n record: MergeRecord;\n reason: \"skip-if\";\n}\n\nexport type MergeDiagnosticCode =\n | PromptDiagnostic[\"code\"]\n | \"unmapped-variable\"\n | \"invalid-skip-condition\"\n | \"max-outputs\"\n | \"max-length\"\n | \"data-source\";\n\n/** A grammar diagnostic from the template, or a merge-level problem. */\nexport interface MergeDiagnostic {\n code: MergeDiagnosticCode;\n message: string;\n /** Variable, for grammar and `unmapped-variable` diagnostics. */\n name?: string;\n start?: number;\n end?: number;\n templateName?: string;\n}\n\nexport interface MergeRecordsResult {\n outputs: MergeOutput[];\n skipped: MergeSkip[];\n diagnostics: MergeDiagnostic[];\n /** Every output's text joined with the separator. */\n text: string;\n /** The variable → field mapping used. */\n mapping: Record<string, string | null>;\n /** The merge stopped early at `maxOutputs` or `maxLength`. */\n truncated: boolean;\n}\n\nfunction isParsedSource(source: unknown): source is MergeDataSource {\n return (\n !!source &&\n typeof source === \"object\" &&\n !Array.isArray(source) &&\n Array.isArray((source as MergeDataSource).fields) &&\n Array.isArray((source as MergeDataSource).records)\n );\n}\n\n/**\n * Merges a prompt with every record of a data source: one resolved output per\n * record, in order. Fields are matched to the prompt's variables\n * automatically (override with `mapping`), blank cells fall back to the\n * variable's default, `{?field}` / `{?field>3}` sections are evaluated per\n * record, and `skipIf` drops records. Grammar diagnostics in the prompt are\n * reported once. Never throws.\n */\nexport function mergeRecords(\n template: string,\n source: MergeDataSource | DataSourceInput,\n options: MergeRecordsOptions = {},\n): MergeRecordsResult {\n const data = isParsedSource(source)\n ? source\n : parseDataSource(source, options.parse);\n const diagnostics: MergeDiagnostic[] = [];\n if (!isParsedSource(source)) {\n for (const warning of data.warnings) {\n if (warning.code === \"empty\") continue;\n diagnostics.push({ code: \"data-source\", message: warning.message });\n }\n }\n\n const variables = extractVariables(template, {\n templates: options.templates,\n bindings: options.bindings,\n maxDepth: options.maxDepth,\n });\n const auto = matchFields(variables, data.fields).mapping;\n const mapping: Record<string, string | null> = { ...auto };\n for (const [variable, field] of Object.entries(options.mapping ?? {})) {\n Object.defineProperty(mapping, variable, {\n value: field,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n for (const variable of variables) {\n const field = mapping[variable.name];\n if (\n (field === null || field === undefined) &&\n variable.defaultValue === undefined &&\n variable.usedAsValue\n ) {\n diagnostics.push({\n code: \"unmapped-variable\",\n message: `No field is mapped to \"${variable.name}\", so it stays as a placeholder`,\n name: variable.name,\n });\n }\n }\n\n let skip: ((record: MergeRecord, values: PromptValues, index: number) => boolean) | undefined;\n if (typeof options.skipIf === \"function\") {\n skip = options.skipIf;\n } else if (typeof options.skipIf === \"string\" && options.skipIf.trim()) {\n const parsed = parseConditionExpression(options.skipIf);\n if (\"error\" in parsed) {\n diagnostics.push({\n code: \"invalid-skip-condition\",\n message: `Invalid skipIf condition \"${options.skipIf}\": ${parsed.error}`,\n });\n } else {\n // The condition may name a field the template never uses: match it to\n // a field the same way variables are (`status` → `Status`).\n const field =\n mapping[parsed.name] ??\n matchFields([parsed.name], data.fields).mapping[parsed.name];\n skip = (record, values) => {\n if (\n field &&\n !Object.prototype.hasOwnProperty.call(values, parsed.name) &&\n Object.prototype.hasOwnProperty.call(record, field)\n ) {\n return evaluateConditionExpression(parsed, {\n ...values,\n [parsed.name]: record[field],\n });\n }\n return evaluateConditionExpression(parsed, values);\n };\n }\n }\n\n const separator =\n options.separator === undefined\n ? \"\\n\\n\"\n : options.separator === \"none\"\n ? \"\"\n : options.separator;\n const maxOutputs = Math.max(0, options.maxOutputs ?? MAX_MERGE_OUTPUTS);\n const maxLength = Math.max(0, options.maxLength ?? MAX_MERGE_LENGTH);\n const first = Math.max(1, Math.floor(options.from ?? 1)) - 1;\n const last = Math.min(\n data.records.length,\n Math.floor(options.to ?? data.records.length),\n );\n\n const outputs: MergeOutput[] = [];\n const skipped: MergeSkip[] = [];\n let length = 0;\n let truncated = false;\n let reportedGrammar = false;\n\n for (let index = first; index < last; index++) {\n const record = data.records[index];\n const values = recordToValues(record, mapping, {\n blankAsMissing: options.blankAsMissing,\n });\n if (skip?.(record, values, index)) {\n skipped.push({ index, record, reason: \"skip-if\" });\n continue;\n }\n if (outputs.length >= maxOutputs) {\n truncated = true;\n diagnostics.push({\n code: \"max-outputs\",\n message: `Stopped after ${maxOutputs} outputs`,\n });\n break;\n }\n const resolved = resolvePrompt(template, options.templates, {\n bindings: options.bindings,\n maxDepth: options.maxDepth,\n values,\n });\n if (!reportedGrammar) {\n // The template's grammar diagnostics are the same for every record.\n reportedGrammar = true;\n diagnostics.push(...resolved.diagnostics);\n }\n const added = resolved.text.length + (outputs.length > 0 ? separator.length : 0);\n if (length + added > maxLength) {\n truncated = true;\n diagnostics.push({\n code: \"max-length\",\n message: `Stopped at ${outputs.length} outputs: the merged text would exceed ${maxLength} characters`,\n });\n break;\n }\n length += added;\n outputs.push({ index, record, values, text: resolved.text, map: resolved.map });\n }\n\n return {\n outputs,\n skipped,\n diagnostics,\n text: outputs.map((output) => output.text).join(separator),\n mapping,\n truncated,\n };\n}\n\n/**\n * Serializes merge outputs for copying or download: `\"text\"` joins them with\n * `separator` (default `\"\\n\\n\"`), `\"json\"` writes an array of\n * `{ record, text }` objects (`record` is 1-based).\n */\nexport function serializeMergeOutputs(\n outputs: ReadonlyArray<Pick<MergeOutput, \"index\" | \"text\" | \"values\">>,\n format: \"text\" | \"json\" = \"text\",\n separator = \"\\n\\n\",\n): string {\n if (format === \"json\") {\n return JSON.stringify(\n outputs.map((output) => ({ record: output.index + 1, text: output.text })),\n null,\n 2,\n );\n }\n return outputs.map((output) => output.text).join(separator === \"none\" ? \"\" : separator);\n}\n"]}
@@ -44,32 +44,32 @@ var _chunkCKRNELPOcjs = require('./chunk-CKRNELPO.cjs');
44
44
 
45
45
 
46
46
 
47
- var _chunkMKA3AHLVcjs = require('./chunk-MKA3AHLV.cjs');
48
47
 
49
48
 
49
+ var _chunkHNDSPZ5Tcjs = require('./chunk-HNDSPZ5T.cjs');
50
50
 
51
51
 
52
52
 
53
53
 
54
54
 
55
+ var _chunk66IMF6ODcjs = require('./chunk-66IMF6OD.cjs');
55
56
 
56
- var _chunkHNDSPZ5Tcjs = require('./chunk-HNDSPZ5T.cjs');
57
57
 
58
58
 
59
59
 
60
60
 
61
61
 
62
- var _chunk66IMF6ODcjs = require('./chunk-66IMF6OD.cjs');
62
+ var _chunkIFHKKVXHcjs = require('./chunk-IFHKKVXH.cjs');
63
63
 
64
64
 
65
+ var _chunkEMQWJA3Gcjs = require('./chunk-EMQWJA3G.cjs');
65
66
 
66
67
 
67
68
 
68
69
 
69
- var _chunkIFHKKVXHcjs = require('./chunk-IFHKKVXH.cjs');
70
70
 
71
71
 
72
- var _chunkEMQWJA3Gcjs = require('./chunk-EMQWJA3G.cjs');
72
+ var _chunkMKA3AHLVcjs = require('./chunk-MKA3AHLV.cjs');
73
73
 
74
74
  // src/extensions/gradient-text.ts
75
75
  var _core = require('@tiptap/core');
@@ -6755,4 +6755,4 @@ function createTableCommands(editor, options = {}) {
6755
6755
 
6756
6756
 
6757
6757
  exports.GradientText = GradientText; exports.SlashCommands = SlashCommands; exports.TemplateSuggestions = TemplateSuggestions; exports.LoadingNode = LoadingNode; exports.SMILIE_REPLACEMENTS = SMILIE_REPLACEMENTS; exports.smilieAutocorrectRules = smilieAutocorrectRules; exports.SmilieReplacer = SmilieReplacer; exports.findHexColors = findHexColors; exports.ColorHighlighter = ColorHighlighter; exports.FontSize = FontSize; exports.Mention = Mention; exports.getMentionNodes = getMentionNodes; exports.setMentionRoleAt = setMentionRoleAt; exports.createMentionExtension = createMentionExtension; exports.Markdown = Markdown2; exports.imagePastePluginKey = imagePastePluginKey; exports.insertImageNode = insertImageNode; exports.updateImageSrc = updateImageSrc; exports.removeImageNode = removeImageNode; exports.handleImageInsertion = handleImageInsertion; exports.Image = Image2; exports.commentsPluginKey = commentsPluginKey; exports.COMMENT_MARK_NAME = COMMENT_MARK_NAME; exports.findCommentRanges = findCommentRanges; exports.getCommentAnchors = getCommentAnchors; exports.getCommentIdsAt = getCommentIdsAt; exports.getCommentStore = getCommentStore; exports.Comments = Comments; exports.getCommentAuthor = getCommentAuthor; exports.compareInEditor = compareInEditor; exports.applyDocumentComparison = applyDocumentComparison; exports.DocumentCompare = DocumentCompare; exports.ImportError = ImportError; exports.createImportContext = createImportContext; exports.ImportAdapterRegistry = ImportAdapterRegistry; exports.DOCX_MIME_TYPES = DOCX_MIME_TYPES; exports.DEFAULT_DOCX_MAX_IMAGE_SIZE = DEFAULT_DOCX_MAX_IMAGE_SIZE; exports.docxToDocumentImport = docxToDocumentImport; exports.createDocxImportAdapter = createDocxImportAdapter; exports.docxImportAdapter = docxImportAdapter; exports.markdownImportAdapter = markdownImportAdapter; exports.htmlImportAdapter = htmlImportAdapter; exports.plainTextImportAdapter = plainTextImportAdapter; exports.rtfImportAdapter = rtfImportAdapter; exports.BUILT_IN_IMPORT_ADAPTERS = BUILT_IN_IMPORT_ADAPTERS; exports.createImportAdapterRegistry = createImportAdapterRegistry; exports.defaultImportRegistry = defaultImportRegistry; exports.registerImportAdapter = registerImportAdapter; exports.unregisterImportAdapter = unregisterImportAdapter; exports.findImportAdapter = findImportAdapter; exports.importFile = importFile; exports.getImportAccept = getImportAccept; exports.htmlToSlice = htmlToSlice; exports.insertImportedDocument = insertImportedDocument; exports.applyImportedReviewData = applyImportedReviewData; exports.importFilesIntoEditor = importFilesIntoEditor; exports.fileImportPluginKey = fileImportPluginKey; exports.FileImport = FileImport; exports.richClipboardPluginKey = richClipboardPluginKey; exports.writeRichClipboard = writeRichClipboard; exports.RichClipboard = RichClipboard; exports.smartQuoteRules = smartQuoteRules; exports.symbolRules = symbolRules; exports.fractionRules = fractionRules; exports.capitalizeSentenceRules = capitalizeSentenceRules; exports.twoInitialCapitalsRules = twoInitialCapitalsRules; exports.defaultAutocorrectRules = defaultAutocorrectRules; exports.DEFAULT_AUTOCORRECT_EXCEPTIONS = DEFAULT_AUTOCORRECT_EXCEPTIONS; exports.autocorrectPluginKey = autocorrectPluginKey; exports.findAutocorrection = findAutocorrection; exports.isInsidePromptToken = isInsidePromptToken; exports.Autocorrect = Autocorrect; exports.outlinePluginKey = outlinePluginKey; exports.computeOutline = computeOutline; exports.buildOutlineTree = buildOutlineTree; exports.getOutline = getOutline; exports.getActiveHeading = getActiveHeading; exports.createOutlineStore = createOutlineStore; exports.navigateToHeading = navigateToHeading; exports.Outline = Outline; exports.tableOfContentsMarkdownIt = tableOfContentsMarkdownIt; exports.footnotesMarkdownIt = footnotesMarkdownIt; exports.tableOfContentsPluginKey = tableOfContentsPluginKey; exports.getTableOfContentsEntries = getTableOfContentsEntries; exports.TableOfContents = TableOfContents; exports.footnotesPluginKey = footnotesPluginKey; exports.getFootnotes = getFootnotes; exports.syncFootnotes = syncFootnotes; exports.FootnoteReference = FootnoteReference; exports.Footnotes = Footnotes; exports.Footnote = Footnote; exports.getBookmarks = getBookmarks; exports.Bookmark = Bookmark; exports.crossReferencePluginKey = crossReferencePluginKey; exports.getCrossReferenceTargets = getCrossReferenceTargets; exports.CrossReference = CrossReference; exports.documentStructureCommandItems = documentStructureCommandItems; exports.getDocumentStructureCommandItems = getDocumentStructureCommandItems; exports.EMPTY_FIND_REPLACE_SNAPSHOT = EMPTY_FIND_REPLACE_SNAPSHOT; exports.FindReplaceStore = FindReplaceStore; exports.findReplacePluginKey = findReplacePluginKey; exports.getFindReplaceState = getFindReplaceState; exports.getFindReplaceStore = getFindReplaceStore; exports.FIND_OPTION_TOGGLES = FIND_OPTION_TOGGLES; exports.formatFindStatus = formatFindStatus; exports.FindReplace = FindReplace; exports.STYLE_ID_ATTRIBUTE = STYLE_ID_ATTRIBUTE; exports.CHARACTER_STYLE_MARK_NAME = CHARACTER_STYLE_MARK_NAME; exports.paragraphStylesPluginKey = paragraphStylesPluginKey; exports.getStyleRegistry = getStyleRegistry; exports.isParagraphStyleAvailable = isParagraphStyleAvailable; exports.getParagraphStyleAt = getParagraphStyleAt; exports.captureSelectionFormat = captureSelectionFormat; exports.CharacterStyle = CharacterStyle; exports.ParagraphStyles = ParagraphStyles; exports.createParagraphStylesStore = createParagraphStylesStore; exports.createRichTextPreset = createRichTextPreset; exports.createFindReplaceCommands = createFindReplaceCommands; exports.validateFindPattern = validateFindPattern; exports.createTableCommands = createTableCommands;
6758
- //# sourceMappingURL=chunk-J3B45HTA.cjs.map
6758
+ //# sourceMappingURL=chunk-XB25WOC2.cjs.map