@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
@@ -8,9 +8,7 @@ import {
8
8
  NO_FILL,
9
9
  toCellFormat
10
10
  } from "../model/format.js";
11
- import { transactionAllowed } from "../schema/guards.js";
12
- import { isLockedCell } from "../schema/locks.js";
13
- import { editsShut } from "../schema/protectionState.js";
11
+ import { editShut, guardedCommand } from "../schema/guards.js";
14
12
  import { cellDefaultsAt, tableCellSources } from "./gridBorders.js";
15
13
  function text(value) {
16
14
  return typeof value === "string" ? value : null;
@@ -40,8 +38,7 @@ function planChanges(rect, edit) {
40
38
  const next = editCellProps(
41
39
  text(cell.attrs.tcPr),
42
40
  edit(rect, pos),
43
- cellDefaultsAt(rect.map, pos, sources),
44
- sources.margins
41
+ cellDefaultsAt(rect.map, pos, sources)
45
42
  );
46
43
  if (!next) continue;
47
44
  changes.push({
@@ -52,19 +49,12 @@ function planChanges(rect, edit) {
52
49
  return changes;
53
50
  }
54
51
  function cellFormatCommand(edit) {
55
- return (state, dispatch) => {
56
- if (!pmIsInTable(state)) return false;
52
+ return guardedCommand((state) => {
53
+ if (!canSetCellFormatting(state)) return null;
57
54
  const rect = selectedRect(state);
58
- if (rect.map.cellsInRect(rect).some((pos) => isLockedCell(rect.table.nodeAt(pos)))) {
59
- return false;
60
- }
61
55
  const changes = planChanges(rect, edit);
62
- if (changes.length === 0) return false;
63
- const transaction = applyChanges(state.tr, rect.tableStart, changes);
64
- if (!transactionAllowed(transaction, state)) return false;
65
- dispatch?.(transaction);
66
- return true;
67
- };
56
+ return changes.length === 0 ? null : applyChanges(state.tr, rect.tableStart, changes);
57
+ });
68
58
  }
69
59
  function shared(values) {
70
60
  const [first, ...rest] = values;
@@ -112,17 +102,18 @@ function selectedCells(state) {
112
102
  const cells = [];
113
103
  for (const pos of rect.map.cellsInRect(rect)) {
114
104
  const cell = rect.table.nodeAt(pos);
115
- if (cell) cells.push(cell);
105
+ if (cell) cells.push({ node: cell, pos: rect.tableStart + pos });
116
106
  }
117
107
  return cells;
118
108
  }
119
109
  function cellFormats(state) {
120
- return selectedCells(state).map((cell) => toCellFormat(cell.attrs.format));
110
+ return selectedCells(state).map(
111
+ ({ node }) => toCellFormat(node.attrs.format)
112
+ );
121
113
  }
122
114
  function canSetCellFormatting(state) {
123
- if (editsShut(state)) return false;
124
115
  const cells = selectedCells(state);
125
- return cells.length > 0 && cells.every((cell) => !isLockedCell(cell));
116
+ return cells.length > 0 && cells.every(({ pos }) => !editShut(state, { kind: "block", at: pos + 1 }));
126
117
  }
127
118
  function sharedValue(values) {
128
119
  const [first, ...rest] = values;
@@ -3,7 +3,7 @@ import {
3
3
  deleteTable as pmDeleteTable,
4
4
  isInTable as pmIsInTable
5
5
  } from "prosemirror-tables";
6
- import { transactionAllowed } from "../schema/guards.js";
6
+ import { guardedCommand } from "../schema/guards.js";
7
7
  import {
8
8
  buildAddColumnAfterTransaction,
9
9
  buildAddColumnBeforeTransaction,
@@ -18,26 +18,22 @@ import {
18
18
  function isInTable(state) {
19
19
  return pmIsInTable(state);
20
20
  }
21
- function toCommand(build) {
22
- return (state, dispatch) => {
23
- const tr = build(state);
24
- if (!tr || !transactionAllowed(tr, state)) return false;
25
- dispatch?.(tr);
26
- return true;
27
- };
28
- }
29
- var addRowBefore = toCommand(
21
+ var addRowBefore = guardedCommand(
30
22
  buildAddRowBeforeTransaction
31
23
  );
32
- var addRowAfter = toCommand(buildAddRowAfterTransaction);
33
- var deleteRow = toCommand(buildDeleteRowTransaction);
34
- var addColumnBefore = toCommand(
24
+ var addRowAfter = guardedCommand(
25
+ buildAddRowAfterTransaction
26
+ );
27
+ var deleteRow = guardedCommand(
28
+ buildDeleteRowTransaction
29
+ );
30
+ var addColumnBefore = guardedCommand(
35
31
  buildAddColumnBeforeTransaction
36
32
  );
37
- var addColumnAfter = toCommand(
33
+ var addColumnAfter = guardedCommand(
38
34
  buildAddColumnAfterTransaction
39
35
  );
40
- var deleteColumn = toCommand(
36
+ var deleteColumn = guardedCommand(
41
37
  buildDeleteColumnTransaction
42
38
  );
43
39
  function buildDeleteTableTransaction(state) {
@@ -46,9 +42,15 @@ function buildDeleteTableTransaction(state) {
46
42
  pmDeleteTable(state, (tr) => captured.push(tr));
47
43
  return captured[0] ?? null;
48
44
  }
49
- var deleteTable = toCommand(buildDeleteTableTransaction);
50
- var mergeCells = toCommand(buildMergeCellsTransaction);
51
- var splitCell = toCommand(buildSplitCellTransaction);
45
+ var deleteTable = guardedCommand(
46
+ buildDeleteTableTransaction
47
+ );
48
+ var mergeCells = guardedCommand(
49
+ buildMergeCellsTransaction
50
+ );
51
+ var splitCell = guardedCommand(
52
+ buildSplitCellTransaction
53
+ );
52
54
  export {
53
55
  addColumnAfter,
54
56
  addColumnBefore,
@@ -2,6 +2,9 @@
2
2
  * Newly created cells and rows inherit only the formatting of the cell or row they
3
3
  * are based on. Values that have to be recomputed from the grid (colspan, rowspan,
4
4
  * colwidth) are not inherited.
5
+ *
6
+ * What that comes to per attr is `docx/cloning`, which answers the same question for a
7
+ * paragraph an edit makes out of another paragraph.
5
8
  */
6
9
  import type { Node as PMNode } from "prosemirror-model";
7
10
  import type { GridRect } from "../docx/tableFormatting";
@@ -1,4 +1,5 @@
1
1
  // src/table/format.ts
2
+ import { CLONE_POLICIES } from "../docx/cloning.js";
2
3
  function isNumberArray(value) {
3
4
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
4
5
  }
@@ -6,18 +7,11 @@ function colwidthOf(cell) {
6
7
  const value = cell.attrs.colwidth;
7
8
  return isNumberArray(value) ? value : null;
8
9
  }
9
- var INHERITED_CELL_ATTRS = ["tcAttrs", "tcPr", "tcW", "format"];
10
10
  function inheritCellAttrs(cell, overrides = {}) {
11
- const attrs = {};
12
- for (const key of INHERITED_CELL_ATTRS) attrs[key] = cell.attrs[key];
13
- return { ...attrs, ...overrides };
11
+ return { ...CLONE_POLICIES.tableCell.attrs(cell, "copy"), ...overrides };
14
12
  }
15
- var INHERITED_ROW_ATTRS = ["trAttrs", "trPr", "format"];
16
13
  function inheritRowAttrs(row) {
17
- if (!row) return null;
18
- const attrs = {};
19
- for (const key of INHERITED_ROW_ATTRS) attrs[key] = row.attrs[key];
20
- return attrs;
14
+ return row ? CLONE_POLICIES.tableRow.attrs(row, "copy") : null;
21
15
  }
22
16
  export {
23
17
  colwidthOf,
@@ -1,42 +1,36 @@
1
1
  /**
2
- * The lines a cell draws because of where it sits in the grid, kept true after a structure edit.
2
+ * The lines and the fill a cell draws because of where it sits in the grid.
3
3
  *
4
4
  * Every line of a table is drawn by its cells (see `docx/tableFormatting`), so which line a side
5
- * falls back on depends on where in the grid the cell sits. A new cell inherits its neighbour's
6
- * formatting, which is what a background has to do but not a line: the row appended under the last
7
- * one would draw the table's outer line against the row above it, and deleting the last row would
8
- * leave the table with no line along its bottom.
5
+ * falls back on depends on where in the grid the cell sits, and so does which parts of the table
6
+ * style dress it. A new cell inherits its neighbour's formatting, which is what a background has to
7
+ * do but not a line: the row appended under the last one would draw the table's outer line against
8
+ * the row above it, and deleting the last row would leave the table with no line along its bottom.
9
+ * A row added under the header row is likewise no header row.
9
10
  *
10
11
  * So the cells of a table whose grid moved derive their display values again, along the same path
11
12
  * the import takes. What a cell wrote down itself lives in its `w:tcPr` and is read straight back
12
- * out of it, so only the share that came from the table can change.
13
+ * out of it, so only the share that came from the table can change. `cellFixes` says which cells
14
+ * carry the wrong lines and `sameFormattingInputs` whether anything they depend on moved; the
15
+ * deriver that runs them after an edit is `editor/plugins/tableDisplay`.
13
16
  */
14
17
  import type { Node as PMNode } from "prosemirror-model";
15
- import { Plugin } from "prosemirror-state";
16
- import { type CellBorderDefaults } from "../docx/tableFormatting";
17
- import { type CellMargins, type InsideBorders, type TableFormat } from "../model/format";
18
- import type { TableGridMap } from "./format";
18
+ import { type CellDefaults, type TableCellSources } from "../docx/tableFormatting";
19
+ import type { NodeAttrs, TableGridMap } from "./format";
19
20
  /**
20
- * What a table lays down for its cells to draw.
21
+ * What this table lays down for its cells to draw.
21
22
  * The values a table style laid down are not in the `tblPr`, so the table carries them separately.
23
+ * A node never changes once it is built, so what is read out of one is read once.
22
24
  */
23
- export interface TableCellSources {
24
- outer: TableFormat | null;
25
- inside: InsideBorders;
26
- margins: CellMargins;
27
- }
28
25
  export declare function tableCellSources(table: PMNode): TableCellSources;
29
- /** The lines the cell at this position falls back on for the sides it draws no border of its own on */
30
- export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources): CellBorderDefaults;
31
- /** Derives shared-border display values before the first editor view is drawn. */
32
- export declare function withDerivedGridBorders(doc: PMNode): PMNode;
33
- /**
34
- * Keeps the derived lines current after a table's grid or border inputs change.
35
- *
36
- * The tables are paired up by the order they stand in. A document that gained or lost a whole table
37
- * pairs the ones after it with the wrong partner, which costs a derivation that changes no cell.
38
- *
39
- * No transaction of its own goes to the history: ProseMirror hands an appended transaction to the
40
- * history as part of the same event, so a single undo takes the edit and this correction back together.
41
- */
42
- export declare function gridBorders(): Plugin;
26
+ /** What the cell at this position falls back on for everything it did not write down itself */
27
+ export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources): CellDefaults;
28
+ export interface CellFix {
29
+ /** The position of the cell within the table's content */
30
+ pos: number;
31
+ attrs: NodeAttrs;
32
+ }
33
+ /** The cells of this table whose display values do not match the spot they now sit in */
34
+ export declare function cellFixes(table: PMNode): CellFix[];
35
+ /** Whether everything the cells' lines are derived from reads the same in both tables */
36
+ export declare function sameFormattingInputs(a: PMNode, b: PMNode): boolean;
@@ -1,32 +1,39 @@
1
1
  // src/table/gridBorders.ts
2
- import { Plugin } from "prosemirror-state";
3
2
  import { TableMap } from "prosemirror-tables";
4
- import { Transform } from "prosemirror-transform";
5
3
  import {
6
- cellBorderDefaults,
4
+ cellDefaultsFor,
7
5
  cellMarginsOf,
8
- gridEdgesOf,
9
6
  insideBordersOf,
10
7
  layerCellMargins,
11
8
  layerInsideBorders,
12
- NO_BORDER_DEFAULTS,
9
+ NO_BAND_SIZES,
10
+ NO_CELL_DEFAULTS,
13
11
  NO_CELL_MARGINS,
14
12
  NO_INSIDE_BORDERS,
15
- readCellProps
13
+ NO_TABLE_STYLE_CONDITIONS,
14
+ readCellProps,
15
+ readTableLook,
16
+ tblStyleIdOf
16
17
  } from "../docx/tableFormatting.js";
17
18
  import {
18
19
  spanCount,
20
+ toBandSizes,
19
21
  toCellFormat,
20
22
  toCellMargins,
21
23
  toInsideBorders,
22
- toTableFormat
24
+ toTableFormat,
25
+ toTableStyleConditions
23
26
  } from "../model/format.js";
27
+ import { parsePropsXml } from "../ooxml/props.js";
24
28
  function text(value) {
25
29
  return typeof value === "string" ? value : null;
26
30
  }
27
31
  function tableCellSources(table) {
32
+ const known = sourcesByTable.get(table);
33
+ if (known) return known;
28
34
  const tblPr = text(table.attrs.tblPr);
29
- return {
35
+ const props = tblPr === null ? null : parsePropsXml(tblPr);
36
+ const sources = {
30
37
  outer: toTableFormat(table.attrs.format),
31
38
  inside: layerInsideBorders(
32
39
  toInsideBorders(table.attrs.styleInside) ?? NO_INSIDE_BORDERS,
@@ -35,14 +42,23 @@ function tableCellSources(table) {
35
42
  margins: layerCellMargins(
36
43
  toCellMargins(table.attrs.styleCellMargins) ?? NO_CELL_MARGINS,
37
44
  cellMarginsOf(tblPr)
38
- )
45
+ ),
46
+ look: readTableLook(props),
47
+ bands: toBandSizes(table.attrs.styleBands) ?? NO_BAND_SIZES,
48
+ conditions: toTableStyleConditions(table.attrs.styleConditions) ?? NO_TABLE_STYLE_CONDITIONS,
49
+ // The style the paragraphs inside resolve against; what it lays down for the cells is already
50
+ // in `styleConditions`
51
+ styleId: tblStyleIdOf(props)
39
52
  };
53
+ sourcesByTable.set(table, sources);
54
+ return sources;
40
55
  }
56
+ var sourcesByTable = /* @__PURE__ */ new WeakMap();
41
57
  function cellDefaultsAt(map, pos, sources) {
42
- return cellBorderDefaults(
43
- gridEdgesOf(map.findCell(pos), { rows: map.height, cols: map.width }),
44
- sources.outer,
45
- sources.inside
58
+ return cellDefaultsFor(
59
+ map.findCell(pos),
60
+ { rows: map.height, cols: map.width },
61
+ sources
46
62
  );
47
63
  }
48
64
  var CELL_FORMAT_KEYS = [
@@ -108,16 +124,12 @@ function cellFixes(table) {
108
124
  const cell = table.nodeAt(pos);
109
125
  if (!cell) continue;
110
126
  const tcPr = text(cell.attrs.tcPr);
111
- const format = readCellProps(
112
- tcPr,
113
- cellDefaultsAt(map, pos, sources),
114
- sources.margins
115
- );
127
+ const format = readCellProps(tcPr, cellDefaultsAt(map, pos, sources));
116
128
  cells.set(pos, {
117
129
  pos,
118
130
  attrs: cell.attrs,
119
131
  format: { ...format },
120
- direct: readCellProps(tcPr, NO_BORDER_DEFAULTS)
132
+ direct: readCellProps(tcPr, NO_CELL_DEFAULTS)
121
133
  });
122
134
  }
123
135
  reconcileSharedBorders(map, cells);
@@ -129,14 +141,6 @@ function cellFixes(table) {
129
141
  }
130
142
  return fixes;
131
143
  }
132
- function tablesOf(doc) {
133
- const tables = [];
134
- doc.descendants((node, pos) => {
135
- if (node.type.spec.tableRole === "table") tables.push({ pos, table: node });
136
- return !node.isTextblock;
137
- });
138
- return tables;
139
- }
140
144
  function sameSpans(a, b) {
141
145
  return spanCount(a.attrs.colspan) === spanCount(b.attrs.colspan) && spanCount(a.attrs.rowspan) === spanCount(b.attrs.rowspan);
142
146
  }
@@ -154,39 +158,11 @@ function sameCellFormattingInputs(a, b) {
154
158
  );
155
159
  }
156
160
  function sameFormattingInputs(a, b) {
157
- return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && sameCellFormattingInputs(a, b);
158
- }
159
- function withDerivedGridBorders(doc) {
160
- const transform = new Transform(doc);
161
- for (const { pos, table } of tablesOf(doc)) {
162
- for (const fix of cellFixes(table)) {
163
- transform.setNodeMarkup(pos + 1 + fix.pos, null, fix.attrs);
164
- }
165
- }
166
- return transform.doc;
167
- }
168
- function gridBorders() {
169
- return new Plugin({
170
- appendTransaction(transactions, oldState, newState) {
171
- if (!transactions.some((transaction) => transaction.docChanged)) {
172
- return null;
173
- }
174
- const before = tablesOf(oldState.doc);
175
- const tr = newState.tr;
176
- tablesOf(newState.doc).forEach(({ pos, table }, index) => {
177
- const was = before[index]?.table;
178
- if (was && sameFormattingInputs(was, table)) return;
179
- for (const fix of cellFixes(table)) {
180
- tr.setNodeMarkup(pos + 1 + fix.pos, null, fix.attrs);
181
- }
182
- });
183
- return tr.docChanged ? tr : null;
184
- }
185
- });
161
+ return sameGrid(a, b) && a.attrs.tblPr === b.attrs.tblPr && a.attrs.format === b.attrs.format && a.attrs.styleInside === b.attrs.styleInside && a.attrs.styleCellMargins === b.attrs.styleCellMargins && a.attrs.styleConditions === b.attrs.styleConditions && a.attrs.styleBands === b.attrs.styleBands && sameCellFormattingInputs(a, b);
186
162
  }
187
163
  export {
188
164
  cellDefaultsAt,
189
- gridBorders,
190
- tableCellSources,
191
- withDerivedGridBorders
165
+ cellFixes,
166
+ sameFormattingInputs,
167
+ tableCellSources
192
168
  };
@@ -7,17 +7,13 @@ import type { EditorState, Transaction } from "prosemirror-state";
7
7
  * Whether several cells can be merged into one.
8
8
  * The selection has to be a rectangle spanning more than one cell, no merged cell may stick out
9
9
  * past that rectangle, and the guards have to let the merge through: a locked cell may not be
10
- * swallowed by another (`schema/locks`).
11
- *
12
- * The two queries are defined from the very transaction the commands run, so they cannot drift
13
- * from them. They live here rather than beside the commands because `./commands` imports these
14
- * builders, and the other way round would turn that import around.
10
+ * swallowed by another (`schema/guards`).
15
11
  */
16
12
  export declare function canMergeCells(state: EditorState): boolean;
17
13
  /**
18
14
  * Whether a split is possible. The cursor has to sit inside a cell that is merged horizontally or
19
15
  * vertically, and the guards have to let the split through: the cells a split makes would each
20
- * carry the original's lock, which is a lock planted in places it was never put (`schema/locks`).
16
+ * carry the original's lock, which is a lock planted in places it was never put (`schema/guards`).
21
17
  */
22
18
  export declare function canSplitCell(state: EditorState): boolean;
23
19
  /**
@@ -11,7 +11,7 @@ import {
11
11
  widthNumber,
12
12
  withWidthNumber
13
13
  } from "../model/format.js";
14
- import { transactionAllowed } from "../schema/guards.js";
14
+ import { guardedCommand } from "../schema/guards.js";
15
15
  import { inheritCellAttrs } from "./format.js";
16
16
  import { cellWidthForGridCol, gridSpanWidth, tableGridCols } from "./widths.js";
17
17
  function tableAfter(tr, tableStart) {
@@ -24,13 +24,13 @@ function cellAt(rect, row, col) {
24
24
  const pos = rect.map.map[row * rect.map.width + col];
25
25
  return pos == null ? null : rect.table.nodeAt(pos);
26
26
  }
27
+ var merging = guardedCommand(buildMergeCellsTransaction);
28
+ var splitting = guardedCommand(buildSplitCellTransaction);
27
29
  function canMergeCells(state) {
28
- const tr = buildMergeCellsTransaction(state);
29
- return tr !== null && transactionAllowed(tr, state);
30
+ return merging(state);
30
31
  }
31
32
  function canSplitCell(state) {
32
- const tr = buildSplitCellTransaction(state);
33
- return tr !== null && transactionAllowed(tr, state);
33
+ return splitting(state);
34
34
  }
35
35
  function coveredWidthSum(rect, type) {
36
36
  let sum = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portone/docx-editor",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "A simple DOCX editor for React, built directly on OOXML.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -107,17 +107,21 @@
107
107
  "build:demo": "vite build --config demo/vite.config.ts",
108
108
  "dev:site": "pnpm --filter @portone/docx-editor-site dev",
109
109
  "build:site": "pnpm --filter @portone/docx-editor-site build",
110
- "check": "pnpm lint && pnpm typecheck && pnpm test",
110
+ "check": "pnpm lint && pnpm typecheck && pnpm test && pnpm test:fixtures && pnpm test:site-release && pnpm check:demo-library",
111
111
  "typecheck": "tsc --noEmit && tsc --noEmit -p e2e && tsc --noEmit -p demo && pnpm --filter @portone/docx-editor-site typecheck",
112
112
  "lint": "pnpm biome check . --diagnostic-level=error",
113
113
  "test": "vitest run",
114
+ "test:fixtures": "node --test scripts/sanitize-fixture.test.mjs",
114
115
  "test:package": "vitest run --dir packaging --no-file-parallelism",
115
116
  "verify:package": "node scripts/verify-package.mjs",
117
+ "check:demo-library": "node scripts/demo-library-pin.mjs",
118
+ "pin:demo-library": "node scripts/demo-library-pin.mjs --write",
116
119
  "api:update": "pnpm build && node scripts/api-report.mjs --local",
117
120
  "spec": "node scripts/index-ooxml-spec.mjs",
118
121
  "changeset": "changeset",
119
122
  "changeset:version": "changeset version",
120
- "test:e2e": "playwright test"
123
+ "test:e2e": "playwright test",
124
+ "test:site-release": "node --test scripts/site-release.test.mjs"
121
125
  },
122
126
  "types": "./dist/index.d.ts"
123
127
  }
@@ -1,7 +0,0 @@
1
- /** Declares a part an export adds in `[Content_Types].xml`, leaving the original text as it came. */
2
- /**
3
- * The content types part with an override for this part, or null when it already declares one.
4
- * `current` is the part as an earlier addition in the same export left it, so that two additions
5
- * do not each write over the other's declaration.
6
- */
7
- export declare function withContentType(parts: Map<string, Uint8Array>, partPath: string, contentType: string, current: Uint8Array | undefined): Uint8Array | null;
@@ -1,38 +0,0 @@
1
- // src/docx/comments/contentTypes.ts
2
- import { DocxExportError } from "../../ooxml/errors.js";
3
- import { decodeUtf8, encodeUtf8 } from "../../ooxml/xml.js";
4
- import { CONTENT_TYPES_PATH } from "./constants.js";
5
- var TYPES_OPEN_TAG = /<(?:[\w.-]+:)?Types\b[^>]*>/;
6
- function withContentType(parts, partPath, contentType, current) {
7
- const original = current ?? parts.get(CONTENT_TYPES_PATH);
8
- if (!original) {
9
- throw new DocxExportError(
10
- "missing-content-types",
11
- `cannot add a part to a package that has no ${CONTENT_TYPES_PATH}`
12
- );
13
- }
14
- const { text, hadBom } = decodeUtf8(original);
15
- const partName = `/${partPath}`;
16
- if (new RegExp(
17
- `<(?:[\\w.-]+:)?Override[^>]+PartName=["']${partName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`,
18
- "i"
19
- ).test(text)) {
20
- return null;
21
- }
22
- const open = TYPES_OPEN_TAG.exec(text);
23
- if (!open) {
24
- throw new DocxExportError(
25
- "malformed-xml",
26
- `${CONTENT_TYPES_PATH} has no Types element`
27
- );
28
- }
29
- const rootName = /^<([^\s>]+)/.exec(open[0])?.[1] ?? "Types";
30
- const separator = rootName.indexOf(":");
31
- const prefix = separator < 0 ? "" : `${rootName.slice(0, separator)}:`;
32
- const declaration = `<${prefix}Override PartName="${partName}" ContentType="${contentType}"/>`;
33
- const at = open.index + open[0].length;
34
- return encodeUtf8(text.slice(0, at) + declaration + text.slice(at), hadBom);
35
- }
36
- export {
37
- withContentType
38
- };