web-doc 0.6.2 → 0.7.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/THIRD_PARTY_NOTICES.md +26 -1
- package/dist/adapters/docx-images.d.ts +13 -4
- package/dist/adapters/docx-images.js +3 -0
- package/dist/adapters/docx-paragraphs.d.ts +65 -0
- package/dist/adapters/docx-paragraphs.js +165 -0
- package/dist/adapters/docx-prepass.d.ts +17 -0
- package/dist/adapters/docx-prepass.js +230 -0
- package/dist/adapters/office.d.ts +31 -5
- package/dist/adapters/office.js +60 -29
- package/dist/adapters/pdf.d.ts +9 -0
- package/dist/adapters/pdf.js +10 -0
- package/dist/assets/pdfium/pdfium.wasm +0 -0
- package/dist/contracts.d.ts +47 -2
- package/dist/edit/assets.d.ts +23 -0
- package/dist/edit/assets.js +75 -0
- package/dist/edit/docx/elements.d.ts +6 -0
- package/dist/edit/docx/elements.js +90 -0
- package/dist/edit/docx/engine.d.ts +51 -0
- package/dist/edit/docx/engine.js +473 -0
- package/dist/edit/docx/handlers.d.ts +3 -0
- package/dist/edit/docx/handlers.js +15 -0
- package/dist/edit/docx/ids.d.ts +45 -0
- package/dist/edit/docx/ids.js +101 -0
- package/dist/edit/docx/model.d.ts +92 -0
- package/dist/edit/docx/model.js +339 -0
- package/dist/edit/docx/operations.d.ts +37 -0
- package/dist/edit/docx/operations.js +3 -0
- package/dist/edit/docx/provider.d.ts +13 -0
- package/dist/edit/docx/provider.js +34 -0
- package/dist/edit/docx/schemas.d.ts +6 -0
- package/dist/edit/docx/schemas.js +192 -0
- package/dist/edit/docx/session.d.ts +37 -0
- package/dist/edit/docx/session.js +426 -0
- package/dist/edit/docx/structure-ops.d.ts +6 -0
- package/dist/edit/docx/structure-ops.js +494 -0
- package/dist/edit/docx/style.d.ts +45 -0
- package/dist/edit/docx/style.js +375 -0
- package/dist/edit/docx/table-ops.d.ts +4 -0
- package/dist/edit/docx/table-ops.js +219 -0
- package/dist/edit/docx/text-ops.d.ts +18 -0
- package/dist/edit/docx/text-ops.js +458 -0
- package/dist/edit/docx/text.d.ts +34 -0
- package/dist/edit/docx/text.js +263 -0
- package/dist/edit/docx/types.d.ts +191 -0
- package/dist/edit/docx/types.js +1 -0
- package/dist/edit/docx/write.d.ts +50 -0
- package/dist/edit/docx/write.js +352 -0
- package/dist/edit/engine.d.ts +117 -0
- package/dist/edit/engine.js +1 -0
- package/dist/edit/history.d.ts +53 -0
- package/dist/edit/history.js +101 -0
- package/dist/edit/ooxml/names.d.ts +20 -0
- package/dist/edit/ooxml/names.js +61 -0
- package/dist/edit/ooxml/opc.d.ts +50 -0
- package/dist/edit/ooxml/opc.js +150 -0
- package/dist/edit/ooxml/package.d.ts +82 -0
- package/dist/edit/ooxml/package.js +233 -0
- package/dist/edit/ooxml/patch.d.ts +51 -0
- package/dist/edit/ooxml/patch.js +250 -0
- package/dist/edit/ooxml/transaction.d.ts +39 -0
- package/dist/edit/ooxml/transaction.js +316 -0
- package/dist/edit/ooxml/worker.d.ts +8 -0
- package/dist/edit/ooxml/worker.js +12 -0
- package/dist/edit/ooxml/writer.d.ts +21 -0
- package/dist/edit/ooxml/writer.js +187 -0
- package/dist/edit/ooxml/xml.d.ts +74 -0
- package/dist/edit/ooxml/xml.js +451 -0
- package/dist/edit/ooxml/zip.d.ts +54 -0
- package/dist/edit/ooxml/zip.js +280 -0
- package/dist/edit/operations.d.ts +19 -0
- package/dist/edit/operations.js +137 -0
- package/dist/edit/pdf/engine/compact.d.ts +6 -0
- package/dist/edit/pdf/engine/compact.js +442 -0
- package/dist/edit/pdf/engine/document.d.ts +95 -0
- package/dist/edit/pdf/engine/document.js +868 -0
- package/dist/edit/pdf/engine/elements.d.ts +45 -0
- package/dist/edit/pdf/engine/elements.js +313 -0
- package/dist/edit/pdf/engine/existing-text.d.ts +4 -0
- package/dist/edit/pdf/engine/existing-text.js +424 -0
- package/dist/edit/pdf/engine/fonts.d.ts +78 -0
- package/dist/edit/pdf/engine/fonts.js +466 -0
- package/dist/edit/pdf/engine/geometry.d.ts +36 -0
- package/dist/edit/pdf/engine/geometry.js +97 -0
- package/dist/edit/pdf/engine/handler.d.ts +21 -0
- package/dist/edit/pdf/engine/handler.js +108 -0
- package/dist/edit/pdf/engine/images.d.ts +33 -0
- package/dist/edit/pdf/engine/images.js +188 -0
- package/dist/edit/pdf/engine/layout.d.ts +23 -0
- package/dist/edit/pdf/engine/layout.js +177 -0
- package/dist/edit/pdf/engine/operations.d.ts +67 -0
- package/dist/edit/pdf/engine/operations.js +3 -0
- package/dist/edit/pdf/engine/pages.d.ts +6 -0
- package/dist/edit/pdf/engine/pages.js +98 -0
- package/dist/edit/pdf/engine/pdfium.d.ts +195 -0
- package/dist/edit/pdf/engine/pdfium.js +249 -0
- package/dist/edit/pdf/engine/shapes.d.ts +4 -0
- package/dist/edit/pdf/engine/shapes.js +183 -0
- package/dist/edit/pdf/engine/tables.d.ts +44 -0
- package/dist/edit/pdf/engine/tables.js +315 -0
- package/dist/edit/pdf/engine/text-box.d.ts +71 -0
- package/dist/edit/pdf/engine/text-box.js +317 -0
- package/dist/edit/pdf/engine/text-layout.d.ts +28 -0
- package/dist/edit/pdf/engine/text-layout.js +67 -0
- package/dist/edit/pdf/engine/transform.d.ts +5 -0
- package/dist/edit/pdf/engine/transform.js +137 -0
- package/dist/edit/pdf/provider.d.ts +35 -0
- package/dist/edit/pdf/provider.js +92 -0
- package/dist/edit/pdf/range-map.d.ts +14 -0
- package/dist/edit/pdf/range-map.js +107 -0
- package/dist/edit/pdf/schemas.d.ts +11 -0
- package/dist/edit/pdf/schemas.js +291 -0
- package/dist/edit/pdf/selection.d.ts +5 -0
- package/dist/edit/pdf/selection.js +152 -0
- package/dist/edit/pdf/session.d.ts +53 -0
- package/dist/edit/pdf/session.js +273 -0
- package/dist/edit/pdf/types.d.ts +336 -0
- package/dist/edit/pdf/types.js +1 -0
- package/dist/edit/pptx/elements.d.ts +74 -0
- package/dist/edit/pptx/elements.js +301 -0
- package/dist/edit/pptx/engine.d.ts +37 -0
- package/dist/edit/pptx/engine.js +466 -0
- package/dist/edit/pptx/geometry.d.ts +72 -0
- package/dist/edit/pptx/geometry.js +193 -0
- package/dist/edit/pptx/handler.d.ts +7 -0
- package/dist/edit/pptx/handler.js +91 -0
- package/dist/edit/pptx/handlers.d.ts +3 -0
- package/dist/edit/pptx/handlers.js +21 -0
- package/dist/edit/pptx/image-table-ops.d.ts +5 -0
- package/dist/edit/pptx/image-table-ops.js +233 -0
- package/dist/edit/pptx/model.d.ts +69 -0
- package/dist/edit/pptx/model.js +170 -0
- package/dist/edit/pptx/operations.d.ts +50 -0
- package/dist/edit/pptx/operations.js +11 -0
- package/dist/edit/pptx/provider.d.ts +17 -0
- package/dist/edit/pptx/provider.js +40 -0
- package/dist/edit/pptx/schemas.d.ts +6 -0
- package/dist/edit/pptx/schemas.js +220 -0
- package/dist/edit/pptx/session.d.ts +44 -0
- package/dist/edit/pptx/session.js +114 -0
- package/dist/edit/pptx/shape-ops.d.ts +10 -0
- package/dist/edit/pptx/shape-ops.js +486 -0
- package/dist/edit/pptx/slide-ops.d.ts +6 -0
- package/dist/edit/pptx/slide-ops.js +353 -0
- package/dist/edit/pptx/style.d.ts +31 -0
- package/dist/edit/pptx/style.js +181 -0
- package/dist/edit/pptx/text-ops.d.ts +13 -0
- package/dist/edit/pptx/text-ops.js +267 -0
- package/dist/edit/pptx/text-write.d.ts +67 -0
- package/dist/edit/pptx/text-write.js +293 -0
- package/dist/edit/pptx/text.d.ts +41 -0
- package/dist/edit/pptx/text.js +99 -0
- package/dist/edit/pptx/types.d.ts +232 -0
- package/dist/edit/pptx/types.js +1 -0
- package/dist/edit/schema.d.ts +11 -0
- package/dist/edit/schema.js +275 -0
- package/dist/edit/session.d.ts +66 -0
- package/dist/edit/session.js +701 -0
- package/dist/edit/sessions.d.ts +8 -0
- package/dist/edit/sessions.js +1 -0
- package/dist/edit/types.d.ts +276 -0
- package/dist/edit/types.js +1 -0
- package/dist/edit/worker-engine.d.ts +31 -0
- package/dist/edit/worker-engine.js +91 -0
- package/dist/fonts/THIRD_PARTY_NOTICES.md +3 -0
- package/dist/fonts/manifest.json +6 -1
- package/dist/fonts/noto-sans-latin-cyrillic.ttf +0 -0
- package/dist/fonts.d.ts +2 -0
- package/dist/fonts.js +4 -0
- package/dist/headless.d.ts +4 -0
- package/dist/headless.js +4 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/limits.js +3 -0
- package/dist/ooxml-edit-worker.d.ts +1 -0
- package/dist/ooxml-edit-worker.js +8 -0
- package/dist/pdf-edit-worker.d.ts +1 -0
- package/dist/pdf-edit-worker.js +35 -0
- package/dist/spreadsheet-viewport.d.ts +5 -0
- package/dist/spreadsheet-viewport.js +11 -0
- package/dist/ui.js +7 -0
- package/dist/viewer.d.ts +6 -0
- package/dist/viewer.js +293 -19
- package/dist/viewport.d.ts +13 -0
- package/dist/viewport.js +126 -1
- package/dist/worker-protocol.d.ts +39 -2
- package/dist/workers/ooxml-edit-worker.js +8671 -0
- package/dist/workers/pdf-edit-worker.js +10844 -0
- package/package.json +3 -3
package/dist/viewer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EditSessionController, } from "./edit/session.js";
|
|
1
2
|
import { linkedAbortController } from "./abort.js";
|
|
2
3
|
import { detectFormat } from "./detect.js";
|
|
3
4
|
import { abortError, normalizeError, ViewerError } from "./errors.js";
|
|
@@ -28,6 +29,12 @@ export class DocumentViewer {
|
|
|
28
29
|
#info;
|
|
29
30
|
#original;
|
|
30
31
|
#originalFileName;
|
|
32
|
+
#originalContentType;
|
|
33
|
+
/** Limits the current document was opened with; reused when it is reopened. */
|
|
34
|
+
#limits;
|
|
35
|
+
#session;
|
|
36
|
+
/** Shared by concurrent `edit()` calls while the engine starts. */
|
|
37
|
+
#sessionStart;
|
|
31
38
|
#activeLoad;
|
|
32
39
|
#activeSearch;
|
|
33
40
|
#selection = null;
|
|
@@ -45,6 +52,7 @@ export class DocumentViewer {
|
|
|
45
52
|
constructor(options, runtime) {
|
|
46
53
|
this.#options = options;
|
|
47
54
|
this.#runtime = runtime;
|
|
55
|
+
this.#limits = runtime.limits;
|
|
48
56
|
this.#state = freezeState({
|
|
49
57
|
status: "idle",
|
|
50
58
|
pageIndex: 0,
|
|
@@ -77,6 +85,7 @@ export class DocumentViewer {
|
|
|
77
85
|
onTextSelection: (range) => void this.selectText(range),
|
|
78
86
|
onCellSelection: (selection) => this.#applyInteractiveCellSelection(selection),
|
|
79
87
|
getSelectionText: () => this.#getCachedSelectionText(),
|
|
88
|
+
onPainted: (pages, revision) => this.#onPainted(pages, revision),
|
|
80
89
|
}, options);
|
|
81
90
|
}
|
|
82
91
|
}
|
|
@@ -151,31 +160,21 @@ export class DocumentViewer {
|
|
|
151
160
|
await adapter.close(handle);
|
|
152
161
|
throw abortError();
|
|
153
162
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
backendInfo.
|
|
163
|
+
let info;
|
|
164
|
+
try {
|
|
165
|
+
info = describeDocument(adapter, backendInfo, detection.format, limits);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
157
168
|
await adapter.close(handle);
|
|
158
|
-
throw
|
|
159
|
-
details: {
|
|
160
|
-
pageCount: backendInfo.pageCount,
|
|
161
|
-
limit: limits.maxDocumentUnits,
|
|
162
|
-
},
|
|
163
|
-
});
|
|
169
|
+
throw error;
|
|
164
170
|
}
|
|
165
|
-
const info = immutableInfo({
|
|
166
|
-
...backendInfo,
|
|
167
|
-
capabilities: {
|
|
168
|
-
textSelection: Boolean(adapter.getTextMap),
|
|
169
|
-
cellSelection: backendInfo.unit === "sheet",
|
|
170
|
-
search: Boolean(adapter.getTextMap),
|
|
171
|
-
thumbnails: backendInfo.unit !== "sheet",
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
171
|
this.#adapter = adapter;
|
|
175
172
|
this.#handle = handle;
|
|
176
173
|
this.#info = info;
|
|
177
174
|
this.#original = loaded.bytes;
|
|
178
175
|
this.#originalFileName = fileName;
|
|
176
|
+
this.#originalContentType = contentType;
|
|
177
|
+
this.#limits = limits;
|
|
179
178
|
this.#update({
|
|
180
179
|
status: "ready",
|
|
181
180
|
format: detection.format,
|
|
@@ -671,6 +670,45 @@ export class DocumentViewer {
|
|
|
671
670
|
}
|
|
672
671
|
return blob;
|
|
673
672
|
}
|
|
673
|
+
async edit(options = {}) {
|
|
674
|
+
const { adapter, info } = this.#assertReady();
|
|
675
|
+
if (this.#session?.core.usable)
|
|
676
|
+
return this.#session.session;
|
|
677
|
+
if (this.#sessionStart)
|
|
678
|
+
return this.#sessionStart;
|
|
679
|
+
const format = editableFormat(adapter, info.format);
|
|
680
|
+
if (!format || !adapter.edit)
|
|
681
|
+
throw new ViewerError("edit-unsupported", "Editing is not available for this document", { details: { format: info.format, reason: "no-engine" } });
|
|
682
|
+
const start = this.#startSession(adapter.edit, format, options);
|
|
683
|
+
this.#sessionStart = start;
|
|
684
|
+
try {
|
|
685
|
+
return await start;
|
|
686
|
+
}
|
|
687
|
+
finally {
|
|
688
|
+
if (this.#sessionStart === start)
|
|
689
|
+
this.#sessionStart = undefined;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
getEditSession() {
|
|
693
|
+
this.#assertAlive();
|
|
694
|
+
return this.#session?.session;
|
|
695
|
+
}
|
|
696
|
+
pageToClient(pageIndex, rect) {
|
|
697
|
+
this.#assertAlive();
|
|
698
|
+
if (this.#state.status !== "ready" ||
|
|
699
|
+
!Number.isInteger(pageIndex) ||
|
|
700
|
+
![rect.x, rect.y, rect.width, rect.height].every(Number.isFinite))
|
|
701
|
+
return undefined;
|
|
702
|
+
return this.#viewport?.pageToClient(pageIndex, rect);
|
|
703
|
+
}
|
|
704
|
+
clientToPage(clientX, clientY) {
|
|
705
|
+
this.#assertAlive();
|
|
706
|
+
if (this.#state.status !== "ready" ||
|
|
707
|
+
!Number.isFinite(clientX) ||
|
|
708
|
+
!Number.isFinite(clientY))
|
|
709
|
+
return undefined;
|
|
710
|
+
return this.#viewport?.clientToPage(clientX, clientY);
|
|
711
|
+
}
|
|
674
712
|
on(type, listener) {
|
|
675
713
|
this.#assertAlive();
|
|
676
714
|
const listeners = this.#listeners.get(type) ?? new Set();
|
|
@@ -700,6 +738,194 @@ export class DocumentViewer {
|
|
|
700
738
|
this.#listeners.clear();
|
|
701
739
|
this.#runtime.release(this);
|
|
702
740
|
}
|
|
741
|
+
async #startSession(provider, format, options) {
|
|
742
|
+
const generation = this.#generation;
|
|
743
|
+
const operation = this.#startOperation(options.signal);
|
|
744
|
+
// A session that broke (failed recovery) makes way for a fresh engine.
|
|
745
|
+
const stale = this.#session;
|
|
746
|
+
this.#session = undefined;
|
|
747
|
+
if (stale)
|
|
748
|
+
await stale.core.end();
|
|
749
|
+
try {
|
|
750
|
+
const engine = await provider.load(this.#original.slice(), {
|
|
751
|
+
format,
|
|
752
|
+
limits: this.#limits,
|
|
753
|
+
fonts: this.#runtime.fonts.registered,
|
|
754
|
+
signal: operation.signal,
|
|
755
|
+
...(this.#originalFileName ? { fileName: this.#originalFileName } : {}),
|
|
756
|
+
...(this.#runtime.assetBaseUrl
|
|
757
|
+
? { assetBaseUrl: this.#runtime.assetBaseUrl }
|
|
758
|
+
: {}),
|
|
759
|
+
});
|
|
760
|
+
if (generation !== this.#generation || operation.signal.aborted) {
|
|
761
|
+
await engine.dispose().catch(() => undefined);
|
|
762
|
+
throw abortError();
|
|
763
|
+
}
|
|
764
|
+
const host = {
|
|
765
|
+
format,
|
|
766
|
+
limits: this.#limits,
|
|
767
|
+
prepareDocument: (bytes, signal) => this.#prepareDocument(bytes, signal),
|
|
768
|
+
commitDocument: (prepared, changedPages) => this.#commitDocument(prepared, changedPages),
|
|
769
|
+
discardDocument: (prepared) => this.#discardDocument(prepared),
|
|
770
|
+
emit: (type, event) => this.#emit(type, event),
|
|
771
|
+
pageOf: (paragraphId) => {
|
|
772
|
+
let first;
|
|
773
|
+
for (const [pageIndex, runs] of this.#textMaps)
|
|
774
|
+
if ((first === undefined || pageIndex < first) &&
|
|
775
|
+
runs.some((run) => run.paragraphId === paragraphId))
|
|
776
|
+
first = pageIndex;
|
|
777
|
+
return first;
|
|
778
|
+
},
|
|
779
|
+
};
|
|
780
|
+
const core = new EditSessionController(engine, host, this.#original, this.#info.pageCount);
|
|
781
|
+
const session = provider.createSession(core, {
|
|
782
|
+
getTextRuns: (pageIndex, signal) => this.#getTextRuns(pageIndex, signal),
|
|
783
|
+
cachedPages: () => [...this.#textMaps.keys()],
|
|
784
|
+
});
|
|
785
|
+
this.#session = { core, session };
|
|
786
|
+
this.#emit("editstatechange", {
|
|
787
|
+
...core.state,
|
|
788
|
+
active: true,
|
|
789
|
+
format,
|
|
790
|
+
});
|
|
791
|
+
return session;
|
|
792
|
+
}
|
|
793
|
+
catch (error) {
|
|
794
|
+
const normalized = normalizeError(error, "edit-failed");
|
|
795
|
+
throw normalized.code === "edit-failed" && !normalized.details
|
|
796
|
+
? new ViewerError("edit-failed", normalized.message, {
|
|
797
|
+
cause: error,
|
|
798
|
+
details: { stage: "load" },
|
|
799
|
+
})
|
|
800
|
+
: normalized;
|
|
801
|
+
}
|
|
802
|
+
finally {
|
|
803
|
+
this.#finishOperation(operation);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Shows edited bytes as the current document: opens them through the
|
|
808
|
+
* adapter, swaps the handle, drops every cache derived from the old content
|
|
809
|
+
* and keeps the view where it was. Returns the new page count.
|
|
810
|
+
*/
|
|
811
|
+
/**
|
|
812
|
+
* Phase one of showing edited bytes: opens them next to the current
|
|
813
|
+
* document. Everything that can fail or be aborted happens here.
|
|
814
|
+
*/
|
|
815
|
+
async #prepareDocument(bytes, signal) {
|
|
816
|
+
const { adapter, handle, info } = this.#assertReady();
|
|
817
|
+
const generation = this.#generation;
|
|
818
|
+
enforceContainerLimits(bytes, info.format, this.#limits);
|
|
819
|
+
const context = {
|
|
820
|
+
format: info.format,
|
|
821
|
+
signal,
|
|
822
|
+
limits: this.#limits,
|
|
823
|
+
reportProgress: (progress) => this.#emit("progress", progress),
|
|
824
|
+
reportWarning: (warning) => this.#emit("warning", warning),
|
|
825
|
+
...(this.#originalFileName ? { fileName: this.#originalFileName } : {}),
|
|
826
|
+
...(this.#originalContentType
|
|
827
|
+
? { contentType: this.#originalContentType }
|
|
828
|
+
: {}),
|
|
829
|
+
...(this.#runtime.assetBaseUrl
|
|
830
|
+
? { assetBaseUrl: this.#runtime.assetBaseUrl }
|
|
831
|
+
: {}),
|
|
832
|
+
};
|
|
833
|
+
const next = adapter.reopen
|
|
834
|
+
? await adapter.reopen(handle, bytes, context)
|
|
835
|
+
: await adapter.open(bytes, context);
|
|
836
|
+
let nextInfo;
|
|
837
|
+
try {
|
|
838
|
+
if (generation !== this.#generation || signal.aborted)
|
|
839
|
+
throw abortError();
|
|
840
|
+
const backendInfo = await adapter.getInfo(next);
|
|
841
|
+
if (generation !== this.#generation || signal.aborted)
|
|
842
|
+
throw abortError();
|
|
843
|
+
nextInfo = describeDocument(adapter, backendInfo, info.format, this.#limits);
|
|
844
|
+
}
|
|
845
|
+
catch (error) {
|
|
846
|
+
await adapter.close(next);
|
|
847
|
+
throw error;
|
|
848
|
+
}
|
|
849
|
+
return {
|
|
850
|
+
pageCount: nextInfo.pageCount,
|
|
851
|
+
handle: next,
|
|
852
|
+
info: nextInfo,
|
|
853
|
+
generation,
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Phase two: swaps the prepared document in. Synchronous and never throws
|
|
858
|
+
* for a preparation of the current document, so a session that reached
|
|
859
|
+
* this point always completes; the old handle is closed in the background.
|
|
860
|
+
*/
|
|
861
|
+
#commitDocument(prepared, changedPages) {
|
|
862
|
+
if (prepared.generation !== this.#generation || !this.#handle) {
|
|
863
|
+
this.#discardDocument(prepared);
|
|
864
|
+
throw new ViewerError("lifecycle-error", "The document was replaced while an edit was being shown");
|
|
865
|
+
}
|
|
866
|
+
const { adapter, handle: previous } = this.#assertReady();
|
|
867
|
+
this.#handle = prepared.handle;
|
|
868
|
+
this.#info = prepared.info;
|
|
869
|
+
this.#invalidateContentCaches();
|
|
870
|
+
this.#update({
|
|
871
|
+
pageCount: prepared.info.pageCount,
|
|
872
|
+
pageIndex: Math.min(this.#state.pageIndex, prepared.info.pageCount - 1),
|
|
873
|
+
});
|
|
874
|
+
for (const warning of prepared.info.warnings ?? [])
|
|
875
|
+
this.#emit("warning", warning);
|
|
876
|
+
const revision = (this.#session?.core.state.revision ?? 0) + 1;
|
|
877
|
+
if (this.#viewport)
|
|
878
|
+
this.#viewport.replaceDocument(prepared.info, changedPages, revision);
|
|
879
|
+
else
|
|
880
|
+
// Headless: nothing paints, so geometry is "current" as soon as the
|
|
881
|
+
// session has emitted documentchange, which happens before the next
|
|
882
|
+
// macrotask.
|
|
883
|
+
setTimeout(() => this.#onPainted([...changedPages], revision), 0);
|
|
884
|
+
void Promise.resolve(adapter.close(previous)).catch((error) => this.#reportError(error));
|
|
885
|
+
return prepared.info.pageCount;
|
|
886
|
+
}
|
|
887
|
+
#discardDocument(prepared) {
|
|
888
|
+
void Promise.resolve(this.#adapter?.close(prepared.handle)).catch((error) => this.#reportError(error));
|
|
889
|
+
}
|
|
890
|
+
/** Painted pages of a content revision become a `layoutchange` while a session is active. */
|
|
891
|
+
#onPainted(pages, revision) {
|
|
892
|
+
const session = this.#session;
|
|
893
|
+
// The viewport reports only paints of its current content, so a revision
|
|
894
|
+
// the session has not committed yet is the only thing to drop.
|
|
895
|
+
if (!session || revision > session.core.state.revision)
|
|
896
|
+
return;
|
|
897
|
+
this.#emit("layoutchange", {
|
|
898
|
+
sessionId: session.core.sessionId,
|
|
899
|
+
revision,
|
|
900
|
+
pages: Object.freeze([...pages]),
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
#reportError(error) {
|
|
904
|
+
const report = globalThis
|
|
905
|
+
.reportError;
|
|
906
|
+
if (report)
|
|
907
|
+
report(error);
|
|
908
|
+
else
|
|
909
|
+
console.error(error);
|
|
910
|
+
}
|
|
911
|
+
/** Forgets everything derived from the document's content, not from its view. */
|
|
912
|
+
#invalidateContentCaches() {
|
|
913
|
+
this.#textMaps.clear();
|
|
914
|
+
this.#textMapBytes = 0;
|
|
915
|
+
// The worker keeps its index; a stale key makes the next search rebuild it.
|
|
916
|
+
this.#fuzzyIndexKey = undefined;
|
|
917
|
+
this.#activeSearch?.abort();
|
|
918
|
+
this.#activeSearch = undefined;
|
|
919
|
+
this.#searchGeneration += 1;
|
|
920
|
+
if (this.#searchResult) {
|
|
921
|
+
this.#searchResult = null;
|
|
922
|
+
this.#emit("searchchange", null);
|
|
923
|
+
}
|
|
924
|
+
if (this.#selection) {
|
|
925
|
+
this.#selection = null;
|
|
926
|
+
this.#emit("selectionchange", null);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
703
929
|
async #getTextRuns(pageIndex, signal) {
|
|
704
930
|
const { adapter, handle, info } = this.#assertReady();
|
|
705
931
|
assertPageIndex(pageIndex, info.pageCount);
|
|
@@ -779,6 +1005,11 @@ export class DocumentViewer {
|
|
|
779
1005
|
this.#update({ panX: x, panY: y });
|
|
780
1006
|
}
|
|
781
1007
|
async #closeDocument() {
|
|
1008
|
+
const session = this.#session;
|
|
1009
|
+
this.#session = undefined;
|
|
1010
|
+
this.#sessionStart = undefined;
|
|
1011
|
+
if (session)
|
|
1012
|
+
await session.core.end();
|
|
782
1013
|
const adapter = this.#adapter;
|
|
783
1014
|
const handle = this.#handle;
|
|
784
1015
|
this.#adapter = undefined;
|
|
@@ -786,6 +1017,7 @@ export class DocumentViewer {
|
|
|
786
1017
|
this.#info = undefined;
|
|
787
1018
|
this.#original = undefined;
|
|
788
1019
|
this.#originalFileName = undefined;
|
|
1020
|
+
this.#originalContentType = undefined;
|
|
789
1021
|
this.#activeSearch?.abort();
|
|
790
1022
|
this.#activeSearch = undefined;
|
|
791
1023
|
this.#searchResult = null;
|
|
@@ -856,9 +1088,51 @@ export class DocumentViewer {
|
|
|
856
1088
|
}
|
|
857
1089
|
#emit(type, event) {
|
|
858
1090
|
for (const listener of this.#listeners.get(type) ?? [])
|
|
859
|
-
|
|
1091
|
+
try {
|
|
1092
|
+
listener(event);
|
|
1093
|
+
}
|
|
1094
|
+
catch (error) {
|
|
1095
|
+
// A listener's bug is its own; it never fails the call that emitted.
|
|
1096
|
+
this.#reportError(error);
|
|
1097
|
+
}
|
|
860
1098
|
}
|
|
861
1099
|
}
|
|
1100
|
+
/** The edit format of `format` when `adapter` can edit it. */
|
|
1101
|
+
/** The session format of a document format the adapter's provider edits. */
|
|
1102
|
+
function editableFormat(adapter, format) {
|
|
1103
|
+
const formats = adapter.edit?.formats ?? [];
|
|
1104
|
+
return formats.includes(format) ? SESSION_FORMATS[format] : undefined;
|
|
1105
|
+
}
|
|
1106
|
+
const SESSION_FORMATS = {
|
|
1107
|
+
pdf: "pdf",
|
|
1108
|
+
pptx: "pptx",
|
|
1109
|
+
pptm: "pptx",
|
|
1110
|
+
ppsx: "pptx",
|
|
1111
|
+
docx: "docx",
|
|
1112
|
+
docm: "docx",
|
|
1113
|
+
};
|
|
1114
|
+
/** Validates backend info and freezes it with the viewer's capability flags. */
|
|
1115
|
+
function describeDocument(adapter, backendInfo, format, limits) {
|
|
1116
|
+
if (!Number.isInteger(backendInfo.pageCount) ||
|
|
1117
|
+
backendInfo.pageCount < 1 ||
|
|
1118
|
+
backendInfo.pageCount > limits.maxDocumentUnits)
|
|
1119
|
+
throw new ViewerError("resource-limit", "Document unit count exceeds the configured limit", {
|
|
1120
|
+
details: {
|
|
1121
|
+
pageCount: backendInfo.pageCount,
|
|
1122
|
+
limit: limits.maxDocumentUnits,
|
|
1123
|
+
},
|
|
1124
|
+
});
|
|
1125
|
+
return immutableInfo({
|
|
1126
|
+
...backendInfo,
|
|
1127
|
+
capabilities: {
|
|
1128
|
+
textSelection: Boolean(adapter.getTextMap),
|
|
1129
|
+
cellSelection: backendInfo.unit === "sheet",
|
|
1130
|
+
search: Boolean(adapter.getTextMap),
|
|
1131
|
+
thumbnails: backendInfo.unit !== "sheet",
|
|
1132
|
+
editing: editableFormat(adapter, format) !== undefined,
|
|
1133
|
+
},
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
862
1136
|
function clampZoom(value) {
|
|
863
1137
|
if (!Number.isFinite(value))
|
|
864
1138
|
return 1;
|
package/dist/viewport.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CellRange, CellSelection, DocumentInfo, HeadlessRenderOptions, SearchMatch, TextRun, TextSelectionRange, ViewerState, SpreadsheetViewportRange } from "./contracts.js";
|
|
2
|
+
import type { PageHit, PageRect, ViewportRect } from "./edit/types.js";
|
|
2
3
|
export interface ViewportHost {
|
|
3
4
|
readonly state: ViewerState;
|
|
4
5
|
renderPage(pageIndex: number, target: HTMLCanvasElement, options: HeadlessRenderOptions): Promise<void>;
|
|
@@ -12,9 +13,15 @@ export interface ViewportHost {
|
|
|
12
13
|
onTextSelection(range: TextSelectionRange): void;
|
|
13
14
|
onCellSelection(selection: CellRange | CellSelection | null): void;
|
|
14
15
|
getSelectionText(): string | undefined;
|
|
16
|
+
/** Pages whose paint for content revision `revision` just finished. */
|
|
17
|
+
onPainted(pages: readonly number[], revision: number): void;
|
|
15
18
|
}
|
|
16
19
|
interface ViewportStrategy {
|
|
17
20
|
setDocument(info: DocumentInfo | undefined): void;
|
|
21
|
+
/** New content of the same document: keeps zoom and scroll, re-renders. */
|
|
22
|
+
replaceDocument(info: DocumentInfo, changedPages?: readonly number[], revision?: number): void;
|
|
23
|
+
pageToClient(pageIndex: number, rect: PageRect): ViewportRect | undefined;
|
|
24
|
+
clientToPage(clientX: number, clientY: number): PageHit | undefined;
|
|
18
25
|
update(): void;
|
|
19
26
|
panBy(deltaX: number, deltaY: number): void;
|
|
20
27
|
goToPage(pageIndex: number): void;
|
|
@@ -30,6 +37,9 @@ export declare class AdaptiveViewport implements ViewportStrategy {
|
|
|
30
37
|
readonly layout?: "continuous" | "single";
|
|
31
38
|
});
|
|
32
39
|
setDocument(info: DocumentInfo | undefined): void;
|
|
40
|
+
replaceDocument(info: DocumentInfo, changedPages?: readonly number[], revision?: number): void;
|
|
41
|
+
pageToClient(pageIndex: number, rect: PageRect): ViewportRect | undefined;
|
|
42
|
+
clientToPage(clientX: number, clientY: number): PageHit | undefined;
|
|
33
43
|
update(): void;
|
|
34
44
|
panBy(deltaX: number, deltaY: number): void;
|
|
35
45
|
goToPage(pageIndex: number): void;
|
|
@@ -45,6 +55,9 @@ export declare class ViewerViewport {
|
|
|
45
55
|
readonly layout?: "continuous" | "single";
|
|
46
56
|
});
|
|
47
57
|
setDocument(info: DocumentInfo | undefined): void;
|
|
58
|
+
replaceDocument(info: DocumentInfo, changedPages?: readonly number[], revision?: number): void;
|
|
59
|
+
pageToClient(pageIndex: number, rect: PageRect): ViewportRect | undefined;
|
|
60
|
+
clientToPage(clientX: number, clientY: number): PageHit | undefined;
|
|
48
61
|
update(): void;
|
|
49
62
|
panBy(deltaX: number, deltaY: number): void;
|
|
50
63
|
goToPage(pageIndex: number): void;
|
package/dist/viewport.js
CHANGED
|
@@ -30,6 +30,19 @@ export class AdaptiveViewport {
|
|
|
30
30
|
}
|
|
31
31
|
this.#strategy.setDocument(info);
|
|
32
32
|
}
|
|
33
|
+
replaceDocument(info, changedPages, revision) {
|
|
34
|
+
const nextKind = info.unit === "sheet" ? "sheet" : "page";
|
|
35
|
+
if (nextKind !== this.#kind)
|
|
36
|
+
this.setDocument(info);
|
|
37
|
+
else
|
|
38
|
+
this.#strategy.replaceDocument(info, changedPages, revision);
|
|
39
|
+
}
|
|
40
|
+
pageToClient(pageIndex, rect) {
|
|
41
|
+
return this.#strategy.pageToClient(pageIndex, rect);
|
|
42
|
+
}
|
|
43
|
+
clientToPage(clientX, clientY) {
|
|
44
|
+
return this.#strategy.clientToPage(clientX, clientY);
|
|
45
|
+
}
|
|
33
46
|
update() {
|
|
34
47
|
this.#strategy.update();
|
|
35
48
|
}
|
|
@@ -70,6 +83,13 @@ export class ViewerViewport {
|
|
|
70
83
|
#onSelectionChange = () => this.#handleSelectionChange();
|
|
71
84
|
#pointers = new Map();
|
|
72
85
|
#info;
|
|
86
|
+
/** Per page: grows when that page's content changed, so only it re-renders. */
|
|
87
|
+
#pageRevisions = [];
|
|
88
|
+
/** The session revision the shown content belongs to; 0 before any edit. */
|
|
89
|
+
#contentRevision = 0;
|
|
90
|
+
/** Pages painted since the last `onPainted`, keyed by content revision. */
|
|
91
|
+
#painted = new Map();
|
|
92
|
+
#paintedFlush = 0;
|
|
73
93
|
#frame = 0;
|
|
74
94
|
#resizeObserver;
|
|
75
95
|
#destroyed = false;
|
|
@@ -126,11 +146,90 @@ export class ViewerViewport {
|
|
|
126
146
|
}
|
|
127
147
|
setDocument(info) {
|
|
128
148
|
this.#info = info;
|
|
149
|
+
this.#pageRevisions = [];
|
|
150
|
+
this.#contentRevision = 0;
|
|
151
|
+
this.#painted.clear();
|
|
129
152
|
this.#appliedZoom = this.#host.state.zoom;
|
|
130
153
|
this.#root.scrollTo({ left: 0, top: 0 });
|
|
131
154
|
this.#clearSlots();
|
|
132
155
|
this.schedule();
|
|
133
156
|
}
|
|
157
|
+
replaceDocument(info, changedPages, revision) {
|
|
158
|
+
const previous = this.#info;
|
|
159
|
+
this.#info = info;
|
|
160
|
+
this.#contentRevision = revision ?? this.#contentRevision + 1;
|
|
161
|
+
// Only pages whose content or size changed get a new render key; the
|
|
162
|
+
// others keep their bitmaps. A changed page count shifts everything
|
|
163
|
+
// from the first changed page on.
|
|
164
|
+
const countChanged = previous?.pageCount !== info.pageCount;
|
|
165
|
+
const from = changedPages === undefined
|
|
166
|
+
? 0
|
|
167
|
+
: countChanged
|
|
168
|
+
? Math.min(...changedPages, info.pageCount)
|
|
169
|
+
: Number.POSITIVE_INFINITY;
|
|
170
|
+
const changed = new Set(changedPages ?? []);
|
|
171
|
+
for (let pageIndex = 0; pageIndex < info.pageCount; pageIndex += 1) {
|
|
172
|
+
const size = info.pageSizes?.[pageIndex];
|
|
173
|
+
const before = previous?.pageSizes?.[pageIndex];
|
|
174
|
+
const resized = size?.width !== before?.width || size?.height !== before?.height;
|
|
175
|
+
if (pageIndex >= from || changed.has(pageIndex) || resized)
|
|
176
|
+
this.#pageRevisions[pageIndex] =
|
|
177
|
+
(this.#pageRevisions[pageIndex] ?? 0) + 1;
|
|
178
|
+
}
|
|
179
|
+
// Slots stay mounted and repaint in place; the browser clamps the scroll
|
|
180
|
+
// position itself once the spacer takes the new document's height.
|
|
181
|
+
this.schedule();
|
|
182
|
+
}
|
|
183
|
+
pageToClient(pageIndex, rect) {
|
|
184
|
+
const page = this.#mountedPage(pageIndex);
|
|
185
|
+
if (!page)
|
|
186
|
+
return undefined;
|
|
187
|
+
return {
|
|
188
|
+
left: page.left + rect.x * page.scale,
|
|
189
|
+
top: page.top + rect.y * page.scale,
|
|
190
|
+
width: rect.width * page.scale,
|
|
191
|
+
height: rect.height * page.scale,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
clientToPage(clientX, clientY) {
|
|
195
|
+
for (const pageIndex of this.#slots.keys()) {
|
|
196
|
+
const page = this.#mountedPage(pageIndex);
|
|
197
|
+
if (!page ||
|
|
198
|
+
clientX < page.left ||
|
|
199
|
+
clientX >= page.left + page.width ||
|
|
200
|
+
clientY < page.top ||
|
|
201
|
+
clientY >= page.top + page.height)
|
|
202
|
+
continue;
|
|
203
|
+
return {
|
|
204
|
+
pageIndex,
|
|
205
|
+
point: {
|
|
206
|
+
x: (clientX - page.left) / page.scale,
|
|
207
|
+
y: (clientY - page.top) / page.scale,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Client-space box of a mounted page and its page-space scale, read from
|
|
215
|
+
* the DOM so it matches what is painted rather than what is scheduled.
|
|
216
|
+
*/
|
|
217
|
+
#mountedPage(pageIndex) {
|
|
218
|
+
const slot = this.#slots.get(pageIndex);
|
|
219
|
+
if (!slot || !this.#info)
|
|
220
|
+
return undefined;
|
|
221
|
+
const box = slot.root.getBoundingClientRect();
|
|
222
|
+
const natural = naturalPageSize(this.#info, pageIndex);
|
|
223
|
+
if (box.width <= 0 || box.height <= 0)
|
|
224
|
+
return undefined;
|
|
225
|
+
return {
|
|
226
|
+
left: box.left,
|
|
227
|
+
top: box.top,
|
|
228
|
+
width: box.width,
|
|
229
|
+
height: box.height,
|
|
230
|
+
scale: box.width / natural.width,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
134
233
|
update() {
|
|
135
234
|
const zoom = this.#host.state.zoom;
|
|
136
235
|
if (this.#info &&
|
|
@@ -198,6 +297,28 @@ export class ViewerViewport {
|
|
|
198
297
|
const size = naturalPageSize(this.#info, this.#host.state.pageIndex);
|
|
199
298
|
return Math.max(0.1, Math.min(8, (this.#root.clientWidth - 24) / size.width, (this.#root.clientHeight - 24) / size.height));
|
|
200
299
|
}
|
|
300
|
+
/** Collects finished paints and reports them once per frame, newest content only. */
|
|
301
|
+
#markPainted(pageIndex, contentRevision) {
|
|
302
|
+
if (contentRevision !== this.#contentRevision)
|
|
303
|
+
return;
|
|
304
|
+
let pages = this.#painted.get(contentRevision);
|
|
305
|
+
if (!pages) {
|
|
306
|
+
pages = new Set();
|
|
307
|
+
this.#painted.clear();
|
|
308
|
+
this.#painted.set(contentRevision, pages);
|
|
309
|
+
}
|
|
310
|
+
pages.add(pageIndex);
|
|
311
|
+
if (this.#paintedFlush)
|
|
312
|
+
return;
|
|
313
|
+
this.#paintedFlush = requestAnimationFrame(() => {
|
|
314
|
+
this.#paintedFlush = 0;
|
|
315
|
+
const current = this.#painted.get(this.#contentRevision);
|
|
316
|
+
this.#painted.clear();
|
|
317
|
+
if (!current || current.size === 0 || this.#destroyed)
|
|
318
|
+
return;
|
|
319
|
+
this.#host.onPainted([...current].sort((a, b) => a - b), this.#contentRevision);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
201
322
|
schedule() {
|
|
202
323
|
if (this.#destroyed || this.#frame)
|
|
203
324
|
return;
|
|
@@ -212,6 +333,8 @@ export class ViewerViewport {
|
|
|
212
333
|
this.#destroyed = true;
|
|
213
334
|
if (this.#frame)
|
|
214
335
|
cancelAnimationFrame(this.#frame);
|
|
336
|
+
if (this.#paintedFlush)
|
|
337
|
+
cancelAnimationFrame(this.#paintedFlush);
|
|
215
338
|
if (this.#zoomSettleTimer)
|
|
216
339
|
clearTimeout(this.#zoomSettleTimer);
|
|
217
340
|
this.#resizeObserver?.disconnect();
|
|
@@ -266,7 +389,7 @@ export class ViewerViewport {
|
|
|
266
389
|
.getSearchMatches(pageIndex)
|
|
267
390
|
.map((match) => `${match.start}:${match.end}`)
|
|
268
391
|
.join(",");
|
|
269
|
-
const renderKey = `${state.zoom}:${window.devicePixelRatio || 1}:${highlights}`;
|
|
392
|
+
const renderKey = `${this.#pageRevisions[pageIndex] ?? 0}:${state.zoom}:${window.devicePixelRatio || 1}:${highlights}`;
|
|
270
393
|
if (slot.renderKey === undefined ||
|
|
271
394
|
(!this.#zoomGestureActive && slot.renderKey !== renderKey)) {
|
|
272
395
|
slot.renderKey = renderKey;
|
|
@@ -320,6 +443,7 @@ export class ViewerViewport {
|
|
|
320
443
|
slot.controller = controller;
|
|
321
444
|
const generation = ++slot.generation;
|
|
322
445
|
const zoom = this.#host.state.zoom;
|
|
446
|
+
const contentRevision = this.#contentRevision;
|
|
323
447
|
try {
|
|
324
448
|
let renderError;
|
|
325
449
|
const rendering = this.#host
|
|
@@ -347,6 +471,7 @@ export class ViewerViewport {
|
|
|
347
471
|
const cssHeight = slot.canvas.height / (window.devicePixelRatio || 1);
|
|
348
472
|
slot.root.style.width = `${cssWidth}px`;
|
|
349
473
|
slot.root.style.height = `${cssHeight}px`;
|
|
474
|
+
this.#markPainted(pageIndex, contentRevision);
|
|
350
475
|
}
|
|
351
476
|
catch (error) {
|
|
352
477
|
if (!controller.signal.aborted) {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { DocumentFormat, DocumentInfo, ResourceLimits, TextRun, ViewerErrorData, ViewerProgress, ViewerWarning } from "./contracts.js";
|
|
2
|
-
|
|
2
|
+
import type { EditableFormat } from "./edit/types.js";
|
|
3
|
+
export type DocumentWorkerOperation = "init" | "open" | "get-info" | "render" | "get-text-map" | "close" | "destroy";
|
|
4
|
+
/** Operations of an edit engine worker; payloads mirror the engine interface. */
|
|
5
|
+
export type EditWorkerOperation = "edit-init" | "edit-open" | "edit-validate" | "edit-apply" | "edit-materialize" | "edit-restore" | "edit-put-asset" | "edit-elements" | "edit-element" | "edit-elements-at" | "edit-find-text" | "edit-text-layout" | "edit-position-at" | "edit-range-rects" | "edit-render-without" | "edit-page-layout" | "edit-pptx-slides" | "edit-pptx-layouts" | "edit-dispose";
|
|
6
|
+
export type WorkerOperation = DocumentWorkerOperation | EditWorkerOperation;
|
|
3
7
|
export interface WorkerRequest {
|
|
4
8
|
readonly kind: "request";
|
|
5
9
|
readonly id: number;
|
|
@@ -44,5 +48,38 @@ export interface WorkerRenderPayload {
|
|
|
44
48
|
readonly zoom: number;
|
|
45
49
|
readonly devicePixelRatio: number;
|
|
46
50
|
}
|
|
47
|
-
export
|
|
51
|
+
export interface EditWorkerInitPayload {
|
|
52
|
+
/** Where the worker fetches the engine's WebAssembly from. */
|
|
53
|
+
readonly wasmUrl: string;
|
|
54
|
+
/** TrueType font for text the standard PDF fonts cannot encode. */
|
|
55
|
+
readonly fallbackFontUrl?: string;
|
|
56
|
+
}
|
|
57
|
+
/** A host-registered font as the edit worker receives it. */
|
|
58
|
+
export interface EditWorkerFont {
|
|
59
|
+
readonly family: string;
|
|
60
|
+
readonly weight: number;
|
|
61
|
+
readonly style: "normal" | "italic" | "oblique";
|
|
62
|
+
/** Font bytes, or an absolute URL the worker fetches on first use. */
|
|
63
|
+
readonly source: ArrayBuffer | string;
|
|
64
|
+
}
|
|
65
|
+
export interface EditWorkerOpenPayload {
|
|
66
|
+
readonly data: ArrayBuffer;
|
|
67
|
+
readonly limits: ResourceLimits;
|
|
68
|
+
/** The session format; a worker that serves several formats picks its engine by it. */
|
|
69
|
+
readonly format?: EditableFormat;
|
|
70
|
+
readonly fileName?: string;
|
|
71
|
+
readonly fonts?: readonly EditWorkerFont[];
|
|
72
|
+
}
|
|
73
|
+
/** A rendered page as the worker returns it; `data` is transferred, not copied. */
|
|
74
|
+
export interface EditWorkerBitmap {
|
|
75
|
+
readonly pageIndex: number;
|
|
76
|
+
readonly scale: number;
|
|
77
|
+
readonly width: number;
|
|
78
|
+
readonly height: number;
|
|
79
|
+
readonly data: ArrayBuffer;
|
|
80
|
+
}
|
|
81
|
+
export interface EditWorkerOpenResult {
|
|
82
|
+
readonly pageCount: number;
|
|
83
|
+
}
|
|
84
|
+
export type WorkerOperationResult = DocumentInfo | readonly TextRun[] | ImageBitmap | ArrayBuffer | EditWorkerOpenResult | undefined;
|
|
48
85
|
export declare function transferablesFor(value: unknown): Transferable[];
|