@coco-vexel/coco-office-editor 0.0.0-stage → 1.0.1

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 (57) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +510 -2
  3. package/THIRD_PARTY_NOTICES.md +212 -0
  4. package/dist/index.cjs +26401 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +12 -0
  7. package/dist/index.d.ts +12 -0
  8. package/dist/index.js +26192 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/model-DB6aN6uJ.d.cts +321 -0
  11. package/dist/model-DB6aN6uJ.d.ts +321 -0
  12. package/dist/native-B6B649CC.d.ts +1111 -0
  13. package/dist/native-Ct9nN06K.d.cts +1111 -0
  14. package/dist/ppt-native.cjs +5334 -0
  15. package/dist/ppt-native.cjs.map +1 -0
  16. package/dist/ppt-native.d.cts +2 -0
  17. package/dist/ppt-native.d.ts +2 -0
  18. package/dist/ppt-native.js +5332 -0
  19. package/dist/ppt-native.js.map +1 -0
  20. package/dist/ppt.cjs +5426 -0
  21. package/dist/ppt.cjs.map +1 -0
  22. package/dist/ppt.d.cts +306 -0
  23. package/dist/ppt.d.ts +306 -0
  24. package/dist/ppt.js +5410 -0
  25. package/dist/ppt.js.map +1 -0
  26. package/dist/spreadsheet.cjs +4276 -0
  27. package/dist/spreadsheet.cjs.map +1 -0
  28. package/dist/spreadsheet.d.cts +676 -0
  29. package/dist/spreadsheet.d.ts +676 -0
  30. package/dist/spreadsheet.js +4213 -0
  31. package/dist/spreadsheet.js.map +1 -0
  32. package/dist/word-editing.cjs +812 -0
  33. package/dist/word-editing.cjs.map +1 -0
  34. package/dist/word-editing.d.cts +149 -0
  35. package/dist/word-editing.d.ts +149 -0
  36. package/dist/word-editing.js +803 -0
  37. package/dist/word-editing.js.map +1 -0
  38. package/dist/word-native.cjs +13400 -0
  39. package/dist/word-native.cjs.map +1 -0
  40. package/dist/word-native.d.cts +4 -0
  41. package/dist/word-native.d.ts +4 -0
  42. package/dist/word-native.js +13293 -0
  43. package/dist/word-native.js.map +1 -0
  44. package/dist/word-prosemirror.cjs +489 -0
  45. package/dist/word-prosemirror.cjs.map +1 -0
  46. package/dist/word-prosemirror.d.cts +21 -0
  47. package/dist/word-prosemirror.d.ts +21 -0
  48. package/dist/word-prosemirror.js +483 -0
  49. package/dist/word-prosemirror.js.map +1 -0
  50. package/dist/word.cjs +16764 -0
  51. package/dist/word.cjs.map +1 -0
  52. package/dist/word.d.cts +84 -0
  53. package/dist/word.d.ts +84 -0
  54. package/dist/word.js +16632 -0
  55. package/dist/word.js.map +1 -0
  56. package/package.json +106 -3
  57. package/src/styles/editor.css +1507 -0
@@ -0,0 +1,803 @@
1
+ import { PluginKey, Plugin } from 'prosemirror-state';
2
+ import { Schema } from 'prosemirror-model';
3
+ import 'prosemirror-commands';
4
+ import 'prosemirror-keymap';
5
+ import 'prosemirror-view';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __defProps = Object.defineProperties;
9
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
10
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
25
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
26
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
27
+ var wordEditorSchema = new Schema({
28
+ nodes: {
29
+ doc: { content: "block+" },
30
+ paragraph: {
31
+ group: "block",
32
+ content: "inline*",
33
+ attrs: {
34
+ paraId: { default: "" },
35
+ story: { default: "body" },
36
+ styleId: { default: null },
37
+ format: { default: null }
38
+ },
39
+ parseDOM: [{ tag: "p" }],
40
+ toDOM: /* @__PURE__ */ __name((node) => ["p", paragraphDomAttrs(node.attrs), 0], "toDOM")
41
+ },
42
+ table: {
43
+ group: "block",
44
+ content: "table_row+",
45
+ attrs: {
46
+ tableId: { default: "" },
47
+ columnWidths: { default: null }
48
+ },
49
+ tableRole: "table",
50
+ toDOM: /* @__PURE__ */ __name((node) => [
51
+ "div",
52
+ { class: "coco-word-table-scroll" },
53
+ ["table", tableDomAttrs(node.attrs), ["tbody", 0]]
54
+ ], "toDOM")
55
+ },
56
+ table_row: {
57
+ content: "table_cell+",
58
+ tableRole: "row",
59
+ toDOM: /* @__PURE__ */ __name(() => ["tr", 0], "toDOM")
60
+ },
61
+ table_cell: {
62
+ content: "block+",
63
+ attrs: {
64
+ colspan: { default: 1 },
65
+ rowspan: { default: 1 },
66
+ width: { default: null },
67
+ shading: { default: null },
68
+ verticalAlignment: { default: null }
69
+ },
70
+ tableRole: "cell",
71
+ toDOM: /* @__PURE__ */ __name((node) => ["td", tableCellDomAttrs(node.attrs), 0], "toDOM")
72
+ },
73
+ image: {
74
+ inline: true,
75
+ group: "inline",
76
+ atom: true,
77
+ attrs: {
78
+ src: {},
79
+ alt: { default: "" },
80
+ width: { default: null },
81
+ height: { default: null },
82
+ drawingId: { default: null }
83
+ },
84
+ toDOM: /* @__PURE__ */ __name((node) => ["img", imageDomAttrs(node.attrs)], "toDOM")
85
+ },
86
+ text: { group: "inline" }
87
+ },
88
+ marks: {
89
+ strong: {
90
+ parseDOM: [{ tag: "strong" }, { tag: "b" }],
91
+ toDOM: /* @__PURE__ */ __name(() => ["strong", 0], "toDOM")
92
+ },
93
+ em: {
94
+ parseDOM: [{ tag: "em" }, { tag: "i" }],
95
+ toDOM: /* @__PURE__ */ __name(() => ["em", 0], "toDOM")
96
+ },
97
+ underline: {
98
+ parseDOM: [{ tag: "u" }],
99
+ toDOM: /* @__PURE__ */ __name(() => ["u", 0], "toDOM")
100
+ },
101
+ textStyle: {
102
+ attrs: {
103
+ color: { default: null },
104
+ fontSize: { default: null }
105
+ },
106
+ parseDOM: [{ tag: "span" }],
107
+ toDOM: /* @__PURE__ */ __name((mark) => ["span", textStyleDomAttrs(mark.attrs), 0], "toDOM")
108
+ }
109
+ }
110
+ });
111
+ new PluginKey("coco-word-decorations");
112
+ var wordStructureNormalizationKey = new PluginKey("coco-word-structure-normalization");
113
+ function paragraphDomAttrs(attrs) {
114
+ const domAttrs = {};
115
+ if (typeof attrs.paraId === "string" && attrs.paraId.length > 0) {
116
+ domAttrs["data-para-id"] = attrs.paraId;
117
+ }
118
+ if (typeof attrs.story === "string" && attrs.story.length > 0) {
119
+ domAttrs["data-story"] = attrs.story;
120
+ }
121
+ if (typeof attrs.styleId === "string" && attrs.styleId.length > 0) {
122
+ domAttrs["data-style-id"] = attrs.styleId;
123
+ }
124
+ const format = isParagraphFormat(attrs.format) ? attrs.format : null;
125
+ if ((format == null ? void 0 : format.outlineLevel) !== void 0) {
126
+ domAttrs["data-outline-level"] = String(format.outlineLevel);
127
+ }
128
+ const style = paragraphStyle(format);
129
+ if (style.length > 0) domAttrs.style = style;
130
+ return domAttrs;
131
+ }
132
+ __name(paragraphDomAttrs, "paragraphDomAttrs");
133
+ function tableDomAttrs(attrs) {
134
+ const domAttrs = {};
135
+ if (typeof attrs.tableId === "string" && attrs.tableId.length > 0) {
136
+ domAttrs["data-table-id"] = attrs.tableId;
137
+ }
138
+ return domAttrs;
139
+ }
140
+ __name(tableDomAttrs, "tableDomAttrs");
141
+ function tableCellDomAttrs(attrs) {
142
+ const domAttrs = {};
143
+ if (typeof attrs.colspan === "number" && attrs.colspan > 1) {
144
+ domAttrs.colspan = String(attrs.colspan);
145
+ }
146
+ if (typeof attrs.rowspan === "number" && attrs.rowspan > 1) {
147
+ domAttrs.rowspan = String(attrs.rowspan);
148
+ }
149
+ const style = [];
150
+ if (typeof attrs.width === "number" && attrs.width > 0) {
151
+ style.push(`width: ${twipsToPt(attrs.width)}`);
152
+ }
153
+ if (isShading(attrs.shading)) {
154
+ const fill = colorToCss(attrs.shading.fill);
155
+ if (fill) style.push(`background-color: ${fill}`);
156
+ }
157
+ if (typeof attrs.verticalAlignment === "string") {
158
+ style.push(`vertical-align: ${attrs.verticalAlignment === "center" ? "middle" : attrs.verticalAlignment}`);
159
+ }
160
+ if (style.length > 0) domAttrs.style = style.join("; ");
161
+ return domAttrs;
162
+ }
163
+ __name(tableCellDomAttrs, "tableCellDomAttrs");
164
+ function imageDomAttrs(attrs) {
165
+ const domAttrs = {
166
+ src: typeof attrs.src === "string" ? attrs.src : "",
167
+ alt: typeof attrs.alt === "string" ? attrs.alt : ""
168
+ };
169
+ if (typeof attrs.drawingId === "string") domAttrs["data-drawing-id"] = attrs.drawingId;
170
+ const style = [];
171
+ if (typeof attrs.width === "number" && attrs.width > 0) {
172
+ style.push(`width: ${attrs.width}px`);
173
+ }
174
+ if (typeof attrs.height === "number" && attrs.height > 0) {
175
+ style.push(`height: ${attrs.height}px`);
176
+ }
177
+ if (style.length > 0) domAttrs.style = style.join("; ");
178
+ return domAttrs;
179
+ }
180
+ __name(imageDomAttrs, "imageDomAttrs");
181
+ function isShading(value) {
182
+ return value !== null && typeof value === "object";
183
+ }
184
+ __name(isShading, "isShading");
185
+ function textStyleDomAttrs(attrs) {
186
+ const style = [];
187
+ const color = typeof attrs.color === "string" ? colorToCss(attrs.color) : null;
188
+ if (color) style.push(`color: ${color}`);
189
+ if (typeof attrs.fontSize === "number") style.push(`font-size: ${attrs.fontSize}pt`);
190
+ return style.length > 0 ? { style: style.join("; ") } : {};
191
+ }
192
+ __name(textStyleDomAttrs, "textStyleDomAttrs");
193
+ function isParagraphFormat(value) {
194
+ return value !== null && typeof value === "object";
195
+ }
196
+ __name(isParagraphFormat, "isParagraphFormat");
197
+ function paragraphStyle(format) {
198
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
199
+ if (!format) return "";
200
+ const declarations = [];
201
+ if (format.alignment) declarations.push(`text-align: ${alignmentToCss(format.alignment)}`);
202
+ if (((_a = format.indent) == null ? void 0 : _a.left) !== void 0) declarations.push(`margin-left: ${twipsToPt(format.indent.left)}`);
203
+ if (((_b = format.indent) == null ? void 0 : _b.right) !== void 0) declarations.push(`margin-right: ${twipsToPt(format.indent.right)}`);
204
+ if (((_c = format.indent) == null ? void 0 : _c.firstLine) !== void 0) {
205
+ declarations.push(`text-indent: ${twipsToPt(format.indent.firstLine)}`);
206
+ }
207
+ if (((_d = format.spacing) == null ? void 0 : _d.before) !== void 0) {
208
+ declarations.push(`margin-top: ${twipsToPt(format.spacing.before)}`);
209
+ }
210
+ if (((_e = format.spacing) == null ? void 0 : _e.after) !== void 0) {
211
+ declarations.push(`margin-bottom: ${twipsToPt(format.spacing.after)}`);
212
+ }
213
+ const lineHeight = lineHeightToCss((_f = format.spacing) == null ? void 0 : _f.line, (_g = format.spacing) == null ? void 0 : _g.lineRule);
214
+ if (lineHeight) declarations.push(`line-height: ${lineHeight}`);
215
+ if (format.fontSize !== void 0) declarations.push(`font-size: ${format.fontSize}pt`);
216
+ if (format.bold !== void 0) declarations.push(`font-weight: ${format.bold ? "700" : "400"}`);
217
+ const borderBottom = borderToCss(format.borderBottom);
218
+ if (borderBottom) {
219
+ declarations.push(`border-bottom: ${borderBottom}`);
220
+ declarations.push(`padding-bottom: ${(_i = (_h = format.borderBottom) == null ? void 0 : _h.space) != null ? _i : 4}pt`);
221
+ }
222
+ return declarations.join("; ");
223
+ }
224
+ __name(paragraphStyle, "paragraphStyle");
225
+ function alignmentToCss(alignment) {
226
+ if (alignment === "both" || alignment === "distribute") return "justify";
227
+ return alignment;
228
+ }
229
+ __name(alignmentToCss, "alignmentToCss");
230
+ function borderToCss(border) {
231
+ var _a;
232
+ if (!border || border.val === "none" || border.val === "nil") return null;
233
+ const color = (_a = colorToCss(border.color)) != null ? _a : "#000000";
234
+ const widthPt = border.size !== void 0 ? Math.max(0.75, border.size / 8) : 0.75;
235
+ const style = border.val === "double" ? "double" : "solid";
236
+ return `${widthPt}pt ${style} ${color}`;
237
+ }
238
+ __name(borderToCss, "borderToCss");
239
+ function lineHeightToCss(line, lineRule) {
240
+ if (line === void 0) return null;
241
+ if (lineRule === "exact" || lineRule === "atLeast") return twipsToPt(line);
242
+ return String(line / 240);
243
+ }
244
+ __name(lineHeightToCss, "lineHeightToCss");
245
+ function twipsToPt(twips) {
246
+ return `${twips / 20}pt`;
247
+ }
248
+ __name(twipsToPt, "twipsToPt");
249
+ function colorToCss(color) {
250
+ if (!color || color === "auto") return null;
251
+ return /^[0-9a-f]{6}$/i.test(color) ? `#${color}` : null;
252
+ }
253
+ __name(colorToCss, "colorToCss");
254
+
255
+ // src/word/editing.ts
256
+ var wordEditingPluginKey = new PluginKey("coco-word-editing");
257
+ var changeSequence = 0;
258
+ function createWordEditingPlugin(options = {}) {
259
+ return new Plugin({
260
+ key: wordEditingPluginKey,
261
+ appendTransaction(transactions, oldState, newState) {
262
+ if (!transactions.some((tr) => tr.docChanged)) return null;
263
+ if (transactions.every((tr) => tr.getMeta(wordStructureNormalizationKey))) return null;
264
+ const blockChanges = blockChangesFromDocumentDiff(oldState.doc, newState.doc);
265
+ const changes = blockChanges.length > 0 ? blockChanges : contentChangesFromDocumentDiff(oldState.doc, newState.doc);
266
+ return changes.length > 0 ? withChanges(newState.tr, changes) : null;
267
+ },
268
+ state: {
269
+ init: /* @__PURE__ */ __name(() => ({ changes: [] }), "init"),
270
+ apply(tr, previous) {
271
+ var _a, _b;
272
+ const meta = tr.getMeta(wordEditingPluginKey);
273
+ if (!((_a = meta == null ? void 0 : meta.changes) == null ? void 0 : _a.length)) return previous;
274
+ const next = { changes: [...previous.changes, ...meta.changes] };
275
+ (_b = options.onChangeSet) == null ? void 0 : _b.call(options, next);
276
+ return next;
277
+ }
278
+ }
279
+ });
280
+ }
281
+ __name(createWordEditingPlugin, "createWordEditingPlugin");
282
+ function getWordChangeSet(state) {
283
+ var _a;
284
+ return (_a = wordEditingPluginKey.getState(state)) != null ? _a : { changes: [] };
285
+ }
286
+ __name(getWordChangeSet, "getWordChangeSet");
287
+ function getWordSelectionInfo(state) {
288
+ var _a, _b;
289
+ const { from, to, empty } = state.selection;
290
+ const $from = state.selection.$from;
291
+ const cellDepth = findParentDepth($from, "table_cell");
292
+ const tableCell = cellDepth === null ? null : {
293
+ depth: cellDepth,
294
+ colspan: Number((_a = $from.node(cellDepth).attrs.colspan) != null ? _a : 1),
295
+ rowspan: Number((_b = $from.node(cellDepth).attrs.rowspan) != null ? _b : 1)
296
+ };
297
+ return {
298
+ from,
299
+ to,
300
+ empty,
301
+ selectedText: state.doc.textBetween(from, to, "\n"),
302
+ paragraphs: selectedParagraphs(state, from, to),
303
+ tableCell
304
+ };
305
+ }
306
+ __name(getWordSelectionInfo, "getWordSelectionInfo");
307
+ function toggleBold(state, dispatch, view) {
308
+ const markType = wordEditorSchema.marks.strong;
309
+ return applySelectionMark(state, dispatch, view, markType, {}, "strong");
310
+ }
311
+ __name(toggleBold, "toggleBold");
312
+ function setFontSize(sizePt) {
313
+ return (state, dispatch, view) => {
314
+ if (!Number.isFinite(sizePt) || sizePt <= 0) return false;
315
+ return applySelectionMark(state, dispatch, view, wordEditorSchema.marks.textStyle, { fontSize: sizePt }, "textStyle");
316
+ };
317
+ }
318
+ __name(setFontSize, "setFontSize");
319
+ function setColor(color) {
320
+ return (state, dispatch, view) => {
321
+ const normalized = normalizeHexColor(color);
322
+ if (!normalized) return false;
323
+ return applySelectionMark(state, dispatch, view, wordEditorSchema.marks.textStyle, { color: normalized }, "textStyle");
324
+ };
325
+ }
326
+ __name(setColor, "setColor");
327
+ function setParagraphAlign(alignment) {
328
+ return (state, dispatch) => {
329
+ const paragraphs = selectedParagraphs(state, state.selection.from, state.selection.to);
330
+ if (paragraphs.length === 0) return false;
331
+ if (!dispatch) return true;
332
+ let tr = state.tr;
333
+ state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
334
+ if (node.type !== wordEditorSchema.nodes.paragraph) return true;
335
+ const format = mergeParagraphFormat(node.attrs.format, { alignment });
336
+ tr = tr.setNodeMarkup(pos, void 0, __spreadProps(__spreadValues({}, node.attrs), { format }));
337
+ return false;
338
+ });
339
+ tr = withChange(tr, {
340
+ kind: "paragraph",
341
+ from: state.selection.from,
342
+ to: state.selection.to,
343
+ paragraphs,
344
+ target: changeTargetForParagraphs(paragraphs),
345
+ status: "captured",
346
+ attr: "alignment",
347
+ value: alignment
348
+ });
349
+ dispatch(tr.scrollIntoView());
350
+ return true;
351
+ };
352
+ }
353
+ __name(setParagraphAlign, "setParagraphAlign");
354
+ function applySelectionMark(state, dispatch, view, markType, attrs, mark) {
355
+ const { from, to, empty } = state.selection;
356
+ if (empty) return false;
357
+ const paragraphs = selectedParagraphs(state, from, to);
358
+ if (paragraphs.length === 0) return false;
359
+ const shouldRemove = mark === "strong" && rangeHasMark(state.doc, from, to, markType);
360
+ if (!dispatch) return true;
361
+ let tr = state.tr;
362
+ if (shouldRemove) {
363
+ tr = tr.removeMark(from, to, markType);
364
+ } else {
365
+ tr = tr.addMark(from, to, markType.create(attrs));
366
+ }
367
+ tr = withChange(tr, {
368
+ kind: "mark",
369
+ from,
370
+ to,
371
+ paragraphs,
372
+ target: changeTargetForParagraphs(paragraphs),
373
+ status: "captured",
374
+ mark,
375
+ value: mark === "strong" ? !shouldRemove : attrs
376
+ });
377
+ dispatch(tr.scrollIntoView());
378
+ view == null ? void 0 : view.focus();
379
+ return true;
380
+ }
381
+ __name(applySelectionMark, "applySelectionMark");
382
+ function selectedParagraphs(state, from, to) {
383
+ const paragraphs = [];
384
+ const scanTo = Math.max(to, from + 1);
385
+ state.doc.nodesBetween(from, scanTo, (node, pos) => {
386
+ if (node.type !== wordEditorSchema.nodes.paragraph) return true;
387
+ const contentStart = pos + 1;
388
+ const contentEnd = contentStart + node.content.size;
389
+ paragraphs.push({
390
+ paraId: typeof node.attrs.paraId === "string" ? node.attrs.paraId : "",
391
+ from: Math.max(from, contentStart) - contentStart,
392
+ to: Math.min(to, contentEnd) - contentStart,
393
+ text: node.textContent,
394
+ styleId: typeof node.attrs.styleId === "string" ? node.attrs.styleId : null,
395
+ story: typeof node.attrs.story === "string" ? node.attrs.story : "body"
396
+ });
397
+ return false;
398
+ });
399
+ return paragraphs;
400
+ }
401
+ __name(selectedParagraphs, "selectedParagraphs");
402
+ function changeTargetForParagraphs(paragraphs) {
403
+ var _a;
404
+ const paragraph = paragraphs[0];
405
+ return __spreadValues({
406
+ story: (_a = paragraph == null ? void 0 : paragraph.story) != null ? _a : "body"
407
+ }, (paragraph == null ? void 0 : paragraph.paraId) ? { paraId: paragraph.paraId } : {});
408
+ }
409
+ __name(changeTargetForParagraphs, "changeTargetForParagraphs");
410
+ function rangeHasMark(doc, from, to, markType) {
411
+ let found = false;
412
+ doc.nodesBetween(from, to, (node) => {
413
+ if (found || !node.isText) return !found;
414
+ found = markType.isInSet(node.marks) !== void 0;
415
+ return !found;
416
+ });
417
+ return found;
418
+ }
419
+ __name(rangeHasMark, "rangeHasMark");
420
+ function withChange(tr, change) {
421
+ return withChanges(tr, [change]);
422
+ }
423
+ __name(withChange, "withChange");
424
+ function withChanges(tr, changesToAdd) {
425
+ var _a, _b;
426
+ const meta = (_a = tr.getMeta(wordEditingPluginKey)) != null ? _a : {};
427
+ const changes = (_b = meta.changes) != null ? _b : [];
428
+ return tr.setMeta(wordEditingPluginKey, __spreadProps(__spreadValues({}, meta), {
429
+ changes: [
430
+ ...changes,
431
+ ...changesToAdd.map((change) => __spreadProps(__spreadValues({}, change), {
432
+ id: `word-edit:${++changeSequence}`,
433
+ createdAt: Date.now()
434
+ }))
435
+ ]
436
+ }));
437
+ }
438
+ __name(withChanges, "withChanges");
439
+ function blockChangesFromDocumentDiff(oldDoc, newDoc) {
440
+ const oldBlocks = topLevelBlockSnapshots(oldDoc);
441
+ const newBlocks = topLevelBlockSnapshots(newDoc);
442
+ const split = splitBlockChange(oldBlocks, newBlocks);
443
+ if (split) return [split];
444
+ const merge = mergeBlockChange(oldBlocks, newBlocks);
445
+ if (merge) return [merge];
446
+ const insertOrDelete = insertOrDeleteBlockChange(oldBlocks, newBlocks);
447
+ return insertOrDelete ? [insertOrDelete] : [];
448
+ }
449
+ __name(blockChangesFromDocumentDiff, "blockChangesFromDocumentDiff");
450
+ function splitBlockChange(oldBlocks, newBlocks) {
451
+ if (newBlocks.length !== oldBlocks.length + 1) return null;
452
+ for (let index = 0; index < oldBlocks.length; index += 1) {
453
+ if (!blockSequencesEqual(oldBlocks.slice(0, index), newBlocks.slice(0, index))) continue;
454
+ if (!blockSequencesEqual(oldBlocks.slice(index + 1), newBlocks.slice(index + 2))) continue;
455
+ const before = oldBlocks[index];
456
+ const first = newBlocks[index];
457
+ const second = newBlocks[index + 1];
458
+ if (before.block.kind !== "paragraph" || first.block.kind !== "paragraph" || second.block.kind !== "paragraph" || first.block.text + second.block.text !== before.block.text) {
459
+ continue;
460
+ }
461
+ return {
462
+ kind: "block",
463
+ blockOp: "split",
464
+ from: before.pos,
465
+ to: before.pos + before.size,
466
+ paragraphs: blockParagraphs([first, second]),
467
+ target: targetForBlock(before.block),
468
+ status: "captured",
469
+ blocks: [first.block, second.block],
470
+ deletedBlocks: [before.block],
471
+ value: {
472
+ before: before.block,
473
+ after: [first.block, second.block]
474
+ }
475
+ };
476
+ }
477
+ return null;
478
+ }
479
+ __name(splitBlockChange, "splitBlockChange");
480
+ function mergeBlockChange(oldBlocks, newBlocks) {
481
+ if (oldBlocks.length !== newBlocks.length + 1) return null;
482
+ for (let index = 0; index < newBlocks.length; index += 1) {
483
+ if (!blockSequencesEqual(oldBlocks.slice(0, index), newBlocks.slice(0, index))) continue;
484
+ if (!blockSequencesEqual(oldBlocks.slice(index + 2), newBlocks.slice(index + 1))) continue;
485
+ const first = oldBlocks[index];
486
+ const second = oldBlocks[index + 1];
487
+ const after = newBlocks[index];
488
+ if (first.block.kind !== "paragraph" || second.block.kind !== "paragraph" || after.block.kind !== "paragraph" || first.block.text + second.block.text !== after.block.text) {
489
+ continue;
490
+ }
491
+ return {
492
+ kind: "block",
493
+ blockOp: "merge",
494
+ from: first.pos,
495
+ to: second.pos + second.size,
496
+ paragraphs: blockParagraphs([after]),
497
+ target: targetForBlock(after.block),
498
+ status: "captured",
499
+ blocks: [after.block],
500
+ deletedBlocks: [first.block, second.block],
501
+ value: {
502
+ before: [first.block, second.block],
503
+ after: after.block
504
+ }
505
+ };
506
+ }
507
+ return null;
508
+ }
509
+ __name(mergeBlockChange, "mergeBlockChange");
510
+ function insertOrDeleteBlockChange(oldBlocks, newBlocks) {
511
+ var _a, _b, _c, _d, _e;
512
+ let prefix = 0;
513
+ const maxPrefix = Math.min(oldBlocks.length, newBlocks.length);
514
+ while (prefix < maxPrefix && blockEquals(oldBlocks[prefix], newBlocks[prefix])) prefix += 1;
515
+ let suffix = 0;
516
+ const maxSuffix = Math.min(oldBlocks.length - prefix, newBlocks.length - prefix);
517
+ while (suffix < maxSuffix && blockEquals(oldBlocks[oldBlocks.length - 1 - suffix], newBlocks[newBlocks.length - 1 - suffix])) {
518
+ suffix += 1;
519
+ }
520
+ const deleted = oldBlocks.slice(prefix, oldBlocks.length - suffix);
521
+ const inserted = newBlocks.slice(prefix, newBlocks.length - suffix);
522
+ if (deleted.length === 0 && inserted.length === 0) return null;
523
+ const first = (_a = inserted[0]) != null ? _a : deleted[0];
524
+ const last = (_c = (_b = inserted[inserted.length - 1]) != null ? _b : deleted[deleted.length - 1]) != null ? _c : first;
525
+ const operation = inserted.length > 0 && deleted.length > 0 ? "replace" : inserted.length > 0 ? "insert" : "delete";
526
+ return {
527
+ kind: "block",
528
+ blockOp: operation,
529
+ from: (_d = first == null ? void 0 : first.pos) != null ? _d : 0,
530
+ to: last ? last.pos + last.size : (_e = first == null ? void 0 : first.pos) != null ? _e : 0,
531
+ paragraphs: blockParagraphs(inserted.length > 0 ? inserted : deleted),
532
+ target: first ? targetForBlock(first.block) : { story: "body" },
533
+ status: "captured",
534
+ blocks: inserted.map((item) => item.block),
535
+ deletedBlocks: deleted.map((item) => item.block),
536
+ value: {
537
+ before: deleted.map((item) => item.block),
538
+ after: inserted.map((item) => item.block)
539
+ }
540
+ };
541
+ }
542
+ __name(insertOrDeleteBlockChange, "insertOrDeleteBlockChange");
543
+ function contentChangesFromDocumentDiff(oldDoc, newDoc) {
544
+ const oldParagraphs = paragraphSnapshots(oldDoc);
545
+ const newParagraphs = paragraphSnapshots(newDoc);
546
+ const oldByParaId = new Map(oldParagraphs.map((paragraph) => [paragraph.paraId, paragraph]));
547
+ const changes = [];
548
+ for (const next of newParagraphs) {
549
+ if (!next.paraId) continue;
550
+ const previous = oldByParaId.get(next.paraId);
551
+ if (!previous || paragraphContentEquals(previous.content, next.content)) continue;
552
+ const diff = contentDiff(previous.content, next.content);
553
+ if (!diff) continue;
554
+ const from = next.pos + 1 + diff.from;
555
+ const to = next.pos + 1 + diff.toAfter;
556
+ const paragraph = {
557
+ paraId: next.paraId,
558
+ from: diff.from,
559
+ to: diff.toAfter,
560
+ text: next.text,
561
+ styleId: next.styleId,
562
+ story: next.story
563
+ };
564
+ if (contentListIsTextOnly(diff.insertedContent) && contentListIsTextOnly(diff.deletedContent)) {
565
+ changes.push({
566
+ kind: "text",
567
+ from,
568
+ to,
569
+ paragraphs: [paragraph],
570
+ target: changeTargetForParagraphs([paragraph]),
571
+ status: "captured",
572
+ textOp: diff.operation,
573
+ text: contentText(diff.insertedContent),
574
+ deletedText: contentText(diff.deletedContent),
575
+ value: {
576
+ operation: diff.operation,
577
+ before: previous.text,
578
+ after: next.text
579
+ }
580
+ });
581
+ continue;
582
+ }
583
+ changes.push({
584
+ kind: "content",
585
+ from,
586
+ to,
587
+ paragraphs: [paragraph],
588
+ target: changeTargetForParagraphs([paragraph]),
589
+ status: "captured",
590
+ contentOp: diff.operation,
591
+ content: mergeTextContent(diff.insertedContent),
592
+ deletedContent: mergeTextContent(diff.deletedContent),
593
+ value: {
594
+ operation: diff.operation,
595
+ before: mergeTextContent(previous.content.map((unit) => unit.content)),
596
+ after: mergeTextContent(next.content.map((unit) => unit.content))
597
+ }
598
+ });
599
+ }
600
+ return changes;
601
+ }
602
+ __name(contentChangesFromDocumentDiff, "contentChangesFromDocumentDiff");
603
+ function paragraphSnapshots(doc) {
604
+ const paragraphs = [];
605
+ doc.descendants((node, pos) => {
606
+ if (node.type !== wordEditorSchema.nodes.paragraph) return true;
607
+ paragraphs.push({
608
+ paraId: typeof node.attrs.paraId === "string" ? node.attrs.paraId : "",
609
+ pos,
610
+ text: node.textContent,
611
+ content: paragraphContentUnits(node),
612
+ styleId: typeof node.attrs.styleId === "string" ? node.attrs.styleId : null,
613
+ story: typeof node.attrs.story === "string" ? node.attrs.story : "body"
614
+ });
615
+ return false;
616
+ });
617
+ return paragraphs;
618
+ }
619
+ __name(paragraphSnapshots, "paragraphSnapshots");
620
+ function topLevelBlockSnapshots(doc) {
621
+ const blocks = [];
622
+ doc.forEach((node, offset, index) => {
623
+ if (node.type === wordEditorSchema.nodes.paragraph) {
624
+ const paraId = typeof node.attrs.paraId === "string" ? node.attrs.paraId : "";
625
+ const story = typeof node.attrs.story === "string" ? node.attrs.story : "body";
626
+ const block = {
627
+ kind: "paragraph",
628
+ paraId,
629
+ story,
630
+ styleId: typeof node.attrs.styleId === "string" ? node.attrs.styleId : null,
631
+ text: node.textContent,
632
+ content: mergeTextContent(paragraphContentUnits(node).map((unit) => unit.content))
633
+ };
634
+ blocks.push({
635
+ key: `paragraph:${paraId || index}`,
636
+ pos: offset,
637
+ size: node.nodeSize,
638
+ block
639
+ });
640
+ return;
641
+ }
642
+ if (node.type === wordEditorSchema.nodes.table) {
643
+ const tableId = typeof node.attrs.tableId === "string" ? node.attrs.tableId : "";
644
+ const block = {
645
+ kind: "table",
646
+ tableId,
647
+ text: node.textContent
648
+ };
649
+ blocks.push({
650
+ key: `table:${tableId || index}`,
651
+ pos: offset,
652
+ size: node.nodeSize,
653
+ block
654
+ });
655
+ }
656
+ });
657
+ return blocks;
658
+ }
659
+ __name(topLevelBlockSnapshots, "topLevelBlockSnapshots");
660
+ function blockSequencesEqual(left, right) {
661
+ return left.length === right.length && left.every((block, index) => blockEquals(block, right[index]));
662
+ }
663
+ __name(blockSequencesEqual, "blockSequencesEqual");
664
+ function blockEquals(left, right) {
665
+ return left.key === right.key;
666
+ }
667
+ __name(blockEquals, "blockEquals");
668
+ function blockParagraphs(blocks) {
669
+ return blocks.flatMap((snapshot) => {
670
+ if (snapshot.block.kind !== "paragraph") return [];
671
+ return [
672
+ {
673
+ paraId: snapshot.block.paraId,
674
+ from: 0,
675
+ to: snapshot.block.text.length,
676
+ text: snapshot.block.text,
677
+ styleId: snapshot.block.styleId,
678
+ story: snapshot.block.story
679
+ }
680
+ ];
681
+ });
682
+ }
683
+ __name(blockParagraphs, "blockParagraphs");
684
+ function targetForBlock(block) {
685
+ if (block.kind === "table") {
686
+ return __spreadValues({
687
+ story: "body"
688
+ }, block.tableId ? { tableId: block.tableId } : {});
689
+ }
690
+ return __spreadValues({
691
+ story: block.story
692
+ }, block.paraId ? { paraId: block.paraId } : {});
693
+ }
694
+ __name(targetForBlock, "targetForBlock");
695
+ function paragraphContentUnits(paragraph) {
696
+ const units = [];
697
+ paragraph.forEach((child) => {
698
+ var _a, _b;
699
+ if (child.isText) {
700
+ for (const char of (_a = child.text) != null ? _a : "") {
701
+ units.push({ key: `text:${char}`, content: { kind: "text", text: char } });
702
+ }
703
+ return;
704
+ }
705
+ if (child.type === wordEditorSchema.nodes.image) {
706
+ const image = imageContent(child);
707
+ units.push({ key: `image:${(_b = image.drawingId) != null ? _b : image.src}`, content: image });
708
+ return;
709
+ }
710
+ units.push({
711
+ key: `${child.type.name}:${JSON.stringify(child.attrs)}`,
712
+ content: { kind: "text", text: child.textContent }
713
+ });
714
+ });
715
+ return units;
716
+ }
717
+ __name(paragraphContentUnits, "paragraphContentUnits");
718
+ function imageContent(node) {
719
+ return {
720
+ kind: "image",
721
+ drawingId: typeof node.attrs.drawingId === "string" ? node.attrs.drawingId : null,
722
+ alt: typeof node.attrs.alt === "string" ? node.attrs.alt : "",
723
+ src: typeof node.attrs.src === "string" ? node.attrs.src : "",
724
+ width: typeof node.attrs.width === "number" ? node.attrs.width : null,
725
+ height: typeof node.attrs.height === "number" ? node.attrs.height : null
726
+ };
727
+ }
728
+ __name(imageContent, "imageContent");
729
+ function contentDiff(before, after) {
730
+ var _a, _b, _c, _d;
731
+ if (paragraphContentEquals(before, after)) return null;
732
+ let prefix = 0;
733
+ const maxPrefix = Math.min(before.length, after.length);
734
+ while (prefix < maxPrefix && ((_a = before[prefix]) == null ? void 0 : _a.key) === ((_b = after[prefix]) == null ? void 0 : _b.key)) prefix += 1;
735
+ let suffix = 0;
736
+ const maxSuffix = Math.min(before.length - prefix, after.length - prefix);
737
+ while (suffix < maxSuffix && ((_c = before[before.length - 1 - suffix]) == null ? void 0 : _c.key) === ((_d = after[after.length - 1 - suffix]) == null ? void 0 : _d.key)) {
738
+ suffix += 1;
739
+ }
740
+ const toBefore = before.length - suffix;
741
+ const toAfter = after.length - suffix;
742
+ const insertedContent = after.slice(prefix, toAfter).map((unit) => unit.content);
743
+ const deletedContent = before.slice(prefix, toBefore).map((unit) => unit.content);
744
+ const operation = insertedContent.length > 0 && deletedContent.length > 0 ? "replace" : insertedContent.length > 0 ? "insert" : "delete";
745
+ return {
746
+ operation,
747
+ from: prefix,
748
+ toBefore,
749
+ toAfter,
750
+ insertedContent,
751
+ deletedContent
752
+ };
753
+ }
754
+ __name(contentDiff, "contentDiff");
755
+ function paragraphContentEquals(left, right) {
756
+ return left.length === right.length && left.every((unit, index) => {
757
+ var _a;
758
+ return unit.key === ((_a = right[index]) == null ? void 0 : _a.key);
759
+ });
760
+ }
761
+ __name(paragraphContentEquals, "paragraphContentEquals");
762
+ function contentListIsTextOnly(content) {
763
+ return content.every((item) => item.kind === "text");
764
+ }
765
+ __name(contentListIsTextOnly, "contentListIsTextOnly");
766
+ function contentText(content) {
767
+ return content.map((item) => item.kind === "text" ? item.text : "").join("");
768
+ }
769
+ __name(contentText, "contentText");
770
+ function mergeTextContent(content) {
771
+ const merged = [];
772
+ for (const item of content) {
773
+ const previous = merged[merged.length - 1];
774
+ if (item.kind === "text" && (previous == null ? void 0 : previous.kind) === "text") {
775
+ previous.text += item.text;
776
+ } else {
777
+ merged.push(__spreadValues({}, item));
778
+ }
779
+ }
780
+ return merged;
781
+ }
782
+ __name(mergeTextContent, "mergeTextContent");
783
+ function mergeParagraphFormat(value, patch) {
784
+ const base = value !== null && typeof value === "object" ? value : {};
785
+ return __spreadValues(__spreadValues({}, base), patch);
786
+ }
787
+ __name(mergeParagraphFormat, "mergeParagraphFormat");
788
+ function normalizeHexColor(color) {
789
+ const trimmed = color.trim().replace(/^#/, "");
790
+ return /^[0-9a-f]{6}$/i.test(trimmed) ? trimmed.toUpperCase() : null;
791
+ }
792
+ __name(normalizeHexColor, "normalizeHexColor");
793
+ function findParentDepth($pos, nodeName) {
794
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
795
+ if ($pos.node(depth).type.name === nodeName) return depth;
796
+ }
797
+ return null;
798
+ }
799
+ __name(findParentDepth, "findParentDepth");
800
+
801
+ export { createWordEditingPlugin, getWordChangeSet, getWordSelectionInfo, setColor, setFontSize, setParagraphAlign, toggleBold, wordEditingPluginKey };
802
+ //# sourceMappingURL=word-editing.js.map
803
+ //# sourceMappingURL=word-editing.js.map