kindy-editor 3.2.6 → 3.2.8

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 (31) hide show
  1. package/dist-lib/assets/{worker-B7ALyZOw.js → worker-DjZBUOhB.js} +1009 -997
  2. package/dist-lib/assets/{worker-z-dyEi8F.js → worker-Du8hmveE.js} +2234 -2222
  3. package/dist-lib/builder.js +4 -4
  4. package/dist-lib/events.js +9 -120
  5. package/dist-lib/export.js +9 -11
  6. package/dist-lib/generate-toc.js +3 -3
  7. package/dist-lib/import.js +2 -2
  8. package/dist-lib/index-D5dkvB0x.js +490 -0
  9. package/dist-lib/{editorApp-Bu3dbUIU.js → kindy-editor-T1YCQdwF.js} +13483 -11185
  10. package/dist-lib/kindy-editor.js +4 -4
  11. package/dist-lib/measure.js +3 -4
  12. package/dist-lib/{measureHost-CpqJsipA.js → measureHost-BG9FPivu.js} +17 -18
  13. package/dist-lib/{paintStyle-Cb7IGKPW.js → metrics-D7Ma2xlj.js} +175 -148
  14. package/dist-lib/{parse-CKw-ZDr9.js → parse-BsUkqk-n.js} +3 -3
  15. package/dist-lib/{pipeline-BkC7G8gU.js → pipeline-CX_Hc5BD.js} +850 -837
  16. package/dist-lib/{qrcode-oNwKusWD.js → qrcode--5MhVNEZ.js} +1 -1
  17. package/dist-lib/{qrcode-efBlPzzh.js → qrcode-CR8i1-w0.js} +11 -11
  18. package/dist-lib/recalc-docx.js +1 -1
  19. package/dist-lib/{recalcToc-Bc8V9Ecn.js → recalcToc-zAFS4S6S.js} +755 -742
  20. package/dist-lib/{stylesheet-BT1DGhnx.js → stylesheet-BfxJTGA5.js} +1 -1
  21. package/dist-lib/{webmcp-ClHEa6Gq.js → webmcp-Ds469lXP.js} +2 -2
  22. package/docs/find-and-replace.md +224 -0
  23. package/docs/security-review.md +26 -0
  24. package/docs/table-editing.md +17 -2
  25. package/docs/table-form-integration.md +53 -1
  26. package/package.json +6 -6
  27. package/types/import.d.ts +7 -0
  28. package/types/kindy-editor.d.ts +30 -0
  29. package/dist-lib/changeAggregator-ZI959nPP.js +0 -376
  30. package/dist-lib/kindy-editor-CToKn_gP.js +0 -2171
  31. package/dist-lib/metrics-CdfHD-8y.js +0 -31
@@ -0,0 +1,490 @@
1
+ import { t as I } from "./qrcode-CR8i1-w0.js";
2
+ const w = "1.0";
3
+ function M(o) {
4
+ const e = /* @__PURE__ */ new Set();
5
+ for (const n of o)
6
+ switch (n.type) {
7
+ case "insertText":
8
+ case "insertRuns":
9
+ case "splitParagraph":
10
+ e.add(n.at.blockId), n.type === "splitParagraph" && e.add(n.newBlockId);
11
+ break;
12
+ case "mergeParagraphs":
13
+ e.add(n.firstBlockId);
14
+ break;
15
+ case "insertBlock":
16
+ e.add(n.block.id);
17
+ break;
18
+ case "setTableRow":
19
+ case "setTableStructure":
20
+ case "setTableStyleRef":
21
+ case "insertTableRow":
22
+ case "removeTableRow":
23
+ case "setRowHeight":
24
+ case "insertTableColumn":
25
+ case "removeTableColumn":
26
+ e.add(n.tableId);
27
+ break;
28
+ case "deleteRange":
29
+ case "setRuns":
30
+ case "setParaStyle":
31
+ case "removeBlock":
32
+ case "setImageProps":
33
+ case "setEquation":
34
+ case "setEquationAlign":
35
+ case "setTableColFractions":
36
+ case "setTableWidthMode":
37
+ case "setTablePreferredWidth":
38
+ case "setTableAlign":
39
+ case "setTableProps":
40
+ e.add(n.blockId);
41
+ break;
42
+ }
43
+ return [...e];
44
+ }
45
+ function S(o, e) {
46
+ const n = { type: "review.operation.applied", data: { operation: o, remote: e } };
47
+ switch (o.type) {
48
+ case "addSuggestion":
49
+ return [n, { type: "review.suggestion.created", data: { suggestionId: o.s.id, kind: o.s.kind, remote: e } }];
50
+ case "removeSuggestion":
51
+ return [n, { type: "review.suggestion.removed", data: { suggestionId: o.id, remote: e } }];
52
+ case "growSuggestion":
53
+ return [n];
54
+ case "addThread": {
55
+ const s = o.t.comments[0];
56
+ return s ? [
57
+ n,
58
+ { type: "review.thread.created", data: { threadId: o.t.id, remote: e } },
59
+ {
60
+ type: "review.comment.added",
61
+ data: {
62
+ threadId: o.t.id,
63
+ commentId: s.id,
64
+ authorId: s.author.id,
65
+ isReply: !1,
66
+ mentionedUserIds: (s.mentions ?? []).map((t) => t.id),
67
+ remote: e
68
+ }
69
+ }
70
+ ] : [n, { type: "review.thread.created", data: { threadId: o.t.id, remote: e } }];
71
+ }
72
+ case "removeThread":
73
+ return [n, { type: "review.thread.removed", data: { threadId: o.id, remote: e } }];
74
+ case "addComment":
75
+ return [n, {
76
+ type: "review.comment.added",
77
+ data: {
78
+ threadId: o.threadId,
79
+ commentId: o.c.id,
80
+ authorId: o.c.author.id,
81
+ isReply: !0,
82
+ mentionedUserIds: (o.c.mentions ?? []).map((s) => s.id),
83
+ remote: e
84
+ }
85
+ }];
86
+ case "removeComment":
87
+ return [n, { type: "review.comment.removed", data: { threadId: o.threadId, commentId: o.commentId, remote: e } }];
88
+ case "editComment":
89
+ return [n, {
90
+ type: "review.comment.edited",
91
+ data: {
92
+ threadId: o.threadId,
93
+ commentId: o.commentId,
94
+ mentionedUserIds: (o.mentions ?? []).map((s) => s.id),
95
+ newlyMentionedUserIds: o.newlyMentionedUserIds ?? [],
96
+ remote: e
97
+ }
98
+ }];
99
+ case "deleteComment":
100
+ return [n, {
101
+ type: "review.comment.deleted",
102
+ data: {
103
+ threadId: o.threadId,
104
+ commentId: o.commentId,
105
+ deletedByUserId: o.deletedBy.id,
106
+ remote: e
107
+ }
108
+ }];
109
+ case "setThreadStatus":
110
+ return [n, { type: "review.thread.status.changed", data: { threadId: o.threadId, status: o.status, remote: e } }];
111
+ }
112
+ }
113
+ function p(o) {
114
+ if (o.length === 0) return [];
115
+ const e = /* @__PURE__ */ new Map();
116
+ for (const s of o) {
117
+ let t = e.get(s.blockId);
118
+ t || (t = [], e.set(s.blockId, t)), t.push({ ...s });
119
+ }
120
+ const n = [];
121
+ for (const [s, t] of e) {
122
+ if (t.length === 0) continue;
123
+ const i = [];
124
+ for (const r of t) {
125
+ if (i.length === 0) {
126
+ i.push(r);
127
+ continue;
128
+ }
129
+ const a = i[i.length - 1];
130
+ if (a.action === "delete" && r.action === "insert" && a.offset === r.offset) {
131
+ a.action = "replace", a.toText = r.toText;
132
+ continue;
133
+ }
134
+ if (a.action === "replace" && r.action === "insert" && r.offset === a.offset + a.toText.length) {
135
+ a.toText += r.toText;
136
+ continue;
137
+ }
138
+ if (a.action === "insert" && r.action === "insert" && r.offset === a.offset + a.toText.length) {
139
+ a.toText += r.toText;
140
+ continue;
141
+ }
142
+ if (a.action === "delete" && r.action === "delete" && r.offset === a.offset) {
143
+ a.fromText += r.fromText;
144
+ continue;
145
+ }
146
+ if (a.action === "delete" && r.action === "delete" && r.offset + r.fromText.length === a.offset) {
147
+ a.offset = r.offset, a.fromText = r.fromText + a.fromText;
148
+ continue;
149
+ }
150
+ i.push(r);
151
+ }
152
+ for (const r of i)
153
+ r.action === "replace" && r.fromText === r.toText || r.action === "insert" && r.toText.length === 0 || r.action === "delete" && r.fromText.length === 0 || n.push({
154
+ action: r.action,
155
+ blockId: s,
156
+ offset: r.offset,
157
+ fromText: r.fromText,
158
+ toText: r.toText
159
+ });
160
+ }
161
+ return n;
162
+ }
163
+ function E(o, e) {
164
+ const n = new Map(Object.entries(e)), s = [];
165
+ for (const t of o)
166
+ if (t.type === "deleteRange") {
167
+ const i = n.get(t.blockId) ?? "", r = Math.max(0, Math.min(t.start, i.length)), a = Math.max(r, Math.min(t.end, i.length)), c = i.slice(r, a);
168
+ c.length > 0 && s.push({
169
+ action: "delete",
170
+ blockId: t.blockId,
171
+ offset: r,
172
+ fromText: c,
173
+ toText: ""
174
+ }), n.set(t.blockId, i.slice(0, r) + i.slice(a));
175
+ } else if (t.type === "insertText") {
176
+ const i = n.get(t.at.blockId) ?? "", r = Math.max(0, Math.min(t.at.offset, i.length));
177
+ t.text.length > 0 && s.push({
178
+ action: "insert",
179
+ blockId: t.at.blockId,
180
+ offset: r,
181
+ fromText: "",
182
+ toText: t.text
183
+ }), n.set(
184
+ t.at.blockId,
185
+ i.slice(0, r) + t.text + i.slice(r)
186
+ );
187
+ } else if (t.type === "insertRuns") {
188
+ const i = I(t.runs), r = n.get(t.at.blockId) ?? "", a = Math.max(0, Math.min(t.at.offset, r.length));
189
+ i.length > 0 && s.push({
190
+ action: "insert",
191
+ blockId: t.at.blockId,
192
+ offset: a,
193
+ fromText: "",
194
+ toText: i
195
+ }), n.set(
196
+ t.at.blockId,
197
+ r.slice(0, a) + i + r.slice(a)
198
+ );
199
+ } else if (t.type === "setRuns") {
200
+ const i = n.get(t.blockId) ?? "", r = I(t.runs);
201
+ i !== r && s.push({
202
+ action: "replace",
203
+ blockId: t.blockId,
204
+ offset: 0,
205
+ fromText: i,
206
+ toText: r
207
+ }), n.set(t.blockId, r);
208
+ } else if (t.type === "splitParagraph") {
209
+ const i = n.get(t.at.blockId) ?? "", r = Math.max(0, Math.min(t.at.offset, i.length)), a = i.slice(0, r), c = i.slice(r);
210
+ n.set(t.at.blockId, a), n.set(t.newBlockId, c);
211
+ } else if (t.type === "removeBlock") {
212
+ const i = n.get(t.blockId) ?? "";
213
+ i.length > 0 && s.push({
214
+ action: "delete",
215
+ blockId: t.blockId,
216
+ offset: 0,
217
+ fromText: i,
218
+ toText: ""
219
+ }), n.set(t.blockId, "");
220
+ }
221
+ return p(s);
222
+ }
223
+ function x(o, e, n, s = 0) {
224
+ if (o === e) return [];
225
+ let t = 0;
226
+ const i = Math.min(o.length, e.length);
227
+ for (; t < i && o[t] === e[t]; )
228
+ t++;
229
+ let r = 0;
230
+ const a = Math.min(o.length - t, e.length - t);
231
+ for (; r < a && o[o.length - 1 - r] === e[e.length - 1 - r]; )
232
+ r++;
233
+ const c = o.slice(t, o.length - r), d = e.slice(t, e.length - r), h = s + t;
234
+ return c.length > 0 && d.length === 0 ? [{ action: "delete", blockId: n, offset: h, fromText: c, toText: "" }] : c.length === 0 && d.length > 0 ? [{ action: "insert", blockId: n, offset: h, fromText: "", toText: d }] : c.length > 0 && d.length > 0 ? [{ action: "replace", blockId: n, offset: h, fromText: c, toText: d }] : [];
235
+ }
236
+ class B {
237
+ detail;
238
+ includeSelection;
239
+ handlers = /* @__PURE__ */ new Map();
240
+ anyHandlers = /* @__PURE__ */ new Set();
241
+ sink;
242
+ redact;
243
+ onError;
244
+ disposed = !1;
245
+ constructor(e = {}) {
246
+ this.detail = e.detail ?? "metadata", this.includeSelection = e.includeSelection ?? !1, this.sink = e.sink, this.redact = e.redact, this.onError = e.onError ?? ((n) => console.error("[kindy-editor:event]", n));
247
+ }
248
+ on(e, n, s = {}) {
249
+ if (this.disposed || s.signal?.aborted) return () => {
250
+ };
251
+ let t = this.handlers.get(e);
252
+ t || this.handlers.set(e, t = /* @__PURE__ */ new Set()), t.add(n);
253
+ const i = () => {
254
+ t?.delete(n), t?.size === 0 && this.handlers.delete(e);
255
+ };
256
+ return s.signal?.addEventListener("abort", i, { once: !0 }), i;
257
+ }
258
+ onAny(e, n = {}) {
259
+ if (this.disposed || n.signal?.aborted) return () => {
260
+ };
261
+ this.anyHandlers.add(e);
262
+ const s = () => {
263
+ this.anyHandlers.delete(e);
264
+ };
265
+ return n.signal?.addEventListener("abort", s, { once: !0 }), s;
266
+ }
267
+ off(e, n) {
268
+ this.handlers.get(e)?.delete(n);
269
+ }
270
+ /** Called by the editor runtime after state is already consistent. Public only
271
+ * for custom bridges; normal integrations subscribe with on/onAny. */
272
+ dispatch(e) {
273
+ if (this.disposed) return;
274
+ const n = this.redact ? this.redact(e) : e;
275
+ if (n) {
276
+ for (const s of this.handlers.get(n.type) ?? []) this.safeCall(s, n);
277
+ for (const s of this.anyHandlers) this.safeCall(s, n);
278
+ if (this.sink)
279
+ try {
280
+ Promise.resolve(this.sink(n)).catch((s) => this.reportError(s, n));
281
+ } catch (s) {
282
+ this.reportError(s, n);
283
+ }
284
+ }
285
+ }
286
+ destroy() {
287
+ this.disposed = !0, this.handlers.clear(), this.anyHandlers.clear();
288
+ }
289
+ safeCall(e, n) {
290
+ try {
291
+ e(n);
292
+ } catch (s) {
293
+ this.reportError(s, n);
294
+ }
295
+ }
296
+ reportError(e, n) {
297
+ try {
298
+ this.onError(e, n);
299
+ } catch (s) {
300
+ console.error("[kindy-editor:event:onError]", s);
301
+ }
302
+ }
303
+ }
304
+ function C(o) {
305
+ const e = o.fetch ?? globalThis.fetch;
306
+ if (!e) throw new Error("createHttpEventSink requires fetch");
307
+ const n = Math.max(1, o.batchSize ?? 25), s = Math.max(10, o.flushIntervalMs ?? 1e3), t = Math.max(1, o.maxAttempts ?? 3);
308
+ let i = [], r = null, a = Promise.resolve(), c = !1;
309
+ const d = () => {
310
+ r && clearTimeout(r), r = null;
311
+ }, h = async () => {
312
+ const l = typeof o.headers == "function" ? await o.headers() : o.headers, f = new Headers(l);
313
+ return f.has("content-type") || f.set("content-type", "application/json"), f;
314
+ }, y = async (l) => {
315
+ let f;
316
+ for (let m = 1; m <= t; m++)
317
+ try {
318
+ const g = await e(o.endpoint, {
319
+ method: "POST",
320
+ headers: await h(),
321
+ body: JSON.stringify({ schemaVersion: l[0]?.schemaVersion ?? "1.0", events: l })
322
+ });
323
+ if (!g.ok) throw new Error(`event sink returned HTTP ${g.status}`);
324
+ return;
325
+ } catch (g) {
326
+ f = g, m < t && await new Promise((b) => setTimeout(b, 100 * 2 ** (m - 1)));
327
+ }
328
+ o.onDeliveryError?.(f, l);
329
+ }, u = async () => {
330
+ if (d(), i.length === 0) return a;
331
+ const l = i;
332
+ i = [], a = a.then(() => y(l)), await a;
333
+ }, T = ((l) => {
334
+ c || o.eventTypes && !o.eventTypes.includes(l.type) || (i.push(l), i.length >= n ? u() : r || (r = setTimeout(() => void u(), s)));
335
+ });
336
+ return T.flush = u, T.destroy = async () => {
337
+ c = !0, await u();
338
+ }, T;
339
+ }
340
+ class k {
341
+ idleMs;
342
+ selectionJumpThreshold;
343
+ constructor(e = {}) {
344
+ this.idleMs = Math.max(100, e.idleMs ?? 1e3), this.selectionJumpThreshold = Math.max(1, e.selectionJumpThreshold ?? 2);
345
+ }
346
+ /**
347
+ * Evaluates if a selection movement constitutes a boundary (e.g. jumped to another block
348
+ * or moved far away from the active typing position).
349
+ */
350
+ shouldCommitOnSelectionChange(e, n, s, t) {
351
+ return !e || s === null || t === null ? !1 : e !== s || n !== null && Math.abs(t - n) > this.selectionJumpThreshold;
352
+ }
353
+ }
354
+ class R {
355
+ policy;
356
+ emit;
357
+ getVersion;
358
+ idGenerator;
359
+ currentSession = null;
360
+ idleTimer = null;
361
+ disposed = !1;
362
+ nextGroupId = 1;
363
+ constructor(e) {
364
+ this.policy = e.policy instanceof k ? e.policy : new k({
365
+ ...typeof e.idleMs == "number" ? { idleMs: e.idleMs } : {},
366
+ ...e.policy
367
+ }), this.emit = e.emit, this.getVersion = e.getVersion ?? (() => 0), this.idGenerator = e.idGenerator ?? (() => `chg-${Date.now()}-${this.nextGroupId++}`);
368
+ }
369
+ /**
370
+ * Tracks a raw applied change. Starts a new session or extends the active session.
371
+ */
372
+ trackChange(e) {
373
+ if (this.disposed) return;
374
+ this.currentSession && this.currentSession.origin !== e.origin && this.flush("origin-change");
375
+ const n = e.version ?? this.getVersion();
376
+ if (!this.currentSession) {
377
+ const t = this.getVersion(), i = e.version ?? t;
378
+ this.currentSession = {
379
+ changeGroupId: this.idGenerator(),
380
+ origin: e.origin,
381
+ ...e.intent !== void 0 ? { intent: e.intent } : {},
382
+ beforeVersion: t,
383
+ afterVersion: i,
384
+ lastTransactionId: e.transactionId,
385
+ initialBlockTexts: /* @__PURE__ */ new Map(),
386
+ currentBlockTexts: /* @__PURE__ */ new Map(),
387
+ diffs: [],
388
+ activeBlockId: e.selectionAfter?.focus.blockId ?? null,
389
+ lastOffset: e.selectionAfter?.focus.offset ?? null
390
+ };
391
+ }
392
+ const s = this.currentSession;
393
+ if (s) {
394
+ s.afterVersion = n, s.lastTransactionId = e.transactionId, e.intent !== void 0 && s.intent === void 0 && (s.intent = e.intent);
395
+ for (const t of e.affectedBlockIds)
396
+ if (!s.initialBlockTexts.has(t)) {
397
+ const i = e.blockTextBefore?.[t] ?? "";
398
+ s.initialBlockTexts.set(t, i), s.currentBlockTexts.set(t, i);
399
+ }
400
+ if (this.applyOpsToCurrentTexts(s.currentBlockTexts, e.ops), e.textDiffs && e.textDiffs.length > 0 && s.diffs.push(...e.textDiffs), e.selectionAfter && (s.activeBlockId = e.selectionAfter.focus.blockId, s.lastOffset = e.selectionAfter.focus.offset), e.origin === "paste" || e.origin === "command") {
401
+ this.flush("explicit");
402
+ return;
403
+ }
404
+ this.restartIdleTimer();
405
+ }
406
+ }
407
+ /**
408
+ * Signals a semantic boundary from the editor environment (blur, save, selection change, etc.).
409
+ */
410
+ notifyBoundary(e, n) {
411
+ if (!(this.disposed || !this.currentSession)) {
412
+ if (e === "selection-jump") {
413
+ this.policy.shouldCommitOnSelectionChange(
414
+ this.currentSession.activeBlockId,
415
+ this.currentSession.lastOffset,
416
+ n?.newBlockId ?? null,
417
+ n?.newOffset ?? null
418
+ ) && this.flush("selection-jump");
419
+ return;
420
+ }
421
+ this.flush(e);
422
+ }
423
+ }
424
+ /**
425
+ * Flushes and commits the active session if one exists and contains non-trivial changes.
426
+ */
427
+ flush(e) {
428
+ this.clearIdleTimer();
429
+ const n = this.currentSession;
430
+ if (!n) return;
431
+ this.currentSession = null;
432
+ const s = [];
433
+ for (const [t, i] of n.initialBlockTexts) {
434
+ const r = n.currentBlockTexts.get(t) ?? i;
435
+ if (i !== r) {
436
+ const a = x(i, r, t);
437
+ s.push(...a);
438
+ }
439
+ }
440
+ s.length !== 0 && this.emit({
441
+ transactionId: n.lastTransactionId,
442
+ changeGroupId: n.changeGroupId,
443
+ beforeVersion: n.beforeVersion,
444
+ afterVersion: n.afterVersion,
445
+ origin: n.origin,
446
+ textDiffs: s,
447
+ ...n.intent ? { intent: n.intent } : {},
448
+ affectedBlockIds: Array.from(n.initialBlockTexts.keys())
449
+ });
450
+ }
451
+ destroy() {
452
+ this.disposed || (this.flush("destroy"), this.disposed = !0);
453
+ }
454
+ applyOpsToCurrentTexts(e, n) {
455
+ for (const s of n)
456
+ if (s.type === "deleteRange") {
457
+ const t = e.get(s.blockId) ?? "", i = Math.max(0, Math.min(s.start, t.length)), r = Math.max(i, Math.min(s.end, t.length));
458
+ e.set(s.blockId, t.slice(0, i) + t.slice(r));
459
+ } else if (s.type === "insertText") {
460
+ const t = e.get(s.at.blockId) ?? "", i = Math.max(0, Math.min(s.at.offset, t.length));
461
+ e.set(s.at.blockId, t.slice(0, i) + s.text + t.slice(i));
462
+ } else if (s.type === "insertRuns") {
463
+ const t = I(s.runs), i = e.get(s.at.blockId) ?? "", r = Math.max(0, Math.min(s.at.offset, i.length));
464
+ e.set(s.at.blockId, i.slice(0, r) + t + i.slice(r));
465
+ } else if (s.type === "setRuns")
466
+ e.set(s.blockId, I(s.runs));
467
+ else if (s.type === "splitParagraph") {
468
+ const t = e.get(s.at.blockId) ?? "", i = Math.max(0, Math.min(s.at.offset, t.length));
469
+ e.set(s.at.blockId, t.slice(0, i)), e.set(s.newBlockId, t.slice(i));
470
+ } else s.type === "removeBlock" && e.set(s.blockId, "");
471
+ }
472
+ restartIdleTimer() {
473
+ this.clearIdleTimer(), this.idleTimer = setTimeout(() => {
474
+ this.flush("idle");
475
+ }, this.policy.idleMs);
476
+ }
477
+ clearIdleTimer() {
478
+ this.idleTimer && (clearTimeout(this.idleTimer), this.idleTimer = null);
479
+ }
480
+ }
481
+ export {
482
+ R as C,
483
+ w as E,
484
+ M as a,
485
+ B as b,
486
+ E as c,
487
+ k as d,
488
+ C as e,
489
+ S as p
490
+ };