@beyondwork/docx-react-component 1.0.37 → 1.0.38

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 (74) hide show
  1. package/package.json +1 -1
  2. package/src/api/public-types.ts +319 -1
  3. package/src/core/commands/section-layout-commands.ts +58 -0
  4. package/src/core/commands/table-grid.ts +431 -0
  5. package/src/core/commands/table-structure-commands.ts +815 -55
  6. package/src/io/export/serialize-main-document.ts +2 -11
  7. package/src/io/export/serialize-numbering.ts +1 -2
  8. package/src/io/export/serialize-tables.ts +74 -0
  9. package/src/io/export/table-properties-xml.ts +139 -4
  10. package/src/io/normalize/normalize-text.ts +15 -0
  11. package/src/io/ooxml/parse-footnotes.ts +60 -0
  12. package/src/io/ooxml/parse-headers-footers.ts +60 -0
  13. package/src/io/ooxml/parse-main-document.ts +137 -0
  14. package/src/io/ooxml/parse-tables.ts +249 -0
  15. package/src/model/canonical-document.ts +34 -0
  16. package/src/runtime/document-layout.ts +4 -2
  17. package/src/runtime/document-navigation.ts +1 -1
  18. package/src/runtime/document-runtime.ts +114 -0
  19. package/src/runtime/layout/default-page-format.ts +96 -0
  20. package/src/runtime/layout/index.ts +45 -0
  21. package/src/runtime/layout/inert-layout-facet.ts +14 -0
  22. package/src/runtime/layout/layout-engine-instance.ts +33 -23
  23. package/src/runtime/layout/margin-preset-catalog.ts +178 -0
  24. package/src/runtime/layout/page-format-catalog.ts +233 -0
  25. package/src/runtime/layout/page-graph.ts +19 -0
  26. package/src/runtime/layout/paginated-layout-engine.ts +142 -9
  27. package/src/runtime/layout/project-block-fragments.ts +91 -0
  28. package/src/runtime/layout/public-facet.ts +709 -16
  29. package/src/runtime/layout/table-render-plan.ts +229 -0
  30. package/src/runtime/render/block-fragment-projection.ts +35 -0
  31. package/src/runtime/render/decoration-resolver.ts +189 -0
  32. package/src/runtime/render/index.ts +57 -0
  33. package/src/runtime/render/pending-op-delta-reader.ts +129 -0
  34. package/src/runtime/render/render-frame-types.ts +317 -0
  35. package/src/runtime/render/render-kernel.ts +755 -0
  36. package/src/runtime/view-state.ts +67 -0
  37. package/src/runtime/workflow-markup.ts +1 -5
  38. package/src/runtime/workflow-rail-segments.ts +280 -0
  39. package/src/ui/WordReviewEditor.tsx +84 -15
  40. package/src/ui/editor-shell-view.tsx +6 -0
  41. package/src/ui/headless/chrome-registry.ts +280 -14
  42. package/src/ui/headless/scoped-chrome-policy.ts +20 -1
  43. package/src/ui/headless/selection-tool-types.ts +10 -0
  44. package/src/ui-tailwind/chrome/chrome-preset-model.ts +23 -2
  45. package/src/ui-tailwind/chrome/role-action-sets.ts +74 -0
  46. package/src/ui-tailwind/chrome/tw-detach-handle.tsx +147 -0
  47. package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +163 -0
  48. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +57 -92
  49. package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +149 -0
  50. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +15 -4
  51. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +274 -138
  52. package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +90 -0
  53. package/src/ui-tailwind/chrome-overlay/index.ts +22 -0
  54. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +86 -0
  55. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +178 -0
  56. package/src/ui-tailwind/chrome-overlay/tw-workspace-view-switcher.tsx +95 -0
  57. package/src/ui-tailwind/editor-surface/fast-text-edit-lane.ts +4 -0
  58. package/src/ui-tailwind/editor-surface/local-edit-session-state.ts +11 -0
  59. package/src/ui-tailwind/editor-surface/perf-probe.ts +7 -1
  60. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +12 -1
  61. package/src/ui-tailwind/editor-surface/pm-decorations.ts +22 -12
  62. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +3 -0
  63. package/src/ui-tailwind/index.ts +33 -0
  64. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +2 -2
  65. package/src/ui-tailwind/review/tw-rail-card.tsx +150 -0
  66. package/src/ui-tailwind/review/tw-review-rail-footer.tsx +52 -0
  67. package/src/ui-tailwind/review/tw-review-rail.tsx +166 -11
  68. package/src/ui-tailwind/review/tw-workflow-tab.tsx +108 -0
  69. package/src/ui-tailwind/theme/editor-theme.css +498 -163
  70. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +559 -0
  71. package/src/ui-tailwind/toolbar/tw-scope-posture-menu.tsx +182 -0
  72. package/src/ui-tailwind/toolbar/tw-shell-header.tsx +162 -0
  73. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +69 -0
  74. package/src/ui-tailwind/tw-review-workspace.tsx +136 -1
@@ -1263,20 +1263,11 @@ function offsetParagraphBoundary(
1263
1263
  };
1264
1264
  }
1265
1265
 
1266
- /**
1267
- * Detect a production build without referencing the Node-only `process`
1268
- * global directly (the production tsconfig excludes @types/node). Returns
1269
- * true when NODE_ENV === "production"; otherwise false (browser or dev).
1270
- */
1271
- function isProductionEnvironment(): boolean {
1266
+ function assertUniqueBookmarkIdsOrWarn(documentXml: string): void {
1272
1267
  const proc = (globalThis as unknown as {
1273
1268
  process?: { env?: Record<string, string | undefined> };
1274
1269
  }).process;
1275
- return proc?.env?.NODE_ENV === "production";
1276
- }
1277
-
1278
- function assertUniqueBookmarkIdsOrWarn(documentXml: string): void {
1279
- if (isProductionEnvironment()) {
1270
+ if (proc?.env?.NODE_ENV === "production") {
1280
1271
  return;
1281
1272
  }
1282
1273
  const seen = new Set<string>();
@@ -276,8 +276,7 @@ function warnClamp(attr: string, from: number, to: number): void {
276
276
  warnedClamps += 1;
277
277
  // Only warn outside of production builds. The test runner shows these
278
278
  // via console.warn automatically; in production this is a silent no-op
279
- // so the Buffer cost is zero. Read NODE_ENV through globalThis so the
280
- // production tsconfig (which excludes @types/node) type-checks cleanly.
279
+ // so the Buffer cost is zero.
281
280
  const proc = (globalThis as unknown as {
282
281
  process?: { env?: Record<string, string | undefined> };
283
282
  }).process;
@@ -47,6 +47,28 @@ function buildTablePropertiesXml(table: ParsedTable): string {
47
47
  if (table.alignment) {
48
48
  children.push(`<w:jc w:val="${table.alignment}"/>`);
49
49
  }
50
+ if (table.indent) {
51
+ children.push(`<w:tblInd w:w="${table.indent.value}" w:type="${table.indent.type}"/>`);
52
+ }
53
+ if (table.layoutMode) {
54
+ children.push(`<w:tblLayout w:type="${table.layoutMode}"/>`);
55
+ }
56
+ if (table.cellSpacing) {
57
+ children.push(`<w:tblCellSpacing w:w="${table.cellSpacing.value}" w:type="${table.cellSpacing.type}"/>`);
58
+ }
59
+ if (table.bidiVisual !== undefined) {
60
+ children.push(table.bidiVisual ? `<w:bidiVisual/>` : `<w:bidiVisual w:val="0"/>`);
61
+ }
62
+ if (table.caption !== undefined) {
63
+ children.push(`<w:tblCaption w:val="${escapeAttribute(table.caption)}"/>`);
64
+ }
65
+ if (table.description !== undefined) {
66
+ children.push(`<w:tblDescription w:val="${escapeAttribute(table.description)}"/>`);
67
+ }
68
+ if (table.floating) {
69
+ const floatingXml = serializeTableFloating(table.floating);
70
+ if (floatingXml) children.push(floatingXml);
71
+ }
50
72
  if (table.borders) {
51
73
  const bordersXml = serializeTableBorders(table.borders);
52
74
  if (bordersXml) children.push(`<w:tblBorders>${bordersXml}</w:tblBorders>`);
@@ -62,8 +84,33 @@ function buildTablePropertiesXml(table: ParsedTable): string {
62
84
  return children.length > 0 ? `<w:tblPr>${children.join("")}</w:tblPr>` : "";
63
85
  }
64
86
 
87
+ function serializeTableFloating(floating: NonNullable<ParsedTable["floating"]>): string {
88
+ const attrs: string[] = [];
89
+ if (floating.horizontalAnchor) attrs.push(`w:horzAnchor="${floating.horizontalAnchor}"`);
90
+ if (floating.verticalAnchor) attrs.push(`w:vertAnchor="${floating.verticalAnchor}"`);
91
+ if (floating.horizontalAlign) attrs.push(`w:tblpXSpec="${floating.horizontalAlign}"`);
92
+ if (floating.horizontalOffset !== undefined) attrs.push(`w:tblpX="${floating.horizontalOffset}"`);
93
+ if (floating.verticalAlign) attrs.push(`w:tblpYSpec="${floating.verticalAlign}"`);
94
+ if (floating.verticalOffset !== undefined) attrs.push(`w:tblpY="${floating.verticalOffset}"`);
95
+ if (floating.leftFromText !== undefined) attrs.push(`w:leftFromText="${floating.leftFromText}"`);
96
+ if (floating.rightFromText !== undefined) attrs.push(`w:rightFromText="${floating.rightFromText}"`);
97
+ if (floating.topFromText !== undefined) attrs.push(`w:topFromText="${floating.topFromText}"`);
98
+ if (floating.bottomFromText !== undefined) attrs.push(`w:bottomFromText="${floating.bottomFromText}"`);
99
+ const tblpPr = attrs.length > 0 ? `<w:tblpPr ${attrs.join(" ")}/>` : "";
100
+ const overlap = floating.overlap !== undefined
101
+ ? `<w:tblOverlap w:val="${floating.overlap ? "overlap" : "never"}"/>`
102
+ : "";
103
+ return `${tblpPr}${overlap}`;
104
+ }
105
+
65
106
  function buildRowPropertiesXml(row: ParsedTableRow): string {
66
107
  const children: string[] = [];
108
+ if (row.cnfStyle) {
109
+ children.push(`<w:cnfStyle w:val="${escapeAttribute(row.cnfStyle)}"/>`);
110
+ }
111
+ if (row.cantSplit !== undefined) {
112
+ children.push(row.cantSplit ? `<w:cantSplit/>` : `<w:cantSplit w:val="0"/>`);
113
+ }
67
114
  if (row.height !== undefined) {
68
115
  const hRuleAttr = row.heightRule ? ` w:hRule="${row.heightRule}"` : "";
69
116
  children.push(`<w:trHeight w:val="${twip(row.height)}"${hRuleAttr}/>`);
@@ -71,6 +118,9 @@ function buildRowPropertiesXml(row: ParsedTableRow): string {
71
118
  if (row.isHeader) {
72
119
  children.push(`<w:tblHeader/>`);
73
120
  }
121
+ if (row.horizontalAlignment) {
122
+ children.push(`<w:jc w:val="${row.horizontalAlignment}"/>`);
123
+ }
74
124
  return children.length > 0 ? `<w:trPr>${children.join("")}</w:trPr>` : "";
75
125
  }
76
126
 
@@ -80,6 +130,9 @@ function ensureCellProperties(cell: ParsedTableCell): string {
80
130
  }
81
131
 
82
132
  const children: string[] = [];
133
+ if (cell.cnfStyle) {
134
+ children.push(`<w:cnfStyle w:val="${escapeAttribute(cell.cnfStyle)}"/>`);
135
+ }
83
136
  if (cell.width) {
84
137
  children.push(serializeWidth("tcW", cell.width));
85
138
  }
@@ -100,6 +153,19 @@ function ensureCellProperties(cell: ParsedTableCell): string {
100
153
  if (cell.shading) {
101
154
  children.push(serializeCellShading(cell.shading));
102
155
  }
156
+ if (cell.margins) {
157
+ const marginsXml = serializeTableCellMargins(cell.margins);
158
+ if (marginsXml) children.push(`<w:tcMar>${marginsXml}</w:tcMar>`);
159
+ }
160
+ if (cell.noWrap !== undefined) {
161
+ children.push(cell.noWrap ? `<w:noWrap/>` : `<w:noWrap w:val="0"/>`);
162
+ }
163
+ if (cell.fitText !== undefined) {
164
+ children.push(cell.fitText ? `<w:tcFitText/>` : `<w:tcFitText w:val="0"/>`);
165
+ }
166
+ if (cell.textDirection) {
167
+ children.push(`<w:textDirection w:val="${cell.textDirection}"/>`);
168
+ }
103
169
  if (cell.verticalAlign) {
104
170
  children.push(`<w:vAlign w:val="${cell.verticalAlign}"/>`);
105
171
  }
@@ -174,3 +240,11 @@ function serializeTableCellMargins(margins: ParsedCellMargins): string {
174
240
  if (margins.right !== undefined) parts.push(`<w:right w:w="${twip(margins.right)}" w:type="dxa"/>`);
175
241
  return parts.join("");
176
242
  }
243
+
244
+ function escapeAttribute(value: string): string {
245
+ return value
246
+ .replace(/&/gu, "&amp;")
247
+ .replace(/"/gu, "&quot;")
248
+ .replace(/</gu, "&lt;")
249
+ .replace(/>/gu, "&gt;");
250
+ }
@@ -44,6 +44,25 @@ interface CellShadingLike {
44
44
  fill?: string;
45
45
  }
46
46
 
47
+ interface TableIndentLike {
48
+ value: number;
49
+ type: string;
50
+ }
51
+
52
+ interface TableFloatingPropertiesLike {
53
+ horizontalAnchor?: string;
54
+ verticalAnchor?: string;
55
+ horizontalAlign?: string;
56
+ horizontalOffset?: number;
57
+ verticalAlign?: string;
58
+ verticalOffset?: number;
59
+ leftFromText?: number;
60
+ rightFromText?: number;
61
+ topFromText?: number;
62
+ bottomFromText?: number;
63
+ overlap?: boolean;
64
+ }
65
+
47
66
  interface TablePropertiesLike {
48
67
  propertiesXml?: string;
49
68
  styleId?: string;
@@ -52,6 +71,13 @@ interface TablePropertiesLike {
52
71
  borders?: TableBordersLike;
53
72
  cellMargins?: TableCellMarginsLike;
54
73
  tblLook?: TableLookLike;
74
+ indent?: TableIndentLike;
75
+ layoutMode?: string;
76
+ cellSpacing?: TableWidthLike;
77
+ caption?: string;
78
+ description?: string;
79
+ bidiVisual?: boolean;
80
+ floating?: TableFloatingPropertiesLike;
55
81
  }
56
82
 
57
83
  interface TableRowPropertiesLike {
@@ -63,6 +89,9 @@ interface TableRowPropertiesLike {
63
89
  height?: number;
64
90
  heightRule?: string;
65
91
  isHeader?: boolean;
92
+ cantSplit?: boolean;
93
+ horizontalAlignment?: string;
94
+ cnfStyle?: string;
66
95
  }
67
96
 
68
97
  interface TableCellPropertiesLike {
@@ -73,6 +102,11 @@ interface TableCellPropertiesLike {
73
102
  borders?: TableBordersLike;
74
103
  shading?: CellShadingLike;
75
104
  verticalAlign?: string;
105
+ textDirection?: string;
106
+ noWrap?: boolean;
107
+ fitText?: boolean;
108
+ margins?: TableCellMarginsLike;
109
+ cnfStyle?: string;
76
110
  }
77
111
 
78
112
  interface PropertyStripSpec {
@@ -82,16 +116,49 @@ interface PropertyStripSpec {
82
116
 
83
117
  const TABLE_PROPERTY_STRIP_SPEC: PropertyStripSpec = {
84
118
  pairedTags: ["w:tblBorders", "w:tblCellMar"],
85
- selfClosingTags: ["w:tblStyle", "w:tblW", "w:jc", "w:tblLook"],
119
+ selfClosingTags: [
120
+ "w:tblStyle",
121
+ "w:tblW",
122
+ "w:jc",
123
+ "w:tblLook",
124
+ "w:tblInd",
125
+ "w:tblLayout",
126
+ "w:tblCellSpacing",
127
+ "w:tblCaption",
128
+ "w:tblDescription",
129
+ "w:bidiVisual",
130
+ "w:tblpPr",
131
+ "w:tblOverlap",
132
+ ],
86
133
  };
87
134
 
88
135
  const ROW_PROPERTY_STRIP_SPEC: PropertyStripSpec = {
89
- selfClosingTags: ["w:gridBefore", "w:wBefore", "w:gridAfter", "w:wAfter", "w:trHeight", "w:tblHeader"],
136
+ selfClosingTags: [
137
+ "w:gridBefore",
138
+ "w:wBefore",
139
+ "w:gridAfter",
140
+ "w:wAfter",
141
+ "w:trHeight",
142
+ "w:tblHeader",
143
+ "w:cantSplit",
144
+ "w:jc",
145
+ "w:cnfStyle",
146
+ ],
90
147
  };
91
148
 
92
149
  const CELL_PROPERTY_STRIP_SPEC: PropertyStripSpec = {
93
- pairedTags: ["w:tcBorders"],
94
- selfClosingTags: ["w:tcW", "w:gridSpan", "w:vMerge", "w:shd", "w:vAlign"],
150
+ pairedTags: ["w:tcBorders", "w:tcMar"],
151
+ selfClosingTags: [
152
+ "w:tcW",
153
+ "w:gridSpan",
154
+ "w:vMerge",
155
+ "w:shd",
156
+ "w:vAlign",
157
+ "w:textDirection",
158
+ "w:noWrap",
159
+ "w:tcFitText",
160
+ "w:cnfStyle",
161
+ ],
95
162
  };
96
163
 
97
164
  export function serializeTablePropertiesXml(table: TablePropertiesLike): string {
@@ -174,6 +241,28 @@ function buildTablePropertiesInnerXml(table: TablePropertiesLike): string {
174
241
  if (table.alignment) {
175
242
  children.push(`<w:jc w:val="${escapeAttribute(table.alignment)}"/>`);
176
243
  }
244
+ if (table.indent) {
245
+ children.push(`<w:tblInd w:w="${table.indent.value}" w:type="${escapeAttribute(table.indent.type)}"/>`);
246
+ }
247
+ if (table.layoutMode) {
248
+ children.push(`<w:tblLayout w:type="${escapeAttribute(table.layoutMode)}"/>`);
249
+ }
250
+ if (table.cellSpacing) {
251
+ children.push(`<w:tblCellSpacing w:w="${table.cellSpacing.value}" w:type="${escapeAttribute(table.cellSpacing.type)}"/>`);
252
+ }
253
+ if (table.bidiVisual !== undefined) {
254
+ children.push(table.bidiVisual ? `<w:bidiVisual/>` : `<w:bidiVisual w:val="0"/>`);
255
+ }
256
+ if (table.caption !== undefined) {
257
+ children.push(`<w:tblCaption w:val="${escapeAttribute(table.caption)}"/>`);
258
+ }
259
+ if (table.description !== undefined) {
260
+ children.push(`<w:tblDescription w:val="${escapeAttribute(table.description)}"/>`);
261
+ }
262
+ if (table.floating) {
263
+ const floatingXml = serializeTableFloating(table.floating);
264
+ if (floatingXml) children.push(floatingXml);
265
+ }
177
266
  if (table.borders) {
178
267
  const bordersXml = serializeBorders(table.borders);
179
268
  if (bordersXml) {
@@ -195,8 +284,30 @@ function buildTablePropertiesInnerXml(table: TablePropertiesLike): string {
195
284
  return children.join("");
196
285
  }
197
286
 
287
+ function serializeTableFloating(floating: TableFloatingPropertiesLike): string {
288
+ const attrs: string[] = [];
289
+ if (floating.horizontalAnchor) attrs.push(`w:horzAnchor="${escapeAttribute(floating.horizontalAnchor)}"`);
290
+ if (floating.verticalAnchor) attrs.push(`w:vertAnchor="${escapeAttribute(floating.verticalAnchor)}"`);
291
+ if (floating.horizontalAlign) attrs.push(`w:tblpXSpec="${escapeAttribute(floating.horizontalAlign)}"`);
292
+ if (floating.horizontalOffset !== undefined) attrs.push(`w:tblpX="${floating.horizontalOffset}"`);
293
+ if (floating.verticalAlign) attrs.push(`w:tblpYSpec="${escapeAttribute(floating.verticalAlign)}"`);
294
+ if (floating.verticalOffset !== undefined) attrs.push(`w:tblpY="${floating.verticalOffset}"`);
295
+ if (floating.leftFromText !== undefined) attrs.push(`w:leftFromText="${floating.leftFromText}"`);
296
+ if (floating.rightFromText !== undefined) attrs.push(`w:rightFromText="${floating.rightFromText}"`);
297
+ if (floating.topFromText !== undefined) attrs.push(`w:topFromText="${floating.topFromText}"`);
298
+ if (floating.bottomFromText !== undefined) attrs.push(`w:bottomFromText="${floating.bottomFromText}"`);
299
+ const tblpPr = attrs.length > 0 ? `<w:tblpPr ${attrs.join(" ")}/>` : "";
300
+ const overlap = floating.overlap !== undefined
301
+ ? `<w:tblOverlap w:val="${floating.overlap ? "overlap" : "never"}"/>`
302
+ : "";
303
+ return `${tblpPr}${overlap}`;
304
+ }
305
+
198
306
  function buildTableRowPropertiesInnerXml(row: TableRowPropertiesLike): string {
199
307
  const children: string[] = [];
308
+ if (row.cnfStyle) {
309
+ children.push(`<w:cnfStyle w:val="${escapeAttribute(row.cnfStyle)}"/>`);
310
+ }
200
311
  if (row.gridBefore !== undefined) {
201
312
  children.push(`<w:gridBefore w:val="${twip(row.gridBefore)}"/>`);
202
313
  }
@@ -213,6 +324,9 @@ function buildTableRowPropertiesInnerXml(row: TableRowPropertiesLike): string {
213
324
  `<w:wAfter w:w="${twip(row.widthAfter.value)}" w:type="${row.widthAfter.type}"/>`,
214
325
  );
215
326
  }
327
+ if (row.cantSplit !== undefined) {
328
+ children.push(row.cantSplit ? `<w:cantSplit/>` : `<w:cantSplit w:val="0"/>`);
329
+ }
216
330
  if (row.height !== undefined) {
217
331
  const hRuleAttr = row.heightRule ? ` w:hRule="${escapeAttribute(row.heightRule)}"` : "";
218
332
  children.push(`<w:trHeight w:val="${twip(row.height)}"${hRuleAttr}/>`);
@@ -228,11 +342,17 @@ function buildTableRowPropertiesInnerXml(row: TableRowPropertiesLike): string {
228
342
  } else if (row.isHeader === false) {
229
343
  children.push(`<w:tblHeader w:val="false"/>`);
230
344
  }
345
+ if (row.horizontalAlignment) {
346
+ children.push(`<w:jc w:val="${escapeAttribute(row.horizontalAlignment)}"/>`);
347
+ }
231
348
  return children.join("");
232
349
  }
233
350
 
234
351
  function buildTableCellPropertiesInnerXml(cell: TableCellPropertiesLike): string {
235
352
  const children: string[] = [];
353
+ if (cell.cnfStyle) {
354
+ children.push(`<w:cnfStyle w:val="${escapeAttribute(cell.cnfStyle)}"/>`);
355
+ }
236
356
  if (cell.width) {
237
357
  children.push(serializeWidth("tcW", cell.width));
238
358
  }
@@ -258,6 +378,21 @@ function buildTableCellPropertiesInnerXml(cell: TableCellPropertiesLike): string
258
378
  children.push(shadingXml);
259
379
  }
260
380
  }
381
+ if (cell.margins) {
382
+ const marginsXml = serializeTableCellMargins(cell.margins);
383
+ if (marginsXml) {
384
+ children.push(`<w:tcMar>${marginsXml}</w:tcMar>`);
385
+ }
386
+ }
387
+ if (cell.noWrap !== undefined) {
388
+ children.push(cell.noWrap ? `<w:noWrap/>` : `<w:noWrap w:val="0"/>`);
389
+ }
390
+ if (cell.fitText !== undefined) {
391
+ children.push(cell.fitText ? `<w:tcFitText/>` : `<w:tcFitText w:val="0"/>`);
392
+ }
393
+ if (cell.textDirection) {
394
+ children.push(`<w:textDirection w:val="${escapeAttribute(cell.textDirection)}"/>`);
395
+ }
261
396
  if (cell.verticalAlign) {
262
397
  children.push(`<w:vAlign w:val="${escapeAttribute(cell.verticalAlign)}"/>`);
263
398
  }
@@ -209,6 +209,13 @@ function normalizeTable(
209
209
  ...(table.borders ? { borders: table.borders } : {}),
210
210
  ...(table.cellMargins ? { cellMargins: table.cellMargins } : {}),
211
211
  ...(table.tblLook ? { tblLook: table.tblLook } : {}),
212
+ ...(table.indent ? { indent: table.indent } : {}),
213
+ ...(table.layoutMode ? { layoutMode: table.layoutMode } : {}),
214
+ ...(table.cellSpacing ? { cellSpacing: table.cellSpacing } : {}),
215
+ ...(table.caption !== undefined ? { caption: table.caption } : {}),
216
+ ...(table.description !== undefined ? { description: table.description } : {}),
217
+ ...(table.bidiVisual !== undefined ? { bidiVisual: table.bidiVisual } : {}),
218
+ ...(table.floating ? { floating: table.floating } : {}),
212
219
  };
213
220
  }
214
221
 
@@ -228,6 +235,9 @@ function normalizeTableRow(
228
235
  ...(row.height !== undefined ? { height: row.height } : {}),
229
236
  ...(row.heightRule ? { heightRule: row.heightRule } : {}),
230
237
  ...(row.isHeader !== undefined ? { isHeader: row.isHeader } : {}),
238
+ ...(row.cantSplit !== undefined ? { cantSplit: row.cantSplit } : {}),
239
+ ...(row.horizontalAlignment ? { horizontalAlignment: row.horizontalAlignment } : {}),
240
+ ...(row.cnfStyle ? { cnfStyle: row.cnfStyle } : {}),
231
241
  cells,
232
242
  };
233
243
  }
@@ -254,6 +264,11 @@ function normalizeTableCell(
254
264
  ...(cell.borders ? { borders: cell.borders } : {}),
255
265
  ...(cell.shading ? { shading: cell.shading } : {}),
256
266
  ...(cell.verticalAlign ? { verticalAlign: cell.verticalAlign } : {}),
267
+ ...(cell.textDirection ? { textDirection: cell.textDirection } : {}),
268
+ ...(cell.noWrap !== undefined ? { noWrap: cell.noWrap } : {}),
269
+ ...(cell.fitText !== undefined ? { fitText: cell.fitText } : {}),
270
+ ...(cell.margins ? { margins: cell.margins } : {}),
271
+ ...(cell.cnfStyle ? { cnfStyle: cell.cnfStyle } : {}),
257
272
  children,
258
273
  };
259
274
  }
@@ -14,16 +14,31 @@ import type {
14
14
  import { classifyFieldInstruction } from "./parse-fields.ts";
15
15
  import {
16
16
  readCellBorders,
17
+ readCellCnfStyle,
18
+ readCellFitText,
19
+ readCellMargins,
20
+ readCellNoWrap,
17
21
  readCellShading,
22
+ readCellTextDirection,
18
23
  readCellVerticalAlign,
19
24
  readCellWidth,
20
25
  readGridColumns as readSharedGridColumns,
26
+ readRowCantSplit,
27
+ readRowCnfStyle,
21
28
  readRowHeight,
22
29
  readRowHeightRule,
30
+ readRowHorizontalAlignment,
23
31
  readRowIsHeader,
24
32
  readTableAlignment,
33
+ readTableBidiVisual,
25
34
  readTableBorders,
35
+ readTableCaption,
26
36
  readTableCellMargins,
37
+ readTableCellSpacing,
38
+ readTableDescription,
39
+ readTableFloating,
40
+ readTableIndent,
41
+ readTableLayoutMode,
27
42
  readTableLook,
28
43
  readTableStyleId,
29
44
  readTableWidth,
@@ -672,6 +687,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
672
687
  let borders: TableNode["borders"];
673
688
  let cellMargins: TableNode["cellMargins"];
674
689
  let tblLook: TableNode["tblLook"];
690
+ let indent: TableNode["indent"];
691
+ let layoutMode: TableNode["layoutMode"];
692
+ let cellSpacing: TableNode["cellSpacing"];
693
+ let caption: TableNode["caption"];
694
+ let description: TableNode["description"];
695
+ let bidiVisual: TableNode["bidiVisual"];
696
+ let floating: TableNode["floating"];
675
697
 
676
698
  for (const child of tblElement.children) {
677
699
  if (child.type !== "element") continue;
@@ -685,6 +707,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
685
707
  borders = readTableBorders(child);
686
708
  cellMargins = readTableCellMargins(child);
687
709
  tblLook = readTableLook(child);
710
+ indent = readTableIndent(child);
711
+ layoutMode = readTableLayoutMode(child);
712
+ cellSpacing = readTableCellSpacing(child);
713
+ caption = readTableCaption(child);
714
+ description = readTableDescription(child);
715
+ bidiVisual = readTableBidiVisual(child);
716
+ floating = readTableFloating(child);
688
717
  } else if (name === "tblGrid") {
689
718
  gridColumns = readGridColumns(child);
690
719
  } else if (name === "tr") {
@@ -703,6 +732,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
703
732
  ...(borders ? { borders } : {}),
704
733
  ...(cellMargins ? { cellMargins } : {}),
705
734
  ...(tblLook ? { tblLook } : {}),
735
+ ...(indent ? { indent } : {}),
736
+ ...(layoutMode ? { layoutMode } : {}),
737
+ ...(cellSpacing ? { cellSpacing } : {}),
738
+ ...(caption !== undefined ? { caption } : {}),
739
+ ...(description !== undefined ? { description } : {}),
740
+ ...(bidiVisual !== undefined ? { bidiVisual } : {}),
741
+ ...(floating ? { floating } : {}),
706
742
  };
707
743
  }
708
744
 
@@ -716,6 +752,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
716
752
  let height: TableRowNode["height"];
717
753
  let heightRule: TableRowNode["heightRule"];
718
754
  let isHeader: TableRowNode["isHeader"];
755
+ let cantSplit: TableRowNode["cantSplit"];
756
+ let horizontalAlignment: TableRowNode["horizontalAlignment"];
757
+ let cnfStyle: TableRowNode["cnfStyle"];
719
758
 
720
759
  for (const child of trElement.children) {
721
760
  if (child.type !== "element") continue;
@@ -726,6 +765,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
726
765
  height = readRowHeight(child);
727
766
  heightRule = readRowHeightRule(child);
728
767
  isHeader = readRowIsHeader(child);
768
+ cantSplit = readRowCantSplit(child);
769
+ horizontalAlignment = readRowHorizontalAlignment(child);
770
+ cnfStyle = readRowCnfStyle(child);
729
771
  } else if (name === "tc") {
730
772
  cells.push(parseSimpleTableCell(child));
731
773
  }
@@ -737,6 +779,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
737
779
  ...(height !== undefined ? { height } : {}),
738
780
  ...(heightRule ? { heightRule } : {}),
739
781
  ...(isHeader !== undefined ? { isHeader } : {}),
782
+ ...(cantSplit !== undefined ? { cantSplit } : {}),
783
+ ...(horizontalAlignment ? { horizontalAlignment } : {}),
784
+ ...(cnfStyle ? { cnfStyle } : {}),
740
785
  cells,
741
786
  };
742
787
  }
@@ -750,6 +795,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
750
795
  let borders: TableCellNode["borders"];
751
796
  let shading: TableCellNode["shading"];
752
797
  let verticalAlign: TableCellNode["verticalAlign"];
798
+ let textDirection: TableCellNode["textDirection"];
799
+ let noWrap: TableCellNode["noWrap"];
800
+ let fitText: TableCellNode["fitText"];
801
+ let margins: TableCellNode["margins"];
802
+ let cnfStyle: TableCellNode["cnfStyle"];
753
803
 
754
804
  for (const child of tcElement.children) {
755
805
  if (child.type !== "element") continue;
@@ -770,6 +820,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
770
820
  borders = readCellBorders(child);
771
821
  shading = readCellShading(child);
772
822
  verticalAlign = readCellVerticalAlign(child);
823
+ textDirection = readCellTextDirection(child);
824
+ noWrap = readCellNoWrap(child);
825
+ fitText = readCellFitText(child);
826
+ margins = readCellMargins(child);
827
+ cnfStyle = readCellCnfStyle(child);
773
828
  } else if (name === "p") {
774
829
  children.push(parseParagraphElement(child));
775
830
  }
@@ -784,6 +839,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
784
839
  ...(borders ? { borders } : {}),
785
840
  ...(shading ? { shading } : {}),
786
841
  ...(verticalAlign ? { verticalAlign } : {}),
842
+ ...(textDirection ? { textDirection } : {}),
843
+ ...(noWrap !== undefined ? { noWrap } : {}),
844
+ ...(fitText !== undefined ? { fitText } : {}),
845
+ ...(margins ? { margins } : {}),
846
+ ...(cnfStyle ? { cnfStyle } : {}),
787
847
  children: children.length > 0 ? children : [{ type: "paragraph", children: [] }],
788
848
  };
789
849
  }
@@ -16,16 +16,31 @@ import { resolveHighlightColor } from "./highlight-colors.ts";
16
16
  import { classifyFieldInstruction } from "./parse-fields.ts";
17
17
  import {
18
18
  readCellBorders,
19
+ readCellCnfStyle,
20
+ readCellFitText,
21
+ readCellMargins,
22
+ readCellNoWrap,
19
23
  readCellShading,
24
+ readCellTextDirection,
20
25
  readCellVerticalAlign,
21
26
  readCellWidth,
22
27
  readGridColumns as readSharedGridColumns,
28
+ readRowCantSplit,
29
+ readRowCnfStyle,
23
30
  readRowHeight,
24
31
  readRowHeightRule,
32
+ readRowHorizontalAlignment,
25
33
  readRowIsHeader,
26
34
  readTableAlignment,
35
+ readTableBidiVisual,
27
36
  readTableBorders,
37
+ readTableCaption,
28
38
  readTableCellMargins,
39
+ readTableCellSpacing,
40
+ readTableDescription,
41
+ readTableFloating,
42
+ readTableIndent,
43
+ readTableLayoutMode,
29
44
  readTableLook,
30
45
  readTableStyleId,
31
46
  readTableWidth,
@@ -927,6 +942,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
927
942
  let borders: TableNode["borders"];
928
943
  let cellMargins: TableNode["cellMargins"];
929
944
  let tblLook: TableNode["tblLook"];
945
+ let indent: TableNode["indent"];
946
+ let layoutMode: TableNode["layoutMode"];
947
+ let cellSpacing: TableNode["cellSpacing"];
948
+ let caption: TableNode["caption"];
949
+ let description: TableNode["description"];
950
+ let bidiVisual: TableNode["bidiVisual"];
951
+ let floating: TableNode["floating"];
930
952
 
931
953
  for (const child of tblElement.children) {
932
954
  if (child.type !== "element") continue;
@@ -940,6 +962,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
940
962
  borders = readTableBorders(child);
941
963
  cellMargins = readTableCellMargins(child);
942
964
  tblLook = readTableLook(child);
965
+ indent = readTableIndent(child);
966
+ layoutMode = readTableLayoutMode(child);
967
+ cellSpacing = readTableCellSpacing(child);
968
+ caption = readTableCaption(child);
969
+ description = readTableDescription(child);
970
+ bidiVisual = readTableBidiVisual(child);
971
+ floating = readTableFloating(child);
943
972
  } else if (name === "tblGrid") {
944
973
  gridColumns = readGridColumns(child);
945
974
  } else if (name === "tr") {
@@ -958,6 +987,13 @@ function parseSimpleTableElement(tblElement: XmlElementNode): TableNode {
958
987
  ...(borders ? { borders } : {}),
959
988
  ...(cellMargins ? { cellMargins } : {}),
960
989
  ...(tblLook ? { tblLook } : {}),
990
+ ...(indent ? { indent } : {}),
991
+ ...(layoutMode ? { layoutMode } : {}),
992
+ ...(cellSpacing ? { cellSpacing } : {}),
993
+ ...(caption !== undefined ? { caption } : {}),
994
+ ...(description !== undefined ? { description } : {}),
995
+ ...(bidiVisual !== undefined ? { bidiVisual } : {}),
996
+ ...(floating ? { floating } : {}),
961
997
  };
962
998
  }
963
999
 
@@ -971,6 +1007,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
971
1007
  let height: TableRowNode["height"];
972
1008
  let heightRule: TableRowNode["heightRule"];
973
1009
  let isHeader: TableRowNode["isHeader"];
1010
+ let cantSplit: TableRowNode["cantSplit"];
1011
+ let horizontalAlignment: TableRowNode["horizontalAlignment"];
1012
+ let cnfStyle: TableRowNode["cnfStyle"];
974
1013
 
975
1014
  for (const child of trElement.children) {
976
1015
  if (child.type !== "element") continue;
@@ -981,6 +1020,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
981
1020
  height = readRowHeight(child);
982
1021
  heightRule = readRowHeightRule(child);
983
1022
  isHeader = readRowIsHeader(child);
1023
+ cantSplit = readRowCantSplit(child);
1024
+ horizontalAlignment = readRowHorizontalAlignment(child);
1025
+ cnfStyle = readRowCnfStyle(child);
984
1026
  } else if (name === "tc") {
985
1027
  cells.push(parseSimpleTableCell(child));
986
1028
  }
@@ -992,6 +1034,9 @@ function parseSimpleTableRow(trElement: XmlElementNode): TableRowNode {
992
1034
  ...(height !== undefined ? { height } : {}),
993
1035
  ...(heightRule ? { heightRule } : {}),
994
1036
  ...(isHeader !== undefined ? { isHeader } : {}),
1037
+ ...(cantSplit !== undefined ? { cantSplit } : {}),
1038
+ ...(horizontalAlignment ? { horizontalAlignment } : {}),
1039
+ ...(cnfStyle ? { cnfStyle } : {}),
995
1040
  cells,
996
1041
  };
997
1042
  }
@@ -1005,6 +1050,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
1005
1050
  let borders: TableCellNode["borders"];
1006
1051
  let shading: TableCellNode["shading"];
1007
1052
  let verticalAlign: TableCellNode["verticalAlign"];
1053
+ let textDirection: TableCellNode["textDirection"];
1054
+ let noWrap: TableCellNode["noWrap"];
1055
+ let fitText: TableCellNode["fitText"];
1056
+ let margins: TableCellNode["margins"];
1057
+ let cnfStyle: TableCellNode["cnfStyle"];
1008
1058
 
1009
1059
  for (const child of tcElement.children) {
1010
1060
  if (child.type !== "element") continue;
@@ -1025,6 +1075,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
1025
1075
  borders = readCellBorders(child);
1026
1076
  shading = readCellShading(child);
1027
1077
  verticalAlign = readCellVerticalAlign(child);
1078
+ textDirection = readCellTextDirection(child);
1079
+ noWrap = readCellNoWrap(child);
1080
+ fitText = readCellFitText(child);
1081
+ margins = readCellMargins(child);
1082
+ cnfStyle = readCellCnfStyle(child);
1028
1083
  } else if (name === "p") {
1029
1084
  children.push(parseParagraphElement(child));
1030
1085
  }
@@ -1039,6 +1094,11 @@ function parseSimpleTableCell(tcElement: XmlElementNode): TableCellNode {
1039
1094
  ...(borders ? { borders } : {}),
1040
1095
  ...(shading ? { shading } : {}),
1041
1096
  ...(verticalAlign ? { verticalAlign } : {}),
1097
+ ...(textDirection ? { textDirection } : {}),
1098
+ ...(noWrap !== undefined ? { noWrap } : {}),
1099
+ ...(fitText !== undefined ? { fitText } : {}),
1100
+ ...(margins ? { margins } : {}),
1101
+ ...(cnfStyle ? { cnfStyle } : {}),
1042
1102
  children: children.length > 0 ? children : [{ type: "paragraph", children: [] }],
1043
1103
  };
1044
1104
  }