@beyondwork/docx-react-component 1.0.18 → 1.0.20
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.
- package/README.md +8 -2
- package/package.json +24 -34
- package/src/api/README.md +5 -1
- package/src/api/public-types.ts +710 -4
- package/src/api/session-state.ts +60 -0
- package/src/core/commands/formatting-commands.ts +2 -1
- package/src/core/commands/image-commands.ts +147 -0
- package/src/core/commands/index.ts +19 -3
- package/src/core/commands/list-commands.ts +231 -36
- package/src/core/commands/paragraph-layout-commands.ts +339 -0
- package/src/core/commands/section-layout-commands.ts +680 -0
- package/src/core/commands/style-commands.ts +262 -0
- package/src/core/search/search-text.ts +357 -0
- package/src/core/selection/mapping.ts +41 -0
- package/src/core/state/editor-state.ts +4 -1
- package/src/index.ts +51 -0
- package/src/io/docx-session.ts +623 -56
- package/src/io/export/serialize-comments.ts +104 -34
- package/src/io/export/serialize-footnotes.ts +198 -1
- package/src/io/export/serialize-headers-footers.ts +203 -10
- package/src/io/export/serialize-main-document.ts +285 -8
- package/src/io/export/serialize-numbering.ts +28 -7
- package/src/io/export/split-review-boundaries.ts +181 -19
- package/src/io/normalize/normalize-text.ts +144 -32
- package/src/io/ooxml/highlight-colors.ts +39 -0
- package/src/io/ooxml/numbering-sentinels.ts +44 -0
- package/src/io/ooxml/parse-comments.ts +85 -19
- package/src/io/ooxml/parse-fields.ts +396 -0
- package/src/io/ooxml/parse-footnotes.ts +452 -22
- package/src/io/ooxml/parse-headers-footers.ts +657 -29
- package/src/io/ooxml/parse-inline-media.ts +30 -0
- package/src/io/ooxml/parse-main-document.ts +807 -20
- package/src/io/ooxml/parse-numbering.ts +7 -0
- package/src/io/ooxml/parse-revisions.ts +317 -38
- package/src/io/ooxml/parse-settings.ts +184 -0
- package/src/io/ooxml/parse-shapes.ts +25 -0
- package/src/io/ooxml/parse-styles.ts +463 -0
- package/src/io/ooxml/parse-theme.ts +32 -0
- package/src/legal/bookmarks.ts +44 -0
- package/src/legal/cross-references.ts +59 -1
- package/src/model/canonical-document.ts +250 -4
- package/src/model/cds-1.0.0.ts +13 -0
- package/src/model/snapshot.ts +87 -2
- package/src/review/store/revision-store.ts +6 -0
- package/src/review/store/revision-types.ts +1 -0
- package/src/runtime/document-layout.ts +332 -0
- package/src/runtime/document-navigation.ts +603 -0
- package/src/runtime/document-runtime.ts +1754 -78
- package/src/runtime/document-search.ts +145 -0
- package/src/runtime/numbering-prefix.ts +47 -26
- package/src/runtime/page-layout-estimation.ts +212 -0
- package/src/runtime/read-only-diagnostics-runtime.ts +9 -0
- package/src/runtime/session-capabilities.ts +35 -3
- package/src/runtime/story-context.ts +164 -0
- package/src/runtime/story-targeting.ts +162 -0
- package/src/runtime/surface-projection.ts +324 -36
- package/src/runtime/table-schema.ts +89 -7
- package/src/runtime/view-state.ts +477 -0
- package/src/runtime/workflow-markup.ts +349 -0
- package/src/ui/WordReviewEditor.tsx +2469 -1344
- package/src/ui/browser-export.ts +52 -0
- package/src/ui/editor-command-bag.ts +120 -0
- package/src/ui/editor-runtime-boundary.ts +1422 -0
- package/src/ui/editor-shell-view.tsx +134 -0
- package/src/ui/editor-surface-controller.tsx +51 -0
- package/src/ui/headless/preserve-editor-selection.ts +5 -0
- package/src/ui/headless/revision-decoration-model.ts +4 -4
- package/src/ui/headless/selection-helpers.ts +20 -0
- package/src/ui/headless/selection-toolbar-model.ts +22 -0
- package/src/ui/headless/use-editor-keyboard.ts +6 -1
- package/src/ui/runtime-snapshot-selectors.ts +197 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +18 -2
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +129 -0
- package/src/ui-tailwind/chrome/tw-layout-panel.tsx +114 -0
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +34 -0
- package/src/ui-tailwind/chrome/tw-page-ruler.tsx +386 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +150 -14
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +128 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +179 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +46 -7
- package/src/ui-tailwind/editor-surface/pm-contextual-ui.ts +31 -0
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +35 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +3 -3
- package/src/ui-tailwind/editor-surface/pm-schema.ts +186 -13
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +191 -68
- package/src/ui-tailwind/editor-surface/search-plugin.ts +19 -68
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +51 -0
- package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +11 -0
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +7 -1
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +528 -85
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +0 -1
- package/src/ui-tailwind/index.ts +2 -1
- package/src/ui-tailwind/page-chrome-model.ts +27 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +277 -147
- package/src/ui-tailwind/review/tw-health-panel.tsx +31 -2
- package/src/ui-tailwind/review/tw-review-rail.tsx +8 -8
- package/src/ui-tailwind/review/tw-revision-sidebar.tsx +15 -15
- package/src/ui-tailwind/theme/editor-theme.css +127 -0
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +4 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +829 -12
- package/src/ui-tailwind/tw-review-workspace.tsx +1238 -42
- package/src/validation/compatibility-engine.ts +119 -24
- package/src/validation/compatibility-report.ts +1 -0
- package/src/validation/diagnostics.ts +1 -0
- package/src/validation/docx-comment-proof.ts +707 -0
|
@@ -104,23 +104,13 @@ function collectContentFeatures(
|
|
|
104
104
|
lists: false,
|
|
105
105
|
hyperlinks: false,
|
|
106
106
|
images: false,
|
|
107
|
+
tables: false,
|
|
108
|
+
sections: false,
|
|
109
|
+
contentControls: false,
|
|
107
110
|
};
|
|
108
111
|
|
|
109
112
|
for (let index = 0; index < content.children.length; index += 1) {
|
|
110
|
-
|
|
111
|
-
if (block.type !== "paragraph") {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
flags.paragraphs = true;
|
|
116
|
-
if (block.styleId?.toLowerCase().startsWith("heading")) {
|
|
117
|
-
flags.headings = true;
|
|
118
|
-
}
|
|
119
|
-
if (block.numbering) {
|
|
120
|
-
flags.lists = true;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
measureParagraph(block, flags);
|
|
113
|
+
measureBlock(content.children[index], flags);
|
|
124
114
|
}
|
|
125
115
|
|
|
126
116
|
const entries: CompatibilityFeatureEntry[] = [];
|
|
@@ -145,16 +135,94 @@ function collectContentFeatures(
|
|
|
145
135
|
if (flags.images) {
|
|
146
136
|
entries.push(supportedEntry("inline-images", "Inline image placements stay attached to preserved media parts."));
|
|
147
137
|
}
|
|
138
|
+
if (flags.tables) {
|
|
139
|
+
entries.push(
|
|
140
|
+
supportedEntry(
|
|
141
|
+
"tables",
|
|
142
|
+
"Structured tables keep cell topology and common visual properties through runtime editing and export.",
|
|
143
|
+
),
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (flags.sections) {
|
|
147
|
+
entries.push(
|
|
148
|
+
supportedEntry(
|
|
149
|
+
"sections",
|
|
150
|
+
"Section boundaries and page-layout properties remain structured and export-safe.",
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (flags.contentControls) {
|
|
155
|
+
entries.push(
|
|
156
|
+
supportedEntry(
|
|
157
|
+
"content-controls",
|
|
158
|
+
"Common content controls render through structured SDT state and round-trip without flattening to opaque placeholders.",
|
|
159
|
+
),
|
|
160
|
+
);
|
|
161
|
+
}
|
|
148
162
|
return entries;
|
|
149
163
|
}
|
|
150
164
|
|
|
165
|
+
function measureBlock(
|
|
166
|
+
block: BlockNode,
|
|
167
|
+
flags: {
|
|
168
|
+
paragraphs: boolean;
|
|
169
|
+
runs: boolean;
|
|
170
|
+
whitespace: boolean;
|
|
171
|
+
headings: boolean;
|
|
172
|
+
lists: boolean;
|
|
173
|
+
hyperlinks: boolean;
|
|
174
|
+
images: boolean;
|
|
175
|
+
tables: boolean;
|
|
176
|
+
sections: boolean;
|
|
177
|
+
contentControls: boolean;
|
|
178
|
+
},
|
|
179
|
+
): number {
|
|
180
|
+
switch (block.type) {
|
|
181
|
+
case "paragraph":
|
|
182
|
+
flags.paragraphs = true;
|
|
183
|
+
if (block.styleId?.toLowerCase().startsWith("heading")) {
|
|
184
|
+
flags.headings = true;
|
|
185
|
+
}
|
|
186
|
+
if (block.numbering) {
|
|
187
|
+
flags.lists = true;
|
|
188
|
+
}
|
|
189
|
+
return measureParagraph(block, flags);
|
|
190
|
+
case "table":
|
|
191
|
+
flags.tables = true;
|
|
192
|
+
return block.rows.reduce(
|
|
193
|
+
(size, row) =>
|
|
194
|
+
size +
|
|
195
|
+
row.cells.reduce(
|
|
196
|
+
(cellSize, cell) =>
|
|
197
|
+
cellSize + cell.children.reduce((childSize, child) => childSize + measureBlock(child, flags), 0),
|
|
198
|
+
0,
|
|
199
|
+
),
|
|
200
|
+
0,
|
|
201
|
+
);
|
|
202
|
+
case "sdt":
|
|
203
|
+
flags.contentControls = true;
|
|
204
|
+
return block.children.reduce((size, child) => size + measureBlock(child, flags), 0);
|
|
205
|
+
case "custom_xml":
|
|
206
|
+
return block.children.reduce((size, child) => size + measureBlock(child, flags), 0);
|
|
207
|
+
case "section_break":
|
|
208
|
+
flags.sections = true;
|
|
209
|
+
return 1;
|
|
210
|
+
default:
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
151
215
|
function measureParagraph(
|
|
152
216
|
paragraph: ParagraphNode,
|
|
153
217
|
flags: {
|
|
218
|
+
paragraphs: boolean;
|
|
154
219
|
runs: boolean;
|
|
155
220
|
whitespace: boolean;
|
|
156
221
|
hyperlinks: boolean;
|
|
157
222
|
images: boolean;
|
|
223
|
+
tables: boolean;
|
|
224
|
+
sections: boolean;
|
|
225
|
+
contentControls: boolean;
|
|
158
226
|
},
|
|
159
227
|
): number {
|
|
160
228
|
let size = 0;
|
|
@@ -170,10 +238,14 @@ function measureParagraph(
|
|
|
170
238
|
function measureInlineNode(
|
|
171
239
|
node: InlineNode,
|
|
172
240
|
flags: {
|
|
241
|
+
paragraphs: boolean;
|
|
173
242
|
runs: boolean;
|
|
174
243
|
whitespace: boolean;
|
|
175
244
|
hyperlinks: boolean;
|
|
176
245
|
images: boolean;
|
|
246
|
+
tables: boolean;
|
|
247
|
+
sections: boolean;
|
|
248
|
+
contentControls: boolean;
|
|
177
249
|
},
|
|
178
250
|
): number {
|
|
179
251
|
switch (node.type) {
|
|
@@ -310,12 +382,12 @@ function collectSubPartFeatures(
|
|
|
310
382
|
Object.keys(subParts.footnoteCollection?.footnotes ?? {}).length +
|
|
311
383
|
Object.keys(subParts.footnoteCollection?.endnotes ?? {}).length;
|
|
312
384
|
|
|
313
|
-
if (hasHeaderFooterContent) {
|
|
385
|
+
if (hasHeaderFooterContent && !entries.some((entry) => entry.featureKey === "headers-footers-lossy")) {
|
|
314
386
|
entries.push({
|
|
315
387
|
featureEntryId: "feature:subparts:headers-footers",
|
|
316
388
|
featureKey: "headers-footers",
|
|
317
|
-
featureClass: "
|
|
318
|
-
message: "Headers and footers
|
|
389
|
+
featureClass: "supported-roundtrip",
|
|
390
|
+
message: "Headers and footers resolve as structured secondary stories with export-safe ownership.",
|
|
319
391
|
details: {
|
|
320
392
|
headerCount: subParts.headers?.length ?? 0,
|
|
321
393
|
footerCount: subParts.footers?.length ?? 0,
|
|
@@ -323,12 +395,12 @@ function collectSubPartFeatures(
|
|
|
323
395
|
});
|
|
324
396
|
}
|
|
325
397
|
|
|
326
|
-
if (noteCount > 0) {
|
|
398
|
+
if (noteCount > 0 && !entries.some((entry) => entry.featureKey === "notes-lossy")) {
|
|
327
399
|
entries.push({
|
|
328
400
|
featureEntryId: "feature:subparts:notes",
|
|
329
401
|
featureKey: "notes",
|
|
330
|
-
featureClass: "
|
|
331
|
-
message: "Footnotes and endnotes
|
|
402
|
+
featureClass: "supported-roundtrip",
|
|
403
|
+
message: "Footnotes and endnotes resolve as structured secondary stories with export-safe ownership.",
|
|
332
404
|
details: {
|
|
333
405
|
footnoteCount: Object.keys(subParts.footnoteCollection?.footnotes ?? {}).length,
|
|
334
406
|
endnoteCount: Object.keys(subParts.footnoteCollection?.endnotes ?? {}).length,
|
|
@@ -407,6 +479,15 @@ function collectLossyBlocks(
|
|
|
407
479
|
const issues: string[] = [];
|
|
408
480
|
|
|
409
481
|
for (const block of blocks) {
|
|
482
|
+
if (block.type === "table") {
|
|
483
|
+
for (const row of block.rows) {
|
|
484
|
+
for (const cell of row.cells) {
|
|
485
|
+
issues.push(...collectLossyBlocks(cell.children, `${surface}:table-cell`));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
|
|
410
491
|
if (block.type !== "paragraph") {
|
|
411
492
|
issues.push(`${surface}:${block.type}`);
|
|
412
493
|
continue;
|
|
@@ -414,9 +495,6 @@ function collectLossyBlocks(
|
|
|
414
495
|
|
|
415
496
|
if (
|
|
416
497
|
block.numbering !== undefined ||
|
|
417
|
-
block.spacing !== undefined ||
|
|
418
|
-
block.indentation !== undefined ||
|
|
419
|
-
block.tabStops !== undefined ||
|
|
420
498
|
block.keepNext !== undefined ||
|
|
421
499
|
block.keepLines !== undefined ||
|
|
422
500
|
block.outlineLevel !== undefined ||
|
|
@@ -445,6 +523,8 @@ function collectLossyInlineContent(
|
|
|
445
523
|
): string[] {
|
|
446
524
|
switch (node.type) {
|
|
447
525
|
case "text": {
|
|
526
|
+
const allowSecondaryStoryColorMarks =
|
|
527
|
+
surface.startsWith("header:") || surface.startsWith("footer:");
|
|
448
528
|
const unsupportedMarks = (node.marks ?? [])
|
|
449
529
|
.filter(
|
|
450
530
|
(mark) =>
|
|
@@ -452,7 +532,14 @@ function collectLossyInlineContent(
|
|
|
452
532
|
mark.type !== "italic" &&
|
|
453
533
|
mark.type !== "underline" &&
|
|
454
534
|
mark.type !== "strikethrough" &&
|
|
455
|
-
mark.type !== "doubleStrikethrough"
|
|
535
|
+
mark.type !== "doubleStrikethrough" &&
|
|
536
|
+
mark.type !== "fontFamily" &&
|
|
537
|
+
mark.type !== "fontSize" &&
|
|
538
|
+
mark.type !== "textColor" &&
|
|
539
|
+
(!allowSecondaryStoryColorMarks || mark.type !== "backgroundColor") &&
|
|
540
|
+
(!allowSecondaryStoryColorMarks || mark.type !== "highlight") &&
|
|
541
|
+
mark.type !== "smallCaps" &&
|
|
542
|
+
mark.type !== "allCaps",
|
|
456
543
|
)
|
|
457
544
|
.map((mark) => `${surface}:mark:${mark.type}`);
|
|
458
545
|
return unsupportedMarks;
|
|
@@ -460,6 +547,14 @@ function collectLossyInlineContent(
|
|
|
460
547
|
case "tab":
|
|
461
548
|
case "hard_break":
|
|
462
549
|
case "footnote_ref":
|
|
550
|
+
case "field":
|
|
551
|
+
case "bookmark_start":
|
|
552
|
+
case "bookmark_end":
|
|
553
|
+
case "shape":
|
|
554
|
+
case "wordart":
|
|
555
|
+
case "vml_shape":
|
|
556
|
+
case "chart_preview":
|
|
557
|
+
case "smartart_preview":
|
|
463
558
|
return [];
|
|
464
559
|
default:
|
|
465
560
|
return [`${surface}:${node.type}`];
|