@portone/docx-editor 0.2.1 → 0.4.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 (253) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/CONTRIBUTING.md +5 -1
  3. package/dist/DocxEditor.d.ts +6 -0
  4. package/dist/DocxEditor.js +13 -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 +12 -7
  10. package/dist/docx/commentOnlyChange.js +9 -156
  11. package/dist/docx/comments/constants.d.ts +0 -1
  12. package/dist/docx/comments/constants.js +0 -2
  13. package/dist/docx/comments/grammar.d.ts +10 -4
  14. package/dist/docx/comments/grammar.js +12 -2
  15. package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
  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 +16 -92
  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.js +8 -10
  22. package/dist/docx/comments/writing.d.ts +19 -7
  23. package/dist/docx/comments/writing.js +59 -112
  24. package/dist/docx/documentSettings.d.ts +7 -0
  25. package/dist/docx/documentSettings.js +10 -2
  26. package/dist/docx/exportDocx.d.ts +40 -5
  27. package/dist/docx/exportDocx.js +88 -74
  28. package/dist/docx/exportRefs.d.ts +5 -2
  29. package/dist/docx/exportRefs.js +3 -1
  30. package/dist/docx/fidelity.d.ts +43 -0
  31. package/dist/docx/fidelity.js +64 -0
  32. package/dist/docx/formatting/attrs.d.ts +45 -0
  33. package/dist/docx/formatting/attrs.js +86 -0
  34. package/dist/docx/formatting/context.d.ts +39 -0
  35. package/dist/docx/formatting/context.js +60 -0
  36. package/dist/docx/formatting/direct.d.ts +6 -5
  37. package/dist/docx/formatting/direct.js +52 -78
  38. package/dist/docx/formatting/resolve.d.ts +51 -0
  39. package/dist/docx/formatting/resolve.js +160 -0
  40. package/dist/docx/formatting/runProperties.d.ts +93 -0
  41. package/dist/docx/formatting/runProperties.js +316 -0
  42. package/dist/docx/formatting/styles.d.ts +25 -2
  43. package/dist/docx/formatting/styles.js +87 -6
  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 +6 -13
  48. package/dist/docx/hyperlink.d.ts +14 -4
  49. package/dist/docx/hyperlink.js +4 -1
  50. package/dist/docx/identities.d.ts +67 -0
  51. package/dist/docx/identities.js +174 -0
  52. package/dist/docx/importDocx.d.ts +12 -1
  53. package/dist/docx/importDocx.js +90 -88
  54. package/dist/docx/importParagraph.d.ts +1 -1
  55. package/dist/docx/importParagraph.js +4 -3
  56. package/dist/docx/importTable.d.ts +2 -2
  57. package/dist/docx/importTable.js +69 -56
  58. package/dist/docx/invariants.d.ts +33 -0
  59. package/dist/docx/invariants.js +269 -0
  60. package/dist/docx/media.d.ts +6 -4
  61. package/dist/docx/media.js +6 -37
  62. package/dist/docx/newLists.d.ts +50 -0
  63. package/dist/docx/newLists.js +59 -0
  64. package/dist/docx/notes.js +3 -7
  65. package/dist/docx/numberingPlanner.d.ts +11 -0
  66. package/dist/docx/numberingPlanner.js +50 -0
  67. package/dist/docx/packageParts.d.ts +42 -0
  68. package/dist/docx/packageParts.js +135 -0
  69. package/dist/docx/pageGeometry.d.ts +2 -0
  70. package/dist/docx/pageGeometry.js +18 -9
  71. package/dist/docx/paraProps.d.ts +10 -22
  72. package/dist/docx/paraProps.js +47 -76
  73. package/dist/docx/partPlan.d.ts +36 -0
  74. package/dist/docx/partPlan.js +59 -0
  75. package/dist/docx/protectionPolicy.d.ts +127 -0
  76. package/dist/docx/protectionPolicy.js +169 -0
  77. package/dist/docx/relationships.d.ts +1 -1
  78. package/dist/docx/relationships.js +8 -13
  79. package/dist/docx/runProps.d.ts +9 -22
  80. package/dist/docx/runProps.js +15 -168
  81. package/dist/docx/scan.js +20 -52
  82. package/dist/docx/sdt.js +9 -34
  83. package/dist/docx/sdtProps.d.ts +8 -1
  84. package/dist/docx/sdtProps.js +10 -0
  85. package/dist/docx/serializeBlock.d.ts +2 -0
  86. package/dist/docx/serializeBlock.js +8 -5
  87. package/dist/docx/serializeTable.js +32 -15
  88. package/dist/docx/session.d.ts +42 -14
  89. package/dist/docx/session.js +53 -17
  90. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  91. package/dist/docx/tableFormatting/conditions.js +196 -0
  92. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  93. package/dist/docx/tableFormatting/editing.js +111 -143
  94. package/dist/docx/tableFormatting/reading.d.ts +63 -23
  95. package/dist/docx/tableFormatting/reading.js +132 -38
  96. package/dist/docx/tableFormatting.d.ts +1 -0
  97. package/dist/docx/tableFormatting.js +1 -0
  98. package/dist/docx/tableTemplate.js +30 -19
  99. package/dist/download.d.ts +8 -5
  100. package/dist/download.js +2 -0
  101. package/dist/editor/clipboard/inlineFormatting.js +19 -30
  102. package/dist/editor/commands/comments/editing.d.ts +6 -2
  103. package/dist/editor/commands/comments/editing.js +19 -31
  104. package/dist/editor/commands/exportQueries.d.ts +15 -0
  105. package/dist/editor/commands/exportQueries.js +14 -0
  106. package/dist/editor/commands/fidelityQueries.d.ts +12 -0
  107. package/dist/editor/commands/fidelityQueries.js +8 -0
  108. package/dist/editor/commands/formatting/editing.d.ts +2 -2
  109. package/dist/editor/commands/formatting/editing.js +26 -108
  110. package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
  111. package/dist/editor/commands/formatting/propertyCommands.js +108 -0
  112. package/dist/editor/commands/formatting/shared.d.ts +3 -3
  113. package/dist/editor/commands/formatting/shared.js +5 -2
  114. package/dist/editor/commands/indentCommands.js +5 -4
  115. package/dist/editor/commands/index.d.ts +11 -0
  116. package/dist/editor/commands/index.js +5 -0
  117. package/dist/editor/commands/linkCommands.js +5 -6
  118. package/dist/editor/commands/listCommands.d.ts +6 -3
  119. package/dist/editor/commands/listCommands.js +73 -30
  120. package/dist/editor/commands/lockCommands.d.ts +7 -1
  121. package/dist/editor/commands/lockCommands.js +35 -46
  122. package/dist/editor/commands/paragraphCommands.js +33 -31
  123. package/dist/editor/commands/spacingCommands.js +1 -1
  124. package/dist/editor/createEditor.d.ts +17 -29
  125. package/dist/editor/createEditor.js +58 -58
  126. package/dist/editor/documentStyles.d.ts +11 -35
  127. package/dist/editor/documentStyles.js +9 -52
  128. package/dist/editor/editorDocument.d.ts +57 -0
  129. package/dist/editor/editorDocument.js +86 -0
  130. package/dist/editor/externalClipboard.d.ts +13 -2
  131. package/dist/editor/externalClipboard.js +76 -75
  132. package/dist/editor/insertTable.js +4 -3
  133. package/dist/editor/paragraphEdits.d.ts +27 -19
  134. package/dist/editor/paragraphEdits.js +18 -19
  135. package/dist/editor/paragraphPlacement.d.ts +11 -0
  136. package/dist/editor/paragraphPlacement.js +18 -0
  137. package/dist/editor/plugins/displayDerivation.d.ts +47 -0
  138. package/dist/editor/plugins/displayDerivation.js +78 -0
  139. package/dist/editor/plugins/imagePaste.js +11 -7
  140. package/dist/editor/plugins/keymap.js +18 -3
  141. package/dist/editor/plugins/numberingDecorations.d.ts +14 -14
  142. package/dist/editor/plugins/numberingDecorations.js +50 -19
  143. package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
  144. package/dist/editor/plugins/paragraphDisplay.js +57 -0
  145. package/dist/editor/plugins/tabLayout.js +1 -1
  146. package/dist/editor/plugins/tableDisplay.d.ts +6 -0
  147. package/dist/editor/plugins/tableDisplay.js +30 -0
  148. package/dist/index.d.ts +2 -0
  149. package/dist/model/format.d.ts +80 -8
  150. package/dist/model/format.js +100 -22
  151. package/dist/model/tabStops.d.ts +9 -0
  152. package/dist/model/tabStops.js +18 -0
  153. package/dist/numbering/listRegistry.d.ts +37 -0
  154. package/dist/numbering/listRegistry.js +112 -0
  155. package/dist/numbering/listTemplate.d.ts +26 -17
  156. package/dist/numbering/listTemplate.js +88 -25
  157. package/dist/numbering/markers.d.ts +15 -6
  158. package/dist/numbering/markers.js +26 -59
  159. package/dist/numbering/parseNumbering.d.ts +84 -6
  160. package/dist/numbering/parseNumbering.js +131 -44
  161. package/dist/numbering/spellers.d.ts +15 -0
  162. package/dist/numbering/spellers.js +96 -0
  163. package/dist/numbering/writeNumbering.d.ts +8 -7
  164. package/dist/numbering/writeNumbering.js +28 -39
  165. package/dist/ooxml/childOrder.d.ts +34 -0
  166. package/dist/ooxml/childOrder.js +496 -0
  167. package/dist/ooxml/conformance.d.ts +28 -0
  168. package/dist/ooxml/conformance.js +20 -0
  169. package/dist/ooxml/element.d.ts +24 -11
  170. package/dist/ooxml/element.js +31 -12
  171. package/dist/ooxml/errors.d.ts +6 -5
  172. package/dist/ooxml/image.d.ts +4 -0
  173. package/dist/ooxml/image.js +2 -5
  174. package/dist/ooxml/names.d.ts +9 -0
  175. package/dist/ooxml/names.js +8 -1
  176. package/dist/ooxml/partSplice.d.ts +67 -0
  177. package/dist/ooxml/partSplice.js +176 -0
  178. package/dist/ooxml/props.d.ts +112 -0
  179. package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
  180. package/dist/ooxml/simpleTypes.d.ts +103 -0
  181. package/dist/ooxml/simpleTypes.js +182 -0
  182. package/dist/ooxml/tabStops.js +8 -27
  183. package/dist/ooxml/tagScan.d.ts +34 -0
  184. package/dist/ooxml/tagScan.js +108 -0
  185. package/dist/ooxml/units.d.ts +25 -13
  186. package/dist/ooxml/units.js +65 -31
  187. package/dist/ooxml/xml.d.ts +35 -15
  188. package/dist/ooxml/xml.js +43 -11
  189. package/dist/page/PageGuides.d.ts +1 -1
  190. package/dist/page/PageGuides.js +0 -13
  191. package/dist/page/blockKinds.d.ts +61 -0
  192. package/dist/page/blockKinds.js +11 -0
  193. package/dist/page/kinds/index.d.ts +6 -0
  194. package/dist/page/kinds/index.js +10 -0
  195. package/dist/page/kinds/paragraphKind.d.ts +10 -0
  196. package/dist/page/kinds/paragraphKind.js +71 -0
  197. package/dist/page/kinds/tableKind.d.ts +10 -0
  198. package/dist/page/kinds/tableKind.js +178 -0
  199. package/dist/page/measureBlocks.d.ts +3 -14
  200. package/dist/page/measureBlocks.js +24 -45
  201. package/dist/page/pageDecorations.d.ts +27 -44
  202. package/dist/page/pageDecorations.js +70 -152
  203. package/dist/page/pageLayout.d.ts +2 -29
  204. package/dist/page/pageLayout.js +39 -16
  205. package/dist/page/usePageLayout.d.ts +2 -24
  206. package/dist/page/usePageLayout.js +5 -48
  207. package/dist/schema/attrRoles.d.ts +25 -18
  208. package/dist/schema/attrRoles.js +110 -68
  209. package/dist/schema/displayDerivation.d.ts +82 -0
  210. package/dist/schema/displayDerivation.js +130 -0
  211. package/dist/schema/docxSchema.d.ts +3 -0
  212. package/dist/schema/docxSchema.js +58 -17
  213. package/dist/schema/editGuard.d.ts +1 -1
  214. package/dist/schema/guards.d.ts +37 -14
  215. package/dist/schema/guards.js +29 -3
  216. package/dist/schema/index.d.ts +2 -0
  217. package/dist/schema/index.js +2 -0
  218. package/dist/schema/locks.d.ts +11 -44
  219. package/dist/schema/locks.js +0 -9
  220. package/dist/schema/preservedGuards.d.ts +26 -6
  221. package/dist/schema/preservedGuards.js +31 -1
  222. package/dist/schema/protection.d.ts +7 -1
  223. package/dist/schema/protection.js +2 -1
  224. package/dist/schema/sourceEquality.d.ts +1 -9
  225. package/dist/schema/sourceEquality.js +1 -27
  226. package/dist/styles/classNames.d.ts +13 -2
  227. package/dist/styles/classNames.js +13 -2
  228. package/dist/styles/inlineStyle.js +15 -6
  229. package/dist/styles.css +16 -18
  230. package/dist/table/cellFormatting.d.ts +8 -1
  231. package/dist/table/cellFormatting.js +11 -20
  232. package/dist/table/commands.js +20 -18
  233. package/dist/table/format.d.ts +3 -0
  234. package/dist/table/format.js +3 -9
  235. package/dist/table/gridBorders.d.ts +24 -30
  236. package/dist/table/gridBorders.js +35 -59
  237. package/dist/table/merge.d.ts +2 -6
  238. package/dist/table/merge.js +5 -5
  239. package/package.json +7 -3
  240. package/dist/docx/comments/contentTypes.d.ts +0 -7
  241. package/dist/docx/comments/contentTypes.js +0 -38
  242. package/dist/docx/comments/verifying.js +0 -206
  243. package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
  244. package/dist/docx/formatting/effectiveParagraph.js +0 -81
  245. package/dist/docx/propsXml.d.ts +0 -67
  246. package/dist/docx/uniqueControls.d.ts +0 -14
  247. package/dist/docx/uniqueControls.js +0 -62
  248. package/dist/editor/plugins/commentReservations.d.ts +0 -5
  249. package/dist/editor/plugins/commentReservations.js +0 -26
  250. package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
  251. package/dist/editor/plugins/styledParagraphs.js +0 -65
  252. package/dist/page/tableMeasurements.d.ts +0 -18
  253. package/dist/page/tableMeasurements.js +0 -119
@@ -1,47 +1,24 @@
1
1
  // src/editor/documentStyles.ts
2
- import { Plugin, PluginKey } from "prosemirror-state";
3
- import { DEFAULT_TAB_STOP_PT } from "../docx/documentSettings.js";
4
2
  import {
5
- NO_DOCUMENT_DEFAULTS,
6
- NO_PARAGRAPH_FORMATTING,
7
- NO_STYLES
8
- } from "../docx/formatting.js";
9
- import {
10
- A4_PORTRAIT,
11
3
  bodyHeightTwips,
12
4
  bodyWidth,
13
5
  twipsToPx
14
6
  } from "../docx/pageGeometry.js";
15
- import { EMPTY_NUMBERING } from "../numbering/parseNumbering.js";
16
- var NO_PARAGRAPH_STYLES = [];
17
- var documentKey = new PluginKey("docxEditorDocument");
18
- function documentStyles(state) {
19
- return documentKey.getState(state)?.styles ?? NO_STYLES;
7
+ import { documentOf } from "./editorDocument.js";
8
+ function documentFormatting(state) {
9
+ return documentOf(state).formatting;
20
10
  }
21
11
  function documentDefaults(state) {
22
- return documentKey.getState(state)?.defaults ?? NO_DOCUMENT_DEFAULTS;
23
- }
24
- function documentParagraphFormatting(state) {
25
- const info = documentKey.getState(state);
26
- if (!info) return NO_PARAGRAPH_FORMATTING;
27
- return {
28
- styles: info.styles,
29
- defaultStyleId: info.paragraphStyles.find((style) => style.isDefault)?.id ?? null,
30
- defaults: info.paragraphDefaults,
31
- numbering: info.numbering
32
- };
12
+ return documentOf(state).defaults;
33
13
  }
34
14
  function documentParagraphStyles(state) {
35
- return documentKey.getState(state)?.paragraphStyles ?? NO_PARAGRAPH_STYLES;
36
- }
37
- function defaultParagraphStyleId(state) {
38
- return documentParagraphStyles(state).find((style) => style.isDefault)?.id ?? null;
15
+ return documentOf(state).paragraphStyles;
39
16
  }
40
17
  function documentGeometry(state) {
41
- return documentKey.getState(state)?.geometry ?? A4_PORTRAIT;
18
+ return documentOf(state).geometry;
42
19
  }
43
20
  function documentDefaultTabStopPt(state) {
44
- return documentKey.getState(state)?.defaultTabStopPt ?? DEFAULT_TAB_STOP_PT;
21
+ return documentOf(state).defaultTabStopPt;
45
22
  }
46
23
  function documentBodyWidthPx(state) {
47
24
  return bodyWidth(documentGeometry(state)).px;
@@ -49,32 +26,12 @@ function documentBodyWidthPx(state) {
49
26
  function documentBodyHeightPx(state) {
50
27
  return twipsToPx(bodyHeightTwips(documentGeometry(state)));
51
28
  }
52
- function documentStyleTable(styles, defaults = NO_DOCUMENT_DEFAULTS, paragraphStyles = NO_PARAGRAPH_STYLES, geometry = A4_PORTRAIT, paragraphDefaults = {}, numbering = EMPTY_NUMBERING, defaultTabStopPt = DEFAULT_TAB_STOP_PT) {
53
- return new Plugin({
54
- key: documentKey,
55
- state: {
56
- init: () => ({
57
- styles,
58
- defaults,
59
- paragraphDefaults,
60
- numbering,
61
- paragraphStyles,
62
- geometry,
63
- defaultTabStopPt
64
- }),
65
- apply: (_tr, current) => current
66
- }
67
- });
68
- }
69
29
  export {
70
- defaultParagraphStyleId,
71
30
  documentBodyHeightPx,
72
31
  documentBodyWidthPx,
73
32
  documentDefaultTabStopPt,
74
33
  documentDefaults,
34
+ documentFormatting,
75
35
  documentGeometry,
76
- documentParagraphFormatting,
77
- documentParagraphStyles,
78
- documentStyleTable,
79
- documentStyles
36
+ documentParagraphStyles
80
37
  };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * What the opened document laid down, held as one value: the formatting context every display
3
+ * value is resolved against, the paper the body is written on, and the identifiers its comment
4
+ * parts have already spent.
5
+ *
6
+ * Commands and the toolbar know nothing about the session, so the snapshot stands for it on their
7
+ * behalf, and `editorDocumentOf` is the one place a session is read into editor values: a screen
8
+ * and a test that open the same document hold the same values.
9
+ */
10
+ import type { Node as PMNode } from "prosemirror-model";
11
+ import { type EditorState, Plugin } from "prosemirror-state";
12
+ import { type FormattingContext, type ParagraphStyleOption } from "../docx/formatting";
13
+ import { type PageGeometry } from "../docx/pageGeometry";
14
+ import type { SessionStore } from "../docx/session";
15
+ import type { DocumentDefaults } from "../model/format";
16
+ /** The document-level values one editing state is built on */
17
+ export interface EditorDocument {
18
+ /** The document these values were read from. Null for a state built without one */
19
+ readonly session: SessionStore | null;
20
+ /** The style chain, the defaults and the list definitions a paragraph's and a run's display values are resolved against */
21
+ readonly formatting: FormattingContext;
22
+ readonly defaults: DocumentDefaults;
23
+ /** The styles the document defines for the style picker to offer */
24
+ readonly paragraphStyles: ParagraphStyleOption[];
25
+ /**
26
+ * Whether the definition of a new list has somewhere to go, which is what the commands that
27
+ * start one ask. A state built without opening a document assumes it has and behaves as every
28
+ * state did before the question was asked.
29
+ */
30
+ readonly canStartNewList: boolean;
31
+ /** The paper the document is written on, which decides the width a new table is fitted to */
32
+ readonly geometry: PageGeometry;
33
+ /** The distance between automatic tab stops when no custom stop applies */
34
+ readonly defaultTabStopPt: number;
35
+ /** Every id already present in the opened Comments part, including unreferenced entries */
36
+ readonly reservedCommentIds: ReadonlySet<string>;
37
+ /** Every paragraph id present in the opened comment parts, including orphan extension entries */
38
+ readonly reservedCommentParaIds: ReadonlySet<string>;
39
+ }
40
+ /** What a state built without an opened document answers: the same as nothing being written down */
41
+ export declare const NO_DOCUMENT: EditorDocument;
42
+ /** The one place an opened document is read into the values the editor holds */
43
+ export declare function editorDocumentOf(session: SessionStore, doc: PMNode): EditorDocument;
44
+ /** The document the state was built for. `NO_DOCUMENT` for a state built without one */
45
+ export declare function documentOf(state: EditorState): EditorDocument;
46
+ /**
47
+ * Holds the snapshot for the lifetime of the state.
48
+ *
49
+ * It is derived again only where a document-level edit could have been recorded - the attrs of the
50
+ * document node, which is where such an edit is written - so an ordinary edit and a selection move
51
+ * both leave the same object behind, allowing the sheet's style to be cached against that identity.
52
+ */
53
+ export declare function editorDocument(document: EditorDocument): Plugin<EditorDocument>;
54
+ /** The comment ids the opened document already spent, which a new comment may not take */
55
+ export declare function reservedCommentIds(state: EditorState): ReadonlySet<string>;
56
+ /** The paragraph ids the opened comment parts already spent */
57
+ export declare function reservedCommentParaIds(state: EditorState): ReadonlySet<string>;
@@ -0,0 +1,86 @@
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 { canDefineNewList } from "../docx/newLists.js";
9
+ import { A4_PORTRAIT } from "../docx/pageGeometry.js";
10
+ import { NEW_LISTS_ATTR, newListsOf } from "../numbering/listRegistry.js";
11
+ var NO_IDS = /* @__PURE__ */ new Set();
12
+ var NO_PARAGRAPH_STYLES = [];
13
+ var NO_DOCUMENT = {
14
+ session: null,
15
+ formatting: NO_FORMATTING,
16
+ defaults: NO_DOCUMENT_DEFAULTS,
17
+ paragraphStyles: NO_PARAGRAPH_STYLES,
18
+ canStartNewList: true,
19
+ geometry: A4_PORTRAIT,
20
+ defaultTabStopPt: DEFAULT_TAB_STOP_PT,
21
+ reservedCommentIds: NO_IDS,
22
+ reservedCommentParaIds: NO_IDS
23
+ };
24
+ function reservedParaIds(session) {
25
+ const paraIds = /* @__PURE__ */ new Set();
26
+ for (const comment of session.comments.ordered) {
27
+ if (comment.paraId !== null) paraIds.add(comment.paraId);
28
+ }
29
+ for (const extension of session.comments.extendedOrdered) {
30
+ paraIds.add(extension.paraId);
31
+ }
32
+ return paraIds;
33
+ }
34
+ function formattingWithNewLists(formatting, doc) {
35
+ const added = newListsOf(doc.attrs[NEW_LISTS_ATTR]);
36
+ if (added.size === 0 && formatting.numbering.added.size === 0) {
37
+ return formatting;
38
+ }
39
+ return { ...formatting, numbering: { ...formatting.numbering, added } };
40
+ }
41
+ function editorDocumentOf(session, doc) {
42
+ return {
43
+ session,
44
+ formatting: formattingWithNewLists(session.formatting, doc),
45
+ defaults: session.defaults,
46
+ paragraphStyles: session.paragraphStyles,
47
+ canStartNewList: canDefineNewList(session),
48
+ geometry: session.geometry,
49
+ defaultTabStopPt: session.defaultTabStopPt,
50
+ reservedCommentIds: new Set(session.comments.byId.keys()),
51
+ reservedCommentParaIds: reservedParaIds(session)
52
+ };
53
+ }
54
+ var editorDocumentKey = new PluginKey("docxEditorDocument");
55
+ function documentOf(state) {
56
+ return editorDocumentKey.getState(state) ?? NO_DOCUMENT;
57
+ }
58
+ function derived(current, doc) {
59
+ return current.session === null ? {
60
+ ...current,
61
+ formatting: formattingWithNewLists(current.formatting, doc)
62
+ } : editorDocumentOf(current.session, doc);
63
+ }
64
+ function editorDocument(document) {
65
+ return new Plugin({
66
+ key: editorDocumentKey,
67
+ state: {
68
+ init: () => document,
69
+ apply: (tr, current, old) => tr.doc.attrs === old.doc.attrs ? current : derived(current, tr.doc)
70
+ }
71
+ });
72
+ }
73
+ function reservedCommentIds(state) {
74
+ return documentOf(state).reservedCommentIds;
75
+ }
76
+ function reservedCommentParaIds(state) {
77
+ return documentOf(state).reservedCommentParaIds;
78
+ }
79
+ export {
80
+ NO_DOCUMENT,
81
+ documentOf,
82
+ editorDocument,
83
+ editorDocumentOf,
84
+ reservedCommentIds,
85
+ reservedCommentParaIds
86
+ };
@@ -1,8 +1,19 @@
1
1
  import { Slice } from "prosemirror-model";
2
- import { type EditorState, Plugin } from "prosemirror-state";
2
+ import { type EditorState, Plugin, type Transaction } from "prosemirror-state";
3
3
  import type { EditorView } from "prosemirror-view";
4
+ import { type NewLists } from "../numbering/listRegistry";
4
5
  import type { ImageToInsert } from "./insertImage";
5
- export declare function richHtmlSlice(state: EditorState, document: Document, source: string, images?: ReadonlyMap<string, ImageToInsert>): Slice | null;
6
+ /** What a paste puts in: the content, and the definitions of the lists it started */
7
+ export interface PastedContent {
8
+ slice: Slice;
9
+ newLists: NewLists;
10
+ }
11
+ export declare function richHtmlSlice(state: EditorState, document: Document, source: string, images?: ReadonlyMap<string, ImageToInsert>): PastedContent | null;
12
+ /**
13
+ * The transaction a paste is put in with: the content, and the definitions of the lists it started
14
+ * recorded on the document node so that the export writes them out and undo takes them back.
15
+ */
16
+ export declare function withPastedContent(tr: Transaction, content: PastedContent): Transaction;
6
17
  export declare function insertRichHtml(view: EditorView, source: string): boolean;
7
18
  export declare function insertClipboardData(view: EditorView, data: {
8
19
  html?: string;
@@ -5,11 +5,24 @@ import {
5
5
  Slice
6
6
  } from "prosemirror-model";
7
7
  import { Plugin } from "prosemirror-state";
8
- import { effectiveParagraphFormat, styleIdOf } from "../docx/formatting.js";
9
- import { withParagraphStyle } from "../docx/paraProps.js";
10
- import { MAX_ILVL, nextNumId } from "../numbering/listTemplate.js";
11
- import { elementXml } from "../ooxml/element.js";
12
- import { wName } from "../ooxml/names.js";
8
+ import {
9
+ paragraphAttrsFor,
10
+ styleIdOf
11
+ } from "../docx/formatting.js";
12
+ import {
13
+ withListNumbering,
14
+ withParagraphStyle
15
+ } from "../docx/paraProps.js";
16
+ import {
17
+ listsWorn,
18
+ NEW_LISTS_ATTR,
19
+ newListsValue
20
+ } from "../numbering/listRegistry.js";
21
+ import {
22
+ allocateList,
23
+ MAX_ILVL,
24
+ templateList
25
+ } from "../numbering/listTemplate.js";
13
26
  import { docxSchema, isPageBreak } from "../schema/index.js";
14
27
  import { editorClassNames } from "../styles/classNames.js";
15
28
  import { PASTED_IMAGE_ATTRIBUTE } from "./clipboard/images.js";
@@ -20,19 +33,11 @@ import {
20
33
  safeHref,
21
34
  withInlineStyle
22
35
  } from "./clipboard/inlineFormatting.js";
23
- import { listRefOf } from "./commands/listCommands.js";
24
- import {
25
- defaultParagraphStyleId,
26
- documentParagraphFormatting,
27
- documentParagraphStyles,
28
- documentStyles
29
- } from "./documentStyles.js";
36
+ import { numIdsIn } from "./commands/listCommands.js";
37
+ import { documentFormatting, documentParagraphStyles } from "./documentStyles.js";
30
38
  import { insertPlainText } from "./plainText.js";
31
39
  import { moveCaretToDrop } from "./plugins/dropCaret.js";
32
- import {
33
- canStartNewList,
34
- documentNumbering
35
- } from "./plugins/numberingDecorations.js";
40
+ import { canStartNewList } from "./plugins/numberingDecorations.js";
36
41
  var BLOCK_TAGS = /* @__PURE__ */ new Set([
37
42
  "ADDRESS",
38
43
  "ARTICLE",
@@ -242,12 +247,7 @@ function blockContext(state, parent, element, preserveParagraphStyle) {
242
247
  };
243
248
  }
244
249
  const styleId = destinationStyleId(state, sourceStyleId, level);
245
- const paragraph = styleId === null ? null : withParagraphStyle(
246
- null,
247
- styleId,
248
- documentStyles(state),
249
- defaultParagraphStyleId(state)
250
- );
250
+ const paragraph = styleId === null ? null : withParagraphStyle(null, styleId);
251
251
  const usesDestinationStyle = editorParagraph && (sourceStyleId === null || paragraph !== null);
252
252
  let inline = parent;
253
253
  if (paragraph === null && level !== null) {
@@ -258,56 +258,24 @@ function blockContext(state, parent, element, preserveParagraphStyle) {
258
258
  paragraph
259
259
  };
260
260
  }
261
- function listParagraphAttrs(state, list) {
261
+ function listParagraphProps(list) {
262
262
  if (!list || list.numId === null) return null;
263
- const ilvl = Math.min(MAX_ILVL, list.level);
264
- const pPr = elementXml(
265
- wName("pPr"),
266
- [],
267
- [
268
- elementXml(
269
- wName("numPr"),
270
- [],
271
- [
272
- elementXml(wName("ilvl"), [[wName("val"), `${ilvl}`]]),
273
- elementXml(wName("numId"), [[wName("val"), `${list.numId}`]])
274
- ]
275
- )
276
- ]
277
- );
278
- return {
279
- pPr,
280
- format: effectiveParagraphFormat(pPr, documentParagraphFormatting(state))
281
- };
282
- }
283
- function paragraphAttrs(state, list, paragraph) {
284
- const listed = listParagraphAttrs(state, list);
285
- if (listed) return listed;
286
- return paragraph ? {
287
- pPr: paragraph.pPr,
288
- format: effectiveParagraphFormat(
289
- paragraph.pPr,
290
- documentParagraphFormatting(state)
291
- ),
292
- styleRun: paragraph.styleRun
293
- } : null;
294
- }
295
- function usedNumIds(state) {
296
- const used = new Set(documentNumbering(state).lists.keys());
297
- state.doc.descendants((node) => {
298
- if (node.type !== docxSchema.nodes.paragraph) return true;
299
- const ref = listRefOf(node);
300
- if (ref) used.add(ref.numId);
301
- return false;
263
+ return withListNumbering(null, {
264
+ numbering: { numId: list.numId, ilvl: Math.min(MAX_ILVL, list.level) },
265
+ indent: { kind: "keep" }
302
266
  });
303
- return used;
267
+ }
268
+ function paragraphAttrs(formatting, list, paragraph) {
269
+ const props = listParagraphProps(list) ?? paragraph;
270
+ return props ? { pPr: props.pPr, ...paragraphAttrsFor(props.pPr, formatting) } : null;
304
271
  }
305
272
  var HtmlReader = class {
306
273
  constructor(state, preserveParagraphStyles, images) {
307
274
  this.state = state;
308
275
  this.preserveParagraphStyles = preserveParagraphStyles;
309
276
  this.images = images;
310
- this.used = usedNumIds(state);
277
+ this.formatting = documentFormatting(state);
278
+ this.used = numIdsIn(state.doc);
311
279
  this.canCreateLists = canStartNewList(state);
312
280
  }
313
281
  state;
@@ -316,6 +284,16 @@ var HtmlReader = class {
316
284
  blocks = [];
317
285
  used;
318
286
  canCreateLists;
287
+ /**
288
+ * What the pasted paragraphs are resolved against: the document's context, holding the
289
+ * definition of each pasted list as it is read, so that an item is drawn against the list it
290
+ * is joining rather than against a list nothing yet defines.
291
+ */
292
+ formatting;
293
+ /** The definitions of every list started while editing, the pasted ones among them */
294
+ get newLists() {
295
+ return this.formatting.numbering.added;
296
+ }
319
297
  read(root) {
320
298
  this.readFlow(root, { style: {}, href: null, preserveWhitespace: false });
321
299
  return this.blocks;
@@ -347,7 +325,7 @@ var HtmlReader = class {
347
325
  }
348
326
  this.blocks.push(
349
327
  docxSchema.nodes.paragraph.create(
350
- paragraphAttrs(this.state, list, paragraph),
328
+ paragraphAttrs(this.formatting, list, paragraph),
351
329
  content
352
330
  )
353
331
  );
@@ -383,11 +361,20 @@ var HtmlReader = class {
383
361
  }
384
362
  flush();
385
363
  }
364
+ /**
365
+ * The number a pasted list takes, registered with the definition that list is drawn and written
366
+ * with. A pasted list is started here just as the list button starts one.
367
+ */
386
368
  takeNumId(kind) {
387
369
  if (!this.canCreateLists) return null;
388
- const id = nextNumId(this.used, kind);
389
- this.used.add(id);
390
- return id;
370
+ const started = allocateList(
371
+ this.formatting.numbering,
372
+ this.used,
373
+ templateList(kind)
374
+ );
375
+ this.formatting = { ...this.formatting, numbering: started.numbering };
376
+ this.used.add(started.numId);
377
+ return started.numId;
391
378
  }
392
379
  readList(list, context, level, inherited) {
393
380
  const kind = list.tagName === "UL" ? "bullet" : "numbered";
@@ -436,15 +423,28 @@ function richHtmlSlice(state, document, source, images = /* @__PURE__ */ new Map
436
423
  const template = document.createElement("template");
437
424
  template.innerHTML = source;
438
425
  const open = sliceDepth(template.content);
439
- const blocks = new HtmlReader(state, open === 0, images).read(
440
- template.content
426
+ const reader = new HtmlReader(state, open === 0, images);
427
+ const blocks = reader.read(template.content);
428
+ return blocks.length === 0 ? null : {
429
+ slice: new Slice(Fragment.fromArray([...blocks]), open, open),
430
+ newLists: reader.newLists
431
+ };
432
+ }
433
+ function withPastedContent(tr, content) {
434
+ return tr.setDocAttribute(
435
+ NEW_LISTS_ATTR,
436
+ newListsValue(listsWorn(content.newLists, numIdsIn(tr.doc)))
441
437
  );
442
- return blocks.length === 0 ? null : new Slice(Fragment.fromArray([...blocks]), open, open);
443
438
  }
444
439
  function insertRichHtml(view, source) {
445
- const slice = richHtmlSlice(view.state, view.dom.ownerDocument, source);
446
- if (slice === null) return false;
447
- view.dispatch(view.state.tr.replaceSelection(slice).scrollIntoView());
440
+ const content = richHtmlSlice(view.state, view.dom.ownerDocument, source);
441
+ if (content === null) return false;
442
+ view.dispatch(
443
+ withPastedContent(
444
+ view.state.tr.replaceSelection(content.slice),
445
+ content
446
+ ).scrollIntoView()
447
+ );
448
448
  return true;
449
449
  }
450
450
  function insertClipboardData(view, data) {
@@ -481,5 +481,6 @@ export {
481
481
  externalClipboard,
482
482
  insertClipboardData,
483
483
  insertRichHtml,
484
- richHtmlSlice
484
+ richHtmlSlice,
485
+ withPastedContent
485
486
  };
@@ -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,7 @@
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";
11
+ import { type FormattingContext } from "../docx/formatting";
12
12
  import type { ParagraphProps } from "../docx/paraProps";
13
13
  export interface ParagraphSpot {
14
14
  pos: number;
@@ -17,28 +17,36 @@ export interface ParagraphSpot {
17
17
  /** The paragraphs the selection spans. Selections covering several table cells are handled too */
18
18
  export declare function selectedParagraphs(state: EditorState): ParagraphSpot[];
19
19
  /**
20
- * The selected paragraphs a lock leaves editable, which is what every paragraph edit works on.
20
+ * The selected paragraphs the guards leave editable, which is what every paragraph edit works on.
21
21
  *
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.
22
+ * A shut paragraph is left out rather than the whole edit refused, the policy character formatting
23
+ * already follows (`schema/guards`): the guard turns down a whole transaction, so asking for it
24
+ * would leave the rest of the selection unedited too. A selection the guards leave nothing of edits
25
+ * nothing, and the command reports that of its own accord, which is the disabled state of the
26
+ * control that runs it.
27
27
  *
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`).
28
+ * A paragraph is rewritten around its content, which is the block intent: only the paragraphs of a
29
+ * locked cell are shut, and a paragraph merely holding a locked control keeps its own alignment,
30
+ * indent and style. A protection that shuts the body shuts every one of them.
33
31
  */
34
32
  export declare function editableParagraphs(state: EditorState): ParagraphSpot[];
35
33
  /** The original formatting XML this paragraph holds. Null when there is none */
36
34
  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;
35
+ /** How to edit a single paragraph. Null skips that paragraph */
36
+ export type ParagraphSurgery = (node: PMNode) => ParagraphProps | null;
37
+ /** What an edit does beyond swapping the fragments of the paragraphs it names */
38
+ export interface ParagraphEditExtras {
39
+ /**
40
+ * The context the new display values are resolved against, which is the state's own unless the
41
+ * edit is itself changing it. An edit that starts a list hands in the context that already
42
+ * holds it, so the paragraph is drawn against the list it is joining in that same transaction.
43
+ */
44
+ formatting?: FormattingContext;
45
+ /**
46
+ * What else the edit records in the same transaction, such as the definition of the list the
47
+ * paragraphs are joining, so that undo takes the two back together.
48
+ */
49
+ alongside?: (tr: Transaction) => void;
50
+ }
43
51
  /** Edits the selected paragraphs in a single transaction. Does nothing when there is nothing to edit */
44
- export declare function editParagraphs(state: EditorState, dispatch: ((tr: Transaction) => void) | undefined, surgery: ParagraphSurgery): boolean;
52
+ export declare function editParagraphs(state: EditorState, dispatch: ((tr: Transaction) => void) | undefined, surgery: ParagraphSurgery, extras?: ParagraphEditExtras): boolean;
@@ -1,13 +1,9 @@
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";
6
+ import { paragraphPlacementAt } from "./paragraphPlacement.js";
11
7
  function selectedParagraphs(state) {
12
8
  const spots = /* @__PURE__ */ new Map();
13
9
  for (const range of state.selection.ranges) {
@@ -20,37 +16,40 @@ function selectedParagraphs(state) {
20
16
  return Array.from(spots, ([pos, node]) => ({ pos, node }));
21
17
  }
22
18
  function editableParagraphs(state) {
23
- if (editsShut(state)) return [];
24
19
  return selectedParagraphs(state).filter(
25
- (spot) => !insideLockedCell(state.doc, spot.pos)
20
+ (spot) => !editShut(state, { kind: "block", at: spot.pos })
26
21
  );
27
22
  }
28
23
  function paragraphPPr(node) {
29
24
  const pPr = node.attrs.pPr;
30
25
  return typeof pPr === "string" ? pPr : null;
31
26
  }
32
- function writeChanges(state, changed) {
27
+ function writeChanges(state, changed, extras) {
33
28
  const tr = state.tr;
34
- const formatting = documentParagraphFormatting(state);
29
+ const formatting = extras.formatting ?? documentFormatting(state);
35
30
  for (const { spot, props } of changed) {
36
31
  tr.setNodeMarkup(tr.mapping.map(spot.pos), void 0, {
37
32
  ...spot.node.attrs,
38
33
  pPr: props.pPr,
39
- format: effectiveParagraphFormat(props.pPr, formatting),
40
- styleRun: props.styleRun
34
+ ...paragraphAttrsFor(
35
+ props.pPr,
36
+ formatting,
37
+ paragraphPlacementAt(state.doc, spot.pos)
38
+ )
41
39
  });
42
40
  }
41
+ extras.alongside?.(tr);
43
42
  return tr;
44
43
  }
45
- function editParagraphs(state, dispatch, surgery) {
46
- const styles = documentStyles(state);
47
- const defaultStyleId = defaultParagraphStyleId(state);
44
+ function editParagraphs(state, dispatch, surgery, extras = {}) {
48
45
  const changed = editableParagraphs(state).flatMap((spot) => {
49
- const props = surgery(spot.node, styles, defaultStyleId);
46
+ const props = surgery(spot.node);
50
47
  return props ? [{ spot, props }] : [];
51
48
  });
52
49
  if (changed.length === 0) return false;
53
- if (dispatch) dispatch(writeChanges(state, changed).scrollIntoView());
50
+ if (dispatch) {
51
+ dispatch(writeChanges(state, changed, extras).scrollIntoView());
52
+ }
54
53
  return true;
55
54
  }
56
55
  export {
@@ -0,0 +1,11 @@
1
+ /** Finds the table-style conditions at an editor position for both reads and writes. */
2
+ import type { Node as PMNode } from "prosemirror-model";
3
+ import type { ParagraphPlacement } from "../docx/formatting";
4
+ /**
5
+ * The part of a table the paragraph stands in, which its table style dresses it by. null for a
6
+ * paragraph of the body, and for one in a cell of a table this editor did not build.
7
+ *
8
+ * The cell is found by walking out of the paragraph rather than passed down, because the walk that
9
+ * runs the derivers goes over the blocks and hands each of them nothing but its own position.
10
+ */
11
+ export declare function paragraphPlacementAt(doc: PMNode, pos: number): ParagraphPlacement | null;
@@ -0,0 +1,18 @@
1
+ // src/editor/paragraphPlacement.ts
2
+ import { TableMap } from "prosemirror-tables";
3
+ import { docxSchema } from "../schema/index.js";
4
+ import { cellDefaultsAt, tableCellSources } from "../table/gridBorders.js";
5
+ function paragraphPlacementAt(doc, pos) {
6
+ const $pos = doc.resolve(pos);
7
+ for (let depth = $pos.depth; depth >= 2; depth -= 1) {
8
+ if ($pos.node(depth).type !== docxSchema.nodes.tableCell) continue;
9
+ const table = $pos.node(depth - 2);
10
+ if (table.type !== docxSchema.nodes.table) return null;
11
+ const cell = $pos.before(depth) - $pos.start(depth - 2);
12
+ return cellDefaultsAt(TableMap.get(table), cell, tableCellSources(table)).placement;
13
+ }
14
+ return null;
15
+ }
16
+ export {
17
+ paragraphPlacementAt
18
+ };