@portone/docx-editor 0.3.0 → 0.5.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 (217) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/assets/editor.png +0 -0
  3. package/dist/DocxEditor.d.ts +1 -1
  4. package/dist/DocxEditor.js +45 -25
  5. package/dist/core.d.ts +1 -1
  6. package/dist/docx/cloning.js +4 -9
  7. package/dist/docx/commentOnlyChange.d.ts +5 -3
  8. package/dist/docx/comments/grammar.d.ts +27 -10
  9. package/dist/docx/comments/grammar.js +18 -67
  10. package/dist/docx/comments/model.d.ts +5 -6
  11. package/dist/docx/comments/model.js +0 -9
  12. package/dist/docx/comments/parts.d.ts +16 -10
  13. package/dist/docx/comments/parts.js +65 -13
  14. package/dist/docx/comments/people.d.ts +11 -3
  15. package/dist/docx/comments/people.js +20 -6
  16. package/dist/docx/comments/policy.js +7 -1
  17. package/dist/docx/comments/reading.d.ts +4 -2
  18. package/dist/docx/comments/reading.js +1 -14
  19. package/dist/docx/comments/writing.js +78 -35
  20. package/dist/docx/exportDocx.js +30 -18
  21. package/dist/docx/exportRefs.d.ts +8 -3
  22. package/dist/docx/exportRefs.js +2 -1
  23. package/dist/docx/fidelity.js +24 -10
  24. package/dist/docx/fields.d.ts +42 -0
  25. package/dist/docx/fields.js +76 -0
  26. package/dist/docx/formatting/attrs.d.ts +20 -2
  27. package/dist/docx/formatting/attrs.js +57 -2
  28. package/dist/docx/formatting/context.d.ts +10 -2
  29. package/dist/docx/formatting/context.js +23 -5
  30. package/dist/docx/formatting/resolve.d.ts +10 -4
  31. package/dist/docx/formatting/resolve.js +31 -11
  32. package/dist/docx/formatting/styles.d.ts +25 -2
  33. package/dist/docx/formatting/styles.js +84 -3
  34. package/dist/docx/headersFooters.d.ts +89 -20
  35. package/dist/docx/headersFooters.js +163 -172
  36. package/dist/docx/hyperlink.d.ts +14 -4
  37. package/dist/docx/hyperlink.js +4 -1
  38. package/dist/docx/importDocx.d.ts +1 -1
  39. package/dist/docx/importDocx.js +135 -74
  40. package/dist/docx/importParagraph.d.ts +16 -4
  41. package/dist/docx/importParagraph.js +87 -93
  42. package/dist/docx/importPolicy.d.ts +70 -0
  43. package/dist/docx/importPolicy.js +190 -0
  44. package/dist/docx/importPreserved.d.ts +30 -0
  45. package/dist/docx/importPreserved.js +54 -0
  46. package/dist/docx/importTable.d.ts +2 -2
  47. package/dist/docx/importTable.js +107 -66
  48. package/dist/docx/invariants.js +42 -31
  49. package/dist/docx/newLists.d.ts +30 -0
  50. package/dist/docx/newLists.js +24 -1
  51. package/dist/docx/notes.d.ts +6 -1
  52. package/dist/docx/notes.js +6 -16
  53. package/dist/docx/numberingPlanner.d.ts +6 -3
  54. package/dist/docx/numberingPlanner.js +38 -7
  55. package/dist/docx/pageGeometry.d.ts +5 -14
  56. package/dist/docx/pageGeometry.js +0 -12
  57. package/dist/docx/protectionPolicy.d.ts +13 -5
  58. package/dist/docx/protectionPolicy.js +32 -22
  59. package/dist/docx/scan.d.ts +18 -8
  60. package/dist/docx/scan.js +17 -11
  61. package/dist/docx/sections.d.ts +126 -0
  62. package/dist/docx/sections.js +207 -0
  63. package/dist/docx/serializeBlock.d.ts +13 -4
  64. package/dist/docx/serializeBlock.js +16 -18
  65. package/dist/docx/serializeParagraph.d.ts +4 -0
  66. package/dist/docx/serializeParagraph.js +1 -0
  67. package/dist/docx/serializePreserved.d.ts +14 -0
  68. package/dist/docx/serializePreserved.js +24 -0
  69. package/dist/docx/serializeStory.d.ts +17 -0
  70. package/dist/docx/serializeStory.js +17 -0
  71. package/dist/docx/serializeTable.js +10 -13
  72. package/dist/docx/session.d.ts +24 -7
  73. package/dist/docx/session.js +37 -6
  74. package/dist/docx/story.d.ts +140 -0
  75. package/dist/docx/story.js +237 -0
  76. package/dist/docx/storyProjection.js +6 -1
  77. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  78. package/dist/docx/tableFormatting/conditions.js +196 -0
  79. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  80. package/dist/docx/tableFormatting/editing.js +4 -5
  81. package/dist/docx/tableFormatting/reading.d.ts +49 -19
  82. package/dist/docx/tableFormatting/reading.js +109 -35
  83. package/dist/docx/tableFormatting.d.ts +1 -0
  84. package/dist/docx/tableFormatting.js +1 -0
  85. package/dist/docx/tableTemplate.js +12 -12
  86. package/dist/editor/clipboard/htmlReader.d.ts +30 -0
  87. package/dist/editor/clipboard/htmlReader.js +302 -0
  88. package/dist/editor/clipboard/internalChannel.d.ts +57 -0
  89. package/dist/editor/clipboard/internalChannel.js +58 -0
  90. package/dist/editor/clipboard/normalizers.d.ts +99 -0
  91. package/dist/editor/clipboard/normalizers.js +199 -0
  92. package/dist/editor/clipboard/parser.d.ts +34 -0
  93. package/dist/editor/clipboard/parser.js +58 -0
  94. package/dist/editor/clipboard/plugin.d.ts +21 -0
  95. package/dist/editor/clipboard/plugin.js +320 -0
  96. package/dist/editor/clipboard/readContext.d.ts +24 -0
  97. package/dist/editor/clipboard/readContext.js +19 -0
  98. package/dist/editor/clipboard/readers.d.ts +33 -0
  99. package/dist/editor/clipboard/readers.js +37 -0
  100. package/dist/editor/commands/comments/editing.d.ts +26 -6
  101. package/dist/editor/commands/comments/editing.js +175 -105
  102. package/dist/editor/commands/comments/model.d.ts +34 -17
  103. package/dist/editor/commands/comments/model.js +11 -0
  104. package/dist/editor/commands/comments/reading.d.ts +5 -3
  105. package/dist/editor/commands/comments/reading.js +8 -58
  106. package/dist/editor/commands/formatting/propertyCommands.js +6 -1
  107. package/dist/editor/commands/index.d.ts +2 -2
  108. package/dist/editor/commands/index.js +2 -0
  109. package/dist/editor/commands/listCommands.d.ts +12 -3
  110. package/dist/editor/commands/listCommands.js +76 -30
  111. package/dist/editor/commands/noteQueries.d.ts +22 -5
  112. package/dist/editor/commands/noteQueries.js +34 -6
  113. package/dist/editor/commands/paragraphCommands.js +6 -1
  114. package/dist/editor/createEditor.js +14 -4
  115. package/dist/editor/documentStyles.d.ts +26 -4
  116. package/dist/editor/documentStyles.js +9 -4
  117. package/dist/editor/editorDocument.d.ts +7 -6
  118. package/dist/editor/editorDocument.js +18 -6
  119. package/dist/editor/imageFiles.d.ts +2 -2
  120. package/dist/editor/imageFiles.js +2 -0
  121. package/dist/editor/insertTable.d.ts +1 -1
  122. package/dist/editor/insertTable.js +2 -2
  123. package/dist/editor/paragraphEdits.d.ts +16 -1
  124. package/dist/editor/paragraphEdits.js +13 -5
  125. package/dist/editor/paragraphPlacement.d.ts +11 -0
  126. package/dist/editor/paragraphPlacement.js +18 -0
  127. package/dist/editor/plainText.d.ts +12 -0
  128. package/dist/editor/plainText.js +2 -1
  129. package/dist/editor/plugins/columnResize.js +6 -3
  130. package/dist/editor/plugins/commentComposer.d.ts +28 -0
  131. package/dist/editor/plugins/commentComposer.js +46 -0
  132. package/dist/editor/plugins/commentDecorations.d.ts +29 -2
  133. package/dist/editor/plugins/commentDecorations.js +89 -15
  134. package/dist/editor/plugins/documentProjection.d.ts +31 -0
  135. package/dist/editor/plugins/documentProjection.js +22 -0
  136. package/dist/editor/plugins/imagePaste.js +20 -10
  137. package/dist/editor/plugins/linkPanel.d.ts +7 -3
  138. package/dist/editor/plugins/linkPanel.js +13 -27
  139. package/dist/editor/plugins/numberingDecorations.d.ts +10 -4
  140. package/dist/editor/plugins/numberingDecorations.js +43 -2
  141. package/dist/editor/plugins/panelState.d.ts +67 -0
  142. package/dist/editor/plugins/panelState.js +54 -0
  143. package/dist/editor/plugins/paragraphDisplay.js +9 -3
  144. package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
  145. package/dist/editor/plugins/tableContextMenu.js +30 -47
  146. package/dist/editor/plugins/tableDisplay.js +19 -5
  147. package/dist/editor/plugins/textContextMenu.d.ts +1 -1
  148. package/dist/editor/plugins/textContextMenu.js +30 -47
  149. package/dist/model/format.d.ts +50 -0
  150. package/dist/model/format.js +65 -0
  151. package/dist/numbering/listRegistry.d.ts +37 -0
  152. package/dist/numbering/listRegistry.js +112 -0
  153. package/dist/numbering/listTemplate.d.ts +26 -17
  154. package/dist/numbering/listTemplate.js +66 -20
  155. package/dist/numbering/markers.d.ts +15 -6
  156. package/dist/numbering/markers.js +26 -59
  157. package/dist/numbering/parseNumbering.d.ts +70 -5
  158. package/dist/numbering/parseNumbering.js +100 -26
  159. package/dist/numbering/spellers.d.ts +15 -0
  160. package/dist/numbering/spellers.js +96 -0
  161. package/dist/numbering/writeNumbering.d.ts +5 -3
  162. package/dist/numbering/writeNumbering.js +15 -15
  163. package/dist/ooxml/conformance.d.ts +28 -0
  164. package/dist/ooxml/conformance.js +20 -0
  165. package/dist/ooxml/errors.d.ts +5 -5
  166. package/dist/ooxml/fragment.d.ts +11 -0
  167. package/dist/ooxml/fragment.js +14 -4
  168. package/dist/ooxml/image.d.ts +3 -4
  169. package/dist/ooxml/image.js +50 -5
  170. package/dist/ooxml/names.d.ts +15 -0
  171. package/dist/ooxml/names.js +10 -1
  172. package/dist/ooxml/partSplice.d.ts +1 -1
  173. package/dist/ooxml/partSplice.js +10 -3
  174. package/dist/ooxml/props.d.ts +8 -0
  175. package/dist/ooxml/props.js +14 -4
  176. package/dist/ooxml/rangeMarkers.d.ts +5 -0
  177. package/dist/ooxml/rangeMarkers.js +24 -0
  178. package/dist/ooxml/xml.d.ts +8 -9
  179. package/dist/ooxml/xml.js +6 -6
  180. package/dist/page/PageGuides.d.ts +8 -4
  181. package/dist/page/PageGuides.js +13 -37
  182. package/dist/page/pageLayout.d.ts +62 -13
  183. package/dist/page/pageLayout.js +91 -37
  184. package/dist/page/usePageLayout.d.ts +14 -11
  185. package/dist/page/usePageLayout.js +21 -29
  186. package/dist/schema/attrRoles.js +44 -19
  187. package/dist/schema/docxSchema.d.ts +9 -1
  188. package/dist/schema/docxSchema.js +220 -139
  189. package/dist/schema/editGuard.d.ts +1 -1
  190. package/dist/schema/guards.js +2 -2
  191. package/dist/schema/index.d.ts +1 -0
  192. package/dist/schema/preservedFragments.d.ts +12 -0
  193. package/dist/schema/preservedFragments.js +38 -0
  194. package/dist/schema/preservedGuards.d.ts +9 -7
  195. package/dist/schema/preservedGuards.js +112 -11
  196. package/dist/schema/protection.d.ts +34 -5
  197. package/dist/schema/protection.js +42 -14
  198. package/dist/schema/rendering.js +3 -1
  199. package/dist/schema/stories.d.ts +49 -0
  200. package/dist/schema/stories.js +78 -0
  201. package/dist/styles/classNames.d.ts +16 -7
  202. package/dist/styles/classNames.js +16 -7
  203. package/dist/styles.css +90 -30
  204. package/dist/table/cellFormatting.js +1 -2
  205. package/dist/table/gridBorders.d.ts +11 -15
  206. package/dist/table/gridBorders.js +32 -18
  207. package/dist/table/resize.d.ts +5 -3
  208. package/dist/ui/CommentsPanel.d.ts +1 -3
  209. package/dist/ui/CommentsPanel.js +24 -15
  210. package/dist/ui/NotesPanel.js +2 -2
  211. package/dist/ui/TextMenu.d.ts +1 -3
  212. package/dist/ui/TextMenu.js +10 -6
  213. package/dist/ui/comments/CommentComposer.d.ts +6 -1
  214. package/dist/ui/comments/CommentComposer.js +26 -3
  215. package/package.json +1 -1
  216. package/dist/editor/externalClipboard.d.ts +0 -11
  217. package/dist/editor/externalClipboard.js +0 -456
@@ -0,0 +1,196 @@
1
+ // src/docx/tableFormatting/conditions.ts
2
+ import { ST_OnOff } from "../../ooxml/simpleTypes.js";
3
+ import { borderLineOfCss, wAttr } from "../../ooxml/units.js";
4
+ import { childByLocalName } from "../../ooxml/xml.js";
5
+ import {
6
+ layerCellMargins,
7
+ NO_BAND_SIZES,
8
+ NO_CELL_MARGINS,
9
+ NO_INSIDE_BORDERS,
10
+ NO_TABLE_STYLE_CONDITIONS
11
+ } from "./reading.js";
12
+ var NO_LOOK = {
13
+ firstRow: false,
14
+ lastRow: false,
15
+ firstColumn: false,
16
+ lastColumn: false,
17
+ noHBand: false,
18
+ noVBand: false
19
+ };
20
+ var LEGACY_LOOK_BITS = {
21
+ firstRow: 32,
22
+ lastRow: 64,
23
+ firstColumn: 128,
24
+ lastColumn: 256,
25
+ noHBand: 512,
26
+ noVBand: 1024
27
+ };
28
+ var SHORT_HEX = /^[0-9a-fA-F]{4}$/;
29
+ function legacyLook(value) {
30
+ const bits = value !== null && SHORT_HEX.test(value) ? Number.parseInt(value, 16) : 0;
31
+ return {
32
+ firstRow: (bits & LEGACY_LOOK_BITS.firstRow) !== 0,
33
+ lastRow: (bits & LEGACY_LOOK_BITS.lastRow) !== 0,
34
+ firstColumn: (bits & LEGACY_LOOK_BITS.firstColumn) !== 0,
35
+ lastColumn: (bits & LEGACY_LOOK_BITS.lastColumn) !== 0,
36
+ noHBand: (bits & LEGACY_LOOK_BITS.noHBand) !== 0,
37
+ noVBand: (bits & LEGACY_LOOK_BITS.noVBand) !== 0
38
+ };
39
+ }
40
+ function readTableLook(tblPr) {
41
+ const el = tblPr ? childByLocalName(tblPr, "tblLook") : null;
42
+ if (!el) return NO_LOOK;
43
+ const legacy = legacyLook(wAttr(el, "val"));
44
+ const written = (name) => ST_OnOff.parse(wAttr(el, name)) ?? legacy[name];
45
+ return {
46
+ firstRow: written("firstRow"),
47
+ lastRow: written("lastRow"),
48
+ firstColumn: written("firstColumn"),
49
+ lastColumn: written("lastColumn"),
50
+ noHBand: written("noHBand"),
51
+ noVBand: written("noVBand")
52
+ };
53
+ }
54
+ function bandWidth(size) {
55
+ return size ?? 1;
56
+ }
57
+ function bandedRows(grid, look) {
58
+ return [look.firstRow ? 1 : 0, look.lastRow ? grid.rows - 1 : grid.rows];
59
+ }
60
+ function bandedColumns(grid, look) {
61
+ return [
62
+ look.firstColumn ? 1 : 0,
63
+ look.lastColumn ? grid.cols - 1 : grid.cols
64
+ ];
65
+ }
66
+ function bandAt(at, [from, to], size) {
67
+ if (at < from || at >= to) return null;
68
+ const index = Math.floor((at - from) / size);
69
+ return {
70
+ first: index % 2 === 0,
71
+ start: from + index * size,
72
+ end: Math.min(from + (index + 1) * size, to)
73
+ };
74
+ }
75
+ function rowsOf(grid, top, bottom) {
76
+ return { top, bottom, left: 0, right: grid.cols };
77
+ }
78
+ function columnsOf(grid, left, right) {
79
+ return { top: 0, bottom: grid.rows, left, right };
80
+ }
81
+ function cellPlacement(rect, grid, look, bands) {
82
+ const found = [];
83
+ const add = (type, region) => {
84
+ found.push({ type, region });
85
+ };
86
+ add("wholeTable", rowsOf(grid, 0, grid.rows));
87
+ const column = look.noVBand ? null : bandAt(rect.left, bandedColumns(grid, look), bandWidth(bands.col));
88
+ if (column) {
89
+ add(
90
+ column.first ? "band1Vert" : "band2Vert",
91
+ columnsOf(grid, column.start, column.end)
92
+ );
93
+ }
94
+ const row = look.noHBand ? null : bandAt(rect.top, bandedRows(grid, look), bandWidth(bands.row));
95
+ if (row) {
96
+ add(
97
+ row.first ? "band1Horz" : "band2Horz",
98
+ rowsOf(grid, row.start, row.end)
99
+ );
100
+ }
101
+ const firstRow = look.firstRow && rect.top === 0;
102
+ const lastRow = look.lastRow && rect.bottom === grid.rows && grid.rows > 1;
103
+ const firstCol = look.firstColumn && rect.left === 0;
104
+ const lastCol = look.lastColumn && rect.right === grid.cols && grid.cols > 1;
105
+ if (firstRow) add("firstRow", rowsOf(grid, 0, 1));
106
+ if (lastRow) add("lastRow", rowsOf(grid, grid.rows - 1, grid.rows));
107
+ if (firstCol) add("firstCol", columnsOf(grid, 0, 1));
108
+ if (lastCol) add("lastCol", columnsOf(grid, grid.cols - 1, grid.cols));
109
+ const corner = (type, top, left) => {
110
+ add(type, { top, bottom: top + 1, left, right: left + 1 });
111
+ };
112
+ if (firstRow && firstCol) corner("nwCell", 0, 0);
113
+ if (firstRow && lastCol) corner("neCell", 0, grid.cols - 1);
114
+ if (lastRow && firstCol) corner("swCell", grid.rows - 1, 0);
115
+ if (lastRow && lastCol) corner("seCell", grid.rows - 1, grid.cols - 1);
116
+ return { rect, grid, conditions: found };
117
+ }
118
+ var NO_CELL_SOURCES = {
119
+ outer: null,
120
+ inside: NO_INSIDE_BORDERS,
121
+ margins: NO_CELL_MARGINS,
122
+ look: NO_LOOK,
123
+ bands: NO_BAND_SIZES,
124
+ conditions: NO_TABLE_STYLE_CONDITIONS,
125
+ styleId: null
126
+ };
127
+ function edgesIn(rect, region) {
128
+ return {
129
+ top: rect.top === region.top,
130
+ bottom: rect.bottom === region.bottom,
131
+ left: rect.left === region.left,
132
+ right: rect.right === region.right
133
+ };
134
+ }
135
+ function tableBorderDefaults(edges, outer, inside) {
136
+ return {
137
+ top: borderLineOfCss(
138
+ edges.top ? outer?.borderTop ?? null : inside.horizontal
139
+ ),
140
+ bottom: borderLineOfCss(
141
+ edges.bottom ? outer?.borderBottom ?? null : inside.horizontal
142
+ ),
143
+ left: borderLineOfCss(
144
+ edges.left ? outer?.borderLeft ?? null : inside.vertical
145
+ ),
146
+ right: borderLineOfCss(
147
+ edges.right ? outer?.borderRight ?? null : inside.vertical
148
+ )
149
+ };
150
+ }
151
+ function conditionBorderDefaults(base, format, edges) {
152
+ const line = (onEdge, edge, within) => borderLineOfCss(onEdge ? edge : within);
153
+ return {
154
+ top: line(edges.top, format.borders.top, format.inside.horizontal) ?? base.top,
155
+ bottom: line(edges.bottom, format.borders.bottom, format.inside.horizontal) ?? base.bottom,
156
+ left: line(edges.left, format.borders.left, format.inside.vertical) ?? base.left,
157
+ right: line(edges.right, format.borders.right, format.inside.vertical) ?? base.right
158
+ };
159
+ }
160
+ function cellDefaultsFor(rect, grid, sources) {
161
+ const placement = cellPlacement(rect, grid, sources.look, sources.bands);
162
+ const whole = { top: 0, bottom: grid.rows, left: 0, right: grid.cols };
163
+ let borders = tableBorderDefaults(
164
+ edgesIn(rect, whole),
165
+ sources.outer,
166
+ sources.inside
167
+ );
168
+ let margins = sources.margins;
169
+ let background = null;
170
+ let verticalAlign = null;
171
+ for (const { type, region } of placement.conditions) {
172
+ const format = sources.conditions[type];
173
+ if (!format) continue;
174
+ borders = conditionBorderDefaults(borders, format, edgesIn(rect, region));
175
+ margins = layerCellMargins(margins, format.margins);
176
+ background = format.background ?? background;
177
+ verticalAlign = format.verticalAlign ?? verticalAlign;
178
+ }
179
+ return {
180
+ borders,
181
+ margins,
182
+ background,
183
+ verticalAlign,
184
+ placement: {
185
+ tableStyleId: sources.styleId,
186
+ conditions: placement.conditions.map((condition) => condition.type)
187
+ }
188
+ };
189
+ }
190
+ export {
191
+ NO_CELL_SOURCES,
192
+ NO_LOOK,
193
+ cellDefaultsFor,
194
+ cellPlacement,
195
+ readTableLook
196
+ };
@@ -3,8 +3,8 @@
3
3
  * only the child and attributes named by the edit are changed, and unsupported formatting stays
4
4
  * untouched.
5
5
  */
6
- import type { CellFormat, CellMargins, CellVerticalAlign, RowFormat } from "../../model/format";
7
- import { type CellBorderDefaults } from "./reading";
6
+ import type { CellFormat, CellVerticalAlign, RowFormat } from "../../model/format";
7
+ import { type CellDefaults } from "./reading";
8
8
  export interface CellProps {
9
9
  /** The whole `<w:tcPr>...</w:tcPr>` XML. null for a cell with no formatting */
10
10
  tcPr: string | null;
@@ -45,11 +45,15 @@ export type CellFormatEdit =
45
45
  /**
46
46
  * The cell formatting XML and display values after one piece of formatting is changed.
47
47
  *
48
+ * What the cell falls back on is what an edit measures against: switching a side off writes `none`
49
+ * over whatever line was being drawn there, and recoloring writes only where a line is drawn at
50
+ * all, so the defaults handed in have to be the ones the cell is actually drawn with.
51
+ *
48
52
  * null when there is nothing to do: a fragment whose shape could not be made out, a value that
49
53
  * cannot be written into the document, or a cell already in the state the job wants. In every one
50
54
  * of those cases the cell keeps its original XML.
51
55
  */
52
- export declare function editCellProps(tcPr: string | null, edit: CellFormatEdit, defaults?: CellBorderDefaults, margins?: CellMargins): CellProps | null;
56
+ export declare function editCellProps(tcPr: string | null, edit: CellFormatEdit, defaults?: CellDefaults): CellProps | null;
53
57
  /**
54
58
  * Whether the cell's own formatting draws a line on any side.
55
59
  * A border color has nothing to act on when it does not, because the lines on screen are then the
@@ -19,8 +19,7 @@ import {
19
19
  } from "../../ooxml/simpleTypes.js";
20
20
  import { normalizeHex } from "../../ooxml/units.js";
21
21
  import {
22
- NO_BORDER_DEFAULTS,
23
- NO_CELL_MARGINS,
22
+ NO_CELL_DEFAULTS,
24
23
  readCellProps,
25
24
  readRowFormat
26
25
  } from "./reading.js";
@@ -212,15 +211,15 @@ function editedProps(edit, props, defaults) {
212
211
  return editedPadding(props, edit.values);
213
212
  }
214
213
  }
215
- function editCellProps(tcPr, edit, defaults = NO_BORDER_DEFAULTS, margins = NO_CELL_MARGINS) {
214
+ function editCellProps(tcPr, edit, defaults = NO_CELL_DEFAULTS) {
216
215
  const props = tcPr === null ? EMPTY_TC_PR : parseProps(tcPr);
217
216
  if (!props) return null;
218
- const edited = editedProps(edit, props, defaults);
217
+ const edited = editedProps(edit, props, defaults.borders);
219
218
  if (!edited) return null;
220
219
  const rendered = renderProps(edited);
221
220
  const next = rendered === "" ? null : rendered;
222
221
  if (next === tcPr) return null;
223
- return { tcPr: next, format: readCellProps(next, defaults, margins) };
222
+ return { tcPr: next, format: readCellProps(next, defaults) };
224
223
  }
225
224
  function drawsOwnCellBorder(tcPr) {
226
225
  const props = tcPr === null ? null : parseProps(tcPr);
@@ -2,11 +2,11 @@
2
2
  * Reads table formatting for display. Table borders and margins are folded into cell values so CSS
3
3
  * collapsed-border resolution matches OOXML inheritance without changing exported XML.
4
4
  */
5
- import type { CellFormat, CellMargins, InsideBorders, RowFormat, TableFormat, TableWidth } from "../../model/format";
5
+ import { type BandSizes, type CellFormat, type CellMargins, type CellStyleFormat, type CellVerticalAlign, type InsideBorders, type RowFormat, type RunFormat, type TableFormat, type TableStyleConditions, type TableStyleOverrideType, type TableWidth } from "../../model/format";
6
6
  import { type BorderLine } from "../../ooxml/units";
7
- export type { CellMargins, InsideBorders } from "../../model/format";
8
- /** The parts of a table a table style formats conditionally (`w:tblStylePr/@w:type`, ST_TblStyleOverrideType) */
9
- export type TableStyleOverrideType = "wholeTable" | "firstRow" | "lastRow" | "firstCol" | "lastCol" | "band1Vert" | "band2Vert" | "band1Horz" | "band2Horz" | "neCell" | "nwCell" | "seCell" | "swCell";
7
+ import type { ParagraphPlacement } from "../formatting/resolve";
8
+ import type { ParagraphFormatLayer } from "../formatting/tabStops";
9
+ export type { BandSizes, CellMargins, CellStyleFormat, InsideBorders, TableStyleConditions, TableStyleOverrideType, } from "../../model/format";
10
10
  /**
11
11
  * The width written down by `<w:tblW>` or `<w:tcW>`.
12
12
  * If we cannot make out what it means it is null, and such a width goes back out unchanged on export.
@@ -50,7 +50,7 @@ export interface CellBorderDefaults {
50
50
  right: BorderLine | null;
51
51
  }
52
52
  export declare const NO_BORDER_DEFAULTS: CellBorderDefaults;
53
- /** Which sides of a cell lie on the edge of the table's grid */
53
+ /** Which sides of a cell lie on the edge of a part of the table */
54
54
  export interface GridEdges {
55
55
  top: boolean;
56
56
  bottom: boolean;
@@ -69,19 +69,48 @@ export interface GridSize {
69
69
  cols: number;
70
70
  }
71
71
  /**
72
- * Which sides of the block a cell covers lie on the edge of the grid, merges included.
73
- * Everything that works out a cell's lines asks this first, whether the cell is being imported,
74
- * created fresh, or looked up again in a table on screen.
72
+ * Everything one cell falls back on for what it did not write down itself, worked out from where
73
+ * it sits in the grid by `cellDefaultsFor`. Everything that reads or edits a cell takes one of
74
+ * these, so the lines a cell draws and the lines an edit measures against are always the same.
75
75
  */
76
- export declare function gridEdgesOf(rect: GridRect, grid: GridSize): GridEdges;
76
+ export interface CellDefaults {
77
+ borders: CellBorderDefaults;
78
+ margins: CellMargins;
79
+ background: string | null;
80
+ verticalAlign: CellVerticalAlign | null;
81
+ /** What the paragraphs inside the cell resolve their formatting against */
82
+ placement: ParagraphPlacement;
83
+ }
84
+ export declare const NO_CELL_DEFAULTS: CellDefaults;
85
+ export declare const NO_BAND_SIZES: BandSizes;
86
+ /** How many rows and columns one band of a table style is made of, read from the style's `w:tblPr` */
87
+ export declare function readBandSizes(tblPr: Element | null): BandSizes;
88
+ export declare function layerBandSizes(style: BandSizes, over: BandSizes): BandSizes;
89
+ export declare const NO_CELL_STYLE_FORMAT: CellStyleFormat;
90
+ export declare const NO_TABLE_STYLE_CONDITIONS: TableStyleConditions;
91
+ /**
92
+ * The formatting one conditional format of a table style lays down (`w:tblStylePr`).
93
+ * Its `w:tblPr` speaks for the region as a whole and its `w:tcPr` for the cells in it, so the
94
+ * cell values are read with the table values underneath them.
95
+ */
96
+ export interface ConditionalTableFormat {
97
+ paragraph: ParagraphFormatLayer;
98
+ run: RunFormat;
99
+ table: TableFormat;
100
+ cell: CellStyleFormat;
101
+ }
77
102
  /**
78
- * The lines the four sides of one cell fall back on.
103
+ * What a conditional format lays down for the cells of its region.
79
104
  *
80
- * A side on the edge of the grid falls on the table's outer border, and one facing another cell on
81
- * the table's inside line. An outer side the document wrote as `none` is passed through as it is:
82
- * the table switched that line off, and nothing is to bring it back.
105
+ * The `w:tcPr` of a conditional format writes the lines of the region rather than of every cell in
106
+ * it: `insideH` and `insideV` are the lines between the cells it covers, which is how the header
107
+ * row of a style with `insideV` set to `nil` is drawn as one unbroken band.
83
108
  */
84
- export declare function cellBorderDefaults(edges: GridEdges, outer: TableFormat | null, inside: InsideBorders): CellBorderDefaults;
109
+ export declare function readCellStyleFormat(tcPr: Element | null, tblPr: Element | null): CellStyleFormat;
110
+ /** Lays one conditional format over the one a style further up the `basedOn` chain wrote for the same part */
111
+ export declare function layerCellStyleFormat(base: CellStyleFormat, over: CellStyleFormat): CellStyleFormat;
112
+ /** The conditions a table style lays down for its cells alone, which is what a table carries for its cells to draw */
113
+ export declare function cellConditionsOf(conditions: Readonly<Partial<Record<TableStyleOverrideType, ConditionalTableFormat>>>): TableStyleConditions;
85
114
  /** The name of the table style `w:tblStyle` points at. null if it points at none */
86
115
  export declare function tblStyleIdOf(tblPr: Element | null): string | null;
87
116
  export declare function readTableFormat(tblPr: Element | null): TableFormat | null;
@@ -89,11 +118,12 @@ export declare function readRowFormat(trPr: Element | null): RowFormat | null;
89
118
  /**
90
119
  * Cell formatting.
91
120
  * A side for which the cell has not written down its own border uses the line that side falls on,
92
- * which is the table's outer border or its inside line depending on where the cell sits.
93
- * The padding works the same way: what the cell wrote down wins, and the table's cell margins lie
94
- * underneath it. null if there is nothing at all to draw.
121
+ * which is the table's outer border, its inside line, or the line a conditional format of its
122
+ * style draws there, depending on where the cell sits.
123
+ * The fill, the vertical alignment and the padding work the same way: what the cell wrote down
124
+ * wins, and what it falls back on lies underneath. null if there is nothing at all to draw.
95
125
  */
96
- export declare function readCellFormat(tcPr: Element | null, defaults: CellBorderDefaults, margins?: CellMargins): CellFormat | null;
126
+ export declare function readCellFormat(tcPr: Element | null, defaults?: CellDefaults): CellFormat | null;
97
127
  /** The inside lines the table lays down, read from the table's own formatting XML */
98
128
  export declare function insideBordersOf(tblPr: string | null): InsideBorders;
99
129
  /** The cell margins the table lays down, read from the table's own formatting XML */
@@ -102,5 +132,5 @@ export declare function cellMarginsOf(tblPr: string | null): CellMargins;
102
132
  * Reads a cell formatting fragment we operated on back into display values, along the same path
103
133
  * the import takes. The same fragment always yields the same display values.
104
134
  */
105
- export declare function readCellProps(tcPr: string | null, defaults: CellBorderDefaults, margins?: CellMargins): CellFormat | null;
135
+ export declare function readCellProps(tcPr: string | null, defaults?: CellDefaults): CellFormat | null;
106
136
  /** The formatting a cell holds. The original XML and the display values read out of it form a pair */
@@ -1,6 +1,10 @@
1
1
  // src/docx/tableFormatting/reading.ts
2
+ import {
3
+ TABLE_STYLE_CONDITIONS
4
+ } from "../../model/format.js";
2
5
  import { parsePropsXml } from "../../ooxml/props.js";
3
6
  import {
7
+ ST_DecimalNumber,
4
8
  ST_MeasurementOrPercent,
5
9
  ST_SignedTwipsMeasure,
6
10
  ST_TwipsMeasure
@@ -8,7 +12,6 @@ import {
8
12
  import {
9
13
  ALIGN_BY_JC,
10
14
  borderLineCss,
11
- borderLineOfCss,
12
15
  borderSide,
13
16
  childValue,
14
17
  isOn,
@@ -109,30 +112,89 @@ var NO_BORDER_DEFAULTS = {
109
112
  left: null,
110
113
  right: null
111
114
  };
112
- function gridEdgesOf(rect, grid) {
115
+ var NO_CELL_DEFAULTS = {
116
+ borders: NO_BORDER_DEFAULTS,
117
+ margins: NO_CELL_MARGINS,
118
+ background: null,
119
+ verticalAlign: null,
120
+ placement: { tableStyleId: null, conditions: [] }
121
+ };
122
+ var NO_BAND_SIZES = { row: null, col: null };
123
+ function bandSize(tblPr, name) {
124
+ const count = ST_DecimalNumber.parse(childValue(tblPr, name));
125
+ return count !== null && count > 0 ? count : null;
126
+ }
127
+ function readBandSizes(tblPr) {
128
+ if (!tblPr) return NO_BAND_SIZES;
129
+ return {
130
+ row: bandSize(tblPr, "tblStyleRowBandSize"),
131
+ col: bandSize(tblPr, "tblStyleColBandSize")
132
+ };
133
+ }
134
+ function layerBandSizes(style, over) {
135
+ return { row: over.row ?? style.row, col: over.col ?? style.col };
136
+ }
137
+ var NO_CELL_STYLE_BORDERS = {
138
+ top: null,
139
+ bottom: null,
140
+ left: null,
141
+ right: null
142
+ };
143
+ var NO_CELL_STYLE_FORMAT = {
144
+ background: null,
145
+ borders: NO_CELL_STYLE_BORDERS,
146
+ inside: NO_INSIDE_BORDERS,
147
+ margins: NO_CELL_MARGINS,
148
+ verticalAlign: null
149
+ };
150
+ var NO_TABLE_STYLE_CONDITIONS = {};
151
+ function conditionBorders(tcBorders, table) {
113
152
  return {
114
- top: rect.top === 0,
115
- bottom: rect.bottom === grid.rows,
116
- left: rect.left === 0,
117
- right: rect.right === grid.cols
153
+ top: borderSide(tcBorders, "top") ?? table.borderTop ?? null,
154
+ bottom: borderSide(tcBorders, "bottom") ?? table.borderBottom ?? null,
155
+ left: borderSide(tcBorders, "left") ?? borderSide(tcBorders, "start") ?? table.borderLeft ?? null,
156
+ right: borderSide(tcBorders, "right") ?? borderSide(tcBorders, "end") ?? table.borderRight ?? null
118
157
  };
119
158
  }
120
- function cellBorderDefaults(edges, outer, inside) {
159
+ function readCellStyleFormat(tcPr, tblPr) {
160
+ const table = readTableFormat(tblPr) ?? {};
161
+ const tcBorders = tcPr ? childByLocalName(tcPr, "tcBorders") : null;
121
162
  return {
122
- top: borderLineOfCss(
123
- edges.top ? outer?.borderTop ?? null : inside.horizontal
124
- ),
125
- bottom: borderLineOfCss(
126
- edges.bottom ? outer?.borderBottom ?? null : inside.horizontal
127
- ),
128
- left: borderLineOfCss(
129
- edges.left ? outer?.borderLeft ?? null : inside.vertical
130
- ),
131
- right: borderLineOfCss(
132
- edges.right ? outer?.borderRight ?? null : inside.vertical
133
- )
163
+ background: (tcPr ? shadingOf(tcPr) : null) ?? table.background ?? null,
164
+ borders: conditionBorders(tcBorders, table),
165
+ inside: layerInsideBorders(readInsideBorders(tblPr), {
166
+ horizontal: borderSide(tcBorders, "insideH"),
167
+ vertical: borderSide(tcBorders, "insideV")
168
+ }),
169
+ margins: readCellMarginsOf(tcPr, "tcMar"),
170
+ verticalAlign: tcPr ? cellVerticalAlignOf(tcPr) : null
134
171
  };
135
172
  }
173
+ function layerCellStyleBorders(base, over) {
174
+ return {
175
+ top: over.top ?? base.top,
176
+ bottom: over.bottom ?? base.bottom,
177
+ left: over.left ?? base.left,
178
+ right: over.right ?? base.right
179
+ };
180
+ }
181
+ function layerCellStyleFormat(base, over) {
182
+ return {
183
+ background: over.background ?? base.background,
184
+ borders: layerCellStyleBorders(base.borders, over.borders),
185
+ inside: layerInsideBorders(base.inside, over.inside),
186
+ margins: layerCellMargins(base.margins, over.margins),
187
+ verticalAlign: over.verticalAlign ?? base.verticalAlign
188
+ };
189
+ }
190
+ function cellConditionsOf(conditions) {
191
+ const cells = {};
192
+ for (const type of TABLE_STYLE_CONDITIONS) {
193
+ const format = conditions[type];
194
+ if (format) cells[type] = format.cell;
195
+ }
196
+ return cells;
197
+ }
136
198
  function tblStyleIdOf(tblPr) {
137
199
  return tblPr ? childValue(tblPr, "tblStyle") : null;
138
200
  }
@@ -178,6 +240,9 @@ var CELL_VERTICAL_ALIGN_BY_VAL = {
178
240
  center: "center",
179
241
  bottom: "bottom"
180
242
  };
243
+ function cellVerticalAlignOf(tcPr) {
244
+ return CELL_VERTICAL_ALIGN_BY_VAL[childValue(tcPr, "vAlign") ?? ""] ?? null;
245
+ }
181
246
  function readCellPadding(tcPr, margins) {
182
247
  const padding = layerCellMargins(margins, readCellMarginsOf(tcPr, "tcMar"));
183
248
  const format = {};
@@ -187,24 +252,26 @@ function readCellPadding(tcPr, margins) {
187
252
  if (padding.leftPt !== null) format.paddingLeftPt = padding.leftPt;
188
253
  return format;
189
254
  }
190
- function readCellFormat(tcPr, defaults, margins = NO_CELL_MARGINS) {
255
+ function readCellFormat(tcPr, defaults = NO_CELL_DEFAULTS) {
191
256
  const borders = tcPr ? childByLocalName(tcPr, "tcBorders") : null;
257
+ const lines = defaults.borders;
192
258
  const format = {};
193
- const top = borderSide(borders, "top") ?? borderLineCss(defaults.top);
259
+ const top = borderSide(borders, "top") ?? borderLineCss(lines.top);
194
260
  if (top) format.borderTop = top;
195
- const bottom = borderSide(borders, "bottom") ?? borderLineCss(defaults.bottom);
261
+ const bottom = borderSide(borders, "bottom") ?? borderLineCss(lines.bottom);
196
262
  if (bottom) format.borderBottom = bottom;
197
- const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? borderLineCss(defaults.left);
263
+ const left = borderSide(borders, "left") ?? borderSide(borders, "start") ?? borderLineCss(lines.left);
198
264
  if (left) format.borderLeft = left;
199
- const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? borderLineCss(defaults.right);
265
+ const right = borderSide(borders, "right") ?? borderSide(borders, "end") ?? borderLineCss(lines.right);
200
266
  if (right) format.borderRight = right;
201
- if (tcPr) {
202
- const background = shadingOf(tcPr);
203
- if (background) format.background = background;
204
- const verticalAlign = CELL_VERTICAL_ALIGN_BY_VAL[childValue(tcPr, "vAlign") ?? ""];
205
- if (verticalAlign) format.verticalAlign = verticalAlign;
206
- }
207
- const padded = { ...format, ...readCellPadding(tcPr, margins) };
267
+ const background = (tcPr ? shadingOf(tcPr) : null) ?? defaults.background;
268
+ if (background) format.background = background;
269
+ const verticalAlign = (tcPr ? cellVerticalAlignOf(tcPr) : null) ?? defaults.verticalAlign;
270
+ if (verticalAlign) format.verticalAlign = verticalAlign;
271
+ const padded = {
272
+ ...format,
273
+ ...readCellPadding(tcPr, defaults.margins)
274
+ };
208
275
  return Object.keys(padded).length > 0 ? padded : null;
209
276
  }
210
277
  function insideBordersOf(tblPr) {
@@ -215,23 +282,30 @@ function cellMarginsOf(tblPr) {
215
282
  const el = tblPr === null ? null : parsePropsXml(tblPr);
216
283
  return readCellMarginsOf(el, "tblCellMar");
217
284
  }
218
- function readCellProps(tcPr, defaults, margins = NO_CELL_MARGINS) {
285
+ function readCellProps(tcPr, defaults = NO_CELL_DEFAULTS) {
219
286
  const el = tcPr === null ? null : parsePropsXml(tcPr);
220
- return readCellFormat(el, defaults, margins);
287
+ return readCellFormat(el, defaults);
221
288
  }
222
289
  export {
290
+ NO_BAND_SIZES,
223
291
  NO_BORDER_DEFAULTS,
292
+ NO_CELL_DEFAULTS,
224
293
  NO_CELL_MARGINS,
294
+ NO_CELL_STYLE_FORMAT,
225
295
  NO_INSIDE_BORDERS,
226
- cellBorderDefaults,
296
+ NO_TABLE_STYLE_CONDITIONS,
297
+ cellConditionsOf,
227
298
  cellMarginsOf,
228
- gridEdgesOf,
229
299
  insideBordersOf,
300
+ layerBandSizes,
230
301
  layerCellMargins,
302
+ layerCellStyleFormat,
231
303
  layerInsideBorders,
304
+ readBandSizes,
232
305
  readCellFormat,
233
306
  readCellMarginsOf,
234
307
  readCellProps,
308
+ readCellStyleFormat,
235
309
  readGridCols,
236
310
  readInsideBorders,
237
311
  readRowFormat,
@@ -1,2 +1,3 @@
1
+ export * from "./tableFormatting/conditions";
1
2
  export * from "./tableFormatting/editing";
2
3
  export * from "./tableFormatting/reading";
@@ -1,3 +1,4 @@
1
1
  // src/docx/tableFormatting.ts
2
+ export * from "./tableFormatting/conditions.js";
2
3
  export * from "./tableFormatting/editing.js";
3
4
  export * from "./tableFormatting/reading.js";
@@ -5,9 +5,8 @@ import { orderedElement, parsePropsXml } from "../ooxml/props.js";
5
5
  import { docxSchema } from "../schema/index.js";
6
6
  import { A4_PORTRAIT, bodyWidth } from "./pageGeometry.js";
7
7
  import {
8
- cellBorderDefaults,
9
- gridEdgesOf,
10
- NO_CELL_MARGINS,
8
+ cellDefaultsFor,
9
+ NO_CELL_SOURCES,
11
10
  readCellFormat,
12
11
  readInsideBorders,
13
12
  readTableFormat,
@@ -81,7 +80,7 @@ function cellTemplate(width, defaults) {
81
80
  tcPr,
82
81
  tcW: readTableWidth(el, "tcW"),
83
82
  // A new table writes no `tblCellMar`, so its cells take their padding from the stylesheet
84
- format: readCellFormat(el, defaults, NO_CELL_MARGINS)
83
+ format: readCellFormat(el, defaults)
85
84
  };
86
85
  }
87
86
  function cellNode(props) {
@@ -109,17 +108,18 @@ function createTableNode(rows, cols, geometry = A4_PORTRAIT) {
109
108
  const gridCols = evenGridCols(cols, total);
110
109
  const tblPr = tablePropsXml(total);
111
110
  const tblPrEl = parsePropsXml(tblPr);
112
- const inside = readInsideBorders(tblPrEl);
113
111
  const outer = readTableFormat(tblPrEl);
112
+ const sources = {
113
+ ...NO_CELL_SOURCES,
114
+ outer,
115
+ inside: readInsideBorders(tblPrEl)
116
+ };
114
117
  const cellAt = (row, col) => cellTemplate(
115
118
  gridCols[col],
116
- cellBorderDefaults(
117
- gridEdgesOf(
118
- { top: row, bottom: row + 1, left: col, right: col + 1 },
119
- { rows, cols }
120
- ),
121
- outer,
122
- inside
119
+ cellDefaultsFor(
120
+ { top: row, bottom: row + 1, left: col, right: col + 1 },
121
+ { rows, cols },
122
+ sources
123
123
  )
124
124
  );
125
125
  return docxSchema.nodes.table.create(
@@ -0,0 +1,30 @@
1
+ import { Slice } from "prosemirror-model";
2
+ import type { Transaction } from "prosemirror-state";
3
+ import { type NewLists } from "../../numbering/listRegistry";
4
+ import type { ListKinds } from "./internalChannel";
5
+ import type { HtmlReadContext } from "./readContext";
6
+ /**
7
+ * The paragraph style a copy carries, which is the one thing a paste needs that the drawing does
8
+ * not already say. It is the style's id alone, where the editor draws the whole `w:pPr`.
9
+ */
10
+ export declare const COPIED_STYLE_ATTRIBUTE = "data-style";
11
+ /** What a paste puts in: the content, and the definitions of the lists it started */
12
+ export interface PastedContent {
13
+ slice: Slice;
14
+ newLists: NewLists;
15
+ /**
16
+ * What the numbers this slice's paragraphs name meant where it was copied
17
+ * (`./internalChannel`). Absent for a reading that gave the lists it read numbers of its own,
18
+ * which knows what kind each is from the markup it read them out of.
19
+ */
20
+ listKinds?: ListKinds;
21
+ }
22
+ /** The content one piece of already parsed markup reads as, or null when it reads as nothing */
23
+ export declare function readHtml(root: ParentNode, context: HtmlReadContext): PastedContent | null;
24
+ /** The same reading, for a caller holding the markup as a string rather than as elements */
25
+ export declare function readHtmlSlice(context: HtmlReadContext, source: string): PastedContent | null;
26
+ /**
27
+ * The transaction a paste is put in with: the content, and the definitions of the lists it started
28
+ * recorded on the document node so that the export writes them out and undo takes them back.
29
+ */
30
+ export declare function withPastedContent(tr: Transaction, content: PastedContent): Transaction;