@portone/docx-editor 0.4.0 → 0.5.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 (180) hide show
  1. package/CHANGELOG.md +201 -0
  2. package/CONTRIBUTING.md +2 -0
  3. package/assets/editor.png +0 -0
  4. package/dist/DocxEditor.d.ts +1 -1
  5. package/dist/DocxEditor.js +44 -25
  6. package/dist/docx/cloning.js +4 -9
  7. package/dist/docx/commentOnlyChange.d.ts +5 -3
  8. package/dist/docx/comments/grammar.d.ts +27 -10
  9. package/dist/docx/comments/grammar.js +18 -67
  10. package/dist/docx/comments/model.d.ts +5 -6
  11. package/dist/docx/comments/model.js +0 -9
  12. package/dist/docx/comments/parts.d.ts +16 -10
  13. package/dist/docx/comments/parts.js +65 -13
  14. package/dist/docx/comments/people.d.ts +11 -3
  15. package/dist/docx/comments/people.js +20 -6
  16. package/dist/docx/comments/policy.js +7 -1
  17. package/dist/docx/comments/reading.d.ts +4 -2
  18. package/dist/docx/comments/reading.js +1 -14
  19. package/dist/docx/comments/writing.js +65 -28
  20. package/dist/docx/exportDocx.js +10 -14
  21. package/dist/docx/exportRefs.d.ts +8 -3
  22. package/dist/docx/exportRefs.js +2 -1
  23. package/dist/docx/fidelity.js +24 -10
  24. package/dist/docx/fields.d.ts +42 -0
  25. package/dist/docx/fields.js +76 -0
  26. package/dist/docx/formatting/styles.d.ts +0 -2
  27. package/dist/docx/formatting/styles.js +2 -15
  28. package/dist/docx/headersFooters.d.ts +89 -20
  29. package/dist/docx/headersFooters.js +163 -172
  30. package/dist/docx/identities.js +17 -26
  31. package/dist/docx/importDocx.d.ts +1 -1
  32. package/dist/docx/importDocx.js +100 -48
  33. package/dist/docx/importParagraph.d.ts +18 -5
  34. package/dist/docx/importParagraph.js +75 -128
  35. package/dist/docx/importPolicy.d.ts +70 -0
  36. package/dist/docx/importPolicy.js +195 -0
  37. package/dist/docx/importPreserved.d.ts +30 -0
  38. package/dist/docx/importPreserved.js +54 -0
  39. package/dist/docx/importTable.js +56 -12
  40. package/dist/docx/invariants.js +16 -18
  41. package/dist/docx/notes.d.ts +6 -1
  42. package/dist/docx/notes.js +6 -16
  43. package/dist/docx/pageGeometry.d.ts +5 -14
  44. package/dist/docx/pageGeometry.js +0 -12
  45. package/dist/docx/protectionPolicy.d.ts +13 -5
  46. package/dist/docx/protectionPolicy.js +32 -22
  47. package/dist/docx/scan.d.ts +18 -8
  48. package/dist/docx/scan.js +17 -11
  49. package/dist/docx/sections.d.ts +126 -0
  50. package/dist/docx/sections.js +207 -0
  51. package/dist/docx/serializeBlock.d.ts +13 -4
  52. package/dist/docx/serializeBlock.js +16 -18
  53. package/dist/docx/serializeParagraph.d.ts +9 -4
  54. package/dist/docx/serializeParagraph.js +23 -58
  55. package/dist/docx/serializePreserved.d.ts +14 -0
  56. package/dist/docx/serializePreserved.js +24 -0
  57. package/dist/docx/serializeStory.d.ts +17 -0
  58. package/dist/docx/serializeStory.js +17 -0
  59. package/dist/docx/serializeTable.js +10 -13
  60. package/dist/docx/session.d.ts +23 -6
  61. package/dist/docx/session.js +26 -5
  62. package/dist/docx/story.d.ts +140 -0
  63. package/dist/docx/story.js +237 -0
  64. package/dist/docx/storyProjection.js +6 -1
  65. package/dist/docx/tableTemplate.d.ts +25 -0
  66. package/dist/docx/tableTemplate.js +30 -16
  67. package/dist/docx/wrappers.d.ts +67 -0
  68. package/dist/docx/wrappers.js +117 -0
  69. package/dist/editor/clipboard/blockReaders.d.ts +74 -0
  70. package/dist/editor/clipboard/blockReaders.js +193 -0
  71. package/dist/editor/clipboard/htmlReader.d.ts +26 -0
  72. package/dist/editor/clipboard/htmlReader.js +376 -0
  73. package/dist/editor/clipboard/inlineFormatting.d.ts +0 -7
  74. package/dist/editor/clipboard/inlineFormatting.js +1 -7
  75. package/dist/editor/clipboard/internalChannel.d.ts +57 -0
  76. package/dist/editor/clipboard/internalChannel.js +58 -0
  77. package/dist/editor/clipboard/normalizers.d.ts +99 -0
  78. package/dist/editor/clipboard/normalizers.js +199 -0
  79. package/dist/editor/clipboard/parser.d.ts +34 -0
  80. package/dist/editor/clipboard/parser.js +58 -0
  81. package/dist/editor/clipboard/plugin.d.ts +21 -0
  82. package/dist/editor/clipboard/plugin.js +188 -0
  83. package/dist/editor/clipboard/readContext.d.ts +34 -0
  84. package/dist/editor/clipboard/readContext.js +25 -0
  85. package/dist/editor/clipboard/readers.d.ts +33 -0
  86. package/dist/editor/clipboard/readers.js +37 -0
  87. package/dist/editor/clipboard/source.d.ts +12 -0
  88. package/dist/editor/clipboard/source.js +21 -0
  89. package/dist/editor/commands/comments/editing.d.ts +26 -6
  90. package/dist/editor/commands/comments/editing.js +177 -106
  91. package/dist/editor/commands/comments/model.d.ts +34 -17
  92. package/dist/editor/commands/comments/model.js +11 -0
  93. package/dist/editor/commands/comments/reading.d.ts +5 -3
  94. package/dist/editor/commands/comments/reading.js +8 -58
  95. package/dist/editor/commands/index.d.ts +2 -2
  96. package/dist/editor/commands/index.js +2 -0
  97. package/dist/editor/commands/linkCommands.js +20 -5
  98. package/dist/editor/commands/listCommands.d.ts +6 -0
  99. package/dist/editor/commands/listCommands.js +3 -2
  100. package/dist/editor/commands/lockCommands.js +59 -16
  101. package/dist/editor/commands/noteQueries.d.ts +22 -5
  102. package/dist/editor/commands/noteQueries.js +34 -6
  103. package/dist/editor/commands/paragraphCommands.js +2 -2
  104. package/dist/editor/createEditor.js +13 -3
  105. package/dist/editor/documentStyles.d.ts +26 -4
  106. package/dist/editor/documentStyles.js +9 -4
  107. package/dist/editor/imageFiles.d.ts +2 -2
  108. package/dist/editor/imageFiles.js +2 -0
  109. package/dist/editor/insertTable.d.ts +1 -1
  110. package/dist/editor/insertTable.js +2 -2
  111. package/dist/editor/plainText.d.ts +12 -0
  112. package/dist/editor/plainText.js +2 -1
  113. package/dist/editor/plugins/columnResize.js +6 -3
  114. package/dist/editor/plugins/commentComposer.d.ts +28 -0
  115. package/dist/editor/plugins/commentComposer.js +46 -0
  116. package/dist/editor/plugins/commentDecorations.d.ts +29 -2
  117. package/dist/editor/plugins/commentDecorations.js +89 -15
  118. package/dist/editor/plugins/documentProjection.d.ts +31 -0
  119. package/dist/editor/plugins/documentProjection.js +22 -0
  120. package/dist/editor/plugins/imagePaste.js +15 -8
  121. package/dist/editor/plugins/linkPanel.d.ts +7 -3
  122. package/dist/editor/plugins/linkPanel.js +13 -27
  123. package/dist/editor/plugins/panelState.d.ts +67 -0
  124. package/dist/editor/plugins/panelState.js +54 -0
  125. package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
  126. package/dist/editor/plugins/tableContextMenu.js +30 -47
  127. package/dist/editor/plugins/textContextMenu.d.ts +1 -1
  128. package/dist/editor/plugins/textContextMenu.js +30 -47
  129. package/dist/ooxml/fragment.d.ts +11 -0
  130. package/dist/ooxml/fragment.js +14 -4
  131. package/dist/ooxml/image.d.ts +3 -4
  132. package/dist/ooxml/image.js +50 -5
  133. package/dist/ooxml/names.d.ts +6 -0
  134. package/dist/ooxml/names.js +2 -0
  135. package/dist/ooxml/props.d.ts +10 -0
  136. package/dist/ooxml/props.js +28 -4
  137. package/dist/ooxml/rangeMarkers.d.ts +5 -0
  138. package/dist/ooxml/rangeMarkers.js +24 -0
  139. package/dist/page/PageGuides.d.ts +7 -3
  140. package/dist/page/PageGuides.js +13 -24
  141. package/dist/page/pageLayout.d.ts +64 -5
  142. package/dist/page/pageLayout.js +90 -29
  143. package/dist/page/usePageLayout.d.ts +14 -4
  144. package/dist/page/usePageLayout.js +19 -20
  145. package/dist/schema/attrRoles.js +46 -23
  146. package/dist/schema/clipboard.d.ts +72 -0
  147. package/dist/schema/clipboard.js +288 -0
  148. package/dist/schema/docxSchema.d.ts +9 -1
  149. package/dist/schema/docxSchema.js +217 -165
  150. package/dist/schema/editGuard.d.ts +1 -1
  151. package/dist/schema/guards.js +2 -2
  152. package/dist/schema/index.d.ts +1 -0
  153. package/dist/schema/locks.d.ts +3 -0
  154. package/dist/schema/locks.js +29 -12
  155. package/dist/schema/preservedFragments.d.ts +12 -0
  156. package/dist/schema/preservedFragments.js +38 -0
  157. package/dist/schema/preservedGuards.d.ts +9 -7
  158. package/dist/schema/preservedGuards.js +112 -11
  159. package/dist/schema/protection.d.ts +34 -5
  160. package/dist/schema/protection.js +42 -14
  161. package/dist/schema/rendering.d.ts +14 -0
  162. package/dist/schema/rendering.js +27 -12
  163. package/dist/schema/stories.d.ts +49 -0
  164. package/dist/schema/stories.js +78 -0
  165. package/dist/schema/wrappers.d.ts +58 -0
  166. package/dist/schema/wrappers.js +77 -0
  167. package/dist/styles/classNames.d.ts +3 -5
  168. package/dist/styles/classNames.js +3 -5
  169. package/dist/styles.css +74 -12
  170. package/dist/table/resize.d.ts +5 -3
  171. package/dist/ui/CommentsPanel.d.ts +1 -3
  172. package/dist/ui/CommentsPanel.js +24 -15
  173. package/dist/ui/NotesPanel.js +2 -2
  174. package/dist/ui/TextMenu.d.ts +1 -3
  175. package/dist/ui/TextMenu.js +10 -6
  176. package/dist/ui/comments/CommentComposer.d.ts +6 -1
  177. package/dist/ui/comments/CommentComposer.js +26 -3
  178. package/package.json +5 -4
  179. package/dist/editor/externalClipboard.d.ts +0 -22
  180. package/dist/editor/externalClipboard.js +0 -486
@@ -1,5 +1,7 @@
1
1
  // src/schema/docxSchema.ts
2
- import { Schema } from "prosemirror-model";
2
+ import {
3
+ Schema
4
+ } from "prosemirror-model";
3
5
  import {
4
6
  spanCount,
5
7
  toBandSizes,
@@ -17,6 +19,7 @@ import {
17
19
  } from "../model/format.js";
18
20
  import {
19
21
  ANY_ELEMENT,
22
+ ANY_ELEMENTS,
20
23
  ATTRIBUTES,
21
24
  acceptRawXml,
22
25
  ELEMENT
@@ -32,7 +35,9 @@ import {
32
35
  tableStyle
33
36
  } from "../styles/inlineStyle.js";
34
37
  import { imageNodeSpec, runMarkSpec } from "./rendering.js";
38
+ import { WRAPPER_ATTRS, WRAPPER_GROUP } from "./wrappers.js";
35
39
  import { imageNodeSpec as imageNodeSpec2, runMarkSpec as runMarkSpec2 } from "./rendering.js";
40
+ var NO_STORIES = Object.freeze({});
36
41
  function isRecord(value) {
37
42
  return typeof value === "object" && value !== null;
38
43
  }
@@ -78,7 +83,7 @@ function repliesHoldTheirXml(value) {
78
83
  const replies = value;
79
84
  return replies.every((reply) => {
80
85
  if (!isRecord(reply)) return true;
81
- return acceptRawXml(ELEMENT("comment"), text(reply.commentXml) ?? null) !== false && acceptRawXml(ANY_ELEMENT, text(reply.extensionXml) ?? null) !== false;
86
+ return acceptRawXml(ANY_ELEMENT, text(reply.extensionXml) ?? null) !== false;
82
87
  });
83
88
  }
84
89
  var SDT_PREFIX = {
@@ -96,22 +101,65 @@ var LINK_PREFIX = {
96
101
  function rawXml(dom, attribute, shape) {
97
102
  return acceptRawXml(shape, dom.getAttribute(attribute));
98
103
  }
104
+ function preservedDisplayOf(value) {
105
+ switch (value) {
106
+ case "text":
107
+ return "text";
108
+ case "break":
109
+ return "break";
110
+ case "chip":
111
+ return "chip";
112
+ default:
113
+ return "hidden";
114
+ }
115
+ }
116
+ function preservedAttributes(node, className) {
117
+ return {
118
+ class: className,
119
+ "data-xml": text(node.attrs.xml),
120
+ "data-element": text(node.attrs.element),
121
+ "data-display": preservedDisplayOf(node.attrs.display),
122
+ "data-text": text(node.attrs.text),
123
+ "data-guarded": node.attrs.guarded === true ? "1" : void 0
124
+ };
125
+ }
126
+ function preservedDom(node, className) {
127
+ const attributes = preservedAttributes(node, className);
128
+ const display = preservedDisplayOf(node.attrs.display);
129
+ const preview = text(node.attrs.text);
130
+ const element = text(node.attrs.element);
131
+ if (display === "break") return ["span", attributes, ["br"]];
132
+ if (display === "text") return ["span", attributes, preview ?? ""];
133
+ if (display === "chip") {
134
+ return [
135
+ "span",
136
+ { ...attributes, title: element ?? UNKNOWN_PLACEHOLDER },
137
+ preview !== void 0 && preview !== "" ? preview : element ?? "?"
138
+ ];
139
+ }
140
+ return ["span", attributes];
141
+ }
142
+ function preservedAttrs(dom) {
143
+ const xml = rawXml(dom, "data-xml", ANY_ELEMENT);
144
+ if (xml === false) return false;
145
+ return {
146
+ xml,
147
+ element: dom.getAttribute("data-element"),
148
+ display: preservedDisplayOf(dom.getAttribute("data-display")),
149
+ text: dom.getAttribute("data-text"),
150
+ guarded: dom.getAttribute("data-guarded") === "1"
151
+ };
152
+ }
99
153
  var TABLE_PLACEHOLDER = "Table (unsupported layout, original is preserved)";
100
154
  var UNKNOWN_PLACEHOLDER = "Unsupported content (not editable, original is preserved)";
101
155
  var TABLE_NAMES = ["w:tbl", "tbl"];
102
- function rawBlockDom(name) {
103
- if (name !== void 0 && TABLE_NAMES.includes(name)) {
104
- return {
105
- className: editorClassNames.tablePlaceholder,
106
- label: TABLE_PLACEHOLDER
107
- };
108
- }
109
- return { className: editorClassNames.rawBlock, label: UNKNOWN_PLACEHOLDER };
156
+ function placeholderLabel(name) {
157
+ return name !== void 0 && TABLE_NAMES.includes(name) ? TABLE_PLACEHOLDER : UNKNOWN_PLACEHOLDER;
158
+ }
159
+ function preservedNameOf(dom) {
160
+ const name = dom.getAttribute("data-name");
161
+ return name === null || name === "" ? null : name;
110
162
  }
111
- var DOCX_RAW_SELECTOR = [
112
- editorClassNames.rawBlock,
113
- editorClassNames.tablePlaceholder
114
- ].map((className) => `div[data-src].${className}`).join(", ");
115
163
  var docxSchema = new Schema({
116
164
  nodes: {
117
165
  doc: {
@@ -121,7 +169,20 @@ var docxSchema = new Schema({
121
169
  * The definitions of the lists started while editing, which the export writes into
122
170
  * numbering.xml. Read back through `numbering/listRegistry`.
123
171
  */
124
- newLists: { default: null }
172
+ newLists: { default: null },
173
+ /**
174
+ * The section properties that close the body: the paper the document's last section is
175
+ * written on, its headers and its page numbering (§17.6.18). Held as the fragment the
176
+ * document wrote, so an untouched document goes back out as the bytes it arrived as.
177
+ * Read through `docx/sections`.
178
+ */
179
+ sectPr: { default: null },
180
+ /**
181
+ * What each side story - a comment's body, a footnote's - currently says, under the key
182
+ * naming it (`./stories`). Read and written through `docx/story`; it never reaches the
183
+ * DOM, so a copy out of the editor carries none of it.
184
+ */
185
+ stories: { default: NO_STORIES }
125
186
  }
126
187
  },
127
188
  paragraph: {
@@ -221,7 +282,13 @@ var docxSchema = new Schema({
221
282
  */
222
283
  styleConditions: { default: null },
223
284
  /** How many rows and columns one band of the table style is made of */
224
- styleBands: { default: null }
285
+ styleBands: { default: null },
286
+ /**
287
+ * The markers that stood between this table's rows: the ones ahead of the first row
288
+ * (`docx/importTable`). They are invisible and belong to no row, so they ride along on
289
+ * the table and go back where they stood
290
+ */
291
+ leadingXml: { default: null }
225
292
  },
226
293
  toDOM(node) {
227
294
  const format = toTableFormat(node.attrs.format);
@@ -246,7 +313,8 @@ var docxSchema = new Schema({
246
313
  "data-style-conditions": formatJson(
247
314
  toTableStyleConditions(node.attrs.styleConditions)
248
315
  ),
249
- "data-style-bands": formatJson(toBandSizes(node.attrs.styleBands))
316
+ "data-style-bands": formatJson(toBandSizes(node.attrs.styleBands)),
317
+ "data-leading": text(node.attrs.leadingXml)
250
318
  };
251
319
  const body = ["tbody", 0];
252
320
  if (gridCols.length === 0) return ["table", attrs, body];
@@ -269,7 +337,8 @@ var docxSchema = new Schema({
269
337
  "data-gridchange",
270
338
  ELEMENT("tblGridChange")
271
339
  );
272
- if (tblAttrs === false || tblPr === false || gridChange === false) {
340
+ const leadingXml = rawXml(dom, "data-leading", ANY_ELEMENTS);
341
+ if (tblAttrs === false || tblPr === false || gridChange === false || leadingXml === false) {
273
342
  return false;
274
343
  }
275
344
  return {
@@ -291,7 +360,8 @@ var docxSchema = new Schema({
291
360
  ),
292
361
  styleBands: toBandSizes(
293
362
  parseJson(dom.getAttribute("data-style-bands"))
294
- )
363
+ ),
364
+ leadingXml
295
365
  };
296
366
  }
297
367
  }
@@ -307,7 +377,11 @@ var docxSchema = new Schema({
307
377
  tblPrEx: { default: null },
308
378
  /** The whole `<w:trPr>...</w:trPr>` XML */
309
379
  trPr: { default: null },
310
- format: { default: null }
380
+ format: { default: null },
381
+ /** The markers that stood ahead of this row's first cell (`docx/importTable`) */
382
+ leadingXml: { default: null },
383
+ /** The markers that stood between this row and the next one, under the table */
384
+ trailingXml: { default: null }
311
385
  },
312
386
  toDOM(node) {
313
387
  const format = toRowFormat(node.attrs.format);
@@ -319,7 +393,9 @@ var docxSchema = new Schema({
319
393
  "data-trattrs": text(node.attrs.trAttrs),
320
394
  "data-tblprex": text(node.attrs.tblPrEx),
321
395
  "data-trpr": text(node.attrs.trPr),
322
- "data-fmt": formatJson(format)
396
+ "data-fmt": formatJson(format),
397
+ "data-leading": text(node.attrs.leadingXml),
398
+ "data-trailing": text(node.attrs.trailingXml)
323
399
  },
324
400
  0
325
401
  ];
@@ -331,14 +407,18 @@ var docxSchema = new Schema({
331
407
  const trAttrs = rawXml(dom, "data-trattrs", ATTRIBUTES);
332
408
  const tblPrEx = rawXml(dom, "data-tblprex", ELEMENT("tblPrEx"));
333
409
  const trPr = rawXml(dom, "data-trpr", ELEMENT("trPr"));
334
- if (trAttrs === false || tblPrEx === false || trPr === false) {
410
+ const leadingXml = rawXml(dom, "data-leading", ANY_ELEMENTS);
411
+ const trailingXml = rawXml(dom, "data-trailing", ANY_ELEMENTS);
412
+ if (trAttrs === false || tblPrEx === false || trPr === false || leadingXml === false || trailingXml === false) {
335
413
  return false;
336
414
  }
337
415
  return {
338
416
  trAttrs,
339
417
  tblPrEx,
340
418
  trPr,
341
- format: toRowFormat(parseJson(dom.getAttribute("data-fmt")))
419
+ format: toRowFormat(parseJson(dom.getAttribute("data-fmt"))),
420
+ leadingXml,
421
+ trailingXml
342
422
  };
343
423
  }
344
424
  }
@@ -372,7 +452,9 @@ var docxSchema = new Schema({
372
452
  * the lock lives inside that very XML.
373
453
  */
374
454
  sdtContentsLocked: { default: false },
375
- sdtDeletionLocked: { default: false }
455
+ sdtDeletionLocked: { default: false },
456
+ /** The markers that stood between this cell and the next one, under the row */
457
+ trailingXml: { default: null }
376
458
  },
377
459
  toDOM(node) {
378
460
  const format = toCellFormat(node.attrs.format);
@@ -394,7 +476,8 @@ var docxSchema = new Schema({
394
476
  "data-fmt": formatJson(format),
395
477
  "data-sdt-prefix": text(node.attrs.sdtPrefix),
396
478
  "data-sdt-contents-locked": locked ? "1" : void 0,
397
- "data-sdt-deletion-locked": node.attrs.sdtDeletionLocked === true ? "1" : void 0
479
+ "data-sdt-deletion-locked": node.attrs.sdtDeletionLocked === true ? "1" : void 0,
480
+ "data-trailing": text(node.attrs.trailingXml)
398
481
  },
399
482
  0
400
483
  ];
@@ -406,7 +489,8 @@ var docxSchema = new Schema({
406
489
  const tcAttrs = rawXml(dom, "data-tcattrs", ATTRIBUTES);
407
490
  const tcPr = rawXml(dom, "data-tcpr", ELEMENT("tcPr"));
408
491
  const sdtPrefix = rawXml(dom, "data-sdt-prefix", SDT_PREFIX);
409
- if (tcAttrs === false || tcPr === false || sdtPrefix === false) {
492
+ const trailingXml = rawXml(dom, "data-trailing", ANY_ELEMENTS);
493
+ if (tcAttrs === false || tcPr === false || sdtPrefix === false || trailingXml === false) {
410
494
  return false;
411
495
  }
412
496
  return {
@@ -421,116 +505,75 @@ var docxSchema = new Schema({
421
505
  format: toCellFormat(parseJson(dom.getAttribute("data-fmt"))),
422
506
  sdtPrefix,
423
507
  sdtContentsLocked: dom.getAttribute("data-sdt-contents-locked") === "1",
424
- sdtDeletionLocked: dom.getAttribute("data-sdt-deletion-locked") === "1"
508
+ sdtDeletionLocked: dom.getAttribute("data-sdt-deletion-locked") === "1",
509
+ trailingXml
425
510
  };
426
511
  }
427
512
  }
428
513
  ]
429
514
  },
430
515
  /**
431
- * The node that carries, as original XML, a block inside a table cell that we do
432
- * not model (a nested table, for instance).
433
- * Unlike a body block it has no original fragment number, so it carries its own
434
- * XML around with it.
516
+ * The one node a block the editor has no model for stands as, wherever it stood: under the
517
+ * body, or inside a table cell.
518
+ *
519
+ * Which of the two it came from is what it carries the original as. A body block is one of the
520
+ * fragments the session holds, so it names that fragment and the bytes go back out untouched;
521
+ * a block inside a cell was never a fragment of its own, so it carries its XML with it.
522
+ *
523
+ * `display` says whether anything of it is on screen. A range marker draws nothing - it stands
524
+ * between blocks and marks a spot rather than holding content - while a table nobody could take
525
+ * apart draws a box saying so.
435
526
  */
436
527
  rawBlock: {
437
528
  group: "block preserved",
438
529
  atom: true,
439
530
  selectable: false,
440
531
  attrs: {
532
+ /** The element, verbatim, for a block the session holds no fragment of */
441
533
  xml: { default: null },
534
+ /** The fragment of the session this block was opened from */
535
+ srcId: { default: null },
442
536
  /** The original element name (for example `w:tbl`) */
443
- name: { default: null }
537
+ name: { default: null },
538
+ display: { default: "chip" },
539
+ /** Whether the deletion guard answers for this block (`./preservedGuards`) */
540
+ guarded: { default: false }
444
541
  },
445
542
  toDOM(node) {
446
- return [
447
- "div",
448
- {
449
- class: `${editorClassNames.rawBlock} ${editorClassNames.rawXmlBlock}`,
450
- "data-xml": text(node.attrs.xml),
451
- "data-name": text(node.attrs.name)
452
- },
453
- UNKNOWN_PLACEHOLDER
454
- ];
543
+ const name = text(node.attrs.name);
544
+ const display = preservedDisplayOf(node.attrs.display);
545
+ const attributes = {
546
+ class: editorClassNames.rawBlock,
547
+ "data-xml": text(node.attrs.xml),
548
+ "data-src": text(node.attrs.srcId) ?? "",
549
+ "data-name": name ?? "",
550
+ "data-display": display,
551
+ "data-guarded": node.attrs.guarded === true ? "1" : void 0
552
+ };
553
+ if (display !== "chip") return ["div", attributes];
554
+ return ["div", attributes, placeholderLabel(name)];
455
555
  },
456
556
  parseDOM: [
457
557
  {
458
- tag: `div.${editorClassNames.rawXmlBlock}`,
558
+ tag: `div.${editorClassNames.rawBlock}[data-name]`,
459
559
  getAttrs: (dom) => {
460
560
  const xml = rawXml(dom, "data-xml", ANY_ELEMENT);
461
561
  if (xml === false) return false;
462
- return { xml, name: dom.getAttribute("data-name") };
463
- }
464
- }
465
- ]
466
- },
467
- /** The node that carries a non-paragraph body block (a table we could not model, sectPr, an unknown element) exactly as it came */
468
- docxRaw: {
469
- group: "block preserved",
470
- atom: true,
471
- selectable: false,
472
- attrs: {
473
- srcId: { default: null },
474
- /** The original element name (for example `w:tbl`) */
475
- name: { default: null }
476
- },
477
- toDOM(node) {
478
- const { className, label } = rawBlockDom(text(node.attrs.name));
479
- return [
480
- "div",
481
- {
482
- class: className,
483
- "data-src": text(node.attrs.srcId) ?? "",
484
- "data-name": text(node.attrs.name)
485
- },
486
- label
487
- ];
488
- },
489
- parseDOM: [
490
- {
491
- tag: DOCX_RAW_SELECTOR,
492
- getAttrs: (dom) => ({
493
- srcId: srcIdOf(dom),
494
- name: dom.getAttribute("data-name")
495
- })
496
- }
497
- ]
498
- },
499
- /** A bookmark range marker that occurs directly under w:body rather than inside a paragraph */
500
- bookmarkBlock: {
501
- group: "block preserved",
502
- atom: true,
503
- isolating: true,
504
- selectable: false,
505
- attrs: {
506
- srcId: { default: null },
507
- name: { default: null }
508
- },
509
- toDOM(node) {
510
- return [
511
- "div",
512
- {
513
- class: editorClassNames.bookmarkBlock,
514
- "data-src": text(node.attrs.srcId) ?? "",
515
- "data-name": text(node.attrs.name),
516
- hidden: "hidden"
562
+ return {
563
+ xml,
564
+ srcId: srcIdOf(dom),
565
+ name: preservedNameOf(dom),
566
+ display: preservedDisplayOf(dom.getAttribute("data-display")),
567
+ guarded: dom.getAttribute("data-guarded") === "1"
568
+ };
517
569
  }
518
- ];
519
- },
520
- parseDOM: [
521
- {
522
- tag: `div.${editorClassNames.bookmarkBlock}`,
523
- getAttrs: (dom) => ({
524
- srcId: srcIdOf(dom),
525
- name: dom.getAttribute("data-name")
526
- })
527
570
  }
528
571
  ]
529
572
  },
530
573
  hardBreak: {
531
574
  group: "inline",
532
575
  inline: true,
533
- marks: "run sdt link",
576
+ marks: "run wrapper",
534
577
  attrs: { brAttrs: { default: null } },
535
578
  toDOM(node) {
536
579
  return [
@@ -563,7 +606,7 @@ var docxSchema = new Schema({
563
606
  group: "inline",
564
607
  inline: true,
565
608
  draggable: true,
566
- marks: "run sdt link",
609
+ marks: "run wrapper",
567
610
  attrs: {
568
611
  /** The image bytes as a data URL */
569
612
  src: { default: null },
@@ -598,7 +641,7 @@ var docxSchema = new Schema({
598
641
  inline: true,
599
642
  atom: true,
600
643
  selectable: false,
601
- marks: "sdt link",
644
+ marks: "wrapper",
602
645
  attrs: {
603
646
  id: { default: null },
604
647
  xml: { default: null }
@@ -630,7 +673,7 @@ var docxSchema = new Schema({
630
673
  inline: true,
631
674
  atom: true,
632
675
  selectable: false,
633
- marks: "sdt link",
676
+ marks: "wrapper",
634
677
  attrs: {
635
678
  id: { default: null },
636
679
  xml: { default: null }
@@ -662,7 +705,7 @@ var docxSchema = new Schema({
662
705
  inline: true,
663
706
  atom: true,
664
707
  selectable: false,
665
- marks: "run sdt link",
708
+ marks: "run wrapper",
666
709
  attrs: {
667
710
  id: { default: null },
668
711
  referenceXml: { default: null },
@@ -672,9 +715,6 @@ var docxSchema = new Schema({
672
715
  authorId: { default: null },
673
716
  initials: { default: null },
674
717
  date: { default: null },
675
- text: { default: "" },
676
- commentXml: { default: null },
677
- imported: { default: false },
678
718
  paraId: { default: null },
679
719
  resolved: { default: false },
680
720
  extensionXml: { default: null },
@@ -693,9 +733,6 @@ var docxSchema = new Schema({
693
733
  "data-comment-author-id": text(node.attrs.authorId),
694
734
  "data-comment-initials": text(node.attrs.initials),
695
735
  "data-comment-date": text(node.attrs.date),
696
- "data-comment-text": text(node.attrs.text),
697
- "data-comment-xml": text(node.attrs.commentXml),
698
- "data-comment-imported": node.attrs.imported === true ? "1" : void 0,
699
736
  "data-comment-para-id": text(node.attrs.paraId),
700
737
  "data-comment-resolved": node.attrs.resolved === true ? "1" : void 0,
701
738
  "data-comment-extension-xml": text(node.attrs.extensionXml),
@@ -713,18 +750,13 @@ var docxSchema = new Schema({
713
750
  "data-reference-xml",
714
751
  ELEMENT("commentReference")
715
752
  );
716
- const commentXml = rawXml(
717
- dom,
718
- "data-comment-xml",
719
- ELEMENT("comment")
720
- );
721
753
  const extensionXml = rawXml(
722
754
  dom,
723
755
  "data-comment-extension-xml",
724
756
  ANY_ELEMENT
725
757
  );
726
758
  const replies = parseJson(dom.getAttribute("data-comment-replies")) ?? [];
727
- if (referenceXml === false || commentXml === false || extensionXml === false || !repliesHoldTheirXml(replies)) {
759
+ if (referenceXml === false || extensionXml === false || !repliesHoldTheirXml(replies)) {
728
760
  return false;
729
761
  }
730
762
  return {
@@ -734,9 +766,6 @@ var docxSchema = new Schema({
734
766
  authorId: dom.getAttribute("data-comment-author-id"),
735
767
  initials: dom.getAttribute("data-comment-initials"),
736
768
  date: dom.getAttribute("data-comment-date"),
737
- text: dom.getAttribute("data-comment-text") ?? "",
738
- commentXml,
739
- imported: dom.getAttribute("data-comment-imported") === "1",
740
769
  paraId: dom.getAttribute("data-comment-para-id"),
741
770
  resolved: dom.getAttribute("data-comment-resolved") === "1",
742
771
  extensionXml,
@@ -752,19 +781,17 @@ var docxSchema = new Schema({
752
781
  inline: true,
753
782
  atom: true,
754
783
  selectable: false,
755
- marks: "run sdt link",
784
+ marks: "run wrapper",
756
785
  attrs: {
757
786
  kind: { default: "footnote" },
758
787
  id: { default: null },
759
788
  label: { default: "?" },
760
- text: { default: "" },
761
789
  customMarkFollows: { default: false },
762
790
  referenceXml: { default: null }
763
791
  },
764
792
  toDOM(node) {
765
793
  const kind = node.attrs.kind === "endnote" ? "Endnote" : "Footnote";
766
794
  const label = text(node.attrs.label) ?? "?";
767
- const body = text(node.attrs.text) ?? "";
768
795
  return [
769
796
  "sup",
770
797
  {
@@ -772,11 +799,9 @@ var docxSchema = new Schema({
772
799
  "data-note-kind": text(node.attrs.kind),
773
800
  "data-note-id": text(node.attrs.id),
774
801
  "data-note-label": label,
775
- "data-note-text": body,
776
802
  "data-custom-mark-follows": node.attrs.customMarkFollows === true ? "1" : void 0,
777
803
  "data-reference-xml": text(node.attrs.referenceXml),
778
- "aria-label": `${kind} ${label}`,
779
- title: body
804
+ "aria-label": `${kind} ${label}`
780
805
  },
781
806
  node.attrs.customMarkFollows === true ? "" : label
782
807
  ];
@@ -795,7 +820,6 @@ var docxSchema = new Schema({
795
820
  kind: dom.getAttribute("data-note-kind") === "endnote" ? "endnote" : "footnote",
796
821
  id: dom.getAttribute("data-note-id"),
797
822
  label: dom.getAttribute("data-note-label") ?? "?",
798
- text: dom.getAttribute("data-note-text") ?? "",
799
823
  customMarkFollows: dom.getAttribute("data-custom-mark-follows") === "1",
800
824
  referenceXml
801
825
  };
@@ -803,29 +827,58 @@ var docxSchema = new Schema({
803
827
  }
804
828
  ]
805
829
  },
830
+ /**
831
+ * One child of a run the editor has no node for, kept as the XML it came as.
832
+ *
833
+ * It wears the run mark, so it is written back inside the same `<w:r>` as the text beside it,
834
+ * which is where `EG_RunInnerContent` says it may stand.
835
+ */
836
+ rawRunContent: {
837
+ group: "inline",
838
+ inline: true,
839
+ atom: true,
840
+ marks: "run wrapper",
841
+ attrs: {
842
+ xml: { default: null },
843
+ /** The local name of the element, for example `fldChar` */
844
+ element: { default: null },
845
+ display: { default: "hidden" },
846
+ /** What a `text` display draws, and the preview a chip shows */
847
+ text: { default: null },
848
+ /** Whether the deletion guard answers for this fragment (`schema/preservedGuards`) */
849
+ guarded: { default: false }
850
+ },
851
+ toDOM(node) {
852
+ return preservedDom(node, editorClassNames.rawRunContent);
853
+ },
854
+ parseDOM: [
855
+ {
856
+ tag: `span.${editorClassNames.rawRunContent}`,
857
+ getAttrs: preservedAttrs
858
+ }
859
+ ]
860
+ },
806
861
  /** The node that carries a non-run element inside a paragraph (a bookmark, for instance) exactly as it came */
807
862
  rawInline: {
808
863
  group: "inline",
809
864
  inline: true,
810
865
  atom: true,
811
- marks: "sdt link",
812
- attrs: { xml: { default: null } },
866
+ marks: "wrapper",
867
+ attrs: {
868
+ xml: { default: null },
869
+ /** The local name of the element; `r` for a run with no content, kept whole */
870
+ element: { default: null },
871
+ display: { default: "hidden" },
872
+ text: { default: null },
873
+ guarded: { default: false }
874
+ },
813
875
  toDOM(node) {
814
- return [
815
- "span",
816
- {
817
- class: editorClassNames.rawInline,
818
- "data-xml": text(node.attrs.xml)
819
- }
820
- ];
876
+ return preservedDom(node, editorClassNames.rawInline);
821
877
  },
822
878
  parseDOM: [
823
879
  {
824
880
  tag: `span.${editorClassNames.rawInline}`,
825
- getAttrs: (dom) => {
826
- const xml = rawXml(dom, "data-xml", ANY_ELEMENT);
827
- return xml === false ? false : { xml };
828
- }
881
+ getAttrs: preservedAttrs
829
882
  }
830
883
  ]
831
884
  },
@@ -837,20 +890,20 @@ var docxSchema = new Schema({
837
890
  *
838
891
  * It is declared ahead of the run mark on purpose: the mark declared first is drawn
839
892
  * outside on screen, so one control can hold the several runs it wrapped in the file.
893
+ * It is declared ahead of the other wrappers for the same reason, which is what settles
894
+ * the nesting of two wrappers written at one and the same depth (`./wrappers`).
840
895
  */
841
896
  sdt: {
897
+ group: WRAPPER_GROUP,
842
898
  // A character typed against either edge of the control belongs outside it
843
899
  inclusive: false,
900
+ // §17.5.2.17 has a control hold a control, so a second one does not replace the first:
901
+ // which stands inside which is what `depth` says (`./wrappers`)
902
+ excludes: "",
844
903
  attrs: {
845
904
  /** The opening XML of the `<w:sdt>`, the same string a wrapped cell carries */
846
905
  sdtPrefix: { default: null },
847
- /**
848
- * Which control this is, counted through the document as it was opened, and never
849
- * written back to the file. Two controls whose XML is identical would otherwise wear
850
- * the very same mark and their text would run into one. The first control gets 0, so
851
- * a control made during editing needs no number of its own.
852
- */
853
- sdtKey: { default: 0 },
906
+ ...WRAPPER_ATTRS,
854
907
  /**
855
908
  * The two clauses of the control's lock: whether its contents may not be edited, and
856
909
  * whether the control itself may not be deleted, not even whole. The `w:lock` inside
@@ -869,7 +922,8 @@ var docxSchema = new Schema({
869
922
  {
870
923
  class: locked ? `${editorClassNames.sdt} ${editorClassNames.sdtLocked}` : editorClassNames.sdt,
871
924
  "data-sdt-prefix": text(mark.attrs.sdtPrefix),
872
- "data-sdt-key": numberText(mark.attrs.sdtKey),
925
+ "data-key": numberText(mark.attrs.key),
926
+ "data-depth": numberText(mark.attrs.depth),
873
927
  "data-sdt-contents-locked": locked ? "1" : void 0,
874
928
  "data-sdt-deletion-locked": mark.attrs.deletionLocked === true ? "1" : void 0
875
929
  },
@@ -884,7 +938,8 @@ var docxSchema = new Schema({
884
938
  if (prefix === null || prefix === false) return false;
885
939
  return {
886
940
  sdtPrefix: prefix,
887
- sdtKey: parseInt10(dom.getAttribute("data-sdt-key"), 0),
941
+ key: parseInt10(dom.getAttribute("data-key"), 0),
942
+ depth: parseInt10(dom.getAttribute("data-depth"), 0),
888
943
  contentsLocked: dom.getAttribute("data-sdt-contents-locked") === "1",
889
944
  deletionLocked: dom.getAttribute("data-sdt-deletion-locked") === "1"
890
945
  };
@@ -900,10 +955,12 @@ var docxSchema = new Schema({
900
955
  * back out inside it (`docx/serializeParagraph`).
901
956
  */
902
957
  link: {
958
+ group: WRAPPER_GROUP,
903
959
  // A character typed against either edge of a link belongs outside it, and that is also what
904
960
  // decides whether a caret counts as standing in one (`editor/commands/linkCommands`)
905
961
  inclusive: false,
906
962
  attrs: {
963
+ ...WRAPPER_ATTRS,
907
964
  /**
908
965
  * The opening XML of the `<w:hyperlink>`, which carries everything about the link we never
909
966
  * read: `w:tooltip`, `w:history`, `w:docLocation`, `w:anchor`. null for a link made in the
@@ -915,14 +972,7 @@ var docxSchema = new Schema({
915
972
  * a bookmark alone, or one whose relationship leads nowhere we can follow: the wrapper still
916
973
  * travels, and no address is offered for it.
917
974
  */
918
- href: { default: null },
919
- /**
920
- * Which link this is, counted through the document as it was opened, and never written back
921
- * to the file. Two links written exactly alike would otherwise wear the very same mark and
922
- * the text they cover would run into one wrapper. The first link gets 0, so a link made
923
- * during editing needs no number of its own.
924
- */
925
- linkKey: { default: 0 }
975
+ href: { default: null }
926
976
  },
927
977
  toDOM(mark) {
928
978
  return [
@@ -934,7 +984,8 @@ var docxSchema = new Schema({
934
984
  // by the link panel instead
935
985
  "data-href": text(mark.attrs.href),
936
986
  "data-link-prefix": text(mark.attrs.linkPrefix),
937
- "data-link-key": numberText(mark.attrs.linkKey)
987
+ "data-key": numberText(mark.attrs.key),
988
+ "data-depth": numberText(mark.attrs.depth)
938
989
  },
939
990
  0
940
991
  ];
@@ -950,7 +1001,8 @@ var docxSchema = new Schema({
950
1001
  return {
951
1002
  linkPrefix: prefix,
952
1003
  href,
953
- linkKey: parseInt10(dom.getAttribute("data-link-key"), 0)
1004
+ key: parseInt10(dom.getAttribute("data-key"), 0),
1005
+ depth: parseInt10(dom.getAttribute("data-depth"), 0)
954
1006
  };
955
1007
  }
956
1008
  }