docxodus 12.4.1 → 12.6.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.
- package/README.md +83 -4
- package/dist/core.d.ts +17 -24
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +44 -221
- package/dist/core.js.map +1 -1
- package/dist/docxodus.worker.js +303 -7
- package/dist/docxodus.worker.js.map +1 -1
- package/dist/editor-reconcile.d.ts +5 -0
- package/dist/editor-reconcile.d.ts.map +1 -1
- package/dist/editor-reconcile.js.map +1 -1
- package/dist/editor.bundle.js +157 -15
- package/dist/editor.d.ts +44 -0
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +209 -22
- package/dist/editor.js.map +1 -1
- package/dist/embed.bundle.js +589 -218
- package/dist/embed.d.ts +1 -1
- package/dist/embed.iife.js +589 -218
- package/dist/embed.js +1 -1
- package/dist/export-assets.json +29 -29
- package/dist/export-browser.bundle.js +109 -4
- package/dist/external-annotation-wire.d.ts +19 -0
- package/dist/external-annotation-wire.d.ts.map +1 -0
- package/dist/external-annotation-wire.js +139 -0
- package/dist/external-annotation-wire.js.map +1 -0
- package/dist/session.bundle.js +276 -8
- package/dist/session.d.ts +66 -13
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +245 -8
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +389 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/verification-request.d.ts +9 -0
- package/dist/verification-request.d.ts.map +1 -0
- package/dist/verification-request.js +37 -0
- package/dist/verification-request.js.map +1 -0
- package/dist/wasm/_framework/DocumentFormat.OpenXml.Framework.wasm +0 -0
- package/dist/wasm/_framework/DocumentFormat.OpenXml.Framework.wasm.br +0 -0
- package/dist/wasm/_framework/DocumentFormat.OpenXml.wasm +0 -0
- package/dist/wasm/_framework/DocumentFormat.OpenXml.wasm.br +0 -0
- package/dist/wasm/_framework/Docxodus.wasm +0 -0
- package/dist/wasm/_framework/Docxodus.wasm.br +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm.br +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm.br +0 -0
- package/dist/wasm/_framework/System.IO.Packaging.wasm +0 -0
- package/dist/wasm/_framework/System.IO.Packaging.wasm.br +0 -0
- package/dist/wasm/_framework/System.Linq.Expressions.wasm +0 -0
- package/dist/wasm/_framework/System.Linq.Expressions.wasm.br +0 -0
- package/dist/wasm/_framework/System.Memory.wasm +0 -0
- package/dist/wasm/_framework/System.Memory.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Uri.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Uri.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Xml.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Xml.wasm.br +0 -0
- package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
- package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm.br +0 -0
- package/dist/wasm/_framework/System.Security.Cryptography.wasm +0 -0
- package/dist/wasm/_framework/System.Security.Cryptography.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.Encodings.Web.wasm +0 -0
- package/dist/wasm/_framework/System.Text.Encodings.Web.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.Json.wasm +0 -0
- package/dist/wasm/_framework/System.Text.Json.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.boot.js +18 -18
- package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
- package/dist/worker-proxy.bundle.js +109 -4
- package/dist/worker-proxy.d.ts +29 -3
- package/dist/worker-proxy.d.ts.map +1 -1
- package/dist/worker-proxy.js +62 -2
- package/dist/worker-proxy.js.map +1 -1
- package/package.json +3 -2
package/dist/embed.bundle.js
CHANGED
|
@@ -113,6 +113,37 @@ var require_dist = __commonJS({
|
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
// src/verification-request.ts
|
|
117
|
+
function serializeVerificationRequest(request) {
|
|
118
|
+
if (request === null || typeof request !== "object" || Array.isArray(request)) {
|
|
119
|
+
throw new RangeError("a verification request must be an object");
|
|
120
|
+
}
|
|
121
|
+
const { companionArtifacts, ...rest } = request;
|
|
122
|
+
const wire = { ...rest };
|
|
123
|
+
if (companionArtifacts !== void 0) {
|
|
124
|
+
wire.companionArtifacts = companionArtifacts.map(encodeCompanion);
|
|
125
|
+
}
|
|
126
|
+
return JSON.stringify(wire);
|
|
127
|
+
}
|
|
128
|
+
function encodeCompanion(artifact) {
|
|
129
|
+
const { bytes, ...rest } = artifact;
|
|
130
|
+
const wire = { ...rest };
|
|
131
|
+
if (bytes !== void 0) wire.bytesB64 = bytesToBase64(bytes);
|
|
132
|
+
return wire;
|
|
133
|
+
}
|
|
134
|
+
function bytesToBase64(bytes) {
|
|
135
|
+
if (typeof btoa === "function") {
|
|
136
|
+
let binary = "";
|
|
137
|
+
const chunkSize = 32768;
|
|
138
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
139
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
140
|
+
binary += String.fromCharCode.apply(null, chunk);
|
|
141
|
+
}
|
|
142
|
+
return btoa(binary);
|
|
143
|
+
}
|
|
144
|
+
return Buffer.from(bytes).toString("base64");
|
|
145
|
+
}
|
|
146
|
+
|
|
116
147
|
// src/types.ts
|
|
117
148
|
var ProjectionScopes = /* @__PURE__ */ ((ProjectionScopes2) => {
|
|
118
149
|
ProjectionScopes2[ProjectionScopes2["Body"] = 1] = "Body";
|
|
@@ -382,9 +413,23 @@ function mutationBatchChangeSet(before, after, key) {
|
|
|
382
413
|
modified: after.filter((_, index) => modified[index])
|
|
383
414
|
};
|
|
384
415
|
}
|
|
416
|
+
var BATCH_REPLAY_CAVEATS = {
|
|
417
|
+
revisionDates: "Tracked-revision date attributes may use the execution clock; compare revision ids, authors, types, text, and anchors across separate executions.",
|
|
418
|
+
commentDates: "Comment date attributes may be generated from the execution clock; supply dates explicitly when byte-identical replay is required.",
|
|
419
|
+
annotationMetadata: "Auto-generated annotation ids or creation timestamps are execution metadata; supply id and created explicitly when byte-identical replay is required.",
|
|
420
|
+
createdAnchors: "Created anchors and related OOXML ids may be generated independently on replay; preview/apply equivalence is semantic and packageHash or anchor ids may differ."
|
|
421
|
+
};
|
|
422
|
+
var BATCH_REPLAY_CAVEAT_TEXTS = new Set(Object.values(BATCH_REPLAY_CAVEATS));
|
|
423
|
+
var RETAINED_PREVIEW_RECEIPTS = 8;
|
|
385
424
|
var DocxSession = class _DocxSession {
|
|
386
425
|
/** @internal */
|
|
387
426
|
constructor(handle, wasm) {
|
|
427
|
+
/**
|
|
428
|
+
* The receipts this client composed for previews it retained, keyed by previewId. The host
|
|
429
|
+
* keeps the package and the binding; the step receipts live only here, so a commit can return
|
|
430
|
+
* the previewed steps and change sets without the host re-parsing a client-composed result.
|
|
431
|
+
*/
|
|
432
|
+
this.retainedPreviewReceipts = /* @__PURE__ */ new Map();
|
|
388
433
|
// ─── Raw escape hatch ────────────────────────────────────────────────
|
|
389
434
|
this.raw = {
|
|
390
435
|
getXml: (anchorId) => this.wasm.RawGetXml(this.handle, anchorId),
|
|
@@ -449,10 +494,152 @@ var DocxSession = class _DocxSession {
|
|
|
449
494
|
* Execute synchronous mutations atomically by default. Atomic success is one undo/version
|
|
450
495
|
* unit; any failed or thrown step restores the exact package and history checkpoint.
|
|
451
496
|
*/
|
|
452
|
-
executeBatch(steps, mode = "atomic") {
|
|
497
|
+
executeBatch(steps, mode = "atomic", transaction) {
|
|
453
498
|
if (mode !== "atomic" && mode !== "best_effort") {
|
|
454
499
|
throw new RangeError(`unknown mutation batch mode: ${String(mode)}`);
|
|
455
500
|
}
|
|
501
|
+
if (transaction === void 0) return this.recorded(steps, mode, void 0, () => this.runBatch(steps, mode));
|
|
502
|
+
return this.runTransactional(
|
|
503
|
+
transaction,
|
|
504
|
+
mode,
|
|
505
|
+
(identity) => this.recorded(steps, mode, identity, () => this.runBatch(steps, mode))
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* What the session's host-owned delivery evidence recorder holds (issue #748). `enabled` is
|
|
510
|
+
* false, with the reason, unless the session was opened with `captureDeliveryEvidence`.
|
|
511
|
+
*/
|
|
512
|
+
getDeliveryEvidenceStatus() {
|
|
513
|
+
if (!this.wasm.GetDeliveryEvidenceStatus) {
|
|
514
|
+
throw new Error("This WASM bundle predates delivery evidence; rebuild docxodus.");
|
|
515
|
+
}
|
|
516
|
+
return JSON.parse(this.wasm.GetDeliveryEvidenceStatus(this.handle));
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Build the receipt-bearing delivery of this session through the shared bundle service: the
|
|
520
|
+
* clean current package (`final-docx`), the source-to-delivered semantic delta, and the change
|
|
521
|
+
* receipt (`change-receipt`) minted from the captured evidence — verifiable with
|
|
522
|
+
* `verifyDeliveryReceipt` against the returned artifact bytes. A history that cannot be
|
|
523
|
+
* attested yields an `incomplete` bundle whose receipt artifact carries the reason, and
|
|
524
|
+
* `evidence.unavailableReason` says why.
|
|
525
|
+
*/
|
|
526
|
+
buildDeliveryReceipt(options) {
|
|
527
|
+
if (!this.wasm.BuildDeliveryReceipt) {
|
|
528
|
+
throw new Error("This WASM bundle predates delivery evidence; rebuild docxodus.");
|
|
529
|
+
}
|
|
530
|
+
const wire = JSON.parse(this.wasm.BuildDeliveryReceipt(this.handle, JSON.stringify(options ?? {})));
|
|
531
|
+
const decode = (base64) => Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
|
|
532
|
+
return {
|
|
533
|
+
status: wire.status,
|
|
534
|
+
verified: wire.verified,
|
|
535
|
+
manifest: wire.manifest,
|
|
536
|
+
manifestBytes: decode(wire.manifestBytes),
|
|
537
|
+
artifacts: wire.artifacts.map((artifact) => {
|
|
538
|
+
const { bytes, ...rest } = artifact;
|
|
539
|
+
return bytes === void 0 ? rest : { ...rest, bytes: decode(bytes) };
|
|
540
|
+
}),
|
|
541
|
+
...wire.evidence ? { evidence: wire.evidence } : {}
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Describe a batch to the session's delivery evidence recorder before running it, and hand
|
|
546
|
+
* it the step results afterwards, so the version steps the batch produced are recorded under
|
|
547
|
+
* this description rather than as unlabeled mutations. A bundle without the recorder, or a
|
|
548
|
+
* session not capturing evidence, simply runs the batch.
|
|
549
|
+
*/
|
|
550
|
+
recorded(steps, mode, identity, run) {
|
|
551
|
+
if (!this.wasm.BeginDeliveryEvidence || !this.wasm.CompleteDeliveryEvidence || !this.wasm.AbandonDeliveryEvidence) {
|
|
552
|
+
return run();
|
|
553
|
+
}
|
|
554
|
+
const described = this.wasm.BeginDeliveryEvidence(
|
|
555
|
+
this.handle,
|
|
556
|
+
JSON.stringify(steps.map((step) => step.args === void 0 ? { tool: step.tool, action: step.action } : { tool: step.tool, action: step.action, args: step.args })),
|
|
557
|
+
mode,
|
|
558
|
+
identity ? JSON.stringify({ transactionId: identity.transactionId, requestFingerprint: identity.requestFingerprint }) : ""
|
|
559
|
+
);
|
|
560
|
+
if (!described) return run();
|
|
561
|
+
let result;
|
|
562
|
+
try {
|
|
563
|
+
result = run();
|
|
564
|
+
return result;
|
|
565
|
+
} finally {
|
|
566
|
+
if (result) this.wasm.CompleteDeliveryEvidence(this.handle, JSON.stringify(result.steps));
|
|
567
|
+
else this.wasm.AbandonDeliveryEvidence(this.handle);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Make a preview retained by {@link previewBatch} (`retain: true`) the live document exactly
|
|
572
|
+
* as previewed: the previewed package is restored byte-for-byte as one undo step, so the
|
|
573
|
+
* generated anchor ids, timestamps and `packageHash` are exactly those the preview reported.
|
|
574
|
+
* The commit is guarded — it refuses with `preview_stale`, editing nothing, when the session's
|
|
575
|
+
* version, package content, tracked-changes mode or revision author moved since the preview,
|
|
576
|
+
* and with `preview_not_found` once the preview expired, was evicted, or was already
|
|
577
|
+
* committed. A `transaction` makes a retry after a lost response safe, as for
|
|
578
|
+
* {@link executeBatch}.
|
|
579
|
+
*/
|
|
580
|
+
commitPreview(previewId, transaction) {
|
|
581
|
+
if (!this.wasm.CommitPreview) {
|
|
582
|
+
throw new Error("This WASM bundle predates retained previews; rebuild docxodus.");
|
|
583
|
+
}
|
|
584
|
+
const commit = () => {
|
|
585
|
+
const envelope = JSON.parse(this.wasm.CommitPreview(this.handle, previewId));
|
|
586
|
+
if (!envelope.success) {
|
|
587
|
+
if (envelope.failure?.error.code === "preview_not_found") this.retainedPreviewReceipts.delete(previewId);
|
|
588
|
+
return envelope;
|
|
589
|
+
}
|
|
590
|
+
const receipt = this.retainedPreviewReceipts.get(previewId);
|
|
591
|
+
this.retainedPreviewReceipts.delete(previewId);
|
|
592
|
+
if (!receipt) return envelope;
|
|
593
|
+
return {
|
|
594
|
+
...receipt,
|
|
595
|
+
preview: false,
|
|
596
|
+
html: null,
|
|
597
|
+
baseVersion: envelope.baseVersion,
|
|
598
|
+
resultVersion: envelope.resultVersion,
|
|
599
|
+
packageHash: envelope.packageHash,
|
|
600
|
+
warnings: receipt.warnings.filter((warning) => !BATCH_REPLAY_CAVEAT_TEXTS.has(warning)),
|
|
601
|
+
retention: envelope.retention
|
|
602
|
+
};
|
|
603
|
+
};
|
|
604
|
+
if (transaction === void 0) return commit();
|
|
605
|
+
return this.runTransactional(transaction, "atomic", () => commit());
|
|
606
|
+
}
|
|
607
|
+
runTransactional(transaction, mode, body) {
|
|
608
|
+
if (!this.wasm.BeginMutationTransaction || !this.wasm.CompleteMutationTransaction || !this.wasm.AbandonMutationTransaction) {
|
|
609
|
+
throw new Error("This WASM bundle predates mutation transactions; rebuild docxodus.");
|
|
610
|
+
}
|
|
611
|
+
if (typeof transaction.transactionId !== "string") {
|
|
612
|
+
throw new RangeError("transactionId must be a string");
|
|
613
|
+
}
|
|
614
|
+
if (transaction.request === null || typeof transaction.request !== "object" || Array.isArray(transaction.request)) {
|
|
615
|
+
throw new RangeError("a mutation transaction needs a request object describing the batch");
|
|
616
|
+
}
|
|
617
|
+
const decision = JSON.parse(this.wasm.BeginMutationTransaction(
|
|
618
|
+
this.handle,
|
|
619
|
+
transaction.transactionId,
|
|
620
|
+
JSON.stringify({ ...transaction.request, mode })
|
|
621
|
+
));
|
|
622
|
+
if (decision.response !== null) {
|
|
623
|
+
return JSON.parse(decision.response);
|
|
624
|
+
}
|
|
625
|
+
let completed = false;
|
|
626
|
+
try {
|
|
627
|
+
const result = {
|
|
628
|
+
...body(decision.transaction),
|
|
629
|
+
transaction: decision.transaction
|
|
630
|
+
};
|
|
631
|
+
this.wasm.CompleteMutationTransaction(
|
|
632
|
+
this.handle,
|
|
633
|
+
transaction.transactionId,
|
|
634
|
+
JSON.stringify(result)
|
|
635
|
+
);
|
|
636
|
+
completed = true;
|
|
637
|
+
return result;
|
|
638
|
+
} finally {
|
|
639
|
+
if (!completed) this.wasm.AbandonMutationTransaction(this.handle, transaction.transactionId);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
runBatch(steps, mode) {
|
|
456
643
|
const baseVersion = this.getVersion();
|
|
457
644
|
const observationWarnings = [];
|
|
458
645
|
const inspect = (label, read, fallback) => {
|
|
@@ -490,16 +677,16 @@ var DocxSession = class _DocxSession {
|
|
|
490
677
|
);
|
|
491
678
|
const warnings = [...observationWarnings];
|
|
492
679
|
if ([...revisionChanges.added, ...revisionChanges.modified].some((revision) => revision.date !== void 0 && revision.date !== null)) {
|
|
493
|
-
warnings.push(
|
|
680
|
+
warnings.push(BATCH_REPLAY_CAVEATS.revisionDates);
|
|
494
681
|
}
|
|
495
682
|
if ([...commentChanges.added, ...commentChanges.modified].some((comment) => comment.date !== void 0 && comment.date !== null)) {
|
|
496
|
-
warnings.push(
|
|
683
|
+
warnings.push(BATCH_REPLAY_CAVEATS.commentDates);
|
|
497
684
|
}
|
|
498
685
|
if (annotationChanges.added.some((annotation) => annotation.created !== void 0 && annotation.created !== null)) {
|
|
499
|
-
warnings.push(
|
|
686
|
+
warnings.push(BATCH_REPLAY_CAVEATS.annotationMetadata);
|
|
500
687
|
}
|
|
501
688
|
if (result.steps.some((step) => step.results.some((edit) => edit.created.length > 0))) {
|
|
502
|
-
warnings.push(
|
|
689
|
+
warnings.push(BATCH_REPLAY_CAVEATS.createdAnchors);
|
|
503
690
|
}
|
|
504
691
|
if (mode === "best_effort" && !result.success) {
|
|
505
692
|
warnings.push("Best-effort execution retains every successful step despite later failures.");
|
|
@@ -723,7 +910,27 @@ var DocxSession = class _DocxSession {
|
|
|
723
910
|
} catch (error) {
|
|
724
911
|
warnings.push(`Preview HTML could not be generated: ${error instanceof Error ? error.message : String(error)}`);
|
|
725
912
|
}
|
|
726
|
-
|
|
913
|
+
let retention;
|
|
914
|
+
if (options?.retain) {
|
|
915
|
+
if (!this.wasm.RetainPreview) {
|
|
916
|
+
throw new Error("This WASM bundle predates retained previews; rebuild docxodus.");
|
|
917
|
+
}
|
|
918
|
+
if (!result.success) {
|
|
919
|
+
warnings.push("The preview did not succeed, so it was not retained for commit.");
|
|
920
|
+
} else {
|
|
921
|
+
const retained = JSON.parse(this.wasm.RetainPreview(shadow.handle));
|
|
922
|
+
warnings.push(...retained.warnings);
|
|
923
|
+
retention = retained.retention ?? void 0;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
const preview = retention ? { ...result, preview: true, warnings, html, retention } : { ...result, preview: true, warnings, html };
|
|
927
|
+
if (retention) {
|
|
928
|
+
if (this.retainedPreviewReceipts.size >= RETAINED_PREVIEW_RECEIPTS) {
|
|
929
|
+
this.retainedPreviewReceipts.delete(this.retainedPreviewReceipts.keys().next().value);
|
|
930
|
+
}
|
|
931
|
+
this.retainedPreviewReceipts.set(retention.previewId, { ...preview, html: null });
|
|
932
|
+
}
|
|
933
|
+
return preview;
|
|
727
934
|
} finally {
|
|
728
935
|
shadow.close();
|
|
729
936
|
}
|
|
@@ -1302,6 +1509,18 @@ var DocxSession = class _DocxSession {
|
|
|
1302
1509
|
imageBytesToBase64(bytes)
|
|
1303
1510
|
));
|
|
1304
1511
|
}
|
|
1512
|
+
/**
|
|
1513
|
+
* Convert an external linked picture into an embedded one using bytes the caller fetched;
|
|
1514
|
+
* the engine never reaches the network itself. Refused for pictures that already embed
|
|
1515
|
+
* their media — see `ImageOccurrence.operations`.
|
|
1516
|
+
*/
|
|
1517
|
+
embedLinkedImage(imageId, bytes) {
|
|
1518
|
+
return JSON.parse(this.wasm.EmbedLinkedImage(
|
|
1519
|
+
this.handle,
|
|
1520
|
+
imageId,
|
|
1521
|
+
imageBytesToBase64(bytes)
|
|
1522
|
+
));
|
|
1523
|
+
}
|
|
1305
1524
|
setImageDimensions(imageId, dimensions) {
|
|
1306
1525
|
return JSON.parse(this.wasm.SetImageDimensions(
|
|
1307
1526
|
this.handle,
|
|
@@ -1432,6 +1651,28 @@ var DocxSession = class _DocxSession {
|
|
|
1432
1651
|
listRevisions() {
|
|
1433
1652
|
return JSON.parse(this.wasm.ListRevisions(this.handle));
|
|
1434
1653
|
}
|
|
1654
|
+
/**
|
|
1655
|
+
* The explicit repairs the registry offers for entries it refuses to resolve (issues
|
|
1656
|
+
* #754–#758): which carriers are defective, whether a unique repair exists, and what it
|
|
1657
|
+
* would do. Read-only; listing, accept and reject never repair.
|
|
1658
|
+
*/
|
|
1659
|
+
listRevisionRepairs() {
|
|
1660
|
+
if (!this.wasm.ListRevisionRepairs) {
|
|
1661
|
+
throw new Error("This WASM bundle predates revision repairs; rebuild docxodus.");
|
|
1662
|
+
}
|
|
1663
|
+
return JSON.parse(this.wasm.ListRevisionRepairs(this.handle));
|
|
1664
|
+
}
|
|
1665
|
+
/**
|
|
1666
|
+
* Perform requested repairs atomically as one undo step. A kind the registry did not offer,
|
|
1667
|
+
* a non-repairable proposal, or a wrap-as-deletion without author and date refuses the whole
|
|
1668
|
+
* call (`revision_repair_rejected`) with nothing mutated. Repaired entries get new ids.
|
|
1669
|
+
*/
|
|
1670
|
+
repairRevisions(repairs) {
|
|
1671
|
+
if (!this.wasm.RepairRevisions) {
|
|
1672
|
+
throw new Error("This WASM bundle predates revision repairs; rebuild docxodus.");
|
|
1673
|
+
}
|
|
1674
|
+
return JSON.parse(this.wasm.RepairRevisions(this.handle, JSON.stringify(repairs)));
|
|
1675
|
+
}
|
|
1435
1676
|
/** Accept ONE revision by the id {@link listRevisions} reported — insertions keep
|
|
1436
1677
|
* their content, deletions are carried out, a move materializes at its destination,
|
|
1437
1678
|
* a format change keeps the new properties. Undoable. */
|
|
@@ -1585,8 +1826,25 @@ var DocxSession = class _DocxSession {
|
|
|
1585
1826
|
* `enclosingAnchor.id` + `span.{start,length}`, so identical needles in the
|
|
1586
1827
|
* same paragraph (the template-fill case where five `[___]` placeholders
|
|
1587
1828
|
* each get a different value) don't collide.
|
|
1829
|
+
*
|
|
1830
|
+
* Pass `format` to replace text and format exactly the replacement atomically, with one
|
|
1831
|
+
* undo/version unit. This interactive path returns an ordinary EditResult and avoids the
|
|
1832
|
+
* package checkpoint/hash required by executeBatch's receipt. Empty replacements only delete.
|
|
1588
1833
|
*/
|
|
1589
|
-
replaceMatch(match, replace) {
|
|
1834
|
+
replaceMatch(match, replace, format) {
|
|
1835
|
+
if (format !== void 0) {
|
|
1836
|
+
if (!this.wasm.ReplaceTextAtSpanWithFormat) {
|
|
1837
|
+
throw new Error("This WASM bundle predates atomic text-plus-format edits; rebuild docxodus.");
|
|
1838
|
+
}
|
|
1839
|
+
return JSON.parse(this.wasm.ReplaceTextAtSpanWithFormat(
|
|
1840
|
+
this.handle,
|
|
1841
|
+
match.enclosingAnchor.id,
|
|
1842
|
+
match.span.start,
|
|
1843
|
+
match.span.length,
|
|
1844
|
+
replace,
|
|
1845
|
+
JSON.stringify(format)
|
|
1846
|
+
));
|
|
1847
|
+
}
|
|
1590
1848
|
return JSON.parse(
|
|
1591
1849
|
this.wasm.ReplaceTextAtSpan(this.handle, match.enclosingAnchor.id, match.span.start, match.span.length, replace)
|
|
1592
1850
|
);
|
|
@@ -1789,7 +2047,16 @@ var DocxSession = class _DocxSession {
|
|
|
1789
2047
|
* With initial projection capture enabled (the default), exact opening bytes are the
|
|
1790
2048
|
* baseline used for dispositions and semantic/package deltas.
|
|
1791
2049
|
*/
|
|
1792
|
-
verifyDeliverable() {
|
|
2050
|
+
verifyDeliverable(request) {
|
|
2051
|
+
if (request !== void 0) {
|
|
2052
|
+
if (!this.wasm.VerifyDeliverableWithRequest) {
|
|
2053
|
+
throw new Error("This WASM bundle predates full verification requests; rebuild docxodus.");
|
|
2054
|
+
}
|
|
2055
|
+
return JSON.parse(this.wasm.VerifyDeliverableWithRequest(
|
|
2056
|
+
this.handle,
|
|
2057
|
+
serializeVerificationRequest(request)
|
|
2058
|
+
));
|
|
2059
|
+
}
|
|
1793
2060
|
return JSON.parse(
|
|
1794
2061
|
this.wasm.VerifyDeliverable(this.handle)
|
|
1795
2062
|
);
|
|
@@ -2018,6 +2285,7 @@ var DocxSession = class _DocxSession {
|
|
|
2018
2285
|
return this.wasm.Save(this.handle);
|
|
2019
2286
|
}
|
|
2020
2287
|
close() {
|
|
2288
|
+
this.retainedPreviewReceipts.clear();
|
|
2021
2289
|
this.wasm.CloseSession(this.handle);
|
|
2022
2290
|
}
|
|
2023
2291
|
// TypeScript 5.2+ disposable protocol
|
|
@@ -2038,6 +2306,129 @@ function openDocxSession(bytes, wasmExports2, settings) {
|
|
|
2038
2306
|
return new DocxSession(handle, bridge);
|
|
2039
2307
|
}
|
|
2040
2308
|
|
|
2309
|
+
// src/external-annotation-wire.ts
|
|
2310
|
+
function readPawlsPage(p) {
|
|
2311
|
+
return {
|
|
2312
|
+
page: {
|
|
2313
|
+
width: p.Page?.Width ?? p.page?.width,
|
|
2314
|
+
height: p.Page?.Height ?? p.page?.height,
|
|
2315
|
+
index: p.Page?.Index ?? p.page?.index
|
|
2316
|
+
},
|
|
2317
|
+
tokens: (p.Tokens || p.tokens || []).map((t) => ({
|
|
2318
|
+
x: t.X ?? t.x,
|
|
2319
|
+
y: t.Y ?? t.y,
|
|
2320
|
+
width: t.Width ?? t.width,
|
|
2321
|
+
height: t.Height ?? t.height,
|
|
2322
|
+
text: t.Text ?? t.text
|
|
2323
|
+
}))
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
function readAnnotationJson(json) {
|
|
2327
|
+
if (!json) return void 0;
|
|
2328
|
+
if (json.Start !== void 0 || json.start !== void 0) {
|
|
2329
|
+
return {
|
|
2330
|
+
id: json.Id ?? json.id,
|
|
2331
|
+
start: json.Start ?? json.start,
|
|
2332
|
+
end: json.End ?? json.end,
|
|
2333
|
+
text: json.Text ?? json.text
|
|
2334
|
+
};
|
|
2335
|
+
}
|
|
2336
|
+
const result = {};
|
|
2337
|
+
for (const [key, value] of Object.entries(json)) {
|
|
2338
|
+
const v = value;
|
|
2339
|
+
result[key] = {
|
|
2340
|
+
bounds: {
|
|
2341
|
+
top: v.Bounds?.Top ?? v.bounds?.top,
|
|
2342
|
+
bottom: v.Bounds?.Bottom ?? v.bounds?.bottom,
|
|
2343
|
+
left: v.Bounds?.Left ?? v.bounds?.left,
|
|
2344
|
+
right: v.Bounds?.Right ?? v.bounds?.right
|
|
2345
|
+
},
|
|
2346
|
+
tokensJsons: (v.TokensJsons || v.tokensJsons || []).map((t) => ({
|
|
2347
|
+
pageIndex: t.PageIndex ?? t.pageIndex,
|
|
2348
|
+
tokenIndex: t.TokenIndex ?? t.tokenIndex
|
|
2349
|
+
})),
|
|
2350
|
+
rawText: v.RawText ?? v.rawText
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
return result;
|
|
2354
|
+
}
|
|
2355
|
+
function readAnnotation(a) {
|
|
2356
|
+
return {
|
|
2357
|
+
id: a.Id ?? a.id,
|
|
2358
|
+
annotationLabel: a.AnnotationLabel ?? a.annotationLabel,
|
|
2359
|
+
rawText: a.RawText ?? a.rawText,
|
|
2360
|
+
page: a.Page ?? a.page,
|
|
2361
|
+
annotationJson: readAnnotationJson(a.AnnotationJson ?? a.annotationJson),
|
|
2362
|
+
parentId: a.ParentId ?? a.parentId,
|
|
2363
|
+
annotationType: a.AnnotationType ?? a.annotationType,
|
|
2364
|
+
structural: a.Structural ?? a.structural
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2367
|
+
function readRelationship(r) {
|
|
2368
|
+
return {
|
|
2369
|
+
id: r.Id ?? r.id,
|
|
2370
|
+
relationshipLabel: r.RelationshipLabel ?? r.relationshipLabel,
|
|
2371
|
+
sourceAnnotationIds: r.SourceAnnotationIds ?? r.sourceAnnotationIds ?? [],
|
|
2372
|
+
targetAnnotationIds: r.TargetAnnotationIds ?? r.targetAnnotationIds ?? [],
|
|
2373
|
+
structural: r.Structural ?? r.structural
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
function readLabel(l) {
|
|
2377
|
+
return {
|
|
2378
|
+
id: l.Id ?? l.id,
|
|
2379
|
+
color: l.Color ?? l.color,
|
|
2380
|
+
description: l.Description ?? l.description ?? "",
|
|
2381
|
+
icon: l.Icon ?? l.icon ?? "",
|
|
2382
|
+
text: l.Text ?? l.text,
|
|
2383
|
+
labelType: l.LabelType ?? l.labelType ?? "text"
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
function readLabels(raw) {
|
|
2387
|
+
const labels = {};
|
|
2388
|
+
for (const [key, value] of Object.entries(raw || {})) labels[key] = readLabel(value);
|
|
2389
|
+
return labels;
|
|
2390
|
+
}
|
|
2391
|
+
function readOpenContractExport(parsed) {
|
|
2392
|
+
return {
|
|
2393
|
+
title: parsed.Title ?? parsed.title,
|
|
2394
|
+
content: parsed.Content ?? parsed.content,
|
|
2395
|
+
description: parsed.Description ?? parsed.description,
|
|
2396
|
+
pageCount: parsed.PageCount ?? parsed.pageCount,
|
|
2397
|
+
pawlsFileContent: (parsed.PawlsFileContent || parsed.pawlsFileContent || []).map(readPawlsPage),
|
|
2398
|
+
docLabels: parsed.DocLabels ?? parsed.docLabels ?? [],
|
|
2399
|
+
labelledText: (parsed.LabelledText || parsed.labelledText || []).map(readAnnotation),
|
|
2400
|
+
relationships: (parsed.Relationships || parsed.relationships)?.map(readRelationship)
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
function readExternalAnnotationSet(parsed) {
|
|
2404
|
+
return {
|
|
2405
|
+
documentId: parsed.DocumentId ?? parsed.documentId,
|
|
2406
|
+
documentHash: parsed.DocumentHash ?? parsed.documentHash,
|
|
2407
|
+
createdAt: parsed.CreatedAt ?? parsed.createdAt,
|
|
2408
|
+
updatedAt: parsed.UpdatedAt ?? parsed.updatedAt,
|
|
2409
|
+
version: parsed.Version ?? parsed.version,
|
|
2410
|
+
...readOpenContractExport(parsed),
|
|
2411
|
+
textLabels: readLabels(parsed.TextLabels || parsed.textLabels),
|
|
2412
|
+
docLabelDefinitions: readLabels(parsed.DocLabelDefinitions || parsed.docLabelDefinitions)
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
function readExternalAnnotationValidation(parsed) {
|
|
2416
|
+
return {
|
|
2417
|
+
isValid: parsed.IsValid ?? parsed.isValid,
|
|
2418
|
+
hashMismatch: parsed.HashMismatch ?? parsed.hashMismatch,
|
|
2419
|
+
issues: (parsed.Issues || parsed.issues || []).map((i) => ({
|
|
2420
|
+
annotationId: i.AnnotationId ?? i.annotationId,
|
|
2421
|
+
issueType: i.IssueType ?? i.issueType,
|
|
2422
|
+
description: i.Description ?? i.description,
|
|
2423
|
+
expectedText: i.ExpectedText ?? i.expectedText,
|
|
2424
|
+
actualText: i.ActualText ?? i.actualText
|
|
2425
|
+
}))
|
|
2426
|
+
};
|
|
2427
|
+
}
|
|
2428
|
+
function readProjectedHtml(parsed) {
|
|
2429
|
+
return parsed.Html ?? parsed.html;
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2041
2432
|
// src/history.ts
|
|
2042
2433
|
var MAX_HISTORY_ARCHIVE_BYTES = 64 * 1024 * 1024;
|
|
2043
2434
|
var DocxHistoryError = class extends Error {
|
|
@@ -6426,11 +6817,21 @@ async function generatePackageManifest(document2) {
|
|
|
6426
6817
|
exports.DocumentConverter.GeneratePackageManifest(bytes)
|
|
6427
6818
|
);
|
|
6428
6819
|
}
|
|
6429
|
-
async function verifyDeliverable(document2, baseline) {
|
|
6820
|
+
async function verifyDeliverable(document2, baseline, request) {
|
|
6430
6821
|
const exports = ensureInitialized();
|
|
6431
6822
|
const bytes = await toBytes(document2);
|
|
6432
6823
|
const baselineBytes = baseline === void 0 ? void 0 : await toBytes(baseline);
|
|
6433
6824
|
await yieldToMain();
|
|
6825
|
+
if (request !== void 0) {
|
|
6826
|
+
const requestJson = serializeVerificationRequest(request);
|
|
6827
|
+
const converter = exports.DocumentConverter;
|
|
6828
|
+
if (!converter.VerifyDeliverableWithRequest || !converter.VerifyDeliverableWithBaselineAndRequest) {
|
|
6829
|
+
throw new Error("This WASM bundle predates full verification requests; rebuild docxodus.");
|
|
6830
|
+
}
|
|
6831
|
+
return JSON.parse(
|
|
6832
|
+
baselineBytes === void 0 ? converter.VerifyDeliverableWithRequest(bytes, requestJson) : converter.VerifyDeliverableWithBaselineAndRequest(baselineBytes, bytes, requestJson)
|
|
6833
|
+
);
|
|
6834
|
+
}
|
|
6434
6835
|
return JSON.parse(
|
|
6435
6836
|
baselineBytes === void 0 ? exports.DocumentConverter.VerifyDeliverable(bytes) : exports.DocumentConverter.VerifyDeliverableWithBaseline(
|
|
6436
6837
|
baselineBytes,
|
|
@@ -6444,7 +6845,7 @@ async function verifyDeliveryReceipt(receiptJson, artifacts) {
|
|
|
6444
6845
|
Object.fromEntries(
|
|
6445
6846
|
Object.entries(artifacts).map(([artifactId, bytes]) => [
|
|
6446
6847
|
artifactId,
|
|
6447
|
-
|
|
6848
|
+
bytesToBase642(bytes)
|
|
6448
6849
|
])
|
|
6449
6850
|
)
|
|
6450
6851
|
);
|
|
@@ -6609,6 +7010,16 @@ async function getRevisions(document2) {
|
|
|
6609
7010
|
}
|
|
6610
7011
|
return JSON.parse(result);
|
|
6611
7012
|
}
|
|
7013
|
+
async function getComments(document2) {
|
|
7014
|
+
const exports = ensureInitialized();
|
|
7015
|
+
const bytes = await toBytes(document2);
|
|
7016
|
+
await yieldToMain();
|
|
7017
|
+
const result = exports.DocumentComparer.GetCommentsJson(bytes);
|
|
7018
|
+
if (isErrorResponse(result)) {
|
|
7019
|
+
throw new Error(`Failed to get comments: ${parseError(result).error}`);
|
|
7020
|
+
}
|
|
7021
|
+
return JSON.parse(result);
|
|
7022
|
+
}
|
|
6612
7023
|
function docxDiffSettingsJson(settings) {
|
|
6613
7024
|
return settings ? JSON.stringify(settings) : "";
|
|
6614
7025
|
}
|
|
@@ -6675,7 +7086,7 @@ async function docxDiffCompareBatch(baseline, candidates, settings, products) {
|
|
|
6675
7086
|
const bytes = await toBytes(candidates[i].document);
|
|
6676
7087
|
payload.push({
|
|
6677
7088
|
name: candidates[i].name ?? String(i),
|
|
6678
|
-
docB64:
|
|
7089
|
+
docB64: bytesToBase642(bytes)
|
|
6679
7090
|
});
|
|
6680
7091
|
}
|
|
6681
7092
|
await yieldToMain();
|
|
@@ -6751,7 +7162,7 @@ async function docxDiffRejectRevisions(redline) {
|
|
|
6751
7162
|
}
|
|
6752
7163
|
return result;
|
|
6753
7164
|
}
|
|
6754
|
-
function
|
|
7165
|
+
function bytesToBase642(bytes) {
|
|
6755
7166
|
if (typeof btoa === "function") {
|
|
6756
7167
|
let binary = "";
|
|
6757
7168
|
const chunkSize = 32768;
|
|
@@ -6767,7 +7178,7 @@ async function reviewersJson(reviewers) {
|
|
|
6767
7178
|
const arr = await Promise.all(
|
|
6768
7179
|
reviewers.map(async (r) => ({
|
|
6769
7180
|
author: r.author,
|
|
6770
|
-
docB64:
|
|
7181
|
+
docB64: bytesToBase642(await toBytes(r.document))
|
|
6771
7182
|
}))
|
|
6772
7183
|
);
|
|
6773
7184
|
return JSON.stringify(arr);
|
|
@@ -7077,77 +7488,7 @@ async function exportToOpenContract(document2) {
|
|
|
7077
7488
|
const error = parseError(result);
|
|
7078
7489
|
throw new Error(`Failed to export to OpenContract format: ${error.error}`);
|
|
7079
7490
|
}
|
|
7080
|
-
|
|
7081
|
-
const convertPawlsPage = (p) => ({
|
|
7082
|
-
page: {
|
|
7083
|
-
width: p.Page?.Width ?? p.page?.width,
|
|
7084
|
-
height: p.Page?.Height ?? p.page?.height,
|
|
7085
|
-
index: p.Page?.Index ?? p.page?.index
|
|
7086
|
-
},
|
|
7087
|
-
tokens: (p.Tokens || p.tokens || []).map((t) => ({
|
|
7088
|
-
x: t.X ?? t.x,
|
|
7089
|
-
y: t.Y ?? t.y,
|
|
7090
|
-
width: t.Width ?? t.width,
|
|
7091
|
-
height: t.Height ?? t.height,
|
|
7092
|
-
text: t.Text ?? t.text
|
|
7093
|
-
}))
|
|
7094
|
-
});
|
|
7095
|
-
const convertAnnotation = (a) => ({
|
|
7096
|
-
id: a.Id ?? a.id,
|
|
7097
|
-
annotationLabel: a.AnnotationLabel ?? a.annotationLabel,
|
|
7098
|
-
rawText: a.RawText ?? a.rawText,
|
|
7099
|
-
page: a.Page ?? a.page,
|
|
7100
|
-
annotationJson: convertAnnotationJson(a.AnnotationJson ?? a.annotationJson),
|
|
7101
|
-
parentId: a.ParentId ?? a.parentId,
|
|
7102
|
-
annotationType: a.AnnotationType ?? a.annotationType,
|
|
7103
|
-
structural: a.Structural ?? a.structural
|
|
7104
|
-
});
|
|
7105
|
-
const convertAnnotationJson = (json) => {
|
|
7106
|
-
if (!json) return void 0;
|
|
7107
|
-
if (json.Start !== void 0 || json.start !== void 0) {
|
|
7108
|
-
return {
|
|
7109
|
-
id: json.Id ?? json.id,
|
|
7110
|
-
start: json.Start ?? json.start,
|
|
7111
|
-
end: json.End ?? json.end,
|
|
7112
|
-
text: json.Text ?? json.text
|
|
7113
|
-
};
|
|
7114
|
-
}
|
|
7115
|
-
const result2 = {};
|
|
7116
|
-
for (const [key, value] of Object.entries(json)) {
|
|
7117
|
-
const v = value;
|
|
7118
|
-
result2[key] = {
|
|
7119
|
-
bounds: {
|
|
7120
|
-
top: v.Bounds?.Top ?? v.bounds?.top,
|
|
7121
|
-
bottom: v.Bounds?.Bottom ?? v.bounds?.bottom,
|
|
7122
|
-
left: v.Bounds?.Left ?? v.bounds?.left,
|
|
7123
|
-
right: v.Bounds?.Right ?? v.bounds?.right
|
|
7124
|
-
},
|
|
7125
|
-
tokensJsons: (v.TokensJsons || v.tokensJsons || []).map((t) => ({
|
|
7126
|
-
pageIndex: t.PageIndex ?? t.pageIndex,
|
|
7127
|
-
tokenIndex: t.TokenIndex ?? t.tokenIndex
|
|
7128
|
-
})),
|
|
7129
|
-
rawText: v.RawText ?? v.rawText
|
|
7130
|
-
};
|
|
7131
|
-
}
|
|
7132
|
-
return result2;
|
|
7133
|
-
};
|
|
7134
|
-
const convertRelationship = (r) => ({
|
|
7135
|
-
id: r.Id ?? r.id,
|
|
7136
|
-
relationshipLabel: r.RelationshipLabel ?? r.relationshipLabel,
|
|
7137
|
-
sourceAnnotationIds: r.SourceAnnotationIds ?? r.sourceAnnotationIds ?? [],
|
|
7138
|
-
targetAnnotationIds: r.TargetAnnotationIds ?? r.targetAnnotationIds ?? [],
|
|
7139
|
-
structural: r.Structural ?? r.structural
|
|
7140
|
-
});
|
|
7141
|
-
return {
|
|
7142
|
-
title: parsed.Title ?? parsed.title,
|
|
7143
|
-
content: parsed.Content ?? parsed.content,
|
|
7144
|
-
description: parsed.Description ?? parsed.description,
|
|
7145
|
-
pageCount: parsed.PageCount ?? parsed.pageCount,
|
|
7146
|
-
pawlsFileContent: (parsed.PawlsFileContent || parsed.pawlsFileContent || []).map(convertPawlsPage),
|
|
7147
|
-
docLabels: parsed.DocLabels ?? parsed.docLabels ?? [],
|
|
7148
|
-
labelledText: (parsed.LabelledText || parsed.labelledText || []).map(convertAnnotation),
|
|
7149
|
-
relationships: (parsed.Relationships || parsed.relationships)?.map(convertRelationship)
|
|
7150
|
-
};
|
|
7491
|
+
return readOpenContractExport(JSON.parse(result));
|
|
7151
7492
|
}
|
|
7152
7493
|
async function convertWmlToMarkdown(document2, settings = {}) {
|
|
7153
7494
|
const exports = ensureInitialized();
|
|
@@ -7253,8 +7594,7 @@ async function createExternalAnnotationSet(document2, documentId) {
|
|
|
7253
7594
|
const error = parseError(result);
|
|
7254
7595
|
throw new Error(`Failed to create external annotation set: ${error.error}`);
|
|
7255
7596
|
}
|
|
7256
|
-
|
|
7257
|
-
return convertExternalAnnotationSet(parsed);
|
|
7597
|
+
return readExternalAnnotationSet(JSON.parse(result));
|
|
7258
7598
|
}
|
|
7259
7599
|
async function validateExternalAnnotations(document2, annotationSet) {
|
|
7260
7600
|
const exports = ensureInitialized();
|
|
@@ -7266,18 +7606,7 @@ async function validateExternalAnnotations(document2, annotationSet) {
|
|
|
7266
7606
|
const error = parseError(result);
|
|
7267
7607
|
throw new Error(`Failed to validate external annotations: ${error.error}`);
|
|
7268
7608
|
}
|
|
7269
|
-
|
|
7270
|
-
return {
|
|
7271
|
-
isValid: parsed.IsValid ?? parsed.isValid,
|
|
7272
|
-
hashMismatch: parsed.HashMismatch ?? parsed.hashMismatch,
|
|
7273
|
-
issues: (parsed.Issues || parsed.issues || []).map((i) => ({
|
|
7274
|
-
annotationId: i.AnnotationId ?? i.annotationId,
|
|
7275
|
-
issueType: i.IssueType ?? i.issueType,
|
|
7276
|
-
description: i.Description ?? i.description,
|
|
7277
|
-
expectedText: i.ExpectedText ?? i.expectedText,
|
|
7278
|
-
actualText: i.ActualText ?? i.actualText
|
|
7279
|
-
}))
|
|
7280
|
-
};
|
|
7609
|
+
return readExternalAnnotationValidation(JSON.parse(result));
|
|
7281
7610
|
}
|
|
7282
7611
|
async function convertDocxToHtmlWithExternalAnnotations(document2, annotationSet, conversionOptions, projectionOptions) {
|
|
7283
7612
|
const exports = ensureInitialized();
|
|
@@ -7298,8 +7627,7 @@ async function convertDocxToHtmlWithExternalAnnotations(document2, annotationSet
|
|
|
7298
7627
|
const error = parseError(result);
|
|
7299
7628
|
throw new Error(`Failed to convert with external annotations: ${error.error}`);
|
|
7300
7629
|
}
|
|
7301
|
-
|
|
7302
|
-
return parsed.Html ?? parsed.html;
|
|
7630
|
+
return readProjectedHtml(JSON.parse(result));
|
|
7303
7631
|
}
|
|
7304
7632
|
async function searchTextOffsets(document2, searchText, maxResults = 100) {
|
|
7305
7633
|
const exports = ensureInitialized();
|
|
@@ -7367,103 +7695,6 @@ function findTextOccurrences(documentText, searchText, maxResults = 100) {
|
|
|
7367
7695
|
}
|
|
7368
7696
|
return results;
|
|
7369
7697
|
}
|
|
7370
|
-
function convertExternalAnnotationSet(parsed) {
|
|
7371
|
-
const convertLabel = (l) => ({
|
|
7372
|
-
id: l.Id ?? l.id,
|
|
7373
|
-
color: l.Color ?? l.color,
|
|
7374
|
-
description: l.Description ?? l.description ?? "",
|
|
7375
|
-
icon: l.Icon ?? l.icon ?? "",
|
|
7376
|
-
text: l.Text ?? l.text,
|
|
7377
|
-
labelType: l.LabelType ?? l.labelType ?? "text"
|
|
7378
|
-
});
|
|
7379
|
-
const convertPawlsPage = (p) => ({
|
|
7380
|
-
page: {
|
|
7381
|
-
width: p.Page?.Width ?? p.page?.width,
|
|
7382
|
-
height: p.Page?.Height ?? p.page?.height,
|
|
7383
|
-
index: p.Page?.Index ?? p.page?.index
|
|
7384
|
-
},
|
|
7385
|
-
tokens: (p.Tokens || p.tokens || []).map((t) => ({
|
|
7386
|
-
x: t.X ?? t.x,
|
|
7387
|
-
y: t.Y ?? t.y,
|
|
7388
|
-
width: t.Width ?? t.width,
|
|
7389
|
-
height: t.Height ?? t.height,
|
|
7390
|
-
text: t.Text ?? t.text
|
|
7391
|
-
}))
|
|
7392
|
-
});
|
|
7393
|
-
const convertAnnotation = (a) => ({
|
|
7394
|
-
id: a.Id ?? a.id,
|
|
7395
|
-
annotationLabel: a.AnnotationLabel ?? a.annotationLabel,
|
|
7396
|
-
rawText: a.RawText ?? a.rawText,
|
|
7397
|
-
page: a.Page ?? a.page,
|
|
7398
|
-
annotationJson: convertAnnotationJson(a.AnnotationJson ?? a.annotationJson),
|
|
7399
|
-
parentId: a.ParentId ?? a.parentId,
|
|
7400
|
-
annotationType: a.AnnotationType ?? a.annotationType,
|
|
7401
|
-
structural: a.Structural ?? a.structural
|
|
7402
|
-
});
|
|
7403
|
-
const convertAnnotationJson = (json) => {
|
|
7404
|
-
if (!json) return void 0;
|
|
7405
|
-
if (json.Start !== void 0 || json.start !== void 0) {
|
|
7406
|
-
return {
|
|
7407
|
-
id: json.Id ?? json.id,
|
|
7408
|
-
start: json.Start ?? json.start,
|
|
7409
|
-
end: json.End ?? json.end,
|
|
7410
|
-
text: json.Text ?? json.text
|
|
7411
|
-
};
|
|
7412
|
-
}
|
|
7413
|
-
const result = {};
|
|
7414
|
-
for (const [key, value] of Object.entries(json)) {
|
|
7415
|
-
const v = value;
|
|
7416
|
-
result[key] = {
|
|
7417
|
-
bounds: {
|
|
7418
|
-
top: v.Bounds?.Top ?? v.bounds?.top,
|
|
7419
|
-
bottom: v.Bounds?.Bottom ?? v.bounds?.bottom,
|
|
7420
|
-
left: v.Bounds?.Left ?? v.bounds?.left,
|
|
7421
|
-
right: v.Bounds?.Right ?? v.bounds?.right
|
|
7422
|
-
},
|
|
7423
|
-
tokensJsons: (v.TokensJsons || v.tokensJsons || []).map((t) => ({
|
|
7424
|
-
pageIndex: t.PageIndex ?? t.pageIndex,
|
|
7425
|
-
tokenIndex: t.TokenIndex ?? t.tokenIndex
|
|
7426
|
-
})),
|
|
7427
|
-
rawText: v.RawText ?? v.rawText
|
|
7428
|
-
};
|
|
7429
|
-
}
|
|
7430
|
-
return result;
|
|
7431
|
-
};
|
|
7432
|
-
const convertRelationship = (r) => ({
|
|
7433
|
-
id: r.Id ?? r.id,
|
|
7434
|
-
relationshipLabel: r.RelationshipLabel ?? r.relationshipLabel,
|
|
7435
|
-
sourceAnnotationIds: r.SourceAnnotationIds ?? r.sourceAnnotationIds ?? [],
|
|
7436
|
-
targetAnnotationIds: r.TargetAnnotationIds ?? r.targetAnnotationIds ?? [],
|
|
7437
|
-
structural: r.Structural ?? r.structural
|
|
7438
|
-
});
|
|
7439
|
-
const textLabels = {};
|
|
7440
|
-
const rawTextLabels = parsed.TextLabels || parsed.textLabels || {};
|
|
7441
|
-
for (const [key, value] of Object.entries(rawTextLabels)) {
|
|
7442
|
-
textLabels[key] = convertLabel(value);
|
|
7443
|
-
}
|
|
7444
|
-
const docLabelDefinitions = {};
|
|
7445
|
-
const rawDocLabelDefs = parsed.DocLabelDefinitions || parsed.docLabelDefinitions || {};
|
|
7446
|
-
for (const [key, value] of Object.entries(rawDocLabelDefs)) {
|
|
7447
|
-
docLabelDefinitions[key] = convertLabel(value);
|
|
7448
|
-
}
|
|
7449
|
-
return {
|
|
7450
|
-
documentId: parsed.DocumentId ?? parsed.documentId,
|
|
7451
|
-
documentHash: parsed.DocumentHash ?? parsed.documentHash,
|
|
7452
|
-
createdAt: parsed.CreatedAt ?? parsed.createdAt,
|
|
7453
|
-
updatedAt: parsed.UpdatedAt ?? parsed.updatedAt,
|
|
7454
|
-
version: parsed.Version ?? parsed.version,
|
|
7455
|
-
title: parsed.Title ?? parsed.title,
|
|
7456
|
-
content: parsed.Content ?? parsed.content,
|
|
7457
|
-
description: parsed.Description ?? parsed.description,
|
|
7458
|
-
pageCount: parsed.PageCount ?? parsed.pageCount,
|
|
7459
|
-
pawlsFileContent: (parsed.PawlsFileContent || parsed.pawlsFileContent || []).map(convertPawlsPage),
|
|
7460
|
-
docLabels: parsed.DocLabels ?? parsed.docLabels ?? [],
|
|
7461
|
-
labelledText: (parsed.LabelledText || parsed.labelledText || []).map(convertAnnotation),
|
|
7462
|
-
relationships: (parsed.Relationships || parsed.relationships)?.map(convertRelationship),
|
|
7463
|
-
textLabels,
|
|
7464
|
-
docLabelDefinitions
|
|
7465
|
-
};
|
|
7466
|
-
}
|
|
7467
7698
|
async function projectAnnotationsOntoHtml(html, annotationSet, projectionOptions) {
|
|
7468
7699
|
const exports = ensureInitialized();
|
|
7469
7700
|
await yieldToMain();
|
|
@@ -7478,8 +7709,7 @@ async function projectAnnotationsOntoHtml(html, annotationSet, projectionOptions
|
|
|
7478
7709
|
const error = parseError(result);
|
|
7479
7710
|
throw new Error(`Failed to project annotations: ${error.error}`);
|
|
7480
7711
|
}
|
|
7481
|
-
|
|
7482
|
-
return parsed.Html ?? parsed.html;
|
|
7712
|
+
return readProjectedHtml(JSON.parse(result));
|
|
7483
7713
|
}
|
|
7484
7714
|
async function addAnnotationToHtml(html, annotation, label, projectionOptions) {
|
|
7485
7715
|
const exports = ensureInitialized();
|
|
@@ -7497,8 +7727,7 @@ async function addAnnotationToHtml(html, annotation, label, projectionOptions) {
|
|
|
7497
7727
|
const error = parseError(result);
|
|
7498
7728
|
throw new Error(`Failed to add annotation to HTML: ${error.error}`);
|
|
7499
7729
|
}
|
|
7500
|
-
|
|
7501
|
-
return parsed.Html ?? parsed.html;
|
|
7730
|
+
return readProjectedHtml(JSON.parse(result));
|
|
7502
7731
|
}
|
|
7503
7732
|
async function removeAnnotationFromHtml(html, annotationId, cssClassPrefix) {
|
|
7504
7733
|
const exports = ensureInitialized();
|
|
@@ -7512,8 +7741,7 @@ async function removeAnnotationFromHtml(html, annotationId, cssClassPrefix) {
|
|
|
7512
7741
|
const error = parseError(result);
|
|
7513
7742
|
throw new Error(`Failed to remove annotation from HTML: ${error.error}`);
|
|
7514
7743
|
}
|
|
7515
|
-
|
|
7516
|
-
return parsed.Html ?? parsed.html;
|
|
7744
|
+
return readProjectedHtml(JSON.parse(result));
|
|
7517
7745
|
}
|
|
7518
7746
|
async function generateAnnotationVisibilityCss(hiddenLabelIds, cssClassPrefix) {
|
|
7519
7747
|
const exports = ensureInitialized();
|
|
@@ -11680,6 +11908,16 @@ function ensureBlockDragStyles(doc) {
|
|
|
11680
11908
|
`;
|
|
11681
11909
|
(doc.head ?? doc.documentElement).appendChild(style);
|
|
11682
11910
|
}
|
|
11911
|
+
var CHROME_CARRIER_ANCHOR = "chrome-carrier";
|
|
11912
|
+
function yieldToEventLoop() {
|
|
11913
|
+
return new Promise((resolve) => {
|
|
11914
|
+
const settle = () => {
|
|
11915
|
+
setTimeout(resolve, 0);
|
|
11916
|
+
};
|
|
11917
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(settle);
|
|
11918
|
+
else settle();
|
|
11919
|
+
});
|
|
11920
|
+
}
|
|
11683
11921
|
function trackedChangeWireName(mode) {
|
|
11684
11922
|
if (mode === 1 /* RenderInline */) return "render_inline";
|
|
11685
11923
|
if (mode === 2 /* StripDeletions */) return "strip_deletions";
|
|
@@ -12347,7 +12585,64 @@ var DocxEditor = class _DocxEditor {
|
|
|
12347
12585
|
}
|
|
12348
12586
|
/** Open a document, render it into `container`, and wire up editing. */
|
|
12349
12587
|
static open(container, bytes, exports, options = {}) {
|
|
12350
|
-
const opts =
|
|
12588
|
+
const opts = _DocxEditor.resolveOptions(options);
|
|
12589
|
+
const editor = _DocxEditor.openSession(container, bytes, exports, opts);
|
|
12590
|
+
try {
|
|
12591
|
+
editor.refreshAnchorMap();
|
|
12592
|
+
if (opts.headerFooter) editor.createRegion();
|
|
12593
|
+
const fullHtml = editor.renderFullHtml(bytes);
|
|
12594
|
+
if (opts.paginated) editor.mountPaginated(fullHtml);
|
|
12595
|
+
else editor.mountHtml(fullHtml);
|
|
12596
|
+
editor.finishMount();
|
|
12597
|
+
return editor;
|
|
12598
|
+
} catch (error) {
|
|
12599
|
+
editor.close();
|
|
12600
|
+
throw error;
|
|
12601
|
+
}
|
|
12602
|
+
}
|
|
12603
|
+
/**
|
|
12604
|
+
* Open a document without holding the main thread for the whole mount (issue #776).
|
|
12605
|
+
*
|
|
12606
|
+
* {@link open} renders and wires the entire document in one synchronous task, which on a
|
|
12607
|
+
* long document is the largest single block of a reading-and-editing session. This variant
|
|
12608
|
+
* pays only the session open up front, then mounts the document in windows of body units,
|
|
12609
|
+
* yielding to the event loop between them: the chrome — stylesheet, section wrappers with
|
|
12610
|
+
* their page geometry, footnote and endnote sections — comes from one cheap engine render
|
|
12611
|
+
* that sees no body content, and each window from the engine's block renderer, which lays
|
|
12612
|
+
* units out exactly as the full render does (the plan's border-box grouping is never split).
|
|
12613
|
+
* The DOM that results is the one {@link open} produces; blocks already mounted are editable
|
|
12614
|
+
* while later windows are still landing, and edits made meanwhile are honoured because every
|
|
12615
|
+
* window renders from the live session.
|
|
12616
|
+
*
|
|
12617
|
+
* Paginated mounts assemble the windows off-screen and paginate once at the end, since
|
|
12618
|
+
* pagination is a one-shot flow over the whole document; the main thread is still free
|
|
12619
|
+
* between windows, and `onProgress` lets a host show the fill.
|
|
12620
|
+
*
|
|
12621
|
+
* A bundle that predates the windowed renders mounts synchronously, exactly like {@link open}.
|
|
12622
|
+
*/
|
|
12623
|
+
static async openAsync(container, bytes, exports, options = {}) {
|
|
12624
|
+
const bridge = exports.DocxSessionBridge;
|
|
12625
|
+
if (typeof bridge.RenderEditorChromeHtml !== "function" || typeof bridge.RenderEditorRangeHtml !== "function" || typeof bridge.ListRenderedBlocks !== "function") {
|
|
12626
|
+
return _DocxEditor.open(container, bytes, exports, options);
|
|
12627
|
+
}
|
|
12628
|
+
const opts = _DocxEditor.resolveOptions(options);
|
|
12629
|
+
const editor = _DocxEditor.openSession(container, bytes, exports, opts);
|
|
12630
|
+
try {
|
|
12631
|
+
editor.refreshAnchorMap();
|
|
12632
|
+
if (opts.headerFooter) editor.createRegion();
|
|
12633
|
+
await editor.mountWindowed(
|
|
12634
|
+
Math.max(1, Math.floor(options.windowSize ?? 24)),
|
|
12635
|
+
options.onProgress
|
|
12636
|
+
);
|
|
12637
|
+
editor.finishMount();
|
|
12638
|
+
return editor;
|
|
12639
|
+
} catch (error) {
|
|
12640
|
+
editor.close();
|
|
12641
|
+
throw error;
|
|
12642
|
+
}
|
|
12643
|
+
}
|
|
12644
|
+
static resolveOptions(options) {
|
|
12645
|
+
return {
|
|
12351
12646
|
cssPrefix: options.cssPrefix ?? "docx-",
|
|
12352
12647
|
fabricateClasses: options.fabricateClasses ?? false,
|
|
12353
12648
|
editable: options.editable ?? true,
|
|
@@ -12366,25 +12661,100 @@ var DocxEditor = class _DocxEditor {
|
|
|
12366
12661
|
onStoryChange: options.onStoryChange,
|
|
12367
12662
|
onCommentsChange: options.onCommentsChange
|
|
12368
12663
|
};
|
|
12664
|
+
}
|
|
12665
|
+
static openSession(container, bytes, exports, opts) {
|
|
12369
12666
|
const handle = exports.DocxSessionBridge.OpenSession(bytes, JSON.stringify({
|
|
12370
12667
|
emitMarkdownPatch: false,
|
|
12371
12668
|
trackedChanges: trackedChangeWireName(opts.trackedChanges),
|
|
12372
12669
|
revisionAuthor: opts.revisionAuthor
|
|
12373
12670
|
}));
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
|
|
12671
|
+
return new _DocxEditor(container, exports, handle, opts);
|
|
12672
|
+
}
|
|
12673
|
+
/** The steps every mount ends with once the body is in the DOM. */
|
|
12674
|
+
finishMount() {
|
|
12675
|
+
this.syncRegionToBody();
|
|
12676
|
+
this.setupBlockDrag();
|
|
12677
|
+
if (this.options.comments) this.createGutter();
|
|
12678
|
+
}
|
|
12679
|
+
/**
|
|
12680
|
+
* The windowed mount behind {@link openAsync}: chrome first, then body units in plan order,
|
|
12681
|
+
* a group-aligned window per task. See {@link openAsync} for the contract.
|
|
12682
|
+
*/
|
|
12683
|
+
async mountWindowed(windowSize, onProgress) {
|
|
12684
|
+
const bridge = this.exports.DocxSessionBridge;
|
|
12685
|
+
const profile = JSON.stringify({ ...JSON.parse(this.editorRenderProfile()), stampAnchors: true });
|
|
12686
|
+
const chrome = bridge.RenderEditorChromeHtml(this.handle, profile);
|
|
12687
|
+
if (chrome.trimStart().startsWith("{")) {
|
|
12688
|
+
throw new Error(JSON.parse(chrome).error ?? "chrome render failed");
|
|
12689
|
+
}
|
|
12690
|
+
const parsed = new DOMParser().parseFromString(chrome, "text/html");
|
|
12691
|
+
parsed.body.querySelectorAll(`[data-section-index] > [data-anchor="${CHROME_CARRIER_ANCHOR}"]`).forEach((el) => el.remove());
|
|
12692
|
+
const styles = Array.from(parsed.querySelectorAll("style")).map((s) => s.outerHTML).join("");
|
|
12693
|
+
const flow = document.createElement("div");
|
|
12694
|
+
flow.className = "docx-body-flow";
|
|
12695
|
+
flow.innerHTML = parsed.body.innerHTML;
|
|
12696
|
+
const hosts = /* @__PURE__ */ new Map();
|
|
12697
|
+
flow.querySelectorAll("[data-section-index]").forEach((el) => hosts.set(Number(el.getAttribute("data-section-index")), el));
|
|
12698
|
+
const attachNow = !this.options.paginated;
|
|
12699
|
+
const wireNow = attachNow && this.options.editable;
|
|
12700
|
+
if (wireNow) this.wireBlocks(flow);
|
|
12701
|
+
if (attachNow) {
|
|
12702
|
+
this.region?.detachPages();
|
|
12703
|
+
this.container.innerHTML = styles;
|
|
12704
|
+
this.readoptGutter();
|
|
12705
|
+
this.container.appendChild(flow);
|
|
12706
|
+
this.editRoot = flow;
|
|
12707
|
+
}
|
|
12708
|
+
const plan = JSON.parse(this.renderPlanJson());
|
|
12709
|
+
if (plan.error) throw new Error(plan.error);
|
|
12710
|
+
const units = plan.body;
|
|
12711
|
+
const sectionOf = new Map(units.map((u) => [unidOf(u.id), u.section ?? 0]));
|
|
12712
|
+
const mounted = /* @__PURE__ */ new Set();
|
|
12713
|
+
const place = (el, sameHostAs) => {
|
|
12714
|
+
el.removeAttribute("xmlns");
|
|
12715
|
+
const unit = el.hasAttribute("data-anchor") ? el : el.querySelector("[data-anchor]");
|
|
12716
|
+
const unid = unit?.getAttribute("data-anchor") ?? "";
|
|
12717
|
+
const host = sameHostAs ?? hosts.get(sectionOf.get(unid) ?? 0) ?? hosts.values().next().value ?? flow;
|
|
12718
|
+
host.insertBefore(el, host.querySelector(":scope > section.endnotes"));
|
|
12719
|
+
if (wireNow) {
|
|
12720
|
+
if (el.hasAttribute("data-anchor")) this.wireBlock(el);
|
|
12721
|
+
this.wireBlocks(el);
|
|
12722
|
+
}
|
|
12723
|
+
unit && mounted.add(unid);
|
|
12724
|
+
el.querySelectorAll("[data-anchor]").forEach((n) => mounted.add(n.getAttribute("data-anchor")));
|
|
12725
|
+
return host;
|
|
12726
|
+
};
|
|
12727
|
+
for (let start2 = 0; start2 < units.length; ) {
|
|
12728
|
+
let end = Math.min(start2 + windowSize, units.length);
|
|
12729
|
+
while (end < units.length && units[end].group !== void 0 && units[end].group === units[end - 1].group) end++;
|
|
12730
|
+
const window2 = units.slice(start2, end);
|
|
12731
|
+
const rendered = JSON.parse(bridge.RenderEditorRangeHtml(
|
|
12732
|
+
this.handle,
|
|
12733
|
+
JSON.stringify(window2.map((u) => u.id)),
|
|
12734
|
+
profile
|
|
12735
|
+
));
|
|
12736
|
+
if (!Array.isArray(rendered)) throw new Error(rendered.error ?? "window render failed");
|
|
12737
|
+
for (const html of rendered) {
|
|
12738
|
+
let host;
|
|
12739
|
+
for (const el of Array.from(new DOMParser().parseFromString(html, "text/html").body.children)) {
|
|
12740
|
+
host = place(el, host);
|
|
12741
|
+
}
|
|
12742
|
+
}
|
|
12743
|
+
for (const unit of window2) {
|
|
12744
|
+
if (mounted.has(unidOf(unit.id))) continue;
|
|
12745
|
+
const el = this.renderInto(unit.id);
|
|
12746
|
+
if (el) place(el);
|
|
12747
|
+
}
|
|
12748
|
+
start2 = end;
|
|
12749
|
+
onProgress?.(start2, units.length);
|
|
12750
|
+
if (start2 < units.length) await yieldToEventLoop();
|
|
12751
|
+
}
|
|
12752
|
+
if (attachNow) {
|
|
12753
|
+
this.stampPlanState();
|
|
12754
|
+
if (this.region) this.dockBands(flow);
|
|
12755
|
+
this.viewport.attach(flow, true);
|
|
12756
|
+
} else {
|
|
12757
|
+
this.mountPaginated(parsed.head.innerHTML + flow.innerHTML);
|
|
12388
12758
|
}
|
|
12389
12759
|
}
|
|
12390
12760
|
/**
|
|
@@ -19696,6 +20066,7 @@ export {
|
|
|
19696
20066
|
generateAnnotationVisibilityCss,
|
|
19697
20067
|
generatePackageManifest,
|
|
19698
20068
|
getAnnotations,
|
|
20069
|
+
getComments,
|
|
19699
20070
|
getDocumentMetadata,
|
|
19700
20071
|
getDocumentStructure,
|
|
19701
20072
|
getParagraphs,
|