@portone/docx-editor 0.1.1 → 0.2.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 (138) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/CONTRIBUTING.md +4 -0
  3. package/README.md +17 -5
  4. package/dist/DocxEditor.d.ts +34 -10
  5. package/dist/DocxEditor.js +69 -24
  6. package/dist/core.d.ts +2 -0
  7. package/dist/core.js +2 -0
  8. package/dist/docx/commentOnlyChange.d.ts +47 -0
  9. package/dist/docx/commentOnlyChange.js +162 -0
  10. package/dist/docx/comments/constants.d.ts +11 -3
  11. package/dist/docx/comments/constants.js +10 -3
  12. package/dist/docx/comments/contentTypes.d.ts +7 -0
  13. package/dist/docx/comments/contentTypes.js +38 -0
  14. package/dist/docx/comments/grammar.d.ts +80 -0
  15. package/dist/docx/comments/grammar.js +213 -0
  16. package/dist/docx/comments/model.d.ts +2 -0
  17. package/dist/docx/comments/model.js +3 -0
  18. package/dist/docx/comments/people.d.ts +39 -0
  19. package/dist/docx/comments/people.js +196 -0
  20. package/dist/docx/comments/reading.d.ts +18 -1
  21. package/dist/docx/comments/reading.js +33 -20
  22. package/dist/docx/comments/verifying.d.ts +44 -0
  23. package/dist/docx/comments/verifying.js +206 -0
  24. package/dist/docx/comments/writing.d.ts +4 -1
  25. package/dist/docx/comments/writing.js +84 -77
  26. package/dist/docx/exportDocx.js +2 -1
  27. package/dist/docx/formatting/direct.js +3 -6
  28. package/dist/docx/headersFooters.js +8 -10
  29. package/dist/docx/importParagraph.js +1 -0
  30. package/dist/docx/notes.js +3 -5
  31. package/dist/docx/paraProps.js +51 -46
  32. package/dist/docx/propsXml.d.ts +20 -2
  33. package/dist/docx/propsXml.js +72 -32
  34. package/dist/docx/relationships.js +8 -3
  35. package/dist/docx/runProps.js +34 -34
  36. package/dist/docx/sdt.js +16 -14
  37. package/dist/docx/serializeBlock.js +1 -2
  38. package/dist/docx/serializeParagraph.d.ts +2 -1
  39. package/dist/docx/serializeParagraph.js +25 -14
  40. package/dist/docx/serializeTable.js +38 -24
  41. package/dist/docx/storyProjection.d.ts +36 -0
  42. package/dist/docx/storyProjection.js +23 -0
  43. package/dist/docx/tableFormatting/editing.js +49 -73
  44. package/dist/docx/tableTemplate.js +24 -3
  45. package/dist/docx/theme.d.ts +0 -6
  46. package/dist/docx/theme.js +0 -8
  47. package/dist/editor/clipboard/images.js +17 -3
  48. package/dist/editor/clipboard/inlineFormatting.d.ts +7 -0
  49. package/dist/editor/clipboard/inlineFormatting.js +1 -0
  50. package/dist/editor/commands/breakCommands.js +6 -2
  51. package/dist/editor/commands/canRunCommand.d.ts +3 -2
  52. package/dist/editor/commands/canRunCommand.js +2 -2
  53. package/dist/editor/commands/comments/editing.js +9 -10
  54. package/dist/editor/commands/comments/model.d.ts +9 -0
  55. package/dist/editor/commands/comments/reading.d.ts +7 -0
  56. package/dist/editor/commands/comments/reading.js +14 -0
  57. package/dist/editor/commands/formatting/editing.js +6 -1
  58. package/dist/editor/commands/historyCommands.js +14 -5
  59. package/dist/editor/commands/index.d.ts +7 -1
  60. package/dist/editor/commands/index.js +4 -0
  61. package/dist/editor/commands/linkCommands.js +2 -0
  62. package/dist/editor/commands/lockCommands.js +12 -1
  63. package/dist/editor/commands/tabCommands.js +4 -2
  64. package/dist/editor/createEditor.d.ts +13 -3
  65. package/dist/editor/createEditor.js +23 -15
  66. package/dist/editor/externalClipboard.js +166 -4
  67. package/dist/editor/insertImage.js +6 -2
  68. package/dist/editor/insertTable.js +2 -1
  69. package/dist/editor/paragraphEdits.d.ts +2 -0
  70. package/dist/editor/paragraphEdits.js +2 -0
  71. package/dist/editor/plugins/documentProtection.d.ts +21 -0
  72. package/dist/editor/plugins/documentProtection.js +44 -0
  73. package/dist/editor/plugins/imagePaste.js +4 -1
  74. package/dist/editor/plugins/keymap.d.ts +11 -1
  75. package/dist/editor/plugins/keymap.js +24 -4
  76. package/dist/editor/plugins/lockedContent.d.ts +4 -2
  77. package/dist/editor/plugins/lockedContent.js +2 -2
  78. package/dist/editor/plugins/tableContextMenu.js +2 -1
  79. package/dist/editor/plugins/textContextMenu.js +6 -1
  80. package/dist/index.d.ts +2 -0
  81. package/dist/numbering/listTemplate.js +32 -10
  82. package/dist/ooxml/element.d.ts +52 -0
  83. package/dist/ooxml/element.js +49 -0
  84. package/dist/ooxml/fragment.d.ts +53 -0
  85. package/dist/ooxml/fragment.js +76 -0
  86. package/dist/ooxml/image.js +4 -3
  87. package/dist/ooxml/names.d.ts +27 -0
  88. package/dist/ooxml/names.js +29 -0
  89. package/dist/ooxml/precedence.d.ts +31 -0
  90. package/dist/ooxml/precedence.js +51 -0
  91. package/dist/ooxml/xml.d.ts +31 -0
  92. package/dist/ooxml/xml.js +27 -0
  93. package/dist/page/blockKinds.d.ts +42 -0
  94. package/dist/page/blockKinds.js +0 -0
  95. package/dist/page/measureBlocks.d.ts +14 -1
  96. package/dist/page/measureBlocks.js +31 -11
  97. package/dist/page/pageDecorations.d.ts +16 -0
  98. package/dist/page/pageDecorations.js +1 -0
  99. package/dist/page/pageLayout.d.ts +8 -43
  100. package/dist/page/pageLayout.js +28 -51
  101. package/dist/page/tableMeasurements.d.ts +10 -2
  102. package/dist/page/tableMeasurements.js +20 -16
  103. package/dist/page/usePageLayout.d.ts +15 -0
  104. package/dist/page/usePageLayout.js +30 -2
  105. package/dist/schema/attrRoles.d.ts +35 -0
  106. package/dist/schema/attrRoles.js +106 -0
  107. package/dist/schema/docxSchema.d.ts +6 -0
  108. package/dist/schema/docxSchema.js +216 -100
  109. package/dist/schema/editGuard.d.ts +99 -0
  110. package/dist/schema/editGuard.js +43 -0
  111. package/dist/schema/guards.d.ts +68 -0
  112. package/dist/schema/guards.js +82 -0
  113. package/dist/schema/locks.d.ts +9 -8
  114. package/dist/schema/locks.js +32 -16
  115. package/dist/schema/preservedGuards.d.ts +30 -0
  116. package/dist/schema/preservedGuards.js +50 -0
  117. package/dist/schema/protection.d.ts +84 -0
  118. package/dist/schema/protection.js +171 -0
  119. package/dist/schema/protectionState.d.ts +20 -0
  120. package/dist/schema/protectionState.js +37 -0
  121. package/dist/schema/sourceEquality.d.ts +27 -0
  122. package/dist/schema/sourceEquality.js +65 -0
  123. package/dist/table/cellFormatting.js +5 -2
  124. package/dist/table/commands.d.ts +2 -2
  125. package/dist/table/commands.js +2 -2
  126. package/dist/table/index.d.ts +2 -2
  127. package/dist/table/merge.d.ts +2 -2
  128. package/dist/table/merge.js +3 -3
  129. package/dist/ui/CommentsPanel.d.ts +3 -3
  130. package/dist/ui/CommentsPanel.js +26 -18
  131. package/dist/ui/LinkCard.d.ts +1 -2
  132. package/dist/ui/LinkCard.js +3 -4
  133. package/dist/ui/TextMenu.js +15 -10
  134. package/package.json +5 -2
  135. package/dist/editor/plugins/bookmarkProtection.d.ts +0 -3
  136. package/dist/editor/plugins/bookmarkProtection.js +0 -28
  137. package/dist/editor/plugins/noteProtection.d.ts +0 -3
  138. package/dist/editor/plugins/noteProtection.js +0 -25
@@ -9,6 +9,7 @@ import {
9
9
  import { editorCssVariables } from "../styles/classNames.js";
10
10
  import { measureSheet } from "./measureBlocks.js";
11
11
  import {
12
+ pageBreaksIn,
12
13
  setPageBreakSpaces,
13
14
  setPagePushes,
14
15
  setTableContinuations
@@ -52,6 +53,27 @@ function useFrameThrottle(run, hold) {
52
53
  function sameOverlay(a, b) {
53
54
  return a !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.sheetHeight === b.sheetHeight && JSON.stringify(a.marks) === JSON.stringify(b.marks) && JSON.stringify(a.badges) === JSON.stringify(b.badges) && JSON.stringify(a.pages) === JSON.stringify(b.pages);
54
55
  }
56
+ function cutsToLegacyMarks(cuts, tables, doc) {
57
+ const spaces = [];
58
+ const tableContinuations = [];
59
+ for (const cut of cuts) {
60
+ const pos = doc.resolve(cut.at).before(1);
61
+ const block = doc.nodeAt(pos);
62
+ if (!block) continue;
63
+ const index = pageBreaksIn(block, pos).findIndex(
64
+ (found) => found.at === cut.at
65
+ );
66
+ if (index >= 0) {
67
+ spaces.push({ pos, index, height: cut.height });
68
+ continue;
69
+ }
70
+ const headers = tables.get(pos);
71
+ if (headers) {
72
+ tableContinuations.push({ pos: cut.at, height: cut.height, ...headers });
73
+ }
74
+ }
75
+ return { spaces, tableContinuations };
76
+ }
55
77
  function usePageLayout({
56
78
  view,
57
79
  layer,
@@ -74,9 +96,14 @@ function usePageLayout({
74
96
  pageBodyHeight: page.bodyHeight,
75
97
  pageStep: page.pageStep
76
98
  });
99
+ const marks = cutsToLegacyMarks(
100
+ layout.cuts,
101
+ measured.tables,
102
+ view.state.doc
103
+ );
77
104
  setPagePushes(view, layout.pushes);
78
- setPageBreakSpaces(view, layout.spaces);
79
- setTableContinuations(view, layout.tableContinuations);
105
+ setPageBreakSpaces(view, marks.spaces);
106
+ setTableContinuations(view, marks.tableContinuations);
80
107
  const sheetHeight = measured.contentTop + layout.bodyHeight + measured.contentBottom;
81
108
  box.style.setProperty(editorCssVariables.sheetHeight, `${sheetHeight}px`);
82
109
  const next = {
@@ -137,5 +164,6 @@ function usePageLayout({
137
164
  return enabled ? overlay : null;
138
165
  }
139
166
  export {
167
+ cutsToLegacyMarks,
140
168
  usePageLayout
141
169
  };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * What each attr of the schema is for, so that a judgement about a node can say which of them it
3
+ * is judging.
4
+ *
5
+ * An attr is one of three things. A `source` attr is what the exporter writes from: the XML the
6
+ * file arrived as, or a value the model owns that replaces part of it. A `display` attr is worked
7
+ * out from the source and the formatting around it, is never written, and is free to change the
8
+ * moment the surroundings do. A `session` attr says which block, control or link of the open
9
+ * document this is, and is never written either.
10
+ *
11
+ * The split exists because a display value changing is not the document changing. Opening a file
12
+ * in the editor re-derives a table's cell borders (`table/gridBorders`), and a comparison that
13
+ * counted that as an edit would rewrite a table nobody touched, losing the markup the writer does
14
+ * not model. `./sourceEquality` leaves display attrs out for that reason, and keeps session attrs
15
+ * in: two blocks that came from different places in the file are different blocks.
16
+ *
17
+ * `attrRoles.test.ts` holds this table against the schema in both directions, so an attr added
18
+ * without a role fails there before it can reach a judgement that does not know what to do with it.
19
+ */
20
+ import { type MarkType, NodeType } from "prosemirror-model";
21
+ export type AttrRole = "source" | "display" | "session";
22
+ type AttrRoles = Readonly<Record<string, Readonly<Record<string, AttrRole>>>>;
23
+ export declare const NODE_ATTR_ROLES: AttrRoles;
24
+ export declare const MARK_ATTR_ROLES: AttrRoles;
25
+ /**
26
+ * What this attr of this node or mark is for.
27
+ *
28
+ * An attr with no role declared is read as `source`: a judgement then compares it, which is the
29
+ * answer that reports a change rather than hiding one. `attrRoles.test.ts` is what keeps the case
30
+ * from arising.
31
+ */
32
+ export declare function attrRole(type: NodeType | MarkType, name: string): AttrRole;
33
+ /** The attrs of this node or mark that are worked out rather than written */
34
+ export declare function displayAttrsOf(type: NodeType | MarkType): readonly string[];
35
+ export {};
@@ -0,0 +1,106 @@
1
+ // src/schema/attrRoles.ts
2
+ import { NodeType } from "prosemirror-model";
3
+ var NODE_ATTR_ROLES = {
4
+ paragraph: {
5
+ srcId: "session",
6
+ pAttrs: "source",
7
+ pPr: "source",
8
+ format: "display",
9
+ styleRun: "display"
10
+ },
11
+ table: {
12
+ srcId: "session",
13
+ tblAttrs: "source",
14
+ tblPr: "source",
15
+ tblW: "source",
16
+ gridCols: "source",
17
+ format: "display",
18
+ styleInside: "display",
19
+ styleCellMargins: "display"
20
+ },
21
+ tableRow: {
22
+ trAttrs: "source",
23
+ tblPrEx: "source",
24
+ trPr: "source",
25
+ format: "display"
26
+ },
27
+ tableCell: {
28
+ colspan: "source",
29
+ rowspan: "source",
30
+ // prosemirror-tables' own attr. Import writes null, the writer never reads it, and the table
31
+ // commands only carry it from one cell to another; a real column resize moves `gridCols`
32
+ colwidth: "display",
33
+ tcAttrs: "source",
34
+ tcPr: "source",
35
+ tcW: "source",
36
+ format: "display",
37
+ // Read from `sdtPrefix` rather than from the file, but a lock is not a display value: leaving
38
+ // it out of the comparison would let a step that unlocks a cell pass as a re-derivation
39
+ sdtPrefix: "source",
40
+ sdtContentsLocked: "source",
41
+ sdtDeletionLocked: "source"
42
+ },
43
+ rawBlock: { xml: "source", name: "source" },
44
+ docxRaw: { srcId: "session", name: "session" },
45
+ bookmarkBlock: { srcId: "session", name: "session" },
46
+ hardBreak: { brAttrs: "source" },
47
+ image: { src: "source", extent: "source", alt: "source", xml: "source" },
48
+ commentStart: { id: "source", xml: "source" },
49
+ commentEnd: { id: "source", xml: "source" },
50
+ commentReference: {
51
+ id: "source",
52
+ referenceXml: "source",
53
+ author: "source",
54
+ authorId: "source",
55
+ initials: "source",
56
+ date: "source",
57
+ text: "source",
58
+ commentXml: "source",
59
+ paraId: "source",
60
+ resolved: "source",
61
+ extensionXml: "source",
62
+ replies: "source",
63
+ // Read to decide whether the comment parts are rewritten at all; neither is written
64
+ imported: "session",
65
+ threadImported: "session"
66
+ },
67
+ noteReference: {
68
+ kind: "source",
69
+ id: "source",
70
+ customMarkFollows: "source",
71
+ referenceXml: "source",
72
+ // Both come from the notes part as the document was opened, and the writer puts back the
73
+ // reference alone: a note renumbered around an edit is the same reference it was
74
+ label: "display",
75
+ text: "display"
76
+ },
77
+ rawInline: { xml: "source" }
78
+ };
79
+ var MARK_ATTR_ROLES = {
80
+ run: { rPr: "source", rAttrs: "source", format: "display" },
81
+ sdt: {
82
+ sdtPrefix: "source",
83
+ // Counted through the document as it was opened, to tell one control from the next
84
+ sdtKey: "session",
85
+ contentsLocked: "source",
86
+ deletionLocked: "source"
87
+ },
88
+ link: { linkPrefix: "source", href: "source", linkKey: "session" },
89
+ tab: { tabAttrs: "source" }
90
+ };
91
+ function rolesOf(type) {
92
+ const roles = type instanceof NodeType ? NODE_ATTR_ROLES[type.name] : MARK_ATTR_ROLES[type.name];
93
+ return roles ?? {};
94
+ }
95
+ function attrRole(type, name) {
96
+ return rolesOf(type)[name] ?? "source";
97
+ }
98
+ function displayAttrsOf(type) {
99
+ return Object.entries(rolesOf(type)).filter(([, role]) => role === "display").map(([name]) => name);
100
+ }
101
+ export {
102
+ MARK_ATTR_ROLES,
103
+ NODE_ATTR_ROLES,
104
+ attrRole,
105
+ displayAttrsOf
106
+ };
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * ProseMirror schema joining preserved DOCX fragments with validated display values. Original XML
3
3
  * remains on nodes and marks so untouched content can round-trip verbatim.
4
+ *
5
+ * Every block sits in one of two groups beside `block`. A `modelled` block is one the editor
6
+ * takes apart and writes back out itself, so the writer decides what it says; a `preserved` one
7
+ * goes back out as the XML it arrived as. Which of the two a block is decides how it is written
8
+ * (`docx/serializeBlock`) and how a submitted file is compared against the original
9
+ * (`docx/storyProjection`), so a new block node has to name one of them.
4
10
  */
5
11
  import { Schema } from "prosemirror-model";
6
12
  export { imageNodeSpec, runMarkSpec } from "./rendering";