@portone/docx-editor 0.3.0 → 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 (90) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/DocxEditor.js +1 -0
  3. package/dist/core.d.ts +1 -1
  4. package/dist/docx/comments/writing.js +14 -8
  5. package/dist/docx/exportDocx.js +20 -4
  6. package/dist/docx/formatting/attrs.d.ts +20 -2
  7. package/dist/docx/formatting/attrs.js +57 -2
  8. package/dist/docx/formatting/context.d.ts +10 -2
  9. package/dist/docx/formatting/context.js +23 -5
  10. package/dist/docx/formatting/resolve.d.ts +10 -4
  11. package/dist/docx/formatting/resolve.js +31 -11
  12. package/dist/docx/formatting/styles.d.ts +25 -2
  13. package/dist/docx/formatting/styles.js +84 -3
  14. package/dist/docx/hyperlink.d.ts +14 -4
  15. package/dist/docx/hyperlink.js +4 -1
  16. package/dist/docx/importDocx.js +46 -37
  17. package/dist/docx/importTable.d.ts +2 -2
  18. package/dist/docx/importTable.js +52 -55
  19. package/dist/docx/invariants.js +26 -13
  20. package/dist/docx/newLists.d.ts +30 -0
  21. package/dist/docx/newLists.js +24 -1
  22. package/dist/docx/numberingPlanner.d.ts +6 -3
  23. package/dist/docx/numberingPlanner.js +38 -7
  24. package/dist/docx/session.d.ts +1 -1
  25. package/dist/docx/session.js +11 -1
  26. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  27. package/dist/docx/tableFormatting/conditions.js +196 -0
  28. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  29. package/dist/docx/tableFormatting/editing.js +4 -5
  30. package/dist/docx/tableFormatting/reading.d.ts +49 -19
  31. package/dist/docx/tableFormatting/reading.js +109 -35
  32. package/dist/docx/tableFormatting.d.ts +1 -0
  33. package/dist/docx/tableFormatting.js +1 -0
  34. package/dist/docx/tableTemplate.js +12 -12
  35. package/dist/editor/commands/formatting/propertyCommands.js +6 -1
  36. package/dist/editor/commands/listCommands.d.ts +6 -3
  37. package/dist/editor/commands/listCommands.js +73 -28
  38. package/dist/editor/commands/paragraphCommands.js +6 -1
  39. package/dist/editor/createEditor.js +1 -1
  40. package/dist/editor/editorDocument.d.ts +7 -6
  41. package/dist/editor/editorDocument.js +18 -6
  42. package/dist/editor/externalClipboard.d.ts +13 -2
  43. package/dist/editor/externalClipboard.js +64 -34
  44. package/dist/editor/paragraphEdits.d.ts +16 -1
  45. package/dist/editor/paragraphEdits.js +13 -5
  46. package/dist/editor/paragraphPlacement.d.ts +11 -0
  47. package/dist/editor/paragraphPlacement.js +18 -0
  48. package/dist/editor/plugins/imagePaste.js +7 -4
  49. package/dist/editor/plugins/numberingDecorations.d.ts +10 -4
  50. package/dist/editor/plugins/numberingDecorations.js +43 -2
  51. package/dist/editor/plugins/paragraphDisplay.js +9 -3
  52. package/dist/editor/plugins/tableDisplay.js +19 -5
  53. package/dist/model/format.d.ts +50 -0
  54. package/dist/model/format.js +65 -0
  55. package/dist/numbering/listRegistry.d.ts +37 -0
  56. package/dist/numbering/listRegistry.js +112 -0
  57. package/dist/numbering/listTemplate.d.ts +26 -17
  58. package/dist/numbering/listTemplate.js +66 -20
  59. package/dist/numbering/markers.d.ts +15 -6
  60. package/dist/numbering/markers.js +26 -59
  61. package/dist/numbering/parseNumbering.d.ts +70 -5
  62. package/dist/numbering/parseNumbering.js +100 -26
  63. package/dist/numbering/spellers.d.ts +15 -0
  64. package/dist/numbering/spellers.js +96 -0
  65. package/dist/numbering/writeNumbering.d.ts +5 -3
  66. package/dist/numbering/writeNumbering.js +15 -15
  67. package/dist/ooxml/conformance.d.ts +28 -0
  68. package/dist/ooxml/conformance.js +20 -0
  69. package/dist/ooxml/errors.d.ts +5 -5
  70. package/dist/ooxml/names.d.ts +9 -0
  71. package/dist/ooxml/names.js +8 -1
  72. package/dist/ooxml/partSplice.d.ts +1 -1
  73. package/dist/ooxml/partSplice.js +10 -3
  74. package/dist/ooxml/xml.d.ts +8 -9
  75. package/dist/ooxml/xml.js +6 -6
  76. package/dist/page/PageGuides.d.ts +1 -1
  77. package/dist/page/PageGuides.js +0 -13
  78. package/dist/page/pageLayout.d.ts +0 -10
  79. package/dist/page/pageLayout.js +3 -10
  80. package/dist/page/usePageLayout.d.ts +0 -7
  81. package/dist/page/usePageLayout.js +2 -9
  82. package/dist/schema/attrRoles.js +8 -1
  83. package/dist/schema/docxSchema.js +32 -3
  84. package/dist/styles/classNames.d.ts +13 -2
  85. package/dist/styles/classNames.js +13 -2
  86. package/dist/styles.css +16 -18
  87. package/dist/table/cellFormatting.js +1 -2
  88. package/dist/table/gridBorders.d.ts +11 -15
  89. package/dist/table/gridBorders.js +32 -18
  90. package/package.json +1 -1
@@ -77,25 +77,18 @@ function pageLayout({
77
77
  const pushes = [];
78
78
  const cuts = [];
79
79
  const splits = [];
80
- const firstPage = {
81
- page: 1,
82
- bodyStart: 0,
83
- exactPage: true,
84
- crossed: false
85
- };
80
+ const firstPage = { page: 1, bodyStart: 0, crossed: false };
86
81
  const pages = [firstPage];
87
82
  if (!(pageBodyHeight > 0)) {
88
83
  return { pushes, cuts, splits, pages, bodyHeight: 0 };
89
84
  }
90
85
  let pageStart = 0;
91
86
  let cursor = 0;
92
- let exactPage = true;
93
87
  const split = (y, crossed, forced) => {
94
- if (!forced) exactPage = false;
95
88
  const page = splits.length + 2;
96
- splits.push({ y: round(y), page, forced, exactPage, crossed });
89
+ splits.push({ y: round(y), page, forced, crossed });
97
90
  pageStart = crossed ? y : y + pageStep;
98
- pages.push({ page, bodyStart: round(pageStart), exactPage, crossed });
91
+ pages.push({ page, bodyStart: round(pageStart), crossed });
99
92
  };
100
93
  const crossTo = (y) => {
101
94
  while (y > pageStart + pageBodyHeight + TOLERANCE_PX) {
@@ -19,12 +19,6 @@ export interface PageMark {
19
19
  height: number;
20
20
  crossed: boolean;
21
21
  }
22
- /** The number laid on the corner of a page */
23
- export interface PageBadge {
24
- page: number;
25
- top: number;
26
- exactPage: boolean;
27
- }
28
22
  /** The paper area of one visual page, used to place its header and footer stories. */
29
23
  export interface PageFace {
30
24
  page: number;
@@ -41,7 +35,6 @@ export interface PageOverlay {
41
35
  /** The sheet height with the last page filled out in full */
42
36
  sheetHeight: number;
43
37
  marks: PageMark[];
44
- badges: PageBadge[];
45
38
  pages: PageFace[];
46
39
  }
47
40
  interface PageLayoutOptions {
@@ -15,7 +15,6 @@ import {
15
15
  pageLayout,
16
16
  pagePixels
17
17
  } from "./pageLayout.js";
18
- var BADGE_INSET_PX = 8;
19
18
  function useFrameThrottle(run, hold) {
20
19
  const latest = useRef({ run, hold });
21
20
  const frame = useRef(0);
@@ -46,7 +45,7 @@ function useFrameThrottle(run, hold) {
46
45
  }, []);
47
46
  }
48
47
  function sameOverlay(a, b) {
49
- return a !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.sheetHeight === b.sheetHeight && JSON.stringify(a.marks) === JSON.stringify(b.marks) && JSON.stringify(a.badges) === JSON.stringify(b.badges) && JSON.stringify(a.pages) === JSON.stringify(b.pages);
48
+ return a !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.sheetHeight === b.sheetHeight && JSON.stringify(a.marks) === JSON.stringify(b.marks) && JSON.stringify(a.pages) === JSON.stringify(b.pages);
50
49
  }
51
50
  function usePageLayout({
52
51
  view,
@@ -84,13 +83,7 @@ function usePageLayout({
84
83
  height: split.crossed ? 0 : PAGE_SPLIT_PX,
85
84
  crossed: split.crossed
86
85
  })),
87
- // The number is laid on the page's top corner. A page crossed into has no margin,
88
- // so the place it was split at is its corner
89
- badges: layout.pages.map((start) => ({
90
- page: start.page,
91
- top: measured.contentTop + start.bodyStart - (start.crossed ? 0 : page.marginTop) + BADGE_INSET_PX,
92
- exactPage: start.exactPage
93
- })),
86
+ // A page crossed into has no margin, so the place it was split at is its top corner
94
87
  pages: layout.pages.map((start) => {
95
88
  const paperTop = measured.contentTop + start.bodyStart - (start.crossed ? 0 : page.marginTop);
96
89
  return {
@@ -1,6 +1,11 @@
1
1
  // src/schema/attrRoles.ts
2
2
  import { NodeType } from "prosemirror-model";
3
3
  var NODE_ATTR_ROLES = {
4
+ doc: {
5
+ // The definitions of the lists started while editing. The export writes numbering.xml from
6
+ // them and nothing derives them again, so they are a source value the document node holds
7
+ newLists: { role: "source", class: "model" }
8
+ },
4
9
  paragraph: {
5
10
  srcId: { role: "session", class: "identity" },
6
11
  pAttrs: { role: "source", class: "preserved" },
@@ -18,7 +23,9 @@ var NODE_ATTR_ROLES = {
18
23
  gridChange: { role: "source", class: "preserved" },
19
24
  format: { role: "display", class: "derived" },
20
25
  styleInside: { role: "display", class: "derived" },
21
- styleCellMargins: { role: "display", class: "derived" }
26
+ styleCellMargins: { role: "display", class: "derived" },
27
+ styleConditions: { role: "display", class: "derived" },
28
+ styleBands: { role: "display", class: "derived" }
22
29
  },
23
30
  tableRow: {
24
31
  trAttrs: { role: "source", class: "preserved" },
@@ -2,6 +2,7 @@
2
2
  import { Schema } from "prosemirror-model";
3
3
  import {
4
4
  spanCount,
5
+ toBandSizes,
5
6
  toCellFormat,
6
7
  toCellMargins,
7
8
  toColWidth,
@@ -11,6 +12,7 @@ import {
11
12
  toRowFormat,
12
13
  toRunFormat,
13
14
  toTableFormat,
15
+ toTableStyleConditions,
14
16
  toTableWidth
15
17
  } from "../model/format.js";
16
18
  import {
@@ -112,7 +114,16 @@ var DOCX_RAW_SELECTOR = [
112
114
  ].map((className) => `div[data-src].${className}`).join(", ");
113
115
  var docxSchema = new Schema({
114
116
  nodes: {
115
- doc: { content: "block+" },
117
+ doc: {
118
+ content: "block+",
119
+ attrs: {
120
+ /**
121
+ * The definitions of the lists started while editing, which the export writes into
122
+ * numbering.xml. Read back through `numbering/listRegistry`.
123
+ */
124
+ newLists: { default: null }
125
+ }
126
+ },
116
127
  paragraph: {
117
128
  group: "block modelled",
118
129
  content: "inline*",
@@ -202,7 +213,15 @@ var docxSchema = new Schema({
202
213
  /** The lines between cells the table style laid down, so an edit can derive them again */
203
214
  styleInside: { default: null },
204
215
  /** The cell margins the table style laid down, carried along for the same reason */
205
- styleCellMargins: { default: null }
216
+ styleCellMargins: { default: null },
217
+ /**
218
+ * What the table style dresses each part of a table with (`w:tblStylePr`), by the part it
219
+ * covers. Which of them a cell takes is worked out from where it sits and the table's own
220
+ * `w:tblLook`, so an edit that moves the grid derives them again
221
+ */
222
+ styleConditions: { default: null },
223
+ /** How many rows and columns one band of the table style is made of */
224
+ styleBands: { default: null }
206
225
  },
207
226
  toDOM(node) {
208
227
  const format = toTableFormat(node.attrs.format);
@@ -223,7 +242,11 @@ var docxSchema = new Schema({
223
242
  ),
224
243
  "data-style-margins": formatJson(
225
244
  toCellMargins(node.attrs.styleCellMargins)
226
- )
245
+ ),
246
+ "data-style-conditions": formatJson(
247
+ toTableStyleConditions(node.attrs.styleConditions)
248
+ ),
249
+ "data-style-bands": formatJson(toBandSizes(node.attrs.styleBands))
227
250
  };
228
251
  const body = ["tbody", 0];
229
252
  if (gridCols.length === 0) return ["table", attrs, body];
@@ -262,6 +285,12 @@ var docxSchema = new Schema({
262
285
  ),
263
286
  styleCellMargins: toCellMargins(
264
287
  parseJson(dom.getAttribute("data-style-margins"))
288
+ ),
289
+ styleConditions: toTableStyleConditions(
290
+ parseJson(dom.getAttribute("data-style-conditions"))
291
+ ),
292
+ styleBands: toBandSizes(
293
+ parseJson(dom.getAttribute("data-style-bands"))
265
294
  )
266
295
  };
267
296
  }
@@ -61,8 +61,6 @@ export declare const editorClassNames: {
61
61
  readonly pageSplit: "docx-editor-page-split";
62
62
  /** The line drawn where a block that cannot be pushed down crosses a page */
63
63
  readonly pageCrossed: "docx-editor-page-crossed";
64
- /** The page number laid on the top corner of a page */
65
- readonly pageBadge: "docx-editor-page-badge";
66
64
  /** A first-section header story projected into a visual page margin */
67
65
  readonly pageHeader: "docx-editor-page-header";
68
66
  /** A first-section footer story projected into a visual page margin */
@@ -165,6 +163,19 @@ export declare const editorCssVariables: {
165
163
  readonly lineHeight: "--docx-editor-line-height";
166
164
  /** The hanging indent width the list marker sits in */
167
165
  readonly markerWidth: "--docx-editor-marker-width";
166
+ /** The room kept after the list marker, which a level asking for no tab closes up (`w:suff`) */
167
+ readonly markerGap: "--docx-editor-marker-gap";
168
+ /** Where the marker sits inside the width kept for it (`w:lvlJc`) */
169
+ readonly markerAlign: "--docx-editor-marker-align";
170
+ /**
171
+ * The formatting the numbering level puts on its marker (`lvl/rPr`). It dresses the marker
172
+ * alone, so it reaches the pseudo-element that draws it and nothing the paragraph holds
173
+ */
174
+ readonly markerFontWeight: "--docx-editor-marker-font-weight";
175
+ readonly markerFontStyle: "--docx-editor-marker-font-style";
176
+ readonly markerColor: "--docx-editor-marker-color";
177
+ readonly markerFontSize: "--docx-editor-marker-font-size";
178
+ readonly markerFontFamily: "--docx-editor-marker-font-family";
168
179
  /** The width calculated for a tab using custom paragraph stops. */
169
180
  readonly tabWidth: "--docx-editor-tab-width";
170
181
  /** The paper height, grown to match the page count */
@@ -56,8 +56,6 @@ var editorClassNames = {
56
56
  pageSplit: `${PREFIX}-page-split`,
57
57
  /** The line drawn where a block that cannot be pushed down crosses a page */
58
58
  pageCrossed: `${PREFIX}-page-crossed`,
59
- /** The page number laid on the top corner of a page */
60
- pageBadge: `${PREFIX}-page-badge`,
61
59
  /** A first-section header story projected into a visual page margin */
62
60
  pageHeader: `${PREFIX}-page-header`,
63
61
  /** A first-section footer story projected into a visual page margin */
@@ -161,6 +159,19 @@ var editorCssVariables = {
161
159
  lineHeight: `--${PREFIX}-line-height`,
162
160
  /** The hanging indent width the list marker sits in */
163
161
  markerWidth: `--${PREFIX}-marker-width`,
162
+ /** The room kept after the list marker, which a level asking for no tab closes up (`w:suff`) */
163
+ markerGap: `--${PREFIX}-marker-gap`,
164
+ /** Where the marker sits inside the width kept for it (`w:lvlJc`) */
165
+ markerAlign: `--${PREFIX}-marker-align`,
166
+ /**
167
+ * The formatting the numbering level puts on its marker (`lvl/rPr`). It dresses the marker
168
+ * alone, so it reaches the pseudo-element that draws it and nothing the paragraph holds
169
+ */
170
+ markerFontWeight: `--${PREFIX}-marker-font-weight`,
171
+ markerFontStyle: `--${PREFIX}-marker-font-style`,
172
+ markerColor: `--${PREFIX}-marker-color`,
173
+ markerFontSize: `--${PREFIX}-marker-font-size`,
174
+ markerFontFamily: `--${PREFIX}-marker-font-family`,
164
175
  /** The width calculated for a tab using custom paragraph stops. */
165
176
  tabWidth: `--${PREFIX}-tab-width`,
166
177
  /** The paper height, grown to match the page count */
package/dist/styles.css CHANGED
@@ -677,22 +677,6 @@ button.docx-editor-comment-body {
677
677
  border-top: 1px dotted rgb(26 79 208 / 40%);
678
678
  }
679
679
 
680
- /* The page number. Laid on the top right corner of every page */
681
- .docx-editor-page-badge {
682
- position: absolute;
683
- right: 10px;
684
- min-width: 18px;
685
- padding: 0 6px;
686
- border-radius: 9px;
687
- background: rgb(0 0 0 / 6%);
688
- color: #808080;
689
- font-family: system-ui, sans-serif;
690
- font-size: 10px;
691
- line-height: 18px;
692
- text-align: center;
693
- letter-spacing: 0.02em;
694
- }
695
-
696
680
  /* Display-only projections of the first section's header and footer stories. */
697
681
  .docx-editor-page-header,
698
682
  .docx-editor-page-footer {
@@ -720,14 +704,28 @@ button.docx-editor-comment-body {
720
704
  * the space.
721
705
  * Because box-sizing is border-box, as long as the number fits inside the space it
722
706
  * does not push where the body starts.
707
+ *
708
+ * A level that asks for a space or for nothing after its number (w:suff) keeps no
709
+ * space at all, so both variables are set to zero and the body starts right after
710
+ * the number. Where the number sits inside the space is the level's w:lvlJc.
711
+ *
712
+ * The level dresses its number and nothing else (lvl/rPr), so its character
713
+ * formatting arrives as variables read here rather than as anything the paragraph
714
+ * wears. Where the level writes none, the number is drawn like the text it stands
715
+ * in front of.
723
716
  */
724
717
  .docx-editor-p[data-marker]::before {
725
718
  content: attr(data-marker);
726
719
  display: inline-block;
727
720
  box-sizing: border-box;
728
721
  min-width: var(--docx-editor-marker-width, 18pt);
729
- padding-right: 4pt;
730
- text-align: left;
722
+ padding-right: var(--docx-editor-marker-gap, 4pt);
723
+ text-align: var(--docx-editor-marker-align, left);
724
+ font-weight: var(--docx-editor-marker-font-weight, inherit);
725
+ font-style: var(--docx-editor-marker-font-style, inherit);
726
+ font-size: var(--docx-editor-marker-font-size, inherit);
727
+ font-family: var(--docx-editor-marker-font-family, inherit);
728
+ color: var(--docx-editor-marker-color, inherit);
731
729
  /* Keeps the paragraph's hanging indent (text-indent) from being inherited and shifting the number again inside its own box */
732
730
  text-indent: 0;
733
731
  user-select: none;
@@ -38,8 +38,7 @@ function planChanges(rect, edit) {
38
38
  const next = editCellProps(
39
39
  text(cell.attrs.tcPr),
40
40
  edit(rect, pos),
41
- cellDefaultsAt(rect.map, pos, sources),
42
- sources.margins
41
+ cellDefaultsAt(rect.map, pos, sources)
43
42
  );
44
43
  if (!next) continue;
45
44
  changes.push({
@@ -1,11 +1,12 @@
1
1
  /**
2
- * The lines a cell draws because of where it sits in the grid.
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
@@ -14,21 +15,16 @@
14
15
  * deriver that runs them after an edit is `editor/plugins/tableDisplay`.
15
16
  */
16
17
  import type { Node as PMNode } from "prosemirror-model";
17
- import { type CellBorderDefaults } from "../docx/tableFormatting";
18
- import { type CellMargins, type InsideBorders, type TableFormat } from "../model/format";
18
+ import { type CellDefaults, type TableCellSources } from "../docx/tableFormatting";
19
19
  import type { NodeAttrs, TableGridMap } from "./format";
20
20
  /**
21
- * What a table lays down for its cells to draw.
21
+ * What this table lays down for its cells to draw.
22
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.
23
24
  */
24
- export interface TableCellSources {
25
- outer: TableFormat | null;
26
- inside: InsideBorders;
27
- margins: CellMargins;
28
- }
29
25
  export declare function tableCellSources(table: PMNode): TableCellSources;
30
- /** The lines the cell at this position falls back on for the sides it draws no border of its own on */
31
- export declare function cellDefaultsAt(map: TableGridMap, pos: number, sources: TableCellSources): CellBorderDefaults;
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;
32
28
  export interface CellFix {
33
29
  /** The position of the cell within the table's content */
34
30
  pos: number;
@@ -1,30 +1,39 @@
1
1
  // src/table/gridBorders.ts
2
2
  import { TableMap } from "prosemirror-tables";
3
3
  import {
4
- cellBorderDefaults,
4
+ cellDefaultsFor,
5
5
  cellMarginsOf,
6
- gridEdgesOf,
7
6
  insideBordersOf,
8
7
  layerCellMargins,
9
8
  layerInsideBorders,
10
- NO_BORDER_DEFAULTS,
9
+ NO_BAND_SIZES,
10
+ NO_CELL_DEFAULTS,
11
11
  NO_CELL_MARGINS,
12
12
  NO_INSIDE_BORDERS,
13
- readCellProps
13
+ NO_TABLE_STYLE_CONDITIONS,
14
+ readCellProps,
15
+ readTableLook,
16
+ tblStyleIdOf
14
17
  } from "../docx/tableFormatting.js";
15
18
  import {
16
19
  spanCount,
20
+ toBandSizes,
17
21
  toCellFormat,
18
22
  toCellMargins,
19
23
  toInsideBorders,
20
- toTableFormat
24
+ toTableFormat,
25
+ toTableStyleConditions
21
26
  } from "../model/format.js";
27
+ import { parsePropsXml } from "../ooxml/props.js";
22
28
  function text(value) {
23
29
  return typeof value === "string" ? value : null;
24
30
  }
25
31
  function tableCellSources(table) {
32
+ const known = sourcesByTable.get(table);
33
+ if (known) return known;
26
34
  const tblPr = text(table.attrs.tblPr);
27
- return {
35
+ const props = tblPr === null ? null : parsePropsXml(tblPr);
36
+ const sources = {
28
37
  outer: toTableFormat(table.attrs.format),
29
38
  inside: layerInsideBorders(
30
39
  toInsideBorders(table.attrs.styleInside) ?? NO_INSIDE_BORDERS,
@@ -33,14 +42,23 @@ function tableCellSources(table) {
33
42
  margins: layerCellMargins(
34
43
  toCellMargins(table.attrs.styleCellMargins) ?? NO_CELL_MARGINS,
35
44
  cellMarginsOf(tblPr)
36
- )
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)
37
52
  };
53
+ sourcesByTable.set(table, sources);
54
+ return sources;
38
55
  }
56
+ var sourcesByTable = /* @__PURE__ */ new WeakMap();
39
57
  function cellDefaultsAt(map, pos, sources) {
40
- return cellBorderDefaults(
41
- gridEdgesOf(map.findCell(pos), { rows: map.height, cols: map.width }),
42
- sources.outer,
43
- sources.inside
58
+ return cellDefaultsFor(
59
+ map.findCell(pos),
60
+ { rows: map.height, cols: map.width },
61
+ sources
44
62
  );
45
63
  }
46
64
  var CELL_FORMAT_KEYS = [
@@ -106,16 +124,12 @@ function cellFixes(table) {
106
124
  const cell = table.nodeAt(pos);
107
125
  if (!cell) continue;
108
126
  const tcPr = text(cell.attrs.tcPr);
109
- const format = readCellProps(
110
- tcPr,
111
- cellDefaultsAt(map, pos, sources),
112
- sources.margins
113
- );
127
+ const format = readCellProps(tcPr, cellDefaultsAt(map, pos, sources));
114
128
  cells.set(pos, {
115
129
  pos,
116
130
  attrs: cell.attrs,
117
131
  format: { ...format },
118
- direct: readCellProps(tcPr, NO_BORDER_DEFAULTS)
132
+ direct: readCellProps(tcPr, NO_CELL_DEFAULTS)
119
133
  });
120
134
  }
121
135
  reconcileSharedBorders(map, cells);
@@ -144,7 +158,7 @@ function sameCellFormattingInputs(a, b) {
144
158
  );
145
159
  }
146
160
  function sameFormattingInputs(a, b) {
147
- 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);
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);
148
162
  }
149
163
  export {
150
164
  cellDefaultsAt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portone/docx-editor",
3
- "version": "0.3.0",
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",