@pixerate/editor 0.22.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 (188) hide show
  1. package/README.md +175 -2
  2. package/THIRD_PARTY_NOTICES.md +139 -0
  3. package/dist/agent/index.cjs +87 -111
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +70 -211
  6. package/dist/agent/index.d.ts +70 -211
  7. package/dist/agent/index.js +78 -102
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +2075 -86
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +608 -186
  14. package/dist/canvas/index.d.ts +608 -186
  15. package/dist/canvas/index.js +2060 -71
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/{chunk-DENSCKFC.js → chunk-3CN2WD3X.js} +1730 -189
  22. package/dist/chunk-3CN2WD3X.js.map +1 -0
  23. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  24. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  25. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  26. package/dist/chunk-664LQYFJ.js +115 -0
  27. package/dist/chunk-664LQYFJ.js.map +1 -0
  28. package/dist/chunk-7DWMJCAT.js +453 -0
  29. package/dist/chunk-7DWMJCAT.js.map +1 -0
  30. package/dist/chunk-ARRTP33I.js +101 -0
  31. package/dist/chunk-ARRTP33I.js.map +1 -0
  32. package/dist/chunk-CPOKFNBG.cjs +101 -0
  33. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  34. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  35. package/dist/chunk-D27YFC46.cjs.map +1 -0
  36. package/dist/chunk-D6FH2YAX.cjs +131 -0
  37. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  38. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  39. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  40. package/dist/chunk-FODNLX5N.js +749 -0
  41. package/dist/chunk-FODNLX5N.js.map +1 -0
  42. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  43. package/dist/chunk-FPENXAEJ.js.map +1 -0
  44. package/dist/chunk-G2I4QJOT.cjs +762 -0
  45. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  46. package/dist/chunk-HLIMTC6N.js +1 -0
  47. package/dist/chunk-HLIMTC6N.js.map +1 -0
  48. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  49. package/dist/chunk-ITBSKI26.js.map +1 -0
  50. package/dist/{chunk-6M3BCTBD.cjs → chunk-MA2F5KHF.cjs} +470 -242
  51. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  52. package/dist/{chunk-SAZRENEZ.cjs → chunk-MCSJFWAO.cjs} +1733 -192
  53. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  54. package/dist/chunk-MKA3AHLV.cjs +256 -0
  55. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  56. package/dist/chunk-OLZJXL4R.cjs +749 -0
  57. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  58. package/dist/chunk-OXSV64JX.js +689 -0
  59. package/dist/chunk-OXSV64JX.js.map +1 -0
  60. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  61. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  62. package/dist/chunk-P6ODPZ4W.js +256 -0
  63. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  64. package/dist/chunk-PGNZKFQS.js +685 -0
  65. package/dist/chunk-PGNZKFQS.js.map +1 -0
  66. package/dist/chunk-PL4JB3BF.cjs +1 -0
  67. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  68. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  69. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  70. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  71. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  72. package/dist/chunk-TNNJXF46.cjs +115 -0
  73. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  74. package/dist/chunk-U5HZSFCS.js +131 -0
  75. package/dist/chunk-U5HZSFCS.js.map +1 -0
  76. package/dist/{chunk-RU52I7QO.js → chunk-U5KWZU4X.js} +388 -160
  77. package/dist/chunk-U5KWZU4X.js.map +1 -0
  78. package/dist/chunk-XNORY7M6.cjs +685 -0
  79. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  80. package/dist/commands/index.cjs +860 -0
  81. package/dist/commands/index.cjs.map +1 -0
  82. package/dist/commands/index.d.cts +244 -0
  83. package/dist/commands/index.d.ts +244 -0
  84. package/dist/commands/index.js +860 -0
  85. package/dist/commands/index.js.map +1 -0
  86. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  87. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  88. package/dist/compare/index.cjs +15 -0
  89. package/dist/compare/index.cjs.map +1 -0
  90. package/dist/compare/index.d.cts +58 -0
  91. package/dist/compare/index.d.ts +58 -0
  92. package/dist/compare/index.js +15 -0
  93. package/dist/compare/index.js.map +1 -0
  94. package/dist/{controller-B7GIybc4.d.cts → controller-BhLLAoi8.d.cts} +119 -5
  95. package/dist/{controller-B7GIybc4.d.ts → controller-BhLLAoi8.d.ts} +119 -5
  96. package/dist/documents-BQjzJNe2.d.ts +76 -0
  97. package/dist/documents-KRTPhvst.d.cts +76 -0
  98. package/dist/extensions/index.cjs +53 -5
  99. package/dist/extensions/index.cjs.map +1 -1
  100. package/dist/extensions/index.d.cts +7 -3
  101. package/dist/extensions/index.d.ts +7 -3
  102. package/dist/extensions/index.js +52 -4
  103. package/dist/generation/index.cjs +1373 -0
  104. package/dist/generation/index.cjs.map +1 -0
  105. package/dist/generation/index.d.cts +554 -0
  106. package/dist/generation/index.d.ts +554 -0
  107. package/dist/generation/index.js +1373 -0
  108. package/dist/generation/index.js.map +1 -0
  109. package/dist/grammar/index.cjs +48 -3
  110. package/dist/grammar/index.cjs.map +1 -1
  111. package/dist/grammar/index.d.cts +322 -100
  112. package/dist/grammar/index.d.ts +322 -100
  113. package/dist/grammar/index.js +54 -9
  114. package/dist/history/index.cjs +12 -2
  115. package/dist/history/index.cjs.map +1 -1
  116. package/dist/history/index.d.cts +211 -7
  117. package/dist/history/index.d.ts +211 -7
  118. package/dist/history/index.js +13 -3
  119. package/dist/image-editor/index.cjs +2244 -38
  120. package/dist/image-editor/index.cjs.map +1 -1
  121. package/dist/image-editor/index.d.cts +742 -4
  122. package/dist/image-editor/index.d.ts +742 -4
  123. package/dist/image-editor/index.js +2222 -16
  124. package/dist/image-editor/index.js.map +1 -1
  125. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  126. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  127. package/dist/index.cjs +193 -98
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +17 -48
  130. package/dist/index.d.ts +17 -48
  131. package/dist/index.js +198 -103
  132. package/dist/index.js.map +1 -1
  133. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  134. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  135. package/dist/persistence/index.cjs +676 -0
  136. package/dist/persistence/index.cjs.map +1 -0
  137. package/dist/persistence/index.d.cts +347 -0
  138. package/dist/persistence/index.d.ts +347 -0
  139. package/dist/persistence/index.js +676 -0
  140. package/dist/persistence/index.js.map +1 -0
  141. package/dist/registry-BDe-vlv3.d.ts +171 -0
  142. package/dist/registry-D32LpIc4.d.cts +354 -0
  143. package/dist/registry-DnzpgY27.d.cts +171 -0
  144. package/dist/registry-evKTP4ls.d.ts +354 -0
  145. package/dist/schema-DYDGdYL9.d.cts +41 -0
  146. package/dist/schema-DYDGdYL9.d.ts +41 -0
  147. package/dist/serializers/index.cjs +4 -3
  148. package/dist/serializers/index.cjs.map +1 -1
  149. package/dist/serializers/index.d.cts +2 -1
  150. package/dist/serializers/index.d.ts +2 -1
  151. package/dist/serializers/index.js +3 -2
  152. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  153. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  154. package/dist/spreadsheet/index.cjs +53 -3
  155. package/dist/spreadsheet/index.cjs.map +1 -1
  156. package/dist/spreadsheet/index.d.cts +247 -18
  157. package/dist/spreadsheet/index.d.ts +247 -18
  158. package/dist/spreadsheet/index.js +58 -8
  159. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  160. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  161. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-BK5sVf4_.d.cts} +18 -136
  162. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-CDjCrwKe.d.ts} +18 -136
  163. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.cts} +1 -1
  164. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.ts} +1 -1
  165. package/dist/types-GT5a5YAX.d.cts +86 -0
  166. package/dist/types-GT5a5YAX.d.ts +86 -0
  167. package/package.json +23 -2
  168. package/dist/chunk-2TWGLC5K.cjs +0 -262
  169. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  170. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  171. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  172. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  173. package/dist/chunk-AXV2ZW34.cjs +0 -118
  174. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  175. package/dist/chunk-B2ZRLN4S.js +0 -118
  176. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  177. package/dist/chunk-DENSCKFC.js.map +0 -1
  178. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  179. package/dist/chunk-KAADNAPF.js +0 -262
  180. package/dist/chunk-KAADNAPF.js.map +0 -1
  181. package/dist/chunk-MJZBNWG7.js.map +0 -1
  182. package/dist/chunk-OYXSKQFR.js.map +0 -1
  183. package/dist/chunk-QGHGJ56O.js.map +0 -1
  184. package/dist/chunk-RU52I7QO.js.map +0 -1
  185. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  186. package/dist/types-BZgcDsC5.d.cts +0 -42
  187. package/dist/types-BZgcDsC5.d.ts +0 -42
  188. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -1,262 +0,0 @@
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; } var _class;// src/history/HistoryManager.ts
2
- var HistoryManager = (_class = class {
3
- __init() {this.undoStack = []}
4
- __init2() {this.redoStack = []}
5
-
6
- __init3() {this.isApplying = false}
7
- __init4() {this.batchDepth = 0}
8
- __init5() {this.currentBatch = null}
9
- __init6() {this.listeners = /* @__PURE__ */ new Set()}
10
-
11
-
12
- constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);
13
- this.maxDepth = _nullishCoalesce(options.maxDepth, () => ( 50));
14
- this.onStateChange = options.onStateChange;
15
- this.cachedState = this.computeState();
16
- }
17
- computeState() {
18
- const canUndo = this.undoStack.length > 0;
19
- const canRedo = this.redoStack.length > 0;
20
- return {
21
- canUndo,
22
- canRedo,
23
- undoName: canUndo ? this.undoStack[this.undoStack.length - 1].name : "",
24
- redoName: canRedo ? this.redoStack[this.redoStack.length - 1].name : "",
25
- undoCount: this.undoStack.length,
26
- redoCount: this.redoStack.length
27
- };
28
- }
29
- /**
30
- * Returns a snapshot of the current history state.
31
- * Cached to maintain referential equality across renders for useSyncExternalStore.
32
- */
33
- getState() {
34
- return this.cachedState;
35
- }
36
- notify() {
37
- this.cachedState = this.computeState();
38
- const state = this.cachedState;
39
- _optionalChain([this, 'access', _ => _.onStateChange, 'optionalCall', _2 => _2(state)]);
40
- this.listeners.forEach((listener) => {
41
- try {
42
- listener(state);
43
- } catch (err) {
44
- console.error("[HistoryManager] Error in state listener:", err);
45
- }
46
- });
47
- }
48
- /**
49
- * Executes a command and pushes it onto the undo stack.
50
- * Clears the redo stack.
51
- */
52
- execute(command) {
53
- if (this.isApplying) {
54
- command.execute();
55
- return;
56
- }
57
- if (this.batchDepth > 0 && this.currentBatch) {
58
- command.execute();
59
- this.currentBatch.push({
60
- ...command,
61
- timestamp: _nullishCoalesce(command.timestamp, () => ( Date.now()))
62
- });
63
- return;
64
- }
65
- command.execute();
66
- this.undoStack.push({
67
- ...command,
68
- timestamp: _nullishCoalesce(command.timestamp, () => ( Date.now()))
69
- });
70
- if (this.undoStack.length > this.maxDepth) {
71
- this.undoStack.shift();
72
- }
73
- this.redoStack = [];
74
- this.notify();
75
- }
76
- /**
77
- * Executes a command, coalescing it with the previous command if they share
78
- * the same `tag` and occurred within `windowMs` (default: 300ms).
79
- * Useful for high-frequency interactions like slider scrubs or node drags.
80
- */
81
- executeMerged(command, options = {}) {
82
- const windowMs = _nullishCoalesce(options.windowMs, () => ( 300));
83
- const now = Date.now();
84
- if (command.tag && this.undoStack.length > 0 && this.batchDepth === 0 && !this.isApplying) {
85
- const top = this.undoStack[this.undoStack.length - 1];
86
- const elapsed = top.timestamp ? now - top.timestamp : Infinity;
87
- if (top.tag === command.tag && elapsed <= windowMs) {
88
- command.execute();
89
- const initialUndo = top.undo;
90
- this.undoStack[this.undoStack.length - 1] = {
91
- name: command.name,
92
- tag: command.tag,
93
- timestamp: now,
94
- execute: command.execute,
95
- undo: initialUndo,
96
- redo: _nullishCoalesce(command.redo, () => ( command.execute))
97
- };
98
- this.redoStack = [];
99
- this.notify();
100
- return;
101
- }
102
- }
103
- this.execute({ ...command, timestamp: now });
104
- }
105
- /**
106
- * Batches multiple commands executed within `fn` into a single atomic undo entry.
107
- */
108
- batch(name, fn) {
109
- if (this.isApplying) {
110
- fn();
111
- return;
112
- }
113
- if (this.batchDepth > 0) {
114
- fn();
115
- return;
116
- }
117
- this.batchDepth++;
118
- this.currentBatch = [];
119
- try {
120
- fn();
121
- } catch (error) {
122
- const executed = _nullishCoalesce(this.currentBatch, () => ( []));
123
- this.batchDepth--;
124
- this.currentBatch = null;
125
- this.rollback(executed);
126
- throw error;
127
- }
128
- this.batchDepth--;
129
- const batchCommands = _nullishCoalesce(this.currentBatch, () => ( []));
130
- this.currentBatch = null;
131
- if (batchCommands.length > 0) {
132
- const compoundCommand = {
133
- name,
134
- timestamp: Date.now(),
135
- execute: () => {
136
- for (let i = 0; i < batchCommands.length; i++) {
137
- (_nullishCoalesce(batchCommands[i].redo, () => ( batchCommands[i].execute)))();
138
- }
139
- },
140
- undo: () => {
141
- for (let i = batchCommands.length - 1; i >= 0; i--) {
142
- batchCommands[i].undo();
143
- }
144
- },
145
- redo: () => {
146
- for (let i = 0; i < batchCommands.length; i++) {
147
- (_nullishCoalesce(batchCommands[i].redo, () => ( batchCommands[i].execute)))();
148
- }
149
- }
150
- };
151
- this.undoStack.push(compoundCommand);
152
- if (this.undoStack.length > this.maxDepth) {
153
- this.undoStack.shift();
154
- }
155
- this.redoStack = [];
156
- this.notify();
157
- }
158
- }
159
- /**
160
- * Reverts already-executed commands of an aborted batch, newest first.
161
- * Commands executed by the undo closures themselves are not recorded.
162
- */
163
- rollback(commands) {
164
- const wasApplying = this.isApplying;
165
- this.isApplying = true;
166
- try {
167
- for (let i = commands.length - 1; i >= 0; i--) {
168
- try {
169
- commands[i].undo();
170
- } catch (err) {
171
- console.error(
172
- `[HistoryManager] Error rolling back "${commands[i].name}" of a failed batch:`,
173
- err
174
- );
175
- }
176
- }
177
- } finally {
178
- this.isApplying = wasApplying;
179
- }
180
- }
181
- /**
182
- * Reverts the most recent command on the undo stack.
183
- * Returns true if a command was undone, false otherwise.
184
- */
185
- undo() {
186
- if (this.undoStack.length === 0 || this.isApplying || this.batchDepth > 0) {
187
- return false;
188
- }
189
- this.isApplying = true;
190
- try {
191
- const command = this.undoStack[this.undoStack.length - 1];
192
- command.undo();
193
- this.undoStack.pop();
194
- this.redoStack.push(command);
195
- return true;
196
- } finally {
197
- this.isApplying = false;
198
- this.notify();
199
- }
200
- }
201
- /**
202
- * Re-applies the most recent undone command on the redo stack.
203
- * Returns true if a command was redone, false otherwise.
204
- */
205
- redo() {
206
- if (this.redoStack.length === 0 || this.isApplying || this.batchDepth > 0) {
207
- return false;
208
- }
209
- this.isApplying = true;
210
- try {
211
- const command = this.redoStack[this.redoStack.length - 1];
212
- (_nullishCoalesce(command.redo, () => ( command.execute)))();
213
- this.redoStack.pop();
214
- this.undoStack.push(command);
215
- return true;
216
- } finally {
217
- this.isApplying = false;
218
- this.notify();
219
- }
220
- }
221
- /**
222
- * Clears both undo and redo stacks.
223
- */
224
- clear() {
225
- this.undoStack = [];
226
- this.redoStack = [];
227
- this.notify();
228
- }
229
- /**
230
- * Subscribes to history state changes.
231
- * The listener is immediately invoked with the current state.
232
- * Returns an unsubscribe function.
233
- */
234
- subscribe(listener) {
235
- this.listeners.add(listener);
236
- listener(this.getState());
237
- return () => {
238
- this.listeners.delete(listener);
239
- };
240
- }
241
- /**
242
- * Utility helper to create a Command from before/after state snapshots.
243
- */
244
- static createSnapshotCommand(options) {
245
- return {
246
- name: options.name,
247
- tag: options.tag,
248
- execute: () => options.apply(options.after),
249
- undo: () => options.apply(options.before),
250
- redo: () => options.apply(options.after)
251
- };
252
- }
253
- }, _class);
254
- function createHistoryManager(options = {}) {
255
- return new HistoryManager(options);
256
- }
257
-
258
-
259
-
260
-
261
- exports.HistoryManager = HistoryManager; exports.createHistoryManager = createHistoryManager;
262
- //# sourceMappingURL=chunk-2TWGLC5K.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-2TWGLC5K.cjs","../src/history/HistoryManager.ts"],"names":[],"mappings":"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","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-2TWGLC5K.cjs","sourcesContent":[null,"import {\n Command,\n HistoryManagerOptions,\n HistoryState,\n MergedExecutionOptions,\n SnapshotCommandOptions,\n} from \"./types\";\n\n/**\n * UI-agnostic History and Undo/Redo manager supporting command closures,\n * snapshot diffs, transaction batching, and high-frequency event coalescing.\n */\nexport class HistoryManager {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxDepth: number;\n private isApplying = false;\n private batchDepth = 0;\n private currentBatch: Command[] | null = null;\n private listeners: Set<(state: HistoryState) => void> = new Set();\n private onStateChange?: (state: HistoryState) => void;\n private cachedState: HistoryState;\n\n constructor(options: HistoryManagerOptions = {}) {\n this.maxDepth = options.maxDepth ?? 50;\n this.onStateChange = options.onStateChange;\n this.cachedState = this.computeState();\n }\n\n private computeState(): HistoryState {\n const canUndo = this.undoStack.length > 0;\n const canRedo = this.redoStack.length > 0;\n return {\n canUndo,\n canRedo,\n undoName: canUndo ? this.undoStack[this.undoStack.length - 1].name : \"\",\n redoName: canRedo ? this.redoStack[this.redoStack.length - 1].name : \"\",\n undoCount: this.undoStack.length,\n redoCount: this.redoStack.length,\n };\n }\n\n /**\n * Returns a snapshot of the current history state.\n * Cached to maintain referential equality across renders for useSyncExternalStore.\n */\n public getState(): HistoryState {\n return this.cachedState;\n }\n\n private notify(): void {\n this.cachedState = this.computeState();\n const state = this.cachedState;\n this.onStateChange?.(state);\n this.listeners.forEach((listener) => {\n try {\n listener(state);\n } catch (err) {\n console.error(\"[HistoryManager] Error in state listener:\", err);\n }\n });\n }\n\n /**\n * Executes a command and pushes it onto the undo stack.\n * Clears the redo stack.\n */\n public execute(command: Command): void {\n if (this.isApplying) {\n command.execute();\n return;\n }\n\n if (this.batchDepth > 0 && this.currentBatch) {\n command.execute();\n this.currentBatch.push({\n ...command,\n timestamp: command.timestamp ?? Date.now(),\n });\n return;\n }\n\n command.execute();\n\n this.undoStack.push({\n ...command,\n timestamp: command.timestamp ?? Date.now(),\n });\n\n if (this.undoStack.length > this.maxDepth) {\n this.undoStack.shift();\n }\n\n this.redoStack = [];\n this.notify();\n }\n\n /**\n * Executes a command, coalescing it with the previous command if they share\n * the same `tag` and occurred within `windowMs` (default: 300ms).\n * Useful for high-frequency interactions like slider scrubs or node drags.\n */\n public executeMerged(\n command: Command,\n options: MergedExecutionOptions = {},\n ): void {\n const windowMs = options.windowMs ?? 300;\n const now = Date.now();\n\n if (\n command.tag &&\n this.undoStack.length > 0 &&\n this.batchDepth === 0 &&\n !this.isApplying\n ) {\n const top = this.undoStack[this.undoStack.length - 1];\n const elapsed = top.timestamp ? now - top.timestamp : Infinity;\n\n if (top.tag === command.tag && elapsed <= windowMs) {\n command.execute();\n // Replace top with merged command keeping the original initial undo\n const initialUndo = top.undo;\n this.undoStack[this.undoStack.length - 1] = {\n name: command.name,\n tag: command.tag,\n timestamp: now,\n execute: command.execute,\n undo: initialUndo,\n redo: command.redo ?? command.execute,\n };\n this.redoStack = [];\n this.notify();\n return;\n }\n }\n\n this.execute({ ...command, timestamp: now });\n }\n\n /**\n * Batches multiple commands executed within `fn` into a single atomic undo entry.\n */\n public batch(name: string, fn: () => void): void {\n if (this.isApplying) {\n fn();\n return;\n }\n\n if (this.batchDepth > 0) {\n // Already inside a batch; execute directly\n fn();\n return;\n }\n\n this.batchDepth++;\n this.currentBatch = [];\n\n try {\n fn();\n } catch (error) {\n const executed = this.currentBatch ?? [];\n this.batchDepth--;\n this.currentBatch = null;\n this.rollback(executed);\n throw error;\n }\n\n this.batchDepth--;\n const batchCommands: Command[] = this.currentBatch ?? [];\n this.currentBatch = null;\n\n if (batchCommands.length > 0) {\n const compoundCommand: Command = {\n name,\n timestamp: Date.now(),\n execute: () => {\n for (let i = 0; i < batchCommands.length; i++) {\n (batchCommands[i].redo ?? batchCommands[i].execute)();\n }\n },\n undo: () => {\n for (let i = batchCommands.length - 1; i >= 0; i--) {\n batchCommands[i].undo();\n }\n },\n redo: () => {\n for (let i = 0; i < batchCommands.length; i++) {\n (batchCommands[i].redo ?? batchCommands[i].execute)();\n }\n },\n };\n\n this.undoStack.push(compoundCommand);\n if (this.undoStack.length > this.maxDepth) {\n this.undoStack.shift();\n }\n this.redoStack = [];\n this.notify();\n }\n }\n\n /**\n * Reverts already-executed commands of an aborted batch, newest first.\n * Commands executed by the undo closures themselves are not recorded.\n */\n private rollback(commands: Command[]): void {\n const wasApplying = this.isApplying;\n this.isApplying = true;\n try {\n for (let i = commands.length - 1; i >= 0; i--) {\n try {\n commands[i].undo();\n } catch (err) {\n console.error(\n `[HistoryManager] Error rolling back \"${commands[i].name}\" of a failed batch:`,\n err,\n );\n }\n }\n } finally {\n this.isApplying = wasApplying;\n }\n }\n\n /**\n * Reverts the most recent command on the undo stack.\n * Returns true if a command was undone, false otherwise.\n */\n public undo(): boolean {\n if (this.undoStack.length === 0 || this.isApplying || this.batchDepth > 0) {\n return false;\n }\n\n this.isApplying = true;\n try {\n const command = this.undoStack[this.undoStack.length - 1];\n // If undo throws, the command stays on the undo stack and the error propagates.\n command.undo();\n this.undoStack.pop();\n this.redoStack.push(command);\n return true;\n } finally {\n this.isApplying = false;\n this.notify();\n }\n }\n\n /**\n * Re-applies the most recent undone command on the redo stack.\n * Returns true if a command was redone, false otherwise.\n */\n public redo(): boolean {\n if (this.redoStack.length === 0 || this.isApplying || this.batchDepth > 0) {\n return false;\n }\n\n this.isApplying = true;\n try {\n const command = this.redoStack[this.redoStack.length - 1];\n // If redo throws, the command stays on the redo stack and the error propagates.\n (command.redo ?? command.execute)();\n this.redoStack.pop();\n this.undoStack.push(command);\n return true;\n } finally {\n this.isApplying = false;\n this.notify();\n }\n }\n\n /**\n * Clears both undo and redo stacks.\n */\n public clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notify();\n }\n\n /**\n * Subscribes to history state changes.\n * The listener is immediately invoked with the current state.\n * Returns an unsubscribe function.\n */\n public subscribe(listener: (state: HistoryState) => void): () => void {\n this.listeners.add(listener);\n listener(this.getState());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Utility helper to create a Command from before/after state snapshots.\n */\n public static createSnapshotCommand<T>(\n options: SnapshotCommandOptions<T>,\n ): Command {\n return {\n name: options.name,\n tag: options.tag,\n execute: () => options.apply(options.after),\n undo: () => options.apply(options.before),\n redo: () => options.apply(options.after),\n };\n }\n}\n\n/**\n * Creates and initializes a new HistoryManager instance.\n */\nexport function createHistoryManager(\n options: HistoryManagerOptions = {},\n): HistoryManager {\n return new HistoryManager(options);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-4SUNJZWB.cjs","../src/grammar/tokenizer.ts","../src/grammar/engine.ts","../src/grammar/resolver.ts","../src/grammar/sourcemap.ts","../src/grammar/fields.ts"],"names":["out"],"mappings":"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EAAA;AACO,EAAA;AACT;AJ6UmB;AACA;AKtaH;AAIR,EAAA;AACA,EAAA;AACK,IAAA;AACX,EAAA;AACiB,EAAA;AAEA,EAAA;AACX,IAAA;AACC,IAAA;AACU,MAAA;AACX,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACW,QAAA;AACb,MAAA;AACY,MAAA;AACd,IAAA;AACW,IAAA;AACP,IAAA;AACS,MAAA;AACb,IAAA;AACO,IAAA;AACT,EAAA;AAGE,EAAA;AAKW,IAAA;AACC,MAAA;AACF,QAAA;AACK,QAAA;AACP,QAAA;AACF,UAAA;AACF,QAAA;AACI,QAAA;AACF,UAAA;AACF,QAAA;AACS,MAAA;AACA,QAAA;AACA,MAAA;AACH,QAAA;AACD,QAAA;AACH,UAAA;AACF,QAAA;AACM,QAAA;AACF,QAAA;AACE,QAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAEgB,EAAA;AACH,EAAA;AACf;AA0BgB;AAIP,EAAA;AACU,IAAA;AACR,IAAA;AACM,IAAA;AACA,IAAA;AAGA,IAAA;AAGH,IAAA;AACK,IAAA;AACf,EAAA;AACJ;AAMgB;AAGgB,EAAA;AAClB,EAAA;AACI,IAAA;AACD,MAAA;AACb,IAAA;AACF,EAAA;AACO,EAAA;AACT;ALsXmB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-4SUNJZWB.cjs","sourcesContent":[null,"import {\n TEMPLATE_REGEX,\n VARIABLE_REGEX,\n INSTRUCTION_REGEX,\n Token,\n PromptDiagnostic,\n} from \"./tokens\";\nimport { matchConditionalTags, parseVariableBody } from \"./variables\";\n\ntype RawMatch = Token & { type: \"template\" | \"variable\" | \"instruction\" | \"conditional\" };\n\nexport interface TokenizeResult {\n tokens: Token[];\n /** Unbalanced conditional tags, which were emitted as text. */\n diagnostics: PromptDiagnostic[];\n}\n\n/**\n * Parses any prompt string into an array of typed tokens in linear order.\n * Plain text between tokens is preserved as `{ type: 'text' }`.\n *\n * Conditional section tags (`{?name}`, `{!name}`, `{/name}`) are only emitted\n * as `conditional` tokens when balanced; unbalanced tags become text. Use\n * `tokenizePromptWithDiagnostics` to find out which tags were rejected.\n */\nexport function tokenizePrompt(text: string): Token[] {\n return tokenizePromptWithDiagnostics(text).tokens;\n}\n\n/**\n * Returns the diagnostics `tokenizePrompt` would report for `text`.\n */\nexport function getPromptDiagnostics(text: string): PromptDiagnostic[] {\n return tokenizePromptWithDiagnostics(text).diagnostics;\n}\n\n/**\n * Like `tokenizePrompt`, but also reports unbalanced conditional tags.\n */\nexport function tokenizePromptWithDiagnostics(text: string): TokenizeResult {\n if (!text) {\n return { tokens: [], diagnostics: [] };\n }\n\n const rawMatches: RawMatch[] = [];\n\n // Match {{template}}\n const tmplRegex = new RegExp(TEMPLATE_REGEX.source, TEMPLATE_REGEX.flags);\n let match: RegExpExecArray | null;\n while ((match = tmplRegex.exec(text)) !== null) {\n rawMatches.push({\n type: \"template\",\n raw: match[0],\n value: match[1].trim(),\n start: match.index,\n end: match.index + match[0].length,\n });\n }\n\n // Match {variable}\n const varRegex = new RegExp(VARIABLE_REGEX.source, VARIABLE_REGEX.flags);\n while ((match = varRegex.exec(text)) !== null) {\n // Avoid double matching if overlapping with template\n const start = match.index;\n const end = start + match[0].length;\n const overlaps = rawMatches.some(\n (m) => !(end <= m.start || start >= m.end),\n );\n if (!overlaps) {\n const parsed = parseVariableBody(match[1]);\n if (parsed.kind === \"conditional\") {\n rawMatches.push({\n type: \"conditional\",\n raw: match[0],\n value: parsed.name,\n start,\n end,\n conditional: parsed.conditional,\n });\n } else {\n const token: RawMatch = {\n type: \"variable\",\n raw: match[0],\n value: parsed.name,\n start,\n end,\n };\n if (parsed.defaultValue !== undefined) {\n token.defaultValue = parsed.defaultValue;\n }\n if (parsed.description !== undefined) {\n token.description = parsed.description;\n }\n rawMatches.push(token);\n }\n }\n }\n\n // Match __instruction__\n const instRegex = new RegExp(\n INSTRUCTION_REGEX.source,\n INSTRUCTION_REGEX.flags,\n );\n while ((match = instRegex.exec(text)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n const overlaps = rawMatches.some(\n (m) => !(end <= m.start || start >= m.end),\n );\n if (!overlaps) {\n rawMatches.push({\n type: \"instruction\",\n raw: match[0],\n value: match[1].trim(),\n start,\n end,\n });\n }\n }\n\n // Sort matches by start index\n rawMatches.sort((a, b) => a.start - b.start);\n\n // Pair conditional tags; unbalanced ones are demoted to text below.\n const diagnostics: PromptDiagnostic[] = [];\n const literal = new Set<RawMatch>();\n const conditionals = rawMatches.filter(\n (m): m is RawMatch & Required<Pick<Token, \"conditional\">> =>\n m.type === \"conditional\",\n );\n matchConditionalTags(\n conditionals.map((m) => ({ conditional: m.conditional, name: m.value })),\n ).forEach((result, i) => {\n if (!result.error) return;\n const tag = conditionals[i];\n literal.add(tag);\n diagnostics.push({\n code: result.error,\n message:\n result.error === \"unclosed-section\"\n ? `Section \"${tag.raw}\" is never closed with \"{/${tag.value}}\"`\n : `\"${tag.raw}\" does not close any open section`,\n name: tag.value,\n start: tag.start,\n end: tag.end,\n });\n });\n\n const tokens: Token[] = [];\n let currentIdx = 0;\n\n const pushText = (start: number, end: number) => {\n const previous = tokens[tokens.length - 1];\n if (previous?.type === \"text\" && previous.end === start) {\n // Merge with text produced by a demoted conditional tag.\n previous.raw = previous.value = text.slice(previous.start, end);\n previous.end = end;\n return;\n }\n const textChunk = text.slice(start, end);\n tokens.push({\n type: \"text\",\n raw: textChunk,\n value: textChunk,\n start,\n end,\n });\n };\n\n for (const m of rawMatches) {\n if (m.start > currentIdx) {\n pushText(currentIdx, m.start);\n }\n if (literal.has(m)) {\n pushText(m.start, m.end);\n } else {\n tokens.push({ ...m });\n }\n currentIdx = m.end;\n }\n\n if (currentIdx < text.length) {\n pushText(currentIdx, text.length);\n }\n\n return { tokens, diagnostics };\n}\n","import type {\n PromptDiagnostic,\n PromptValues,\n Template,\n TemplateVersion,\n Token,\n} from \"./tokens\";\nimport type { SourceMapSegment } from \"./sourcemap\";\nimport { tokenizePromptWithDiagnostics } from \"./tokenizer\";\nimport { evaluateCondition, getSuppliedValue } from \"./variables\";\n\n/**\n * Finds the latest version of a template based on `latestVersion` or last version entry.\n */\nexport function getLatestVersion(\n template: Template,\n): TemplateVersion | undefined {\n if (!template.versions || template.versions.length === 0) {\n if (template.body !== undefined) {\n return {\n id: template.id || \"default\",\n version: \"1.0\",\n body: template.body,\n };\n }\n return undefined;\n }\n if (template.latestVersion) {\n const found = template.versions.find(\n (v) => v.version === template.latestVersion,\n );\n if (found) return found;\n }\n return template.versions[template.versions.length - 1];\n}\n\n/** Marker substituted for a template tag that would recurse into itself. */\nexport const TEMPLATE_LOOP_ERROR = \"[Template loop detected]\";\n/** Marker substituted for a template tag nested deeper than `maxDepth`. */\nexport const TEMPLATE_DEPTH_ERROR = \"[Template max depth exceeded]\";\n\n/**\n * Returns the body a template tag resolves to, honoring version bindings.\n */\nexport function getTemplateBody(\n template: Template,\n bindings?: Record<string, string>,\n): string | undefined {\n const boundVersionId = bindings?.[template.name];\n if (boundVersionId && template.versions) {\n const boundVersion = template.versions.find(\n (v) => v.id === boundVersionId || v.version === boundVersionId,\n );\n return boundVersion?.body;\n }\n return getLatestVersion(template)?.body ?? template.body;\n}\n\nexport interface ResolvePromptOptions {\n /** Template version bindings (`{ templateName: versionIdOrVersion }`). */\n bindings?: Record<string, string>;\n /** Maximum template nesting depth (default 10). */\n maxDepth?: number;\n /**\n * Values for `{variable}` slots and `{?variable}` / `{!variable}` sections.\n * When omitted, variables and section tags are left exactly as written.\n */\n values?: PromptValues;\n}\n\nexport interface ResolvePromptResult {\n text: string;\n map: SourceMapSegment[];\n diagnostics: PromptDiagnostic[];\n}\n\ntype Segment = SourceMapSegment & { locked?: boolean };\n\n/** Accumulates resolved text and, at the top level, source map segments. */\nclass Output {\n text = \"\";\n constructor(readonly segments: Segment[] | null) {}\n\n /** Text copied verbatim from the raw input. Locked segments never merge. */\n raw(rawStart: number, rawEnd: number, value: string, locked = false) {\n const resolvedStart = this.text.length;\n this.text += value;\n if (!this.segments) return;\n const last = this.segments[this.segments.length - 1];\n if (\n !locked &&\n last &&\n last.source === \"raw\" &&\n !last.locked &&\n last.rawEnd === rawStart &&\n last.resolvedEnd === resolvedStart\n ) {\n last.rawEnd = rawEnd;\n last.resolvedEnd = this.text.length;\n return;\n }\n this.segments.push({\n resolvedStart,\n resolvedEnd: this.text.length,\n source: \"raw\",\n rawStart,\n rawEnd,\n ...(locked ? { locked } : {}),\n });\n }\n\n /** Text that replaces a raw range (template body, value, removed section). */\n replaced(\n rawStart: number,\n rawEnd: number,\n value: string,\n extra: Pick<\n SourceMapSegment,\n \"source\" | \"templateName\" | \"variableName\" | \"valueSource\"\n >,\n ) {\n const resolvedStart = this.text.length;\n this.text += value;\n this.segments?.push({\n resolvedStart,\n resolvedEnd: this.text.length,\n rawStart,\n rawEnd,\n ...extra,\n });\n }\n}\n\n/** Pairs balanced conditional tokens (the tokenizer guarantees nesting). */\nfunction pairSections(tokens: Token[]): Map<number, number> {\n const pairs = new Map<number, number>();\n const stack: number[] = [];\n tokens.forEach((token, index) => {\n if (token.type !== \"conditional\") return;\n if (token.conditional === \"end\") {\n const open = stack.pop();\n if (open !== undefined) pairs.set(open, index);\n } else {\n stack.push(index);\n }\n });\n return pairs;\n}\n\n/**\n * Resolves a prompt: expands `{{templates}}` recursively (with loop and depth\n * protection), and, when `values` are given, substitutes `{variables}` (falling\n * back to their `|default`) and keeps or removes `{?name}…{/name}` sections.\n *\n * Template bodies are parsed on their own, so a section must open and close\n * within the same body. Templates inside a removed section are never expanded\n * and cannot trigger loop or depth errors. Unbalanced section tags are kept as\n * literal text and reported in `diagnostics`.\n *\n * Returns the resolved text, a source map from resolved to raw offsets, and\n * diagnostics. With no `values` the text matches the original template-only\n * resolver exactly.\n */\nexport function resolvePrompt(\n text: string,\n templates: Template[] = [],\n options: ResolvePromptOptions = {},\n): ResolvePromptResult {\n const templateMap = new Map<string, Template>();\n for (const t of templates) {\n templateMap.set(t.name, t);\n }\n const maxDepth = options.maxDepth ?? 10;\n const values = options.values;\n const diagnostics: PromptDiagnostic[] = [];\n const reported = new Set<string>();\n\n function resolveInto(\n source: string,\n out: Output,\n visited: Set<string>,\n depth: number,\n templateName: string | undefined,\n ): void {\n const { tokens, diagnostics: found } =\n tokenizePromptWithDiagnostics(source);\n for (const diagnostic of found) {\n const key = `${templateName ?? \"\"}\\u0000${diagnostic.start}\\u0000${diagnostic.code}`;\n if (reported.has(key)) continue;\n reported.add(key);\n diagnostics.push(\n templateName === undefined ? diagnostic : { ...diagnostic, templateName },\n );\n }\n const pairs = values ? pairSections(tokens) : null;\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (token.type === \"template\") {\n const name = token.value;\n if (visited.has(name)) {\n out.replaced(token.start, token.end, TEMPLATE_LOOP_ERROR, {\n source: \"template\",\n templateName: name,\n });\n continue;\n }\n const template = templateMap.get(name);\n const body = template\n ? getTemplateBody(template, options.bindings)\n : undefined;\n if (body === undefined) {\n out.raw(token.start, token.end, token.raw, true);\n continue;\n }\n if (depth + 1 > maxDepth) {\n out.replaced(token.start, token.end, TEMPLATE_DEPTH_ERROR, {\n source: \"template\",\n templateName: name,\n });\n continue;\n }\n const nested = new Output(null);\n const nextVisited = new Set(visited);\n nextVisited.add(name);\n resolveInto(body, nested, nextVisited, depth + 1, name);\n out.replaced(token.start, token.end, nested.text, {\n source: \"template\",\n templateName: name,\n });\n continue;\n }\n\n if (values && token.type === \"variable\") {\n const supplied = getSuppliedValue(values, token.value);\n const value = supplied ?? token.defaultValue;\n if (value !== undefined) {\n out.replaced(token.start, token.end, value, {\n source: \"variable\",\n variableName: token.value,\n valueSource: supplied !== undefined ? \"value\" : \"default\",\n });\n continue;\n }\n }\n\n if (values && token.type === \"conditional\" && token.conditional) {\n const tagInfo = {\n source: \"conditional\" as const,\n variableName: token.value,\n };\n if (token.conditional !== \"end\") {\n const close = pairs!.get(i)!;\n if (!evaluateCondition(token.conditional, token.value, values)) {\n // Drop the whole section, tags included.\n out.replaced(token.start, tokens[close].end, \"\", tagInfo);\n i = close;\n continue;\n }\n }\n out.replaced(token.start, token.end, \"\", tagInfo);\n continue;\n }\n\n out.raw(token.start, token.end, token.raw);\n }\n }\n\n const out = new Output([]);\n resolveInto(text, out, new Set(), 0, undefined);\n\n const map: SourceMapSegment[] = out.segments!.map(\n ({ locked: _locked, ...segment }) => segment,\n );\n if (map.length === 0) {\n map.push({\n resolvedStart: 0,\n resolvedEnd: 0,\n source: \"raw\",\n rawStart: 0,\n rawEnd: 0,\n });\n }\n return { text: out.text, map, diagnostics };\n}\n\n/** A token annotated with the value it resolves to. */\nexport interface EvaluatedToken extends Token {\n /** Variables only, when values were given: the substituted text. */\n resolvedValue?: string;\n /** Variables only: whether `resolvedValue` came from `values` or the default. */\n valueSource?: \"value\" | \"default\";\n}\n\n/**\n * Tokenizes a prompt for display. Without `values` this is `tokenizePrompt`.\n * With `values`, sections whose condition fails are removed (tags included),\n * the tags of kept sections are dropped, and each variable that has a value or\n * a default carries it in `resolvedValue`. Templates are not expanded; resolve\n * them first (without values) if the display should show their bodies.\n */\nexport function evaluatePromptTokens(\n text: string,\n values?: PromptValues,\n): EvaluatedToken[] {\n const tokens = tokenizePromptWithDiagnostics(text).tokens;\n if (!values) return tokens;\n\n const pairs = pairSections(tokens);\n const result: EvaluatedToken[] = [];\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token.type === \"conditional\") {\n if (\n token.conditional !== \"end\" &&\n !evaluateCondition(token.conditional!, token.value, values)\n ) {\n i = pairs.get(i)!;\n }\n continue;\n }\n if (token.type === \"variable\") {\n const supplied = getSuppliedValue(values, token.value);\n const value = supplied ?? token.defaultValue;\n if (value !== undefined) {\n result.push({\n ...token,\n resolvedValue: value,\n valueSource: supplied !== undefined ? \"value\" : \"default\",\n });\n continue;\n }\n }\n result.push(token);\n }\n return result;\n}\n","import {\n TEMPLATE_REGEX,\n VARIABLE_REGEX,\n INSTRUCTION_REGEX,\n Template,\n PromptValues,\n} from \"./tokens\";\nimport { resolvePrompt } from \"./engine\";\nimport { parseVariableBody } from \"./variables\";\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. 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 match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n set.add(parseVariableBody(match[1]).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. */\n usedInCondition: boolean;\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 describe(token.value, templateName).usedInCondition = 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 /** Only used by `{?name}` / `{!name}` conditions, never substituted. */\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,\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"]}