@beyondwork/docx-react-component 1.0.42 → 1.0.45
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 +17 -0
- package/package.json +5 -4
- package/src/api/editor-state-types.ts +110 -0
- package/src/api/public-types.ts +333 -4
- package/src/core/commands/formatting-commands.ts +7 -1
- package/src/core/commands/index.ts +60 -10
- package/src/core/commands/text-commands.ts +59 -0
- package/src/core/search/search-text.ts +15 -2
- package/src/core/selection/review-anchors.ts +131 -21
- package/src/index.ts +29 -1
- package/src/io/chart-preview-resolver.ts +281 -0
- package/src/io/docx-session.ts +692 -2
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +38 -9
- package/src/io/export/twip.ts +1 -1
- package/src/io/load-scheduler.ts +230 -0
- package/src/io/normalize/normalize-text.ts +116 -0
- package/src/io/ooxml/parse-comments.ts +0 -33
- package/src/io/ooxml/parse-complex-content.ts +14 -0
- package/src/io/ooxml/parse-main-document.ts +4 -0
- package/src/io/ooxml/workflow-payload-validator.ts +97 -1
- package/src/io/ooxml/workflow-payload.ts +172 -1
- package/src/preservation/opaque-region.ts +5 -0
- package/src/review/store/comment-remapping.ts +2 -2
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/document-runtime.ts +661 -42
- package/src/runtime/edit-dispatch/dispatch-text-command.ts +98 -0
- package/src/runtime/edit-dispatch/index.ts +2 -0
- package/src/runtime/edit-dispatch/list-aware-dispatch.ts +125 -0
- package/src/runtime/editor-state-channel.ts +544 -0
- package/src/runtime/editor-state-integration.ts +217 -0
- package/src/runtime/editor-surface/capabilities.ts +411 -0
- package/src/runtime/layout/index.ts +2 -0
- package/src/runtime/layout/inert-layout-facet.ts +4 -0
- package/src/runtime/layout/layout-engine-instance.ts +63 -2
- package/src/runtime/layout/layout-engine-version.ts +41 -0
- package/src/runtime/layout/paginated-layout-engine.ts +211 -14
- package/src/runtime/layout/public-facet.ts +430 -1
- package/src/runtime/perf-counters.ts +28 -0
- package/src/runtime/prerender/cache-envelope.ts +29 -0
- package/src/runtime/prerender/cache-key.ts +66 -0
- package/src/runtime/prerender/font-fingerprint.ts +17 -0
- package/src/runtime/prerender/graph-canonicalize.ts +121 -0
- package/src/runtime/prerender/indexeddb-cache.ts +184 -0
- package/src/runtime/prerender/prerender-document.ts +145 -0
- package/src/runtime/render/block-fragment-projection.ts +2 -0
- package/src/runtime/render/render-frame-types.ts +17 -0
- package/src/runtime/render/render-kernel.ts +172 -29
- package/src/runtime/selection/post-edit-validator.ts +77 -0
- package/src/runtime/surface-projection.ts +45 -7
- package/src/runtime/workflow-markup.ts +71 -16
- package/src/ui/WordReviewEditor.tsx +142 -237
- package/src/ui/editor-command-bag.ts +14 -0
- package/src/ui/editor-runtime-boundary.ts +115 -12
- package/src/ui/editor-shell-view.tsx +10 -0
- package/src/ui/editor-surface-controller.tsx +5 -0
- package/src/ui/headless/selection-helpers.ts +10 -0
- package/src/ui/runtime-shortcut-dispatch.ts +28 -68
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +62 -2
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +281 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +48 -0
- package/src/ui-tailwind/editor-surface/paste-plain-text.ts +72 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +118 -8
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +76 -165
- package/src/ui-tailwind/editor-surface/pm-schema.ts +170 -4
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +58 -7
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +265 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +8 -255
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +47 -0
- package/src/ui-tailwind/index.ts +5 -1
- package/src/ui-tailwind/page-stack/tw-endnote-area.tsx +57 -0
- package/src/ui-tailwind/page-stack/tw-footnote-area.tsx +71 -0
- package/src/ui-tailwind/page-stack/tw-page-footer-band.tsx +73 -0
- package/src/ui-tailwind/page-stack/tw-page-header-band.tsx +74 -0
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +477 -0
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +374 -0
- package/src/ui-tailwind/page-stack/use-visible-block-range.ts +157 -0
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +155 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +77 -16
- package/src/ui-tailwind/theme/editor-theme.css +47 -14
- package/src/ui-tailwind/tw-review-workspace.tsx +303 -123
package/src/io/docx-session.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CompatibilityReport as PublicCompatibilityReport,
|
|
3
3
|
EditorError,
|
|
4
|
+
EditorHostAdapter,
|
|
4
5
|
EditorSessionState,
|
|
5
6
|
EditorWarning as PublicEditorWarning,
|
|
6
7
|
EditorAnchorProjection as PublicEditorAnchorProjection,
|
|
@@ -39,7 +40,12 @@ import {
|
|
|
39
40
|
type ParsedInlineNode,
|
|
40
41
|
type ParsedPermStartInlineNode,
|
|
41
42
|
} from "./ooxml/parse-main-document.ts";
|
|
42
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
normalizeParsedTextDocument,
|
|
45
|
+
normalizeParsedTextDocumentAsync,
|
|
46
|
+
} from "./normalize/normalize-text.ts";
|
|
47
|
+
import { resolveChartPreviewsForDocument } from "./chart-preview-resolver.ts";
|
|
48
|
+
import { type LoadScheduler } from "./load-scheduler.ts";
|
|
43
49
|
import {
|
|
44
50
|
CONTENT_TYPES_PATH,
|
|
45
51
|
PACKAGE_RELATIONSHIPS_PATH,
|
|
@@ -213,6 +219,26 @@ interface LoadDocxEditorSessionOptions {
|
|
|
213
219
|
sourceLabel?: string;
|
|
214
220
|
bytes: Uint8Array | ArrayBuffer;
|
|
215
221
|
editorBuild?: string;
|
|
222
|
+
/**
|
|
223
|
+
* Fastload P2: optional instrumentation callback invoked once per
|
|
224
|
+
* completed load stage. Stage ordering: opc → body →
|
|
225
|
+
* styles-numbering-comments → skeleton-ready. `durationMs` is
|
|
226
|
+
* measured against `performance.now()` boundaries inside the loader.
|
|
227
|
+
*
|
|
228
|
+
* Pure instrumentation — has no effect on returned session shape.
|
|
229
|
+
* Safe to leave undefined; existing callers observe no behavior
|
|
230
|
+
* change.
|
|
231
|
+
*/
|
|
232
|
+
onLoadStage?: (stage: import("../api/public-types.ts").LoadStage, durationMs: number) => void;
|
|
233
|
+
/**
|
|
234
|
+
* Stage 0B.1: host-adapter surface. The sync loader accepts the option for
|
|
235
|
+
* API symmetry with {@link LoadDocxEditorSessionAsyncOptions} but does not
|
|
236
|
+
* invoke `renderChartPreview` — chart-preview synthesis is asynchronous, so
|
|
237
|
+
* hosts that want preview bitmaps must call {@link loadDocxEditorSessionAsync}.
|
|
238
|
+
* Other adapter methods (load/saveSession/logEvent) are not consumed by the
|
|
239
|
+
* loader itself and are carried through unchanged.
|
|
240
|
+
*/
|
|
241
|
+
hostAdapter?: EditorHostAdapter;
|
|
216
242
|
}
|
|
217
243
|
|
|
218
244
|
export interface LoadedDocxEditorSession {
|
|
@@ -225,6 +251,8 @@ export interface LoadedDocxEditorSession {
|
|
|
225
251
|
sessionState: EditorSessionState | PersistedEditorSnapshot,
|
|
226
252
|
options?: ExportDocxOptions,
|
|
227
253
|
) => Promise<ExportResult>;
|
|
254
|
+
/** Schema 1.2 — editorState block parsed from the 1.2 payload, if present. */
|
|
255
|
+
initialEditorStatePayload?: import("./ooxml/workflow-payload.ts").EditorStatePayload;
|
|
228
256
|
}
|
|
229
257
|
|
|
230
258
|
interface ImportedDocxState {
|
|
@@ -277,6 +305,37 @@ const BLOCKING_COMMENT_DIAGNOSTIC_CODES = new Set<CommentImportDiagnostic["code"
|
|
|
277
305
|
"preserve_only_revision_overlap",
|
|
278
306
|
]);
|
|
279
307
|
|
|
308
|
+
interface StageEmitter {
|
|
309
|
+
emit(stage: import("../api/public-types.ts").LoadStage): void;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Fastload P2 (hoisted in P6): build a stage-event emitter. When no callback
|
|
314
|
+
* is supplied the emitter is a zero-cost no-op. Shared between the sync and
|
|
315
|
+
* async load orchestrators so both paths emit `load-stage` events at the
|
|
316
|
+
* same four boundaries: `opc` → `body` → `styles-numbering-comments` →
|
|
317
|
+
* `skeleton-ready`.
|
|
318
|
+
*/
|
|
319
|
+
function createStageEmitter(
|
|
320
|
+
onStage: LoadDocxEditorSessionOptions["onLoadStage"],
|
|
321
|
+
): StageEmitter {
|
|
322
|
+
if (!onStage) {
|
|
323
|
+
return {
|
|
324
|
+
emit() {
|
|
325
|
+
/* no-op */
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
let cursor = loadStageNow();
|
|
330
|
+
return {
|
|
331
|
+
emit(stage) {
|
|
332
|
+
const nextMark = loadStageNow();
|
|
333
|
+
onStage(stage, nextMark - cursor);
|
|
334
|
+
cursor = nextMark;
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
280
339
|
export function loadDocxEditorSession(
|
|
281
340
|
options: LoadDocxEditorSessionOptions,
|
|
282
341
|
): LoadedDocxEditorSession {
|
|
@@ -285,6 +344,9 @@ export function loadDocxEditorSession(
|
|
|
285
344
|
? options.editorBuild
|
|
286
345
|
: "dev";
|
|
287
346
|
const sourceBytes = toUint8Array(options.bytes);
|
|
347
|
+
|
|
348
|
+
const stages = createStageEmitter(options.onLoadStage);
|
|
349
|
+
|
|
288
350
|
let sourcePackage: OpcPackage;
|
|
289
351
|
|
|
290
352
|
try {
|
|
@@ -297,6 +359,7 @@ export function loadDocxEditorSession(
|
|
|
297
359
|
}),
|
|
298
360
|
);
|
|
299
361
|
}
|
|
362
|
+
stages.emit("opc");
|
|
300
363
|
const embeddedWorkflowPayload = parseWorkflowPayloadEnvelopeFromPackage(sourcePackage);
|
|
301
364
|
const embeddedWorkflowMetadata = embeddedWorkflowPayload?.workflowMetadata;
|
|
302
365
|
const embeddedWorkflowOverlay = embeddedWorkflowPayload?.workflowOverlay;
|
|
@@ -376,6 +439,7 @@ export function loadDocxEditorSession(
|
|
|
376
439
|
parsedDocument,
|
|
377
440
|
mainDocumentPath,
|
|
378
441
|
);
|
|
442
|
+
stages.emit("body");
|
|
379
443
|
const commentsPartPath = resolveCommentsPartPath(
|
|
380
444
|
sourcePackage,
|
|
381
445
|
mainDocumentPath,
|
|
@@ -438,6 +502,7 @@ export function loadDocxEditorSession(
|
|
|
438
502
|
normalizedDocument.preservation.opaqueFragments,
|
|
439
503
|
normalizedRevisions.revisions,
|
|
440
504
|
);
|
|
505
|
+
stages.emit("styles-numbering-comments");
|
|
441
506
|
const importedStoryRevisions: ReviewRevisionRecord[] = [];
|
|
442
507
|
const importedStoryRevisionDiagnostics: ParsedRevisionsResult["diagnostics"] = [];
|
|
443
508
|
const subPartOpaqueState = createSubPartOpaqueImportState(
|
|
@@ -813,6 +878,7 @@ export function loadDocxEditorSession(
|
|
|
813
878
|
},
|
|
814
879
|
};
|
|
815
880
|
|
|
881
|
+
stages.emit("skeleton-ready");
|
|
816
882
|
return {
|
|
817
883
|
initialSessionState,
|
|
818
884
|
initialSnapshot: snapshot,
|
|
@@ -820,6 +886,9 @@ export function loadDocxEditorSession(
|
|
|
820
886
|
protectionSnapshot: importedProtectionSnapshot,
|
|
821
887
|
exportDocx: async (nextSessionState, exportOptions) =>
|
|
822
888
|
exportDocxEditorSession(importedState, nextSessionState, exportOptions),
|
|
889
|
+
...(embeddedWorkflowPayload?.editorState
|
|
890
|
+
? { initialEditorStatePayload: embeddedWorkflowPayload.editorState }
|
|
891
|
+
: {}),
|
|
823
892
|
};
|
|
824
893
|
} catch (error) {
|
|
825
894
|
return createDiagnosticsSession(
|
|
@@ -829,6 +898,623 @@ export function loadDocxEditorSession(
|
|
|
829
898
|
}
|
|
830
899
|
}
|
|
831
900
|
|
|
901
|
+
interface LoadDocxEditorSessionAsyncOptions extends LoadDocxEditorSessionOptions {
|
|
902
|
+
/**
|
|
903
|
+
* Scheduler that the async loader awaits between parse stages. Callers
|
|
904
|
+
* in DOM environments should construct this with `createLoadScheduler()`
|
|
905
|
+
* (auto-detects scheduler.yield → MessageChannel → setTimeout backend).
|
|
906
|
+
* Callers in Node / SSR should pass
|
|
907
|
+
* `createLoadScheduler({ backendOverride: "sync" })` — sync backend
|
|
908
|
+
* yields resolve without task-boundary latency, so the async path
|
|
909
|
+
* behaves like the sync path from the test harness POV.
|
|
910
|
+
*/
|
|
911
|
+
scheduler: LoadScheduler;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Fastload P6: async sibling of {@link loadDocxEditorSession} that yields to
|
|
916
|
+
* the browser between parse stages. Parse sequence is byte-equivalent to
|
|
917
|
+
* the sync path (asserted on every F*.docx fixture in
|
|
918
|
+
* `test/io/fastload-parity.test.ts`). Yields fire at:
|
|
919
|
+
* 1. after OPC read,
|
|
920
|
+
* 2. after `parseMainDocumentXml`,
|
|
921
|
+
* 3. between every header/footer sub-part parse,
|
|
922
|
+
* 4. after footnotes/endnotes parse,
|
|
923
|
+
* 5. after theme + settings + styles parse,
|
|
924
|
+
* 6. after `buildCompatibilityReport`,
|
|
925
|
+
* plus mid-walk yields every 256 blocks inside
|
|
926
|
+
* `normalizeParsedTextDocumentAsync` (stage 3 — body normalize).
|
|
927
|
+
*
|
|
928
|
+
* Sync `loadDocxEditorSession` remains the only entry point for Node tests
|
|
929
|
+
* and SSR. The DOM boundary in `editor-runtime-boundary.ts` calls this
|
|
930
|
+
* async path so the browser can paint the skeleton mid-parse.
|
|
931
|
+
*/
|
|
932
|
+
export async function loadDocxEditorSessionAsync(
|
|
933
|
+
options: LoadDocxEditorSessionAsyncOptions,
|
|
934
|
+
): Promise<LoadedDocxEditorSession> {
|
|
935
|
+
const { scheduler } = options;
|
|
936
|
+
const editorBuild =
|
|
937
|
+
typeof options.editorBuild === "string" && options.editorBuild.length > 0
|
|
938
|
+
? options.editorBuild
|
|
939
|
+
: "dev";
|
|
940
|
+
const sourceBytes = toUint8Array(options.bytes);
|
|
941
|
+
|
|
942
|
+
const stages = createStageEmitter(options.onLoadStage);
|
|
943
|
+
|
|
944
|
+
let sourcePackage: OpcPackage;
|
|
945
|
+
|
|
946
|
+
try {
|
|
947
|
+
sourcePackage = readOpcPackage(sourceBytes);
|
|
948
|
+
} catch (error) {
|
|
949
|
+
return createDiagnosticsSession(
|
|
950
|
+
options,
|
|
951
|
+
createPackageImportDiagnostics({
|
|
952
|
+
issue: classifyCorruptPackageError(error),
|
|
953
|
+
}),
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
stages.emit("opc");
|
|
957
|
+
await scheduler.yield();
|
|
958
|
+
const embeddedWorkflowPayload = parseWorkflowPayloadEnvelopeFromPackage(sourcePackage);
|
|
959
|
+
const embeddedWorkflowMetadata = embeddedWorkflowPayload?.workflowMetadata;
|
|
960
|
+
const embeddedWorkflowOverlay = embeddedWorkflowPayload?.workflowOverlay;
|
|
961
|
+
|
|
962
|
+
const mainDocumentPath = resolveMainDocumentPartPath(sourcePackage);
|
|
963
|
+
const brokenRelationshipIssues = collectBrokenInternalRelationshipIssues(
|
|
964
|
+
sourcePackage,
|
|
965
|
+
mainDocumentPath,
|
|
966
|
+
);
|
|
967
|
+
if (brokenRelationshipIssues.length > 0) {
|
|
968
|
+
return createDiagnosticsSession(
|
|
969
|
+
options,
|
|
970
|
+
createPackageImportDiagnostics({
|
|
971
|
+
issue: {
|
|
972
|
+
...brokenRelationshipIssues[0],
|
|
973
|
+
message: summarizeBrokenRelationshipIssues(brokenRelationshipIssues),
|
|
974
|
+
details: {
|
|
975
|
+
issueCount: brokenRelationshipIssues.length,
|
|
976
|
+
targets: brokenRelationshipIssues.map((issue) => issue.targetPartPath).filter(Boolean),
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
}),
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (!mainDocumentPath) {
|
|
984
|
+
return createDiagnosticsSession(
|
|
985
|
+
options,
|
|
986
|
+
createPackageImportDiagnostics({
|
|
987
|
+
issue: createMissingPartIssue(MAIN_DOCUMENT_PATH),
|
|
988
|
+
}),
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
const documentPart = sourcePackage.parts.get(mainDocumentPath);
|
|
993
|
+
if (!documentPart) {
|
|
994
|
+
return createDiagnosticsSession(
|
|
995
|
+
options,
|
|
996
|
+
createPackageImportDiagnostics({
|
|
997
|
+
issue: createMissingPartIssue(mainDocumentPath),
|
|
998
|
+
}),
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
if (documentPart.contentType !== MAIN_DOCUMENT_CONTENT_TYPE) {
|
|
1002
|
+
return createDiagnosticsSession(
|
|
1003
|
+
options,
|
|
1004
|
+
createValidationImportDiagnostics({
|
|
1005
|
+
message: `DOCX main document part ${mainDocumentPath} must use content type ${MAIN_DOCUMENT_CONTENT_TYPE}.`,
|
|
1006
|
+
}),
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
try {
|
|
1011
|
+
const sourceDocumentXml = decodeUtf8(documentPart.bytes);
|
|
1012
|
+
const importedRevisions = parseRevisionsFromDocumentXml(sourceDocumentXml);
|
|
1013
|
+
const numberingPartPath = resolveDocumentRelatedPartPath(
|
|
1014
|
+
sourcePackage,
|
|
1015
|
+
mainDocumentPath,
|
|
1016
|
+
documentPart.relationships,
|
|
1017
|
+
NUMBERING_RELATIONSHIP_TYPE,
|
|
1018
|
+
NUMBERING_PART_PATH,
|
|
1019
|
+
);
|
|
1020
|
+
const parsedNumbering = numberingPartPath
|
|
1021
|
+
? parseNumberingXml(
|
|
1022
|
+
decodeUtf8(sourcePackage.parts.get(numberingPartPath)?.bytes ?? new Uint8Array()),
|
|
1023
|
+
)
|
|
1024
|
+
: createEmptyNumberingCatalog();
|
|
1025
|
+
const mediaParts = collectInlineMediaParts(sourcePackage);
|
|
1026
|
+
const parsedDocument = parseMainDocumentXml(
|
|
1027
|
+
sourceDocumentXml,
|
|
1028
|
+
documentPart.relationships,
|
|
1029
|
+
mediaParts,
|
|
1030
|
+
mainDocumentPath,
|
|
1031
|
+
);
|
|
1032
|
+
await scheduler.yield();
|
|
1033
|
+
const protectionRanges = extractProtectionRanges(parsedDocument.blocks);
|
|
1034
|
+
const normalizedDocument = await normalizeParsedTextDocumentAsync(
|
|
1035
|
+
parsedDocument,
|
|
1036
|
+
mainDocumentPath,
|
|
1037
|
+
scheduler,
|
|
1038
|
+
);
|
|
1039
|
+
stages.emit("body");
|
|
1040
|
+
await scheduler.yield();
|
|
1041
|
+
const commentsPartPath = resolveCommentsPartPath(
|
|
1042
|
+
sourcePackage,
|
|
1043
|
+
mainDocumentPath,
|
|
1044
|
+
documentPart.relationships,
|
|
1045
|
+
);
|
|
1046
|
+
const commentsExtendedPartPath = resolveDocumentRelatedPartPath(
|
|
1047
|
+
sourcePackage,
|
|
1048
|
+
mainDocumentPath,
|
|
1049
|
+
documentPart.relationships,
|
|
1050
|
+
COMMENTS_EXTENDED_RELATIONSHIP_TYPE,
|
|
1051
|
+
COMMENTS_EXTENDED_PART_PATH,
|
|
1052
|
+
);
|
|
1053
|
+
const commentsIdsPartPath = resolveDocumentRelatedPartPath(
|
|
1054
|
+
sourcePackage,
|
|
1055
|
+
mainDocumentPath,
|
|
1056
|
+
documentPart.relationships,
|
|
1057
|
+
COMMENTS_IDS_RELATIONSHIP_TYPE,
|
|
1058
|
+
COMMENTS_IDS_PART_PATH,
|
|
1059
|
+
);
|
|
1060
|
+
const peoplePartPath = resolveDocumentRelatedPartPath(
|
|
1061
|
+
sourcePackage,
|
|
1062
|
+
mainDocumentPath,
|
|
1063
|
+
documentPart.relationships,
|
|
1064
|
+
PEOPLE_RELATIONSHIP_TYPE,
|
|
1065
|
+
PEOPLE_PART_PATH,
|
|
1066
|
+
);
|
|
1067
|
+
const parsedComments = commentsPartPath
|
|
1068
|
+
? parseCommentsFromOoxml(
|
|
1069
|
+
sourceDocumentXml,
|
|
1070
|
+
{
|
|
1071
|
+
commentsXml: decodeUtf8(sourcePackage.parts.get(commentsPartPath)?.bytes ?? new Uint8Array()),
|
|
1072
|
+
commentsExtendedXml: decodeUtf8(
|
|
1073
|
+
sourcePackage.parts.get(commentsExtendedPartPath ?? "")?.bytes ?? new Uint8Array(),
|
|
1074
|
+
),
|
|
1075
|
+
commentsIdsXml: decodeUtf8(
|
|
1076
|
+
sourcePackage.parts.get(commentsIdsPartPath ?? "")?.bytes ?? new Uint8Array(),
|
|
1077
|
+
),
|
|
1078
|
+
peopleXml: decodeUtf8(
|
|
1079
|
+
sourcePackage.parts.get(peoplePartPath ?? "")?.bytes ?? new Uint8Array(),
|
|
1080
|
+
),
|
|
1081
|
+
},
|
|
1082
|
+
)
|
|
1083
|
+
: {
|
|
1084
|
+
threads: [] as CommentThread[],
|
|
1085
|
+
diagnostics: [] as CommentImportDiagnostic[],
|
|
1086
|
+
definitions: [] as ImportedCommentDefinition[],
|
|
1087
|
+
sourceRootTag: undefined,
|
|
1088
|
+
sourceExtendedRootTag: undefined,
|
|
1089
|
+
sourceIdsRootTag: undefined,
|
|
1090
|
+
sourcePeopleRootTag: undefined,
|
|
1091
|
+
peopleAuthors: [] as string[],
|
|
1092
|
+
};
|
|
1093
|
+
const normalizedRevisions = normalizeImportedRevisionRecords(
|
|
1094
|
+
importedRevisions,
|
|
1095
|
+
normalizedDocument.content,
|
|
1096
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1097
|
+
);
|
|
1098
|
+
const normalizedComments = normalizeImportedCommentThreads(
|
|
1099
|
+
parsedComments,
|
|
1100
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1101
|
+
normalizedRevisions.revisions,
|
|
1102
|
+
);
|
|
1103
|
+
stages.emit("styles-numbering-comments");
|
|
1104
|
+
const importedStoryRevisions: ReviewRevisionRecord[] = [];
|
|
1105
|
+
const importedStoryRevisionDiagnostics: ParsedRevisionsResult["diagnostics"] = [];
|
|
1106
|
+
const subPartOpaqueState = createSubPartOpaqueImportState(
|
|
1107
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1108
|
+
normalizedDocument.diagnostics.warnings,
|
|
1109
|
+
);
|
|
1110
|
+
// ---- Parse sub-parts: headers, footers, footnotes, endnotes, theme ----
|
|
1111
|
+
const headerFooterRefs = parseHeaderFooterReferences(sourceDocumentXml);
|
|
1112
|
+
const parsedHeaders: HeaderDocument[] = [];
|
|
1113
|
+
const parsedFooters: FooterDocument[] = [];
|
|
1114
|
+
const sourceHeaderPaths: Array<{ partPath: string; relationshipId: string }> = [];
|
|
1115
|
+
const sourceFooterPaths: Array<{ partPath: string; relationshipId: string }> = [];
|
|
1116
|
+
const seenSubPartKeys = new Set<string>();
|
|
1117
|
+
|
|
1118
|
+
for (const ref of headerFooterRefs) {
|
|
1119
|
+
const dedupeKey = `${ref.kind}:${ref.variant}:${ref.relationshipId}`;
|
|
1120
|
+
if (seenSubPartKeys.has(dedupeKey)) {
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
seenSubPartKeys.add(dedupeKey);
|
|
1124
|
+
|
|
1125
|
+
const relationship = documentPart.relationships.find(
|
|
1126
|
+
(r) => r.id === ref.relationshipId && r.targetMode === "internal",
|
|
1127
|
+
);
|
|
1128
|
+
if (!relationship) {
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const partPath = resolveRelationshipTarget(mainDocumentPath, relationship);
|
|
1133
|
+
const partBytes = sourcePackage.parts.get(partPath)?.bytes;
|
|
1134
|
+
if (!partBytes) {
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
await scheduler.yield();
|
|
1139
|
+
const xml = decodeUtf8(partBytes);
|
|
1140
|
+
if (ref.kind === "header") {
|
|
1141
|
+
const parsedHeaderRevisions = parseRevisionsFromStoryXml(xml);
|
|
1142
|
+
const parsed = parseHeaderXml(xml);
|
|
1143
|
+
parsedHeaders.push({
|
|
1144
|
+
variant: ref.variant,
|
|
1145
|
+
partPath,
|
|
1146
|
+
relationshipId: ref.relationshipId,
|
|
1147
|
+
...(ref.sectionIndex !== undefined ? { sectionIndex: ref.sectionIndex } : {}),
|
|
1148
|
+
blocks: normalizeSubPartOpaqueBlocks(
|
|
1149
|
+
parsed.blocks,
|
|
1150
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1151
|
+
normalizedDocument.diagnostics.warnings,
|
|
1152
|
+
partPath,
|
|
1153
|
+
subPartOpaqueState,
|
|
1154
|
+
),
|
|
1155
|
+
});
|
|
1156
|
+
importedStoryRevisions.push(
|
|
1157
|
+
...parsedHeaderRevisions.revisions.map((revision): ReviewRevisionRecord => ({
|
|
1158
|
+
...revision,
|
|
1159
|
+
metadata: {
|
|
1160
|
+
...revision.metadata,
|
|
1161
|
+
storyTarget: {
|
|
1162
|
+
kind: "header" as const,
|
|
1163
|
+
relationshipId: ref.relationshipId,
|
|
1164
|
+
variant: ref.variant,
|
|
1165
|
+
...(ref.sectionIndex !== undefined ? { sectionIndex: ref.sectionIndex } : {}),
|
|
1166
|
+
},
|
|
1167
|
+
},
|
|
1168
|
+
})),
|
|
1169
|
+
);
|
|
1170
|
+
importedStoryRevisionDiagnostics.push(...parsedHeaderRevisions.diagnostics);
|
|
1171
|
+
sourceHeaderPaths.push({ partPath, relationshipId: ref.relationshipId });
|
|
1172
|
+
} else {
|
|
1173
|
+
const parsedFooterRevisions = parseRevisionsFromStoryXml(xml);
|
|
1174
|
+
const parsed = parseFooterXml(xml);
|
|
1175
|
+
parsedFooters.push({
|
|
1176
|
+
variant: ref.variant,
|
|
1177
|
+
partPath,
|
|
1178
|
+
relationshipId: ref.relationshipId,
|
|
1179
|
+
...(ref.sectionIndex !== undefined ? { sectionIndex: ref.sectionIndex } : {}),
|
|
1180
|
+
blocks: normalizeSubPartOpaqueBlocks(
|
|
1181
|
+
parsed.blocks,
|
|
1182
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1183
|
+
normalizedDocument.diagnostics.warnings,
|
|
1184
|
+
partPath,
|
|
1185
|
+
subPartOpaqueState,
|
|
1186
|
+
),
|
|
1187
|
+
});
|
|
1188
|
+
importedStoryRevisions.push(
|
|
1189
|
+
...parsedFooterRevisions.revisions.map((revision): ReviewRevisionRecord => ({
|
|
1190
|
+
...revision,
|
|
1191
|
+
metadata: {
|
|
1192
|
+
...revision.metadata,
|
|
1193
|
+
storyTarget: {
|
|
1194
|
+
kind: "footer" as const,
|
|
1195
|
+
relationshipId: ref.relationshipId,
|
|
1196
|
+
variant: ref.variant,
|
|
1197
|
+
...(ref.sectionIndex !== undefined ? { sectionIndex: ref.sectionIndex } : {}),
|
|
1198
|
+
},
|
|
1199
|
+
},
|
|
1200
|
+
})),
|
|
1201
|
+
);
|
|
1202
|
+
importedStoryRevisionDiagnostics.push(...parsedFooterRevisions.diagnostics);
|
|
1203
|
+
sourceFooterPaths.push({ partPath, relationshipId: ref.relationshipId });
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
const footnotesPartPath = resolveDocumentRelatedPartPath(
|
|
1208
|
+
sourcePackage,
|
|
1209
|
+
mainDocumentPath,
|
|
1210
|
+
documentPart.relationships,
|
|
1211
|
+
FOOTNOTES_RELATIONSHIP_TYPE,
|
|
1212
|
+
FOOTNOTES_PART_PATH,
|
|
1213
|
+
);
|
|
1214
|
+
const footnotesRelationshipId = documentPart.relationships.find(
|
|
1215
|
+
(r) => r.type === FOOTNOTES_RELATIONSHIP_TYPE && r.targetMode === "internal",
|
|
1216
|
+
)?.id;
|
|
1217
|
+
const endnotesPartPath = resolveDocumentRelatedPartPath(
|
|
1218
|
+
sourcePackage,
|
|
1219
|
+
mainDocumentPath,
|
|
1220
|
+
documentPart.relationships,
|
|
1221
|
+
ENDNOTES_RELATIONSHIP_TYPE,
|
|
1222
|
+
ENDNOTES_PART_PATH,
|
|
1223
|
+
);
|
|
1224
|
+
const endnotesRelationshipId = documentPart.relationships.find(
|
|
1225
|
+
(r) => r.type === ENDNOTES_RELATIONSHIP_TYPE && r.targetMode === "internal",
|
|
1226
|
+
)?.id;
|
|
1227
|
+
|
|
1228
|
+
let footnoteCollection: FootnoteCollection | undefined;
|
|
1229
|
+
if (footnotesPartPath) {
|
|
1230
|
+
footnoteCollection = parseFootnotesXml(
|
|
1231
|
+
decodeUtf8(sourcePackage.parts.get(footnotesPartPath)?.bytes ?? new Uint8Array()),
|
|
1232
|
+
);
|
|
1233
|
+
normalizeFootnoteCollectionOpaqueBlocks(
|
|
1234
|
+
footnoteCollection,
|
|
1235
|
+
"footnote",
|
|
1236
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1237
|
+
normalizedDocument.diagnostics.warnings,
|
|
1238
|
+
footnotesPartPath,
|
|
1239
|
+
subPartOpaqueState,
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
if (endnotesPartPath) {
|
|
1243
|
+
footnoteCollection = parseEndnotesXml(
|
|
1244
|
+
decodeUtf8(sourcePackage.parts.get(endnotesPartPath)?.bytes ?? new Uint8Array()),
|
|
1245
|
+
footnoteCollection,
|
|
1246
|
+
);
|
|
1247
|
+
normalizeFootnoteCollectionOpaqueBlocks(
|
|
1248
|
+
footnoteCollection,
|
|
1249
|
+
"endnote",
|
|
1250
|
+
normalizedDocument.preservation.opaqueFragments,
|
|
1251
|
+
normalizedDocument.diagnostics.warnings,
|
|
1252
|
+
endnotesPartPath,
|
|
1253
|
+
subPartOpaqueState,
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
await scheduler.yield();
|
|
1257
|
+
|
|
1258
|
+
const themeRelationship = documentPart.relationships.find(
|
|
1259
|
+
(r) => r.type === "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" &&
|
|
1260
|
+
r.targetMode === "internal",
|
|
1261
|
+
);
|
|
1262
|
+
const themePartPath = themeRelationship
|
|
1263
|
+
? resolveRelationshipTarget(mainDocumentPath, themeRelationship)
|
|
1264
|
+
: undefined;
|
|
1265
|
+
const parsedTheme =
|
|
1266
|
+
themePartPath && sourcePackage.parts.has(themePartPath)
|
|
1267
|
+
? parseThemeXml(
|
|
1268
|
+
decodeUtf8(sourcePackage.parts.get(themePartPath)?.bytes ?? new Uint8Array()),
|
|
1269
|
+
)
|
|
1270
|
+
: undefined;
|
|
1271
|
+
const resolvedTheme = parsedTheme ? resolveTheme(parsedTheme) : undefined;
|
|
1272
|
+
const settingsPartPath = resolveDocumentRelatedPartPath(
|
|
1273
|
+
sourcePackage,
|
|
1274
|
+
mainDocumentPath,
|
|
1275
|
+
documentPart.relationships,
|
|
1276
|
+
SETTINGS_RELATIONSHIP_TYPE,
|
|
1277
|
+
SETTINGS_PART_PATH,
|
|
1278
|
+
);
|
|
1279
|
+
const parsedSettings =
|
|
1280
|
+
settingsPartPath && sourcePackage.parts.has(settingsPartPath)
|
|
1281
|
+
? parseSettingsXml(
|
|
1282
|
+
decodeUtf8(sourcePackage.parts.get(settingsPartPath)?.bytes ?? new Uint8Array()),
|
|
1283
|
+
)
|
|
1284
|
+
: undefined;
|
|
1285
|
+
const settingsXmlForProtection =
|
|
1286
|
+
settingsPartPath && sourcePackage.parts.has(settingsPartPath)
|
|
1287
|
+
? decodeUtf8(sourcePackage.parts.get(settingsPartPath)?.bytes ?? new Uint8Array())
|
|
1288
|
+
: "";
|
|
1289
|
+
const documentProtection = extractDocumentProtection(settingsXmlForProtection);
|
|
1290
|
+
const importedProtectionSnapshot = buildProtectionSnapshot(documentProtection, protectionRanges);
|
|
1291
|
+
|
|
1292
|
+
// ---- Parse styles.xml for canonical style catalog ----
|
|
1293
|
+
const stylesPartPath = resolveDocumentRelatedPartPath(
|
|
1294
|
+
sourcePackage,
|
|
1295
|
+
mainDocumentPath,
|
|
1296
|
+
documentPart.relationships,
|
|
1297
|
+
STYLES_RELATIONSHIP_TYPE,
|
|
1298
|
+
STYLES_PART_PATH,
|
|
1299
|
+
);
|
|
1300
|
+
const parsedStyles =
|
|
1301
|
+
stylesPartPath && sourcePackage.parts.has(stylesPartPath)
|
|
1302
|
+
? parseStylesXml(
|
|
1303
|
+
decodeUtf8(sourcePackage.parts.get(stylesPartPath)?.bytes ?? new Uint8Array()),
|
|
1304
|
+
)
|
|
1305
|
+
: parseStylesXml("");
|
|
1306
|
+
await scheduler.yield();
|
|
1307
|
+
|
|
1308
|
+
const subParts: SubPartsCatalog | undefined =
|
|
1309
|
+
parsedHeaders.length > 0 ||
|
|
1310
|
+
parsedFooters.length > 0 ||
|
|
1311
|
+
footnoteCollection !== undefined ||
|
|
1312
|
+
parsedTheme !== undefined ||
|
|
1313
|
+
normalizedDocument.finalSectionProperties !== undefined ||
|
|
1314
|
+
resolvedTheme !== undefined ||
|
|
1315
|
+
parsedSettings !== undefined
|
|
1316
|
+
? {
|
|
1317
|
+
headers: parsedHeaders,
|
|
1318
|
+
footers: parsedFooters,
|
|
1319
|
+
...(footnoteCollection !== undefined ? { footnoteCollection } : {}),
|
|
1320
|
+
...(parsedTheme !== undefined ? { theme: parsedTheme } : {}),
|
|
1321
|
+
...(normalizedDocument.finalSectionProperties !== undefined
|
|
1322
|
+
? { finalSectionProperties: normalizedDocument.finalSectionProperties }
|
|
1323
|
+
: {}),
|
|
1324
|
+
...(resolvedTheme !== undefined ? { resolvedTheme } : {}),
|
|
1325
|
+
...(parsedSettings !== undefined ? { settings: parsedSettings } : {}),
|
|
1326
|
+
}
|
|
1327
|
+
: undefined;
|
|
1328
|
+
|
|
1329
|
+
const timestamp = new Date().toISOString();
|
|
1330
|
+
const translatedWorkflowState = translateClmCommentsToWorkflow({
|
|
1331
|
+
comments: normalizedComments.threads,
|
|
1332
|
+
workflowOverlay: embeddedWorkflowOverlay,
|
|
1333
|
+
workflowMetadata: embeddedWorkflowMetadata,
|
|
1334
|
+
timestamp,
|
|
1335
|
+
});
|
|
1336
|
+
const importedDocument = createImportedCanonicalDocument({
|
|
1337
|
+
documentId: options.documentId,
|
|
1338
|
+
timestamp,
|
|
1339
|
+
numbering: parsedNumbering,
|
|
1340
|
+
media: normalizedDocument.media,
|
|
1341
|
+
content: normalizedDocument.content,
|
|
1342
|
+
subParts,
|
|
1343
|
+
parsedStyles,
|
|
1344
|
+
preservation: {
|
|
1345
|
+
...normalizedDocument.preservation,
|
|
1346
|
+
packageParts: {
|
|
1347
|
+
...normalizedDocument.preservation.packageParts,
|
|
1348
|
+
...collectPreservedPackageParts(sourcePackage, [
|
|
1349
|
+
mainDocumentPath,
|
|
1350
|
+
numberingPartPath,
|
|
1351
|
+
commentsPartPath,
|
|
1352
|
+
commentsExtendedPartPath,
|
|
1353
|
+
commentsIdsPartPath,
|
|
1354
|
+
peoplePartPath,
|
|
1355
|
+
]),
|
|
1356
|
+
},
|
|
1357
|
+
},
|
|
1358
|
+
diagnostics: {
|
|
1359
|
+
warnings: [
|
|
1360
|
+
...createBrokenRelationshipWarnings(sourcePackage, mainDocumentPath),
|
|
1361
|
+
...normalizedDocument.diagnostics.warnings,
|
|
1362
|
+
...normalizedRevisions.diagnostics.map((diagnostic, index) => ({
|
|
1363
|
+
diagnosticId: `diagnostic:revision-import-${index + 1}`,
|
|
1364
|
+
warningId: `warning:revision-import-${diagnostic.revisionId}`,
|
|
1365
|
+
source: "review" as const,
|
|
1366
|
+
message: diagnostic.message,
|
|
1367
|
+
})),
|
|
1368
|
+
...importedStoryRevisionDiagnostics.map((diagnostic, index) => ({
|
|
1369
|
+
diagnosticId: `diagnostic:story-revision-import-${index + 1}`,
|
|
1370
|
+
warningId: `warning:story-revision-import-${diagnostic.revisionId}`,
|
|
1371
|
+
source: "review" as const,
|
|
1372
|
+
message: diagnostic.message,
|
|
1373
|
+
})),
|
|
1374
|
+
...normalizedComments.diagnostics.map((diagnostic, index) => ({
|
|
1375
|
+
diagnosticId: `diagnostic:comment-import-${index + 1}`,
|
|
1376
|
+
warningId: `warning:comment-import-${diagnostic.commentId}`,
|
|
1377
|
+
source: "review" as const,
|
|
1378
|
+
message: diagnostic.message,
|
|
1379
|
+
})),
|
|
1380
|
+
],
|
|
1381
|
+
errors: [],
|
|
1382
|
+
},
|
|
1383
|
+
review: {
|
|
1384
|
+
comments: toRuntimeCommentRecords(translatedWorkflowState.comments),
|
|
1385
|
+
revisions: toRuntimeRevisionRecords([
|
|
1386
|
+
...normalizedRevisions.revisions,
|
|
1387
|
+
...importedStoryRevisions,
|
|
1388
|
+
]),
|
|
1389
|
+
},
|
|
1390
|
+
});
|
|
1391
|
+
// Stage 0B.1: if the host implements `renderChartPreview`, resolve
|
|
1392
|
+
// chart_preview nodes inline so the first snapshot already carries the
|
|
1393
|
+
// synthesized `previewMediaId`. Fallback-safe: returning null or throwing
|
|
1394
|
+
// is per-chart — the typed badge renders as if the adapter weren't set.
|
|
1395
|
+
const document = (await resolveChartPreviewsForDocument(
|
|
1396
|
+
importedDocument,
|
|
1397
|
+
sourcePackage,
|
|
1398
|
+
options.hostAdapter,
|
|
1399
|
+
)) as CanonicalDocumentEnvelope;
|
|
1400
|
+
const compatibility = buildCompatibilityReport({
|
|
1401
|
+
document,
|
|
1402
|
+
generatedAt: timestamp,
|
|
1403
|
+
});
|
|
1404
|
+
await scheduler.yield();
|
|
1405
|
+
const snapshot = createImportedSnapshot({
|
|
1406
|
+
documentId: options.documentId,
|
|
1407
|
+
editorBuild,
|
|
1408
|
+
timestamp,
|
|
1409
|
+
document,
|
|
1410
|
+
compatibility: toPublicCompatibilityReport(compatibility),
|
|
1411
|
+
protectionSnapshot: importedProtectionSnapshot,
|
|
1412
|
+
sourcePackage: createPersistedSourcePackage(sourceBytes, options.sourceLabel),
|
|
1413
|
+
workflowOverlay: translatedWorkflowState.workflowOverlay,
|
|
1414
|
+
workflowMetadata: translatedWorkflowState.workflowMetadata,
|
|
1415
|
+
});
|
|
1416
|
+
const snapshotIssues = validatePersistedEditorSnapshot(snapshot);
|
|
1417
|
+
if (snapshotIssues.length > 0) {
|
|
1418
|
+
const firstIssue = snapshotIssues[0];
|
|
1419
|
+
return createDiagnosticsSession(
|
|
1420
|
+
options,
|
|
1421
|
+
createValidationImportDiagnostics({
|
|
1422
|
+
message: `DOCX import produced an invalid editor state during validation${firstIssue ? ` (${firstIssue.path}: ${firstIssue.message})` : "."}`,
|
|
1423
|
+
source: "import",
|
|
1424
|
+
details: {
|
|
1425
|
+
issueCount: snapshotIssues.length,
|
|
1426
|
+
firstIssuePath: firstIssue?.path,
|
|
1427
|
+
},
|
|
1428
|
+
}),
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
const initialSessionState = editorSessionStateFromPersistedSnapshot(snapshot);
|
|
1432
|
+
const importedState: ImportedDocxState = {
|
|
1433
|
+
sourceBytes: new Uint8Array(sourceBytes),
|
|
1434
|
+
sourcePackage,
|
|
1435
|
+
sourceDocumentXml,
|
|
1436
|
+
sourceDocumentPartPath: mainDocumentPath,
|
|
1437
|
+
sourceDocumentRelationships: documentPart.relationships,
|
|
1438
|
+
sourceDocumentAttributes: extractDocumentRootAttributes(sourceDocumentXml),
|
|
1439
|
+
sourceNumberingPartPath: numberingPartPath,
|
|
1440
|
+
sourceNumberingRelationshipId: documentPart.relationships.find(
|
|
1441
|
+
(relationship) =>
|
|
1442
|
+
relationship.type === NUMBERING_RELATIONSHIP_TYPE &&
|
|
1443
|
+
relationship.targetMode === "internal",
|
|
1444
|
+
)?.id,
|
|
1445
|
+
sourceCommentsPartPath: commentsPartPath,
|
|
1446
|
+
sourceCommentsRelationshipId: documentPart.relationships.find(
|
|
1447
|
+
(relationship) =>
|
|
1448
|
+
relationship.type === COMMENTS_RELATIONSHIP_TYPE &&
|
|
1449
|
+
relationship.targetMode === "internal",
|
|
1450
|
+
)?.id,
|
|
1451
|
+
sourceCommentsRootTag: normalizedComments.sourceRootTag,
|
|
1452
|
+
sourceCommentsExtendedPartPath: commentsExtendedPartPath,
|
|
1453
|
+
sourceCommentsExtendedRelationshipId: documentPart.relationships.find(
|
|
1454
|
+
(relationship) =>
|
|
1455
|
+
relationship.type === COMMENTS_EXTENDED_RELATIONSHIP_TYPE &&
|
|
1456
|
+
relationship.targetMode === "internal",
|
|
1457
|
+
)?.id,
|
|
1458
|
+
sourceCommentsExtendedRootTag: normalizedComments.sourceExtendedRootTag,
|
|
1459
|
+
sourceCommentsIdsPartPath: commentsIdsPartPath,
|
|
1460
|
+
sourceCommentsIdsRelationshipId: documentPart.relationships.find(
|
|
1461
|
+
(relationship) =>
|
|
1462
|
+
relationship.type === COMMENTS_IDS_RELATIONSHIP_TYPE &&
|
|
1463
|
+
relationship.targetMode === "internal",
|
|
1464
|
+
)?.id,
|
|
1465
|
+
sourceCommentsIdsRootTag: normalizedComments.sourceIdsRootTag,
|
|
1466
|
+
sourcePeoplePartPath: peoplePartPath,
|
|
1467
|
+
sourcePeopleRelationshipId: documentPart.relationships.find(
|
|
1468
|
+
(relationship) =>
|
|
1469
|
+
relationship.type === PEOPLE_RELATIONSHIP_TYPE &&
|
|
1470
|
+
relationship.targetMode === "internal",
|
|
1471
|
+
)?.id,
|
|
1472
|
+
sourcePeopleRootTag: normalizedComments.sourcePeopleRootTag,
|
|
1473
|
+
sourcePeopleAuthors: normalizedComments.peopleAuthors,
|
|
1474
|
+
protectionSnapshot: buildProtectionSnapshot(documentProtection, protectionRanges),
|
|
1475
|
+
preservedCommentDefinitions: normalizedComments.preservedDefinitions,
|
|
1476
|
+
blockingCommentDiagnostics: normalizedComments.diagnostics.filter((diagnostic) =>
|
|
1477
|
+
BLOCKING_COMMENT_DIAGNOSTIC_CODES.has(diagnostic.code),
|
|
1478
|
+
),
|
|
1479
|
+
initialCanonicalSignature: serializeCanonicalDocumentForExport(document),
|
|
1480
|
+
sourceSubPartPaths: {
|
|
1481
|
+
headers: sourceHeaderPaths,
|
|
1482
|
+
footers: sourceFooterPaths,
|
|
1483
|
+
footnotesPartPath,
|
|
1484
|
+
footnotesRelationshipId,
|
|
1485
|
+
endnotesPartPath,
|
|
1486
|
+
endnotesRelationshipId,
|
|
1487
|
+
themePartPath,
|
|
1488
|
+
themeRelationshipId: themeRelationship?.id,
|
|
1489
|
+
},
|
|
1490
|
+
};
|
|
1491
|
+
|
|
1492
|
+
stages.emit("skeleton-ready");
|
|
1493
|
+
return {
|
|
1494
|
+
initialSessionState,
|
|
1495
|
+
initialSnapshot: snapshot,
|
|
1496
|
+
readOnly: false,
|
|
1497
|
+
protectionSnapshot: importedProtectionSnapshot,
|
|
1498
|
+
exportDocx: async (nextSessionState, exportOptions) =>
|
|
1499
|
+
exportDocxEditorSession(importedState, nextSessionState, exportOptions),
|
|
1500
|
+
...(embeddedWorkflowPayload?.editorState
|
|
1501
|
+
? { initialEditorStatePayload: embeddedWorkflowPayload.editorState }
|
|
1502
|
+
: {}),
|
|
1503
|
+
};
|
|
1504
|
+
} catch (error) {
|
|
1505
|
+
return createDiagnosticsSession(
|
|
1506
|
+
options,
|
|
1507
|
+
createImportDiagnosticsFromError(error),
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
function loadStageNow(): number {
|
|
1513
|
+
return typeof performance !== "undefined" && typeof performance.now === "function"
|
|
1514
|
+
? performance.now()
|
|
1515
|
+
: Date.now();
|
|
1516
|
+
}
|
|
1517
|
+
|
|
832
1518
|
function exportDocxEditorSession(
|
|
833
1519
|
state: ImportedDocxState,
|
|
834
1520
|
sessionStateOrSnapshot: EditorSessionState | PersistedEditorSnapshot,
|
|
@@ -1286,7 +1972,9 @@ function exportDocxEditorSession(
|
|
|
1286
1972
|
}
|
|
1287
1973
|
|
|
1288
1974
|
ensureHostMetadataParts(exportSession, state.sourcePackage, currentDocument);
|
|
1289
|
-
|
|
1975
|
+
// Schema 1.2: pass through editorState payload collected by the runtime channel.
|
|
1976
|
+
const internalEditorState = (options as { _editorState?: import("./ooxml/workflow-payload.ts").EditorStatePayload } | undefined)?._editorState;
|
|
1977
|
+
ensureWorkflowPayloadParts(exportSession, sessionState, currentDocument, state.sourcePackage, internalEditorState);
|
|
1290
1978
|
|
|
1291
1979
|
return {
|
|
1292
1980
|
bytes: exportSession.serialize(),
|
|
@@ -3012,11 +3700,13 @@ function ensureWorkflowPayloadParts(
|
|
|
3012
3700
|
sessionState: EditorSessionState,
|
|
3013
3701
|
document: CanonicalDocumentEnvelope,
|
|
3014
3702
|
sourcePackage: OpcPackage,
|
|
3703
|
+
editorState?: import("./ooxml/workflow-payload.ts").EditorStatePayload,
|
|
3015
3704
|
): void {
|
|
3016
3705
|
const payloadParts = buildWorkflowPayloadParts({
|
|
3017
3706
|
sourcePackage,
|
|
3018
3707
|
workflowMetadata: sessionState.workflowMetadata,
|
|
3019
3708
|
workflowOverlay: sessionState.workflowOverlay,
|
|
3709
|
+
editorState,
|
|
3020
3710
|
documentId: sessionState.documentId,
|
|
3021
3711
|
createdAt: document.createdAt,
|
|
3022
3712
|
updatedAt: document.updatedAt,
|