@portone/docx-editor 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/CHANGELOG.md +174 -0
  2. package/CONTRIBUTING.md +9 -1
  3. package/dist/DocxEditor.d.ts +6 -0
  4. package/dist/DocxEditor.js +12 -29
  5. package/dist/core.d.ts +23 -8
  6. package/dist/core.js +9 -4
  7. package/dist/docx/cloning.d.ts +38 -0
  8. package/dist/docx/cloning.js +74 -0
  9. package/dist/docx/commentOnlyChange.d.ts +14 -7
  10. package/dist/docx/commentOnlyChange.js +9 -139
  11. package/dist/docx/comments/constants.d.ts +3 -4
  12. package/dist/docx/comments/constants.js +4 -5
  13. package/dist/docx/comments/grammar.d.ts +86 -0
  14. package/dist/docx/comments/grammar.js +223 -0
  15. package/dist/docx/comments/parts.d.ts +52 -0
  16. package/dist/docx/comments/parts.js +279 -0
  17. package/dist/docx/comments/people.d.ts +11 -2
  18. package/dist/docx/comments/people.js +28 -106
  19. package/dist/docx/comments/policy.d.ts +7 -0
  20. package/dist/docx/comments/policy.js +43 -0
  21. package/dist/docx/comments/reading.d.ts +5 -3
  22. package/dist/docx/comments/reading.js +30 -29
  23. package/dist/docx/comments/writing.d.ts +19 -7
  24. package/dist/docx/comments/writing.js +105 -137
  25. package/dist/docx/documentSettings.d.ts +7 -0
  26. package/dist/docx/documentSettings.js +10 -2
  27. package/dist/docx/exportDocx.d.ts +40 -5
  28. package/dist/docx/exportDocx.js +71 -72
  29. package/dist/docx/exportRefs.d.ts +5 -2
  30. package/dist/docx/exportRefs.js +3 -1
  31. package/dist/docx/fidelity.d.ts +43 -0
  32. package/dist/docx/fidelity.js +64 -0
  33. package/dist/docx/formatting/attrs.d.ts +27 -0
  34. package/dist/docx/formatting/attrs.js +31 -0
  35. package/dist/docx/formatting/context.d.ts +31 -0
  36. package/dist/docx/formatting/context.js +42 -0
  37. package/dist/docx/formatting/direct.d.ts +6 -5
  38. package/dist/docx/formatting/direct.js +52 -81
  39. package/dist/docx/formatting/resolve.d.ts +45 -0
  40. package/dist/docx/formatting/resolve.js +140 -0
  41. package/dist/docx/formatting/runProperties.d.ts +93 -0
  42. package/dist/docx/formatting/runProperties.js +316 -0
  43. package/dist/docx/formatting/styles.js +3 -3
  44. package/dist/docx/formatting/tabStops.js +7 -22
  45. package/dist/docx/formatting.d.ts +4 -1
  46. package/dist/docx/formatting.js +4 -1
  47. package/dist/docx/headersFooters.js +13 -22
  48. package/dist/docx/identities.d.ts +67 -0
  49. package/dist/docx/identities.js +174 -0
  50. package/dist/docx/importDocx.d.ts +12 -1
  51. package/dist/docx/importDocx.js +72 -79
  52. package/dist/docx/importParagraph.d.ts +1 -1
  53. package/dist/docx/importParagraph.js +4 -3
  54. package/dist/docx/importTable.d.ts +1 -1
  55. package/dist/docx/importTable.js +17 -1
  56. package/dist/docx/invariants.d.ts +33 -0
  57. package/dist/docx/invariants.js +256 -0
  58. package/dist/docx/media.d.ts +6 -4
  59. package/dist/docx/media.js +6 -37
  60. package/dist/docx/newLists.d.ts +20 -0
  61. package/dist/docx/newLists.js +36 -0
  62. package/dist/docx/notes.js +6 -12
  63. package/dist/docx/numberingPlanner.d.ts +8 -0
  64. package/dist/docx/numberingPlanner.js +19 -0
  65. package/dist/docx/packageParts.d.ts +42 -0
  66. package/dist/docx/packageParts.js +135 -0
  67. package/dist/docx/pageGeometry.d.ts +2 -0
  68. package/dist/docx/pageGeometry.js +18 -9
  69. package/dist/docx/paraProps.d.ts +10 -22
  70. package/dist/docx/paraProps.js +75 -99
  71. package/dist/docx/partPlan.d.ts +36 -0
  72. package/dist/docx/partPlan.js +59 -0
  73. package/dist/docx/protectionPolicy.d.ts +127 -0
  74. package/dist/docx/protectionPolicy.js +169 -0
  75. package/dist/docx/relationships.d.ts +1 -1
  76. package/dist/docx/relationships.js +15 -15
  77. package/dist/docx/runProps.d.ts +9 -22
  78. package/dist/docx/runProps.js +15 -168
  79. package/dist/docx/scan.js +20 -52
  80. package/dist/docx/sdt.js +14 -37
  81. package/dist/docx/sdtProps.d.ts +8 -1
  82. package/dist/docx/sdtProps.js +10 -0
  83. package/dist/docx/serializeBlock.d.ts +2 -0
  84. package/dist/docx/serializeBlock.js +9 -7
  85. package/dist/docx/serializeParagraph.d.ts +2 -1
  86. package/dist/docx/serializeParagraph.js +25 -14
  87. package/dist/docx/serializeTable.js +63 -32
  88. package/dist/docx/session.d.ts +42 -14
  89. package/dist/docx/session.js +43 -17
  90. package/dist/docx/storyProjection.d.ts +36 -0
  91. package/dist/docx/storyProjection.js +23 -0
  92. package/dist/docx/tableFormatting/editing.js +130 -185
  93. package/dist/docx/tableFormatting/reading.d.ts +16 -6
  94. package/dist/docx/tableFormatting/reading.js +40 -20
  95. package/dist/docx/tableTemplate.js +37 -5
  96. package/dist/docx/theme.d.ts +0 -6
  97. package/dist/docx/theme.js +0 -8
  98. package/dist/download.d.ts +8 -5
  99. package/dist/download.js +2 -0
  100. package/dist/editor/clipboard/images.js +17 -3
  101. package/dist/editor/clipboard/inlineFormatting.d.ts +7 -0
  102. package/dist/editor/clipboard/inlineFormatting.js +20 -30
  103. package/dist/editor/commands/breakCommands.js +4 -3
  104. package/dist/editor/commands/canRunCommand.d.ts +2 -2
  105. package/dist/editor/commands/canRunCommand.js +1 -1
  106. package/dist/editor/commands/comments/editing.d.ts +6 -2
  107. package/dist/editor/commands/comments/editing.js +21 -36
  108. package/dist/editor/commands/exportQueries.d.ts +15 -0
  109. package/dist/editor/commands/exportQueries.js +14 -0
  110. package/dist/editor/commands/fidelityQueries.d.ts +12 -0
  111. package/dist/editor/commands/fidelityQueries.js +8 -0
  112. package/dist/editor/commands/formatting/editing.d.ts +2 -2
  113. package/dist/editor/commands/formatting/editing.js +26 -108
  114. package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
  115. package/dist/editor/commands/formatting/propertyCommands.js +103 -0
  116. package/dist/editor/commands/formatting/shared.d.ts +3 -3
  117. package/dist/editor/commands/formatting/shared.js +5 -2
  118. package/dist/editor/commands/historyCommands.js +2 -1
  119. package/dist/editor/commands/indentCommands.js +5 -4
  120. package/dist/editor/commands/index.d.ts +11 -0
  121. package/dist/editor/commands/index.js +5 -0
  122. package/dist/editor/commands/linkCommands.js +5 -6
  123. package/dist/editor/commands/listCommands.js +8 -10
  124. package/dist/editor/commands/lockCommands.d.ts +7 -1
  125. package/dist/editor/commands/lockCommands.js +35 -37
  126. package/dist/editor/commands/paragraphCommands.js +28 -31
  127. package/dist/editor/commands/spacingCommands.js +1 -1
  128. package/dist/editor/commands/tabCommands.js +4 -3
  129. package/dist/editor/createEditor.d.ts +17 -29
  130. package/dist/editor/createEditor.js +61 -67
  131. package/dist/editor/documentStyles.d.ts +11 -35
  132. package/dist/editor/documentStyles.js +9 -52
  133. package/dist/editor/editorDocument.d.ts +56 -0
  134. package/dist/editor/editorDocument.js +74 -0
  135. package/dist/editor/externalClipboard.js +166 -33
  136. package/dist/editor/insertImage.js +4 -3
  137. package/dist/editor/insertTable.js +4 -3
  138. package/dist/editor/paragraphEdits.d.ts +11 -18
  139. package/dist/editor/paragraphEdits.js +7 -16
  140. package/dist/editor/plugins/displayDerivation.d.ts +47 -0
  141. package/dist/editor/plugins/displayDerivation.js +78 -0
  142. package/dist/editor/plugins/documentProtection.d.ts +3 -3
  143. package/dist/editor/plugins/imagePaste.js +4 -3
  144. package/dist/editor/plugins/keymap.js +18 -3
  145. package/dist/editor/plugins/lockedContent.d.ts +4 -4
  146. package/dist/editor/plugins/lockedContent.js +1 -1
  147. package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
  148. package/dist/editor/plugins/numberingDecorations.js +7 -17
  149. package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
  150. package/dist/editor/plugins/paragraphDisplay.js +51 -0
  151. package/dist/editor/plugins/tabLayout.js +1 -1
  152. package/dist/editor/plugins/tableDisplay.d.ts +6 -0
  153. package/dist/editor/plugins/tableDisplay.js +16 -0
  154. package/dist/index.d.ts +2 -0
  155. package/dist/model/format.d.ts +30 -8
  156. package/dist/model/format.js +35 -22
  157. package/dist/model/tabStops.d.ts +9 -0
  158. package/dist/model/tabStops.js +18 -0
  159. package/dist/numbering/listTemplate.js +49 -10
  160. package/dist/numbering/parseNumbering.d.ts +14 -1
  161. package/dist/numbering/parseNumbering.js +35 -22
  162. package/dist/numbering/writeNumbering.d.ts +3 -4
  163. package/dist/numbering/writeNumbering.js +14 -25
  164. package/dist/ooxml/childOrder.d.ts +34 -0
  165. package/dist/ooxml/childOrder.js +496 -0
  166. package/dist/ooxml/element.d.ts +65 -0
  167. package/dist/ooxml/element.js +68 -0
  168. package/dist/ooxml/errors.d.ts +3 -2
  169. package/dist/ooxml/fragment.d.ts +53 -0
  170. package/dist/ooxml/fragment.js +76 -0
  171. package/dist/ooxml/image.d.ts +4 -0
  172. package/dist/ooxml/image.js +3 -5
  173. package/dist/ooxml/names.d.ts +27 -0
  174. package/dist/ooxml/names.js +29 -0
  175. package/dist/ooxml/partSplice.d.ts +67 -0
  176. package/dist/ooxml/partSplice.js +169 -0
  177. package/dist/ooxml/precedence.d.ts +31 -0
  178. package/dist/ooxml/precedence.js +51 -0
  179. package/dist/ooxml/props.d.ts +112 -0
  180. package/dist/ooxml/props.js +214 -0
  181. package/dist/ooxml/simpleTypes.d.ts +103 -0
  182. package/dist/ooxml/simpleTypes.js +182 -0
  183. package/dist/ooxml/tabStops.js +8 -27
  184. package/dist/ooxml/tagScan.d.ts +34 -0
  185. package/dist/ooxml/tagScan.js +108 -0
  186. package/dist/ooxml/units.d.ts +25 -13
  187. package/dist/ooxml/units.js +65 -31
  188. package/dist/ooxml/xml.d.ts +52 -0
  189. package/dist/ooxml/xml.js +64 -5
  190. package/dist/page/blockKinds.d.ts +103 -0
  191. package/dist/page/blockKinds.js +11 -0
  192. package/dist/page/kinds/index.d.ts +6 -0
  193. package/dist/page/kinds/index.js +10 -0
  194. package/dist/page/kinds/paragraphKind.d.ts +10 -0
  195. package/dist/page/kinds/paragraphKind.js +71 -0
  196. package/dist/page/kinds/tableKind.d.ts +10 -0
  197. package/dist/page/kinds/tableKind.js +178 -0
  198. package/dist/page/measureBlocks.d.ts +3 -1
  199. package/dist/page/measureBlocks.js +24 -25
  200. package/dist/page/pageDecorations.d.ts +27 -28
  201. package/dist/page/pageDecorations.js +70 -151
  202. package/dist/page/pageLayout.d.ts +10 -62
  203. package/dist/page/pageLayout.js +60 -53
  204. package/dist/page/usePageLayout.d.ts +2 -2
  205. package/dist/page/usePageLayout.js +3 -11
  206. package/dist/schema/attrRoles.d.ts +42 -0
  207. package/dist/schema/attrRoles.js +141 -0
  208. package/dist/schema/displayDerivation.d.ts +82 -0
  209. package/dist/schema/displayDerivation.js +130 -0
  210. package/dist/schema/docxSchema.d.ts +9 -0
  211. package/dist/schema/docxSchema.js +237 -114
  212. package/dist/schema/editGuard.d.ts +99 -0
  213. package/dist/schema/editGuard.js +43 -0
  214. package/dist/schema/guards.d.ts +91 -0
  215. package/dist/schema/guards.js +108 -0
  216. package/dist/schema/index.d.ts +2 -0
  217. package/dist/schema/index.js +2 -0
  218. package/dist/schema/locks.d.ts +17 -77
  219. package/dist/schema/locks.js +26 -70
  220. package/dist/schema/preservedGuards.d.ts +50 -0
  221. package/dist/schema/preservedGuards.js +80 -0
  222. package/dist/schema/protection.d.ts +17 -4
  223. package/dist/schema/protection.js +4 -2
  224. package/dist/schema/sourceEquality.d.ts +19 -0
  225. package/dist/schema/sourceEquality.js +39 -0
  226. package/dist/styles/inlineStyle.js +15 -6
  227. package/dist/table/cellFormatting.d.ts +8 -1
  228. package/dist/table/cellFormatting.js +10 -17
  229. package/dist/table/commands.d.ts +2 -2
  230. package/dist/table/commands.js +20 -18
  231. package/dist/table/format.d.ts +3 -0
  232. package/dist/table/format.js +3 -9
  233. package/dist/table/gridBorders.d.ts +14 -16
  234. package/dist/table/gridBorders.js +3 -41
  235. package/dist/table/index.d.ts +2 -2
  236. package/dist/table/merge.d.ts +4 -8
  237. package/dist/table/merge.js +5 -5
  238. package/package.json +10 -3
  239. package/dist/docx/comments/contentTypes.d.ts +0 -7
  240. package/dist/docx/comments/contentTypes.js +0 -38
  241. package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
  242. package/dist/docx/formatting/effectiveParagraph.js +0 -81
  243. package/dist/docx/propsXml.d.ts +0 -49
  244. package/dist/docx/propsXml.js +0 -302
  245. package/dist/docx/uniqueControls.d.ts +0 -14
  246. package/dist/docx/uniqueControls.js +0 -62
  247. package/dist/editor/plugins/bookmarkProtection.d.ts +0 -3
  248. package/dist/editor/plugins/bookmarkProtection.js +0 -28
  249. package/dist/editor/plugins/commentReservations.d.ts +0 -5
  250. package/dist/editor/plugins/commentReservations.js +0 -26
  251. package/dist/editor/plugins/noteProtection.d.ts +0 -3
  252. package/dist/editor/plugins/noteProtection.js +0 -25
  253. package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
  254. package/dist/editor/plugins/styledParagraphs.js +0 -65
  255. package/dist/page/tableMeasurements.d.ts +0 -10
  256. package/dist/page/tableMeasurements.js +0 -115
@@ -0,0 +1,74 @@
1
+ // src/editor/editorDocument.ts
2
+ import { Plugin, PluginKey } from "prosemirror-state";
3
+ import { DEFAULT_TAB_STOP_PT } from "../docx/documentSettings.js";
4
+ import {
5
+ NO_DOCUMENT_DEFAULTS,
6
+ NO_FORMATTING
7
+ } from "../docx/formatting.js";
8
+ import { A4_PORTRAIT } from "../docx/pageGeometry.js";
9
+ var NO_IDS = /* @__PURE__ */ new Set();
10
+ var NO_PARAGRAPH_STYLES = [];
11
+ var NO_DOCUMENT = {
12
+ session: null,
13
+ formatting: NO_FORMATTING,
14
+ defaults: NO_DOCUMENT_DEFAULTS,
15
+ paragraphStyles: NO_PARAGRAPH_STYLES,
16
+ canStartNewList: true,
17
+ geometry: A4_PORTRAIT,
18
+ defaultTabStopPt: DEFAULT_TAB_STOP_PT,
19
+ reservedCommentIds: NO_IDS,
20
+ reservedCommentParaIds: NO_IDS
21
+ };
22
+ function reservedParaIds(session) {
23
+ const paraIds = /* @__PURE__ */ new Set();
24
+ for (const comment of session.comments.ordered) {
25
+ if (comment.paraId !== null) paraIds.add(comment.paraId);
26
+ }
27
+ for (const extension of session.comments.extendedOrdered) {
28
+ paraIds.add(extension.paraId);
29
+ }
30
+ return paraIds;
31
+ }
32
+ function editorDocumentOf(session) {
33
+ return {
34
+ session,
35
+ formatting: session.formatting,
36
+ defaults: session.defaults,
37
+ paragraphStyles: session.paragraphStyles,
38
+ canStartNewList: session.numberingPartPath !== null,
39
+ geometry: session.geometry,
40
+ defaultTabStopPt: session.defaultTabStopPt,
41
+ reservedCommentIds: new Set(session.comments.byId.keys()),
42
+ reservedCommentParaIds: reservedParaIds(session)
43
+ };
44
+ }
45
+ var editorDocumentKey = new PluginKey("docxEditorDocument");
46
+ function documentOf(state) {
47
+ return editorDocumentKey.getState(state) ?? NO_DOCUMENT;
48
+ }
49
+ function derive(session, _doc) {
50
+ return editorDocumentOf(session);
51
+ }
52
+ function editorDocument(document) {
53
+ return new Plugin({
54
+ key: editorDocumentKey,
55
+ state: {
56
+ init: () => document,
57
+ apply: (tr, current, old) => current.session === null || tr.doc.attrs === old.doc.attrs ? current : derive(current.session, tr.doc)
58
+ }
59
+ });
60
+ }
61
+ function reservedCommentIds(state) {
62
+ return documentOf(state).reservedCommentIds;
63
+ }
64
+ function reservedCommentParaIds(state) {
65
+ return documentOf(state).reservedCommentParaIds;
66
+ }
67
+ export {
68
+ NO_DOCUMENT,
69
+ documentOf,
70
+ editorDocument,
71
+ editorDocumentOf,
72
+ reservedCommentIds,
73
+ reservedCommentParaIds
74
+ };
@@ -1,25 +1,28 @@
1
1
  // src/editor/externalClipboard.ts
2
- import { Fragment, Slice } from "prosemirror-model";
2
+ import {
3
+ DOMSerializer,
4
+ Fragment,
5
+ Slice
6
+ } from "prosemirror-model";
3
7
  import { Plugin } from "prosemirror-state";
4
- import { effectiveParagraphFormat, styleIdOf } from "../docx/formatting.js";
5
- import { withParagraphStyle } from "../docx/paraProps.js";
8
+ import { paragraphAttrsFor, styleIdOf } from "../docx/formatting.js";
9
+ import {
10
+ withListNumbering,
11
+ withParagraphStyle
12
+ } from "../docx/paraProps.js";
6
13
  import { MAX_ILVL, nextNumId } from "../numbering/listTemplate.js";
7
- import { docxSchema } from "../schema/index.js";
14
+ import { docxSchema, isPageBreak } from "../schema/index.js";
8
15
  import { editorClassNames } from "../styles/classNames.js";
9
16
  import { PASTED_IMAGE_ATTRIBUTE } from "./clipboard/images.js";
10
17
  import {
11
18
  appendInline,
12
19
  contextFor,
13
20
  marksFor,
21
+ safeHref,
14
22
  withInlineStyle
15
23
  } from "./clipboard/inlineFormatting.js";
16
24
  import { listRefOf } from "./commands/listCommands.js";
17
- import {
18
- defaultParagraphStyleId,
19
- documentParagraphFormatting,
20
- documentParagraphStyles,
21
- documentStyles
22
- } from "./documentStyles.js";
25
+ import { documentFormatting, documentParagraphStyles } from "./documentStyles.js";
23
26
  import { insertPlainText } from "./plainText.js";
24
27
  import { moveCaretToDrop } from "./plugins/dropCaret.js";
25
28
  import {
@@ -59,11 +62,149 @@ var HEADING_FALLBACKS = {
59
62
  5: { bold: true, fontSizePt: 10 },
60
63
  6: { bold: true, fontSizePt: 8 }
61
64
  };
65
+ var PUBLIC_ATTRIBUTES = /* @__PURE__ */ new Set([
66
+ "alt",
67
+ "aria-label",
68
+ "class",
69
+ "colspan",
70
+ "height",
71
+ "href",
72
+ "lang",
73
+ "rowspan",
74
+ "src",
75
+ "style",
76
+ "width"
77
+ ]);
78
+ var COPIED_STYLE_ATTRIBUTE = "data-style";
79
+ function isAttributes(value) {
80
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Node);
81
+ }
82
+ function publicAttributes(attrs) {
83
+ return Object.fromEntries(
84
+ Object.entries(attrs).filter(([name]) => PUBLIC_ATTRIBUTES.has(name))
85
+ );
86
+ }
87
+ function isSpecArray(value) {
88
+ return Array.isArray(value) && typeof value[0] === "string";
89
+ }
90
+ function stripPrivateAttributes(spec) {
91
+ if (!isSpecArray(spec)) return spec;
92
+ const [tag, ...rest] = spec;
93
+ const attrs = isAttributes(rest[0]) ? publicAttributes(rest[0]) : null;
94
+ const children = (attrs === null ? rest : rest.slice(1)).map(
95
+ (child) => isSpecArray(child) ? stripPrivateAttributes(child) : child
96
+ );
97
+ return attrs === null ? [tag, ...children] : [tag, attrs, ...children];
98
+ }
99
+ function withDomAttribute(spec, name, value) {
100
+ if (!isSpecArray(spec)) return spec;
101
+ const [tag, ...rest] = spec;
102
+ return isAttributes(rest[0]) ? [tag, { ...rest[0], [name]: value }, ...rest.slice(1)] : [tag, { [name]: value }, ...rest];
103
+ }
104
+ function asTag(spec, tag) {
105
+ return isSpecArray(spec) ? [tag, ...spec.slice(1)] : spec;
106
+ }
107
+ function copiedMarkSpec(mark, spec) {
108
+ const stripped = stripPrivateAttributes(spec);
109
+ if (mark.type !== docxSchema.marks.link) return stripped;
110
+ const href = safeHref(
111
+ typeof mark.attrs.href === "string" ? mark.attrs.href : null
112
+ );
113
+ return href === null ? stripped : asTag(withDomAttribute(stripped, "href", href), "a");
114
+ }
115
+ function copiedNodeSpec(node, spec) {
116
+ const stripped = stripPrivateAttributes(spec);
117
+ if (node.type !== docxSchema.nodes.paragraph) return stripped;
118
+ const styleId = styleIdOf(node.attrs.pPr);
119
+ return styleId === null ? stripped : withDomAttribute(stripped, COPIED_STYLE_ATTRIBUTE, styleId);
120
+ }
121
+ function clipboardSerializer() {
122
+ const drawn = DOMSerializer.fromSchema(docxSchema);
123
+ const nodes = Object.fromEntries(
124
+ Object.entries(drawn.nodes).map(([name, toDOM]) => [
125
+ name,
126
+ (node) => copiedNodeSpec(node, toDOM(node))
127
+ ])
128
+ );
129
+ const marks = Object.fromEntries(
130
+ Object.entries(drawn.marks).map(([name, toDOM]) => [
131
+ name,
132
+ (mark, inline) => copiedMarkSpec(mark, toDOM(mark, inline))
133
+ ])
134
+ );
135
+ return new DOMSerializer(nodes, marks);
136
+ }
137
+ var UNREADABLE_BLOCKS = /* @__PURE__ */ new Set([
138
+ "bookmarkBlock",
139
+ "docxRaw",
140
+ "rawBlock"
141
+ ]);
142
+ function stringAttr(value) {
143
+ return typeof value === "string" ? value : "";
144
+ }
145
+ function inlineText(node) {
146
+ if (node.isText) return node.text ?? "";
147
+ if (node.type === docxSchema.nodes.hardBreak) {
148
+ return isPageBreak(node.attrs.brAttrs) ? "\f" : "\n";
149
+ }
150
+ if (node.type === docxSchema.nodes.image) return stringAttr(node.attrs.alt);
151
+ if (node.type === docxSchema.nodes.noteReference) {
152
+ return node.attrs.customMarkFollows === true ? "" : stringAttr(node.attrs.label);
153
+ }
154
+ return "";
155
+ }
156
+ function rowsText(table) {
157
+ const rows = [];
158
+ table.forEach((row) => {
159
+ const cells = [];
160
+ row.forEach((cell) => {
161
+ cells.push(fragmentText(cell.content));
162
+ });
163
+ rows.push(cells.join(" "));
164
+ });
165
+ return rows.join("\n");
166
+ }
167
+ function blockText(node) {
168
+ if (node.type === docxSchema.nodes.table) return rowsText(node);
169
+ if (UNREADABLE_BLOCKS.has(node.type.name)) return "";
170
+ return fragmentText(node.content);
171
+ }
172
+ function fragmentText(fragment) {
173
+ const pieces = [];
174
+ fragment.forEach((child) => {
175
+ pieces.push(child.isInline ? inlineText(child) : blockText(child));
176
+ });
177
+ return pieces.join(fragment.firstChild?.isInline === true ? "" : "\n");
178
+ }
179
+ function bareWrappers(content, openStart, openEnd) {
180
+ const wrapper = content.firstChild;
181
+ if (openStart <= 1 || openEnd <= 1 || content.childCount !== 1)
182
+ return content;
183
+ if (wrapper === null || wrapper.childCount !== 1) return content;
184
+ return Fragment.from(
185
+ wrapper.type.create(
186
+ null,
187
+ bareWrappers(wrapper.content, openStart - 1, openEnd - 1),
188
+ wrapper.marks
189
+ )
190
+ );
191
+ }
192
+ function copiedSlice(slice) {
193
+ return new Slice(
194
+ bareWrappers(slice.content, slice.openStart, slice.openEnd),
195
+ slice.openStart,
196
+ slice.openEnd
197
+ );
198
+ }
199
+ function clipboardText(slice) {
200
+ return fragmentText(slice.content);
201
+ }
62
202
  function normalizedStyleName(value) {
63
203
  return value.toLowerCase().replace(/[\s_-]+/g, "");
64
204
  }
65
205
  function copiedStyleId(element) {
66
- return element.classList.contains(editorClassNames.paragraph) ? styleIdOf(element.getAttribute("data-ppr")) : null;
206
+ if (!element.classList.contains(editorClassNames.paragraph)) return null;
207
+ return element.getAttribute(COPIED_STYLE_ATTRIBUTE) ?? styleIdOf(element.getAttribute("data-ppr"));
67
208
  }
68
209
  function headingLevel(element, sourceStyleId) {
69
210
  const direct = HEADING_LEVELS[element.tagName];
@@ -97,12 +238,7 @@ function blockContext(state, parent, element, preserveParagraphStyle) {
97
238
  };
98
239
  }
99
240
  const styleId = destinationStyleId(state, sourceStyleId, level);
100
- const paragraph = styleId === null ? null : withParagraphStyle(
101
- null,
102
- styleId,
103
- documentStyles(state),
104
- defaultParagraphStyleId(state)
105
- );
241
+ const paragraph = styleId === null ? null : withParagraphStyle(null, styleId);
106
242
  const usesDestinationStyle = editorParagraph && (sourceStyleId === null || paragraph !== null);
107
243
  let inline = parent;
108
244
  if (paragraph === null && level !== null) {
@@ -113,25 +249,18 @@ function blockContext(state, parent, element, preserveParagraphStyle) {
113
249
  paragraph
114
250
  };
115
251
  }
116
- function listParagraphAttrs(state, list) {
252
+ function listParagraphProps(list) {
117
253
  if (!list || list.numId === null) return null;
118
- const ilvl = Math.min(MAX_ILVL, list.level);
119
- const pPr = `<w:pPr><w:numPr><w:ilvl w:val="${ilvl}"/><w:numId w:val="${list.numId}"/></w:numPr></w:pPr>`;
120
- return {
121
- pPr,
122
- format: effectiveParagraphFormat(pPr, documentParagraphFormatting(state))
123
- };
254
+ return withListNumbering(null, {
255
+ numbering: { numId: list.numId, ilvl: Math.min(MAX_ILVL, list.level) },
256
+ indent: { kind: "keep" }
257
+ });
124
258
  }
125
259
  function paragraphAttrs(state, list, paragraph) {
126
- const listed = listParagraphAttrs(state, list);
127
- if (listed) return listed;
128
- return paragraph ? {
129
- pPr: paragraph.pPr,
130
- format: effectiveParagraphFormat(
131
- paragraph.pPr,
132
- documentParagraphFormatting(state)
133
- ),
134
- styleRun: paragraph.styleRun
260
+ const props = listParagraphProps(list) ?? paragraph;
261
+ return props ? {
262
+ pPr: props.pPr,
263
+ ...paragraphAttrsFor(props.pPr, documentFormatting(state))
135
264
  } : null;
136
265
  }
137
266
  function usedNumIds(state) {
@@ -294,8 +423,12 @@ function insertClipboardData(view, data) {
294
423
  insertPlainText(view, data.text ?? "");
295
424
  }
296
425
  function externalClipboard() {
426
+ const serializer = clipboardSerializer();
297
427
  return new Plugin({
298
428
  props: {
429
+ clipboardSerializer: serializer,
430
+ clipboardTextSerializer: clipboardText,
431
+ transformCopied: copiedSlice,
299
432
  handlePaste(view, event) {
300
433
  insertClipboardData(view, {
301
434
  html: event.clipboardData?.getData("text/html"),
@@ -2,10 +2,11 @@
2
2
  import { insertPoint } from "prosemirror-transform";
3
3
  import { toImageExtent, toImageSrc } from "../ooxml/image.js";
4
4
  import { docxSchema } from "../schema/index.js";
5
- import { replacementShut } from "../schema/locks.js";
6
- import { editsShut } from "../schema/protectionState.js";
5
+ import { editShut, selectionIntents } from "../schema/guards.js";
7
6
  function insertPosition(state) {
8
- if (editsShut(state) || replacementShut(state.selection, state.doc)) {
7
+ if (selectionIntents(state.selection, "replace").some(
8
+ (intent) => editShut(state, intent)
9
+ )) {
9
10
  return null;
10
11
  }
11
12
  return insertPoint(state.doc, state.selection.from, docxSchema.nodes.image);
@@ -4,7 +4,7 @@ import {
4
4
  TextSelection
5
5
  } from "prosemirror-state";
6
6
  import { createTableNode, isTableSide } from "../docx/tableTemplate.js";
7
- import { editsShut } from "../schema/protectionState.js";
7
+ import { editShut } from "../schema/guards.js";
8
8
  import { documentGeometry } from "./documentStyles.js";
9
9
  function isInTable($pos) {
10
10
  for (let depth = $pos.depth; depth > 0; depth -= 1) {
@@ -14,8 +14,9 @@ function isInTable($pos) {
14
14
  }
15
15
  function insertPosition(state) {
16
16
  const $from = state.selection.$from;
17
- if (editsShut(state) || $from.depth === 0 || isInTable($from)) return null;
18
- return $from.after(1);
17
+ if ($from.depth === 0 || isInTable($from)) return null;
18
+ const at = $from.after(1);
19
+ return editShut(state, { kind: "insert", at }) ? null : at;
19
20
  }
20
21
  function canInsertTable(state) {
21
22
  return insertPosition(state) !== null;
@@ -8,7 +8,6 @@
8
8
  */
9
9
  import type { Node as PMNode } from "prosemirror-model";
10
10
  import type { EditorState, Transaction } from "prosemirror-state";
11
- import { type StyleTable } from "../docx/formatting";
12
11
  import type { ParagraphProps } from "../docx/paraProps";
13
12
  export interface ParagraphSpot {
14
13
  pos: number;
@@ -17,28 +16,22 @@ export interface ParagraphSpot {
17
16
  /** The paragraphs the selection spans. Selections covering several table cells are handled too */
18
17
  export declare function selectedParagraphs(state: EditorState): ParagraphSpot[];
19
18
  /**
20
- * The selected paragraphs a lock leaves editable, which is what every paragraph edit works on.
19
+ * The selected paragraphs the guards leave editable, which is what every paragraph edit works on.
21
20
  *
22
- * A locked stretch is left out rather than the whole edit refused, the policy character formatting
23
- * already follows (`commands/formattingCommands`): the guard turns down a whole transaction, so
24
- * asking for it would leave the rest of the selection unedited too. A selection the lock leaves
25
- * nothing of edits nothing, and the command reports that of its own accord, which is the disabled
26
- * state of the control that runs it.
21
+ * A shut paragraph is left out rather than the whole edit refused, the policy character formatting
22
+ * already follows (`schema/guards`): the guard turns down a whole transaction, so asking for it
23
+ * would leave the rest of the selection unedited too. A selection the guards leave nothing of edits
24
+ * nothing, and the command reports that of its own accord, which is the disabled state of the
25
+ * control that runs it.
27
26
  *
28
- * Only the paragraphs of a locked cell are shut. A paragraph merely holding a locked control keeps
29
- * its own alignment, indent and style, which is what `insideLockedCell` says and
30
- * `rangeTouchesLocked` would not (`schema/locks`).
31
- *
32
- * A protection that shuts the body leaves no paragraph editable (`schema/protection`).
27
+ * A paragraph is rewritten around its content, which is the block intent: only the paragraphs of a
28
+ * locked cell are shut, and a paragraph merely holding a locked control keeps its own alignment,
29
+ * indent and style. A protection that shuts the body shuts every one of them.
33
30
  */
34
31
  export declare function editableParagraphs(state: EditorState): ParagraphSpot[];
35
32
  /** The original formatting XML this paragraph holds. Null when there is none */
36
33
  export declare function paragraphPPr(node: PMNode): string | null;
37
- /**
38
- * How to edit a single paragraph. Null skips that paragraph.
39
- * The style table and the document's default paragraph style come along, because the display values
40
- * of the edited fragment are read back with the style the paragraph wears laid underneath.
41
- */
42
- export type ParagraphSurgery = (node: PMNode, styles: StyleTable, defaultStyleId: string | null) => ParagraphProps | null;
34
+ /** How to edit a single paragraph. Null skips that paragraph */
35
+ export type ParagraphSurgery = (node: PMNode) => ParagraphProps | null;
43
36
  /** Edits the selected paragraphs in a single transaction. Does nothing when there is nothing to edit */
44
37
  export declare function editParagraphs(state: EditorState, dispatch: ((tr: Transaction) => void) | undefined, surgery: ParagraphSurgery): boolean;
@@ -1,13 +1,8 @@
1
1
  // src/editor/paragraphEdits.ts
2
- import { effectiveParagraphFormat } from "../docx/formatting.js";
2
+ import { paragraphAttrsFor } from "../docx/formatting.js";
3
3
  import { docxSchema } from "../schema/index.js";
4
- import { insideLockedCell } from "../schema/locks.js";
5
- import { editsShut } from "../schema/protectionState.js";
6
- import {
7
- defaultParagraphStyleId,
8
- documentParagraphFormatting,
9
- documentStyles
10
- } from "./documentStyles.js";
4
+ import { editShut } from "../schema/guards.js";
5
+ import { documentFormatting } from "./documentStyles.js";
11
6
  function selectedParagraphs(state) {
12
7
  const spots = /* @__PURE__ */ new Map();
13
8
  for (const range of state.selection.ranges) {
@@ -20,9 +15,8 @@ function selectedParagraphs(state) {
20
15
  return Array.from(spots, ([pos, node]) => ({ pos, node }));
21
16
  }
22
17
  function editableParagraphs(state) {
23
- if (editsShut(state)) return [];
24
18
  return selectedParagraphs(state).filter(
25
- (spot) => !insideLockedCell(state.doc, spot.pos)
19
+ (spot) => !editShut(state, { kind: "block", at: spot.pos })
26
20
  );
27
21
  }
28
22
  function paragraphPPr(node) {
@@ -31,22 +25,19 @@ function paragraphPPr(node) {
31
25
  }
32
26
  function writeChanges(state, changed) {
33
27
  const tr = state.tr;
34
- const formatting = documentParagraphFormatting(state);
28
+ const formatting = documentFormatting(state);
35
29
  for (const { spot, props } of changed) {
36
30
  tr.setNodeMarkup(tr.mapping.map(spot.pos), void 0, {
37
31
  ...spot.node.attrs,
38
32
  pPr: props.pPr,
39
- format: effectiveParagraphFormat(props.pPr, formatting),
40
- styleRun: props.styleRun
33
+ ...paragraphAttrsFor(props.pPr, formatting)
41
34
  });
42
35
  }
43
36
  return tr;
44
37
  }
45
38
  function editParagraphs(state, dispatch, surgery) {
46
- const styles = documentStyles(state);
47
- const defaultStyleId = defaultParagraphStyleId(state);
48
39
  const changed = editableParagraphs(state).flatMap((spot) => {
49
- const props = surgery(spot.node, styles, defaultStyleId);
40
+ const props = surgery(spot.node);
50
41
  return props ? [{ spot, props }] : [];
51
42
  });
52
43
  if (changed.length === 0) return false;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Keeps every display value of the document current: the ones an edit moved, after that edit, and
3
+ * every one at once when the document snapshot the values are resolved against is replaced.
4
+ *
5
+ * The derivers are registered here and run through the one walk `schema/displayDerivation`
6
+ * defines. What a node maps back to is settled here as well, from the mapping of the transactions
7
+ * that changed the document: a node whose content survived those transactions is the node that
8
+ * stood where its opening maps back to, and one whose content did not is new. A node rewritten
9
+ * where it stands (`setNodeMarkup`) therefore still maps back to itself, which is what lets a
10
+ * table resized or a paragraph re-aligned be told from a table or a paragraph put in.
11
+ *
12
+ * The transaction this appends carries the display-only pass (`schema/guards`), since it changes
13
+ * nothing a lock or a protection answers for, and goes to the history as part of the edit it
14
+ * follows, so that one undo takes the edit and its values back together. The re-derivation after
15
+ * a snapshot change follows no edit and goes to the history not at all: the values follow the
16
+ * snapshot, and undoing whatever replaced the snapshot derives them again.
17
+ */
18
+ import type { Node as PMNode } from "prosemirror-model";
19
+ import { Plugin } from "prosemirror-state";
20
+ import { type DisplayDeriver } from "../../schema/displayDerivation";
21
+ import { type EditorDocument } from "../editorDocument";
22
+ /** What a deriver of this editor resolves against */
23
+ export interface DerivationContext {
24
+ readonly document: EditorDocument;
25
+ /**
26
+ * Where the composition the browser holds open stands, which a deriver leaves alone: rewriting
27
+ * the node it stands in redraws it, and a redraw under an open composition is what the browser
28
+ * answers by taking the composition down. Null while nothing is being composed, and while every
29
+ * value is being worked out again from nothing, when nothing may be left standing.
30
+ */
31
+ readonly composingAt: number | null;
32
+ }
33
+ export type DocumentDeriver = DisplayDeriver<DerivationContext>;
34
+ export declare const DISPLAY_DERIVERS: readonly DocumentDeriver[];
35
+ /**
36
+ * The document with every display value worked out against this snapshot, which is what a state
37
+ * is built over: the values a document arrived with were worked out against whatever opened it.
38
+ */
39
+ export declare function withDerivedDisplay(doc: PMNode, document: EditorDocument, derivers?: readonly DocumentDeriver[]): PMNode;
40
+ /**
41
+ * Derives the display values again after every change: for the nodes an edit moved, and for every
42
+ * node when the snapshot was replaced.
43
+ *
44
+ * An appended transaction is handed nothing but states, so the view an open composition is read
45
+ * from is the one the plugin is given when it mounts.
46
+ */
47
+ export declare function displayDerivation(derivers?: readonly DocumentDeriver[]): Plugin;
@@ -0,0 +1,78 @@
1
+ // src/editor/plugins/displayDerivation.ts
2
+ import { Plugin } from "prosemirror-state";
3
+ import { Mapping, Transform } from "prosemirror-transform";
4
+ import {
5
+ deriveDisplay,
6
+ displayOnly
7
+ } from "../../schema/displayDerivation.js";
8
+ import { documentOf } from "../editorDocument.js";
9
+ import { paragraphDisplay } from "./paragraphDisplay.js";
10
+ import { tableDisplay } from "./tableDisplay.js";
11
+ var DISPLAY_DERIVERS = [
12
+ tableDisplay,
13
+ paragraphDisplay
14
+ ];
15
+ var nothingBefore = () => null;
16
+ function withDerivedDisplay(doc, document, derivers = DISPLAY_DERIVERS) {
17
+ const transform = new Transform(doc);
18
+ deriveDisplay(
19
+ transform,
20
+ { document, composingAt: null },
21
+ derivers,
22
+ nothingBefore
23
+ );
24
+ return transform.doc;
25
+ }
26
+ function previousIn(before, transactions) {
27
+ const mapping = new Mapping();
28
+ for (const transaction of transactions) {
29
+ mapping.appendMapping(transaction.mapping);
30
+ }
31
+ const back = mapping.invert();
32
+ return (node, pos) => {
33
+ const inside = node.isLeaf ? pos : pos + 1;
34
+ if (back.mapResult(inside, 1).deleted) return null;
35
+ const was = before.nodeAt(back.map(pos, 1));
36
+ return was !== null && was.type === node.type ? was : null;
37
+ };
38
+ }
39
+ function composingAt(view, state) {
40
+ return view?.composing === true ? state.selection.from : null;
41
+ }
42
+ function displayDerivation(derivers = DISPLAY_DERIVERS) {
43
+ let live = null;
44
+ return new Plugin({
45
+ view(view) {
46
+ live = view;
47
+ return {
48
+ destroy() {
49
+ live = null;
50
+ }
51
+ };
52
+ },
53
+ appendTransaction(transactions, oldState, newState) {
54
+ const document = documentOf(newState);
55
+ const replaced = document !== documentOf(oldState);
56
+ if (!replaced && !transactions.some((transaction) => transaction.docChanged)) {
57
+ return null;
58
+ }
59
+ const tr = newState.tr.setMeta(displayOnly, true);
60
+ if (replaced) tr.setMeta("addToHistory", false);
61
+ deriveDisplay(
62
+ tr,
63
+ {
64
+ document,
65
+ composingAt: replaced ? null : composingAt(live, newState)
66
+ },
67
+ derivers,
68
+ replaced ? nothingBefore : previousIn(oldState.doc, transactions)
69
+ );
70
+ return tr.docChanged ? tr : null;
71
+ }
72
+ });
73
+ }
74
+ export {
75
+ DISPLAY_DERIVERS,
76
+ displayDerivation,
77
+ withDerivedDisplay
78
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Holds the protection the editor runs under (`schema/protection`) in the state, where the guard
3
- * and the commands read it. The guard itself stands in `lockedContent`, which enforces
4
- * `transactionAllowed` for locks and protection in one pass.
2
+ * Holds the protection the editor runs under (`schema/protection`) in the state, where the guards
3
+ * and the commands read it. The runtime filter stands in `lockedContent`, which enforces every
4
+ * guard `schema/guards` registers, the protection among them, in one pass.
5
5
  */
6
6
  import { Plugin, type Transaction } from "prosemirror-state";
7
7
  import type { EditableComments, EditingProtection, ProtectionState } from "../../schema/protection";
@@ -2,8 +2,7 @@
2
2
  import { isHistoryTransaction } from "prosemirror-history";
3
3
  import { Plugin, PluginKey } from "prosemirror-state";
4
4
  import { Decoration, DecorationSet } from "prosemirror-view";
5
- import { replacementShut } from "../../schema/locks.js";
6
- import { editsShut } from "../../schema/protectionState.js";
5
+ import { editShut, selectionIntents } from "../../schema/guards.js";
7
6
  import {
8
7
  hasResolvableClipboardImages,
9
8
  resolveClipboardImages
@@ -223,7 +222,9 @@ function imagePaste() {
223
222
  props: {
224
223
  decorations: (state) => imagePasteKey.getState(state)?.decorations,
225
224
  handlePaste(view, event) {
226
- if (editsShut(view.state) || replacementShut(view.state.selection, view.state.doc)) {
225
+ if (selectionIntents(view.state.selection, "replace").some(
226
+ (intent) => editShut(view.state, intent)
227
+ )) {
227
228
  return false;
228
229
  }
229
230
  if (view.state.selection.ranges.length > 1) return false;
@@ -5,6 +5,7 @@ import { keydownHandler } from "prosemirror-keymap";
5
5
  import { Plugin } from "prosemirror-state";
6
6
  import { goToNextCell } from "prosemirror-tables";
7
7
  import { canSplit } from "prosemirror-transform";
8
+ import { splitParagraphAttrs } from "../../docx/cloning.js";
8
9
  import { toParagraphFormat } from "../../model/format.js";
9
10
  import { docxSchema } from "../../schema/index.js";
10
11
  import { insertLineBreak, insertPageBreak } from "../commands/breakCommands.js";
@@ -42,13 +43,27 @@ var splitParagraph = (state, dispatch) => {
42
43
  const tr = state.tr;
43
44
  if (!state.selection.empty) tr.deleteSelection();
44
45
  const at = tr.mapping.map(state.selection.$from.pos);
45
- const parent = tr.doc.resolve(at).parent;
46
+ const $at = tr.doc.resolve(at);
47
+ const parent = $at.parent;
46
48
  if (parent.type !== docxSchema.nodes.paragraph) return false;
47
- const types = [{ type: docxSchema.nodes.paragraph, attrs: parent.attrs }];
49
+ const { before, after } = splitParagraphAttrs(parent);
50
+ const types = [{ type: docxSchema.nodes.paragraph, attrs: after }];
48
51
  if (!canSplit(tr.doc, at, 1, types)) return false;
49
- if (dispatch) dispatch(tr.split(at, 1, types).scrollIntoView());
52
+ if (dispatch) {
53
+ const beforePos = $at.before();
54
+ tr.split(at, 1, types);
55
+ if (!keptEveryAttr(parent, before)) {
56
+ tr.setNodeMarkup(beforePos, null, before);
57
+ }
58
+ dispatch(tr.scrollIntoView());
59
+ }
50
60
  return true;
51
61
  };
62
+ function keptEveryAttr(paragraph, attrs) {
63
+ return Object.keys(paragraph.attrs).every(
64
+ (name) => attrs[name] === paragraph.attrs[name]
65
+ );
66
+ }
52
67
  var preserveTableFollowingParagraph = (state) => {
53
68
  const { $from } = state.selection;
54
69
  if (!state.selection.empty || $from.depth !== 1 || $from.parent.type !== docxSchema.nodes.paragraph || $from.parent.content.size !== 0 || $from.parentOffset !== 0) {