@pixerate/editor 0.23.0 → 0.24.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 (155) hide show
  1. package/README.md +96 -1
  2. package/THIRD_PARTY_NOTICES.md +51 -0
  3. package/dist/agent/index.cjs +9 -8
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +4 -3
  6. package/dist/agent/index.d.ts +4 -3
  7. package/dist/agent/index.js +3 -2
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +1210 -17
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +318 -1
  12. package/dist/canvas/index.d.ts +318 -1
  13. package/dist/canvas/index.js +1199 -6
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/{chunk-QBJ22YZR.js → chunk-3CN2WD3X.js} +1354 -206
  16. package/dist/chunk-3CN2WD3X.js.map +1 -0
  17. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  18. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  19. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  20. package/dist/chunk-664LQYFJ.js +115 -0
  21. package/dist/chunk-664LQYFJ.js.map +1 -0
  22. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  23. package/dist/chunk-D27YFC46.cjs.map +1 -0
  24. package/dist/chunk-D6FH2YAX.cjs +131 -0
  25. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  26. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  27. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  28. package/dist/chunk-FODNLX5N.js +749 -0
  29. package/dist/chunk-FODNLX5N.js.map +1 -0
  30. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  31. package/dist/chunk-FPENXAEJ.js.map +1 -0
  32. package/dist/chunk-HLIMTC6N.js +1 -0
  33. package/dist/chunk-HLIMTC6N.js.map +1 -0
  34. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  35. package/dist/chunk-ITBSKI26.js.map +1 -0
  36. package/dist/{chunk-XDMXXC4Z.cjs → chunk-MA2F5KHF.cjs} +350 -227
  37. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  38. package/dist/{chunk-RIKBJLS2.cjs → chunk-MCSJFWAO.cjs} +1356 -208
  39. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  40. package/dist/chunk-MKA3AHLV.cjs +256 -0
  41. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  42. package/dist/chunk-OLZJXL4R.cjs +749 -0
  43. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  44. package/dist/chunk-OXSV64JX.js +689 -0
  45. package/dist/chunk-OXSV64JX.js.map +1 -0
  46. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  47. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  48. package/dist/chunk-P6ODPZ4W.js +256 -0
  49. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  50. package/dist/chunk-PGNZKFQS.js +685 -0
  51. package/dist/chunk-PGNZKFQS.js.map +1 -0
  52. package/dist/chunk-PL4JB3BF.cjs +1 -0
  53. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  54. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  55. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  56. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  57. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  58. package/dist/chunk-TNNJXF46.cjs +115 -0
  59. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  60. package/dist/chunk-U5HZSFCS.js +131 -0
  61. package/dist/chunk-U5HZSFCS.js.map +1 -0
  62. package/dist/{chunk-K3R5NG2D.js → chunk-U5KWZU4X.js} +251 -128
  63. package/dist/chunk-U5KWZU4X.js.map +1 -0
  64. package/dist/chunk-XNORY7M6.cjs +685 -0
  65. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  66. package/dist/commands/index.d.cts +5 -353
  67. package/dist/commands/index.d.ts +5 -353
  68. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  69. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  70. package/dist/compare/index.cjs +15 -0
  71. package/dist/compare/index.cjs.map +1 -0
  72. package/dist/compare/index.d.cts +58 -0
  73. package/dist/compare/index.d.ts +58 -0
  74. package/dist/compare/index.js +15 -0
  75. package/dist/compare/index.js.map +1 -0
  76. package/dist/{controller-pePCJLT1.d.cts → controller-BhLLAoi8.d.cts} +45 -4
  77. package/dist/{controller-pePCJLT1.d.ts → controller-BhLLAoi8.d.ts} +45 -4
  78. package/dist/documents-BQjzJNe2.d.ts +76 -0
  79. package/dist/documents-KRTPhvst.d.cts +76 -0
  80. package/dist/extensions/index.cjs +53 -5
  81. package/dist/extensions/index.cjs.map +1 -1
  82. package/dist/extensions/index.d.cts +7 -3
  83. package/dist/extensions/index.d.ts +7 -3
  84. package/dist/extensions/index.js +52 -4
  85. package/dist/generation/index.cjs +1373 -0
  86. package/dist/generation/index.cjs.map +1 -0
  87. package/dist/generation/index.d.cts +554 -0
  88. package/dist/generation/index.d.ts +554 -0
  89. package/dist/generation/index.js +1373 -0
  90. package/dist/generation/index.js.map +1 -0
  91. package/dist/grammar/index.cjs +48 -3
  92. package/dist/grammar/index.cjs.map +1 -1
  93. package/dist/grammar/index.d.cts +322 -100
  94. package/dist/grammar/index.d.ts +322 -100
  95. package/dist/grammar/index.js +54 -9
  96. package/dist/image-editor/index.cjs +1831 -30
  97. package/dist/image-editor/index.cjs.map +1 -1
  98. package/dist/image-editor/index.d.cts +590 -3
  99. package/dist/image-editor/index.d.ts +590 -3
  100. package/dist/image-editor/index.js +1807 -6
  101. package/dist/image-editor/index.js.map +1 -1
  102. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  103. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  104. package/dist/index.cjs +162 -25
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.cts +14 -8
  107. package/dist/index.d.ts +14 -8
  108. package/dist/index.js +174 -37
  109. package/dist/index.js.map +1 -1
  110. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  111. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  112. package/dist/persistence/index.cjs +676 -0
  113. package/dist/persistence/index.cjs.map +1 -0
  114. package/dist/persistence/index.d.cts +347 -0
  115. package/dist/persistence/index.d.ts +347 -0
  116. package/dist/persistence/index.js +676 -0
  117. package/dist/persistence/index.js.map +1 -0
  118. package/dist/{registry-D5-R90p0.d.cts → registry-BDe-vlv3.d.ts} +2 -40
  119. package/dist/registry-D32LpIc4.d.cts +354 -0
  120. package/dist/{registry-D5-R90p0.d.ts → registry-DnzpgY27.d.cts} +2 -40
  121. package/dist/registry-evKTP4ls.d.ts +354 -0
  122. package/dist/schema-DYDGdYL9.d.cts +41 -0
  123. package/dist/schema-DYDGdYL9.d.ts +41 -0
  124. package/dist/serializers/index.cjs +4 -3
  125. package/dist/serializers/index.cjs.map +1 -1
  126. package/dist/serializers/index.d.cts +2 -1
  127. package/dist/serializers/index.d.ts +2 -1
  128. package/dist/serializers/index.js +3 -2
  129. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  130. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  131. package/dist/spreadsheet/index.cjs +37 -3
  132. package/dist/spreadsheet/index.cjs.map +1 -1
  133. package/dist/spreadsheet/index.d.cts +188 -17
  134. package/dist/spreadsheet/index.d.ts +188 -17
  135. package/dist/spreadsheet/index.js +43 -9
  136. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  137. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  138. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-BK5sVf4_.d.cts} +18 -136
  139. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-CDjCrwKe.d.ts} +18 -136
  140. package/package.json +16 -1
  141. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  142. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  143. package/dist/chunk-AXV2ZW34.cjs +0 -118
  144. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  145. package/dist/chunk-B2ZRLN4S.js +0 -118
  146. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  147. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  148. package/dist/chunk-K3R5NG2D.js.map +0 -1
  149. package/dist/chunk-MJZBNWG7.js.map +0 -1
  150. package/dist/chunk-OYXSKQFR.js.map +0 -1
  151. package/dist/chunk-QBJ22YZR.js.map +0 -1
  152. package/dist/chunk-QGHGJ56O.js.map +0 -1
  153. package/dist/chunk-RIKBJLS2.cjs.map +0 -1
  154. package/dist/chunk-XDMXXC4Z.cjs.map +0 -1
  155. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -1,5 +1,7 @@
1
- import { T as Token, P as PromptDiagnostic, d as PromptValues, f as Template, g as TemplateVersion, a as ConditionalKind, c as PromptValue } from '../tokens-CyLZmIei.cjs';
2
- export { C as ColorGradient, I as INSTRUCTION_REGEX, b as PromptDiagnosticCode, e as TEMPLATE_REGEX, h as TokenType, V as VARIABLE_REGEX, i as instructionRegex, t as templateRegex, v as variableRegex } from '../tokens-CyLZmIei.cjs';
1
+ import { b as Token, a as PromptDiagnostic, P as PromptValues, T as Template, i as TemplateVersion, d as ConditionComparison, e as ConditionalKind, c as ComparisonOperator, g as PromptValue } from '../tokens-D7yXvUU6.cjs';
2
+ export { C as ColorGradient, I as INSTRUCTION_REGEX, f as PromptDiagnosticCode, h as TEMPLATE_REGEX, j as TokenType, V as VARIABLE_REGEX, k as instructionRegex, t as templateRegex, v as variableRegex } from '../tokens-D7yXvUU6.cjs';
3
+ import { S as SourceMapSegment } from '../sourcemap-C8AH3MBQ.cjs';
4
+ export { R as ResolveTemplatesOptions, e as extractInstructionNames, a as extractTemplateNames, b as extractVariableNames, m as mapRawOffsetToResolved, c as mapResolvedOffsetToRaw, r as resolveTemplates, d as resolveTemplatesWithMapping, f as resolveVariables } from '../sourcemap-C8AH3MBQ.cjs';
3
5
 
4
6
  interface TokenizeResult {
5
7
  tokens: Token[];
@@ -24,93 +26,6 @@ declare function getPromptDiagnostics(text: string): PromptDiagnostic[];
24
26
  */
25
27
  declare function tokenizePromptWithDiagnostics(text: string): TokenizeResult;
26
28
 
27
- interface ResolveTemplatesOptions {
28
- bindings?: Record<string, string>;
29
- maxDepth?: number;
30
- /**
31
- * Values for `{variable}` slots and `{?variable}` sections. When omitted,
32
- * variables, defaults and section tags are left exactly as written.
33
- */
34
- values?: PromptValues;
35
- }
36
- /**
37
- * Recursively resolves template tags `{{template_name}}` in a given text.
38
- * A tag that would recurse into itself is replaced with `TEMPLATE_LOOP_ERROR`,
39
- * and a tag nested deeper than `maxDepth` with `TEMPLATE_DEPTH_ERROR`; the rest
40
- * of the text still resolves normally.
41
- *
42
- * Pass `options.values` to also fill variables (falling back to their
43
- * `{name|default}`) and evaluate `{?name}…{/name}` / `{!name}…{/name}`
44
- * sections, including those inside template bodies. See `resolvePrompt` for
45
- * the source map and diagnostics.
46
- */
47
- declare function resolveTemplates(text: string, templates?: Template[], options?: ResolveTemplatesOptions): string;
48
- /**
49
- * Replaces `{variableName}` with values from a dictionary, falling back to a
50
- * `{variableName|default}` when no value is supplied, and evaluates
51
- * `{?name}…{/name}` / `{!name}…{/name}` sections. Variables with neither a
52
- * value nor a default are left as written. Templates are not expanded.
53
- */
54
- declare function resolveVariables(text: string, values: PromptValues): string;
55
- /**
56
- * Extracts unique template names referenced in text.
57
- */
58
- declare function extractTemplateNames(text: string): string[];
59
- /**
60
- * Extracts unique variable names referenced in text, including names used by
61
- * conditional section tags. Defaults and descriptions are stripped.
62
- */
63
- declare function extractVariableNames(text: string): string[];
64
- /**
65
- * Extracts unique instruction names referenced in text.
66
- */
67
- declare function extractInstructionNames(text: string): string[];
68
-
69
- /**
70
- * One contiguous piece of resolved output and the raw range it came from.
71
- *
72
- * - `raw`: copied verbatim; offsets map character by character.
73
- * - `template`: the expansion of a `{{template}}` tag.
74
- * - `variable`: a substituted value or `|default` for a `{variable}` tag.
75
- * - `conditional`: a section tag, or a whole removed section. These segments
76
- * are empty in the resolved text (`resolvedStart === resolvedEnd`).
77
- *
78
- * Offsets inside non-raw segments map to the start of their raw range.
79
- */
80
- interface SourceMapSegment {
81
- resolvedStart: number;
82
- resolvedEnd: number;
83
- source: "raw" | "template" | "variable" | "conditional";
84
- rawStart: number;
85
- rawEnd: number;
86
- templateName?: string;
87
- /** Variable substituted (`variable`) or tested (`conditional`). */
88
- variableName?: string;
89
- /** For `variable` segments: whether a supplied value or the default was used. */
90
- valueSource?: "value" | "default";
91
- }
92
- /**
93
- * Resolves templates in text while tracking character offset mapping
94
- * between the raw input and the fully resolved output.
95
- *
96
- * Pass `options.values` to also substitute variables and evaluate conditional
97
- * sections (see `resolvePrompt`); without it the output is unchanged from the
98
- * template-only behavior.
99
- */
100
- declare function resolveTemplatesWithMapping(text: string, templates?: Template[], templateBindings?: Record<string, string>, options?: Pick<ResolveTemplatesOptions, "maxDepth" | "values">): {
101
- text: string;
102
- map: SourceMapSegment[];
103
- diagnostics: PromptDiagnostic[];
104
- };
105
- /**
106
- * Maps an offset in resolved text back to the corresponding offset in raw text.
107
- */
108
- declare function mapResolvedOffsetToRaw(resolvedOffset: number, map: SourceMapSegment[]): number;
109
- /**
110
- * Maps an offset in raw text to the corresponding offset in resolved text.
111
- */
112
- declare function mapRawOffsetToResolved(rawOffset: number, map: SourceMapSegment[]): number;
113
-
114
29
  /**
115
30
  * Finds the latest version of a template based on `latestVersion` or last version entry.
116
31
  */
@@ -211,8 +126,76 @@ declare function isPromptValueSet(value: PromptValue): boolean;
211
126
  * value (it renders as nothing); `null`/`undefined` are not.
212
127
  */
213
128
  declare function getSuppliedValue(values: PromptValues, name: string): string | undefined;
214
- /** Whether a section opened by `{?name}` / `{!name}` keeps its body. */
215
- declare function evaluateCondition(conditional: Exclude<ConditionalKind, "end">, name: string, values: PromptValues): boolean;
129
+ /**
130
+ * Whether a section opened by `{?name}` / `{!name}` keeps its body. With a
131
+ * `comparison` (from `{?name>3}`), the supplied value is compared instead of
132
+ * tested for presence; a missing value compares as `""`.
133
+ */
134
+ declare function evaluateCondition(conditional: Exclude<ConditionalKind, "end">, name: string, values: PromptValues, comparison?: ConditionComparison): boolean;
135
+ /**
136
+ * Compares two texts like a mail-merge `IF` field: as numbers when both parse
137
+ * as plain decimal numbers (so `"7"` equals `"7.0"`), otherwise as
138
+ * case-insensitive text.
139
+ */
140
+ declare function compareConditionValues(left: string, operator: ComparisonOperator, right: string): boolean;
141
+ /**
142
+ * The variable a conditional tag name compares when it is written as a
143
+ * comparison (`amount>100` → `amount`), or `undefined`. A tag only acts as a
144
+ * comparison when it is closed by `{/subject}`.
145
+ */
146
+ declare function conditionSubject(name: string): string | undefined;
147
+ type ParsedComparison = {
148
+ subject: string;
149
+ comparison: ConditionComparison;
150
+ error?: undefined;
151
+ } | {
152
+ subject: string;
153
+ comparison?: undefined;
154
+ error: string;
155
+ };
156
+ /**
157
+ * Parses a comparison condition such as `amount >= 100`, `status=paid`,
158
+ * `status <> "on hold"` or `note=""`. Returns `undefined` when `text` has no
159
+ * subject and operator, or an `error` when the comparison is malformed
160
+ * (missing value, doubled operator, unterminated quote). `!=` is accepted as
161
+ * a synonym for `<>`.
162
+ */
163
+ declare function parseComparison(text: string): ParsedComparison | undefined;
164
+ /** Writes a comparison operand back as condition text, quoting it when needed. */
165
+ declare function formatComparisonOperand(operand: string): string;
166
+ /**
167
+ * The display form of a conditional tag: `{?name}`, `{!name}`, `{/name}`, or
168
+ * `{?amount>100}` for a comparison.
169
+ */
170
+ declare function formatConditionalTag(tag: {
171
+ conditional?: ConditionalKind;
172
+ value: string;
173
+ comparison?: ConditionComparison;
174
+ }): string;
175
+ /** A tooltip for a conditional tag, e.g. `Shown when "amount" > 100`. */
176
+ declare function describeConditionalTag(tag: {
177
+ conditional?: ConditionalKind;
178
+ value: string;
179
+ comparison?: ConditionComparison;
180
+ }): string;
181
+ /** A parsed standalone condition (see `parseConditionExpression`). */
182
+ interface ConditionExpression {
183
+ /** `true` for `!name` / `!name=value`: the condition is inverted. */
184
+ negated: boolean;
185
+ name: string;
186
+ comparison?: ConditionComparison;
187
+ }
188
+ /**
189
+ * Parses a condition written like the inside of a section tag, without the
190
+ * braces: `vip` (has a value), `!vip` (has none), `amount>100`,
191
+ * `!status=paid`. A leading `?` is allowed. Used by options such as
192
+ * `mergeRecords({ skipIf })`. Returns `{ error }` for malformed text.
193
+ */
194
+ declare function parseConditionExpression(text: string): ConditionExpression | {
195
+ error: string;
196
+ };
197
+ /** Evaluates a parsed condition expression against values. */
198
+ declare function evaluateConditionExpression(expression: ConditionExpression, values: PromptValues): boolean;
216
199
  interface ConditionalTagLike {
217
200
  conditional: ConditionalKind;
218
201
  name: string;
@@ -220,15 +203,24 @@ interface ConditionalTagLike {
220
203
  interface ConditionalTagMatch {
221
204
  /** Index of the partner tag, or -1 when the tag is unbalanced. */
222
205
  partner: number;
223
- /** Set when unbalanced. */
224
- error?: "unclosed-section" | "unexpected-close";
206
+ /** Set when unbalanced, or on both tags of a malformed comparison pair. */
207
+ error?: "unclosed-section" | "unexpected-close" | "invalid-condition";
208
+ /**
209
+ * Set on both tags of a pair whose open tag is a comparison closed by its
210
+ * subject (`{?amount>100}…{/amount}`).
211
+ */
212
+ comparison?: ParsedComparison;
225
213
  }
226
214
  /**
227
215
  * Pairs conditional tags given in document order. A close tag pairs with the
228
- * nearest open tag of the same name; open tags skipped over are reported as
229
- * unclosed, and a close tag with no open partner as unexpected. Unbalanced tags
230
- * never throw: callers treat them as literal text. The surviving pairs are
231
- * always properly nested.
216
+ * nearest open tag of the same name, or with the nearest open comparison tag
217
+ * whose subject it names (`{?amount>100}` is closed by `{/amount}`; closing
218
+ * it with `{/amount>100}` keeps the old meaning, a presence check on a
219
+ * variable named `amount>100`). Open tags skipped over are reported as
220
+ * unclosed, a close tag with no open partner as unexpected, and a malformed
221
+ * comparison pair as an invalid condition. Unbalanced tags never throw:
222
+ * callers treat them as literal text. The surviving pairs are always properly
223
+ * nested.
232
224
  */
233
225
  declare function matchConditionalTags(tags: ConditionalTagLike[]): ConditionalTagMatch[];
234
226
 
@@ -241,8 +233,13 @@ interface VariableDescriptor {
241
233
  description?: string;
242
234
  /** Appears as a `{name}` slot. */
243
235
  usedAsValue: boolean;
244
- /** Appears in a `{?name}` / `{!name}` condition. */
236
+ /** Appears in a `{?name}` / `{!name}` condition (including comparisons). */
245
237
  usedInCondition: boolean;
238
+ /**
239
+ * Present (and `true`) when the variable is compared in a condition such as
240
+ * `{?amount>100}`, so a form should ask for its text, not a checkbox.
241
+ */
242
+ usedInComparison?: true;
246
243
  /** Number of `{name…}` slots and condition tags (closing tags excluded). */
247
244
  occurrences: number;
248
245
  /** Templates whose bodies mention the variable, in discovery order. */
@@ -276,7 +273,10 @@ interface VariableFormField {
276
273
  * leaves the `{name}` placeholder in the resolved prompt.
277
274
  */
278
275
  required: boolean;
279
- /** Only used by `{?name}` / `{!name}` conditions, never substituted. */
276
+ /**
277
+ * Only used by `{?name}` / `{!name}` presence conditions, never substituted
278
+ * or compared (a form can show a checkbox).
279
+ */
280
280
  conditionOnly: boolean;
281
281
  }
282
282
  /**
@@ -292,4 +292,226 @@ declare function getVariableFormFields(text: string, options?: ExtractVariablesO
292
292
  */
293
293
  declare function compactVariableValues(input: Record<string, string | null | undefined>): PromptValues;
294
294
 
295
- export { ConditionalKind, type ConditionalTagLike, type ConditionalTagMatch, type EvaluatedToken, type ExtractVariablesOptions, type ParsedVariableBody, PromptDiagnostic, PromptValue, PromptValues, type ResolvePromptOptions, type ResolvePromptResult, type ResolveTemplatesOptions, type SourceMapSegment, TEMPLATE_DEPTH_ERROR, TEMPLATE_LOOP_ERROR, Template, TemplateVersion, Token, type TokenizeResult, type VariableDescriptor, type VariableFormField, compactVariableValues, escapeVariableText, evaluateCondition, evaluatePromptTokens, extractInstructionNames, extractTemplateNames, extractVariableNames, extractVariables, getLatestVersion, getPromptDiagnostics, getSuppliedValue, getTemplateBody, getVariableFormFields, isPromptValueSet, mapRawOffsetToResolved, mapResolvedOffsetToRaw, matchConditionalTags, parseVariableBody, resolvePrompt, resolveTemplates, resolveTemplatesWithMapping, resolveVariables, tokenizePrompt, tokenizePromptWithDiagnostics, unescapeVariableText };
295
+ /** Most records a data source keeps by default. */
296
+ declare const MAX_DATA_SOURCE_RECORDS = 100000;
297
+ /** Most fields a data source keeps by default. */
298
+ declare const MAX_DATA_SOURCE_FIELDS = 1000;
299
+ /** One record: field name → cell text. */
300
+ type MergeRecord = Record<string, string>;
301
+ /** Anything `parseDataSource` accepts. */
302
+ type DataSourceInput = string | ReadonlyArray<ReadonlyArray<unknown>> | ReadonlyArray<Readonly<Record<string, unknown>>>;
303
+ interface ParseDataSourceOptions {
304
+ /**
305
+ * Field separator for delimited text. `"auto"` (the default) picks whichever
306
+ * of `,` `;` and tab occurs most often in the first line (outside quotes),
307
+ * preferring `,` on a tie.
308
+ */
309
+ delimiter?: "auto" | string;
310
+ /**
311
+ * Whether the first row names the fields (default `true`). Without a header
312
+ * the fields are `Column 1`…`Column N`. Ignored for arrays of objects.
313
+ */
314
+ hasHeader?: boolean;
315
+ /**
316
+ * How to read a string: `"auto"` (default) parses text starting with `[` as
317
+ * JSON and falls back to delimited text when that fails.
318
+ */
319
+ format?: "auto" | "csv" | "json";
320
+ /** Record cap (default `MAX_DATA_SOURCE_RECORDS`). */
321
+ maxRecords?: number;
322
+ /** Field cap (default `MAX_DATA_SOURCE_FIELDS`). */
323
+ maxFields?: number;
324
+ }
325
+ type DataSourceWarningCode = "empty" | "invalid-json" | "unsupported-json" | "blank-header" | "duplicate-header" | "ragged-rows" | "records-truncated" | "fields-truncated";
326
+ interface DataSourceWarning {
327
+ code: DataSourceWarningCode;
328
+ message: string;
329
+ /** For `ragged-rows`: how many records were padded or cut. */
330
+ count?: number;
331
+ }
332
+ interface MergeDataSource {
333
+ /** Field names: trimmed, unique (case-insensitively), never blank. */
334
+ fields: string[];
335
+ /** One entry per record, with every field present. */
336
+ records: MergeRecord[];
337
+ warnings: DataSourceWarning[];
338
+ /** How the input was read. */
339
+ format: "csv" | "json" | "rows" | "objects";
340
+ /** The delimiter used for delimited text. */
341
+ delimiter?: string;
342
+ }
343
+ /** Counts the auto-detect candidates in the first line, ignoring quoted text. */
344
+ declare function detectDelimiter(text: string): string;
345
+ /**
346
+ * Field names from a header row: names are trimmed, a blank name becomes
347
+ * `Column N` (its 1-based position), and repeats (compared case-insensitively)
348
+ * are numbered `Name 2`, `Name 3`, ….
349
+ */
350
+ declare function normalizeFieldNames(row: ReadonlyArray<unknown>): string[];
351
+ /**
352
+ * Reads a mail-merge data source.
353
+ *
354
+ * - **Text**: CSV / TSV (RFC 4180 quoting, doubled quotes, CRLF / LF / CR,
355
+ * a leading BOM ignored) with the delimiter auto-detected, or JSON (an
356
+ * array of objects or of arrays).
357
+ * - **Rows** (`unknown[][]`): the first row is the header unless
358
+ * `hasHeader: false`.
359
+ * - **Objects**: the fields are the union of keys in first-seen order.
360
+ *
361
+ * Blank rows are skipped, header names are normalised (`normalizeFieldNames`),
362
+ * records are padded or cut to the header width, and records and fields are
363
+ * capped. Cells become strings (`null` → `""`, nested values → JSON). Problems
364
+ * are reported in `warnings`; this never throws.
365
+ */
366
+ declare function parseDataSource(input: DataSourceInput, options?: ParseDataSourceOptions): MergeDataSource;
367
+ /** Lower-cases and drops spaces, `_`, `-` and `.` so `First Name` matches `first_name`. */
368
+ declare function normalizeFieldKey(name: string): string;
369
+ /**
370
+ * Built-in alias groups for `matchFields`: any name in a group matches any
371
+ * other (after `normalizeFieldKey`). Extended from Word's address-block
372
+ * field detection.
373
+ */
374
+ declare const FIELD_ALIASES: ReadonlyArray<ReadonlyArray<string>>;
375
+ type FieldMatchKind = "exact" | "normalized" | "alias";
376
+ interface FieldMatch {
377
+ variable: string;
378
+ /** The matched field, or `null`. */
379
+ field: string | null;
380
+ kind: FieldMatchKind | null;
381
+ }
382
+ interface FieldMapping {
383
+ /** Variable → field (or `null` when unmatched), in variable order. */
384
+ mapping: Record<string, string | null>;
385
+ matches: FieldMatch[];
386
+ unmatchedVariables: string[];
387
+ /** Fields no variable maps to. */
388
+ unusedFields: string[];
389
+ }
390
+ interface MatchFieldsOptions {
391
+ /** Extra alias groups, checked after the built-in ones. */
392
+ aliases?: ReadonlyArray<ReadonlyArray<string>>;
393
+ }
394
+ /**
395
+ * Maps prompt variables to data source fields: an exact name first, then a
396
+ * case-, space- and punctuation-insensitive match (`first_name` ↔
397
+ * `First Name`), then an alias (`FirstName` ↔ `First` / `GivenName`, see
398
+ * `FIELD_ALIASES`). Several variables may map to the same field.
399
+ */
400
+ declare function matchFields(variables: ReadonlyArray<string | {
401
+ name: string;
402
+ }>, fields: ReadonlyArray<string>, options?: MatchFieldsOptions): FieldMapping;
403
+ interface RecordToValuesOptions {
404
+ /**
405
+ * Treat blank cells as missing so `{name|default}` falls back to its
406
+ * default (default `true`). With `false`, a blank cell renders as empty.
407
+ */
408
+ blankAsMissing?: boolean;
409
+ }
410
+ /**
411
+ * The prompt values for one record: every field under its own name, then
412
+ * each mapped variable set from its field (a `null` mapping leaves the
413
+ * variable unset even if a field shares its name).
414
+ */
415
+ declare function recordToValues(record: MergeRecord, mapping?: Readonly<Record<string, string | null | undefined>>, options?: RecordToValuesOptions): PromptValues;
416
+
417
+ /**
418
+ * Multi-record merge: resolves one prompt per data source record with
419
+ * `resolvePrompt`, like Word's Finish & Merge.
420
+ */
421
+
422
+ /** Default cap on merged outputs. */
423
+ declare const MAX_MERGE_OUTPUTS = 10000;
424
+ /** Default cap on the total length of merged text (characters). */
425
+ declare const MAX_MERGE_LENGTH = 20000000;
426
+ interface MergeRecordsOptions {
427
+ /** Templates for `{{name}}` tags. */
428
+ templates?: Template[];
429
+ /** Template version bindings. */
430
+ bindings?: Record<string, string>;
431
+ /** Maximum template nesting depth (default 10). */
432
+ maxDepth?: number;
433
+ /**
434
+ * Variable → field. Variables left out are matched automatically with
435
+ * `matchFields`; a `null` entry leaves the variable unset.
436
+ */
437
+ mapping?: Record<string, string | null>;
438
+ /**
439
+ * Text placed between outputs in the joined `text`: default `"\n\n"`.
440
+ * `"none"` joins them with nothing in between.
441
+ */
442
+ separator?: string;
443
+ /**
444
+ * Drops a record's output when this holds. Either a function of the record
445
+ * (and its prompt values), or a condition written like the inside of a
446
+ * section tag: `void`, `!email`, `status=cancelled`, `amount<10`. The
447
+ * condition is evaluated against the record's prompt values (mapped
448
+ * variables and raw field names); a name that is neither is matched to a
449
+ * field like a variable (`status` → `Status`).
450
+ */
451
+ skipIf?: string | ((record: MergeRecord, values: PromptValues, index: number) => boolean);
452
+ /** Stop after this many outputs (default `MAX_MERGE_OUTPUTS`). */
453
+ maxOutputs?: number;
454
+ /** Stop once the outputs reach this many characters (default `MAX_MERGE_LENGTH`). */
455
+ maxLength?: number;
456
+ /** First record to merge, 1-based (default 1). */
457
+ from?: number;
458
+ /** Last record to merge, 1-based and inclusive (default: the last). */
459
+ to?: number;
460
+ /** See `recordToValues` (default `true`: blank cells use defaults). */
461
+ blankAsMissing?: boolean;
462
+ /** Options for parsing `source` when it is not already parsed. */
463
+ parse?: ParseDataSourceOptions;
464
+ }
465
+ interface MergeOutput {
466
+ /** 0-based index of the record in the data source. */
467
+ index: number;
468
+ record: MergeRecord;
469
+ /** The values the prompt was resolved with. */
470
+ values: PromptValues;
471
+ text: string;
472
+ map: SourceMapSegment[];
473
+ }
474
+ interface MergeSkip {
475
+ index: number;
476
+ record: MergeRecord;
477
+ reason: "skip-if";
478
+ }
479
+ type MergeDiagnosticCode = PromptDiagnostic["code"] | "unmapped-variable" | "invalid-skip-condition" | "max-outputs" | "max-length" | "data-source";
480
+ /** A grammar diagnostic from the template, or a merge-level problem. */
481
+ interface MergeDiagnostic {
482
+ code: MergeDiagnosticCode;
483
+ message: string;
484
+ /** Variable, for grammar and `unmapped-variable` diagnostics. */
485
+ name?: string;
486
+ start?: number;
487
+ end?: number;
488
+ templateName?: string;
489
+ }
490
+ interface MergeRecordsResult {
491
+ outputs: MergeOutput[];
492
+ skipped: MergeSkip[];
493
+ diagnostics: MergeDiagnostic[];
494
+ /** Every output's text joined with the separator. */
495
+ text: string;
496
+ /** The variable → field mapping used. */
497
+ mapping: Record<string, string | null>;
498
+ /** The merge stopped early at `maxOutputs` or `maxLength`. */
499
+ truncated: boolean;
500
+ }
501
+ /**
502
+ * Merges a prompt with every record of a data source: one resolved output per
503
+ * record, in order. Fields are matched to the prompt's variables
504
+ * automatically (override with `mapping`), blank cells fall back to the
505
+ * variable's default, `{?field}` / `{?field>3}` sections are evaluated per
506
+ * record, and `skipIf` drops records. Grammar diagnostics in the prompt are
507
+ * reported once. Never throws.
508
+ */
509
+ declare function mergeRecords(template: string, source: MergeDataSource | DataSourceInput, options?: MergeRecordsOptions): MergeRecordsResult;
510
+ /**
511
+ * Serializes merge outputs for copying or download: `"text"` joins them with
512
+ * `separator` (default `"\n\n"`), `"json"` writes an array of
513
+ * `{ record, text }` objects (`record` is 1-based).
514
+ */
515
+ declare function serializeMergeOutputs(outputs: ReadonlyArray<Pick<MergeOutput, "index" | "text" | "values">>, format?: "text" | "json", separator?: string): string;
516
+
517
+ export { ComparisonOperator, ConditionComparison, type ConditionExpression, ConditionalKind, type ConditionalTagLike, type ConditionalTagMatch, type DataSourceInput, type DataSourceWarning, type DataSourceWarningCode, type EvaluatedToken, type ExtractVariablesOptions, FIELD_ALIASES, type FieldMapping, type FieldMatch, type FieldMatchKind, MAX_DATA_SOURCE_FIELDS, MAX_DATA_SOURCE_RECORDS, MAX_MERGE_LENGTH, MAX_MERGE_OUTPUTS, type MatchFieldsOptions, type MergeDataSource, type MergeDiagnostic, type MergeDiagnosticCode, type MergeOutput, type MergeRecord, type MergeRecordsOptions, type MergeRecordsResult, type MergeSkip, type ParseDataSourceOptions, type ParsedComparison, type ParsedVariableBody, PromptDiagnostic, PromptValue, PromptValues, type RecordToValuesOptions, type ResolvePromptOptions, type ResolvePromptResult, SourceMapSegment, TEMPLATE_DEPTH_ERROR, TEMPLATE_LOOP_ERROR, Template, TemplateVersion, Token, type TokenizeResult, type VariableDescriptor, type VariableFormField, compactVariableValues, compareConditionValues, conditionSubject, describeConditionalTag, detectDelimiter, escapeVariableText, evaluateCondition, evaluateConditionExpression, evaluatePromptTokens, extractVariables, formatComparisonOperand, formatConditionalTag, getLatestVersion, getPromptDiagnostics, getSuppliedValue, getTemplateBody, getVariableFormFields, isPromptValueSet, matchConditionalTags, matchFields, mergeRecords, normalizeFieldKey, normalizeFieldNames, parseComparison, parseConditionExpression, parseDataSource, parseVariableBody, recordToValues, resolvePrompt, serializeMergeOutputs, tokenizePrompt, tokenizePromptWithDiagnostics, unescapeVariableText };