@harbour-enterprises/superdoc 2.0.0-next.22 → 2.0.0-next.23
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/dist/chunks/{PdfViewer-F9XQJkng.cjs → PdfViewer-BPh-D_Hz.cjs} +2 -2
- package/dist/chunks/{PdfViewer-CGUK5UvE.es.js → PdfViewer-CBOz7W4_.es.js} +2 -2
- package/dist/chunks/{SuperConverter-BgQ_7WLE.cjs → SuperConverter-H5PfOKjB.cjs} +1 -1
- package/dist/chunks/{SuperConverter-94ypJzq2.es.js → SuperConverter-tJ_8LYGZ.es.js} +1 -1
- package/dist/chunks/{index-BgvzOicm.cjs → index-BZQlqpzE.cjs} +5 -5
- package/dist/chunks/{index-BYTMVIbP.cjs → index-BihcZqMS.cjs} +672 -20
- package/dist/chunks/{index-YkVH-fFY.es.js → index-CJc-jUP_.es.js} +672 -20
- package/dist/chunks/{index-BpXSabgi.es.js → index-DKYzdefu.es.js} +5 -5
- package/dist/super-editor/converter.cjs +1 -1
- package/dist/super-editor/converter.es.js +1 -1
- package/dist/super-editor.cjs +2 -2
- package/dist/super-editor.es.js +2 -2
- package/dist/superdoc.cjs +3 -3
- package/dist/superdoc.es.js +3 -3
- package/dist/superdoc.umd.js +690 -37
- package/dist/superdoc.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/superdoc.umd.js
CHANGED
|
@@ -35746,7 +35746,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
35746
35746
|
static getStoredSuperdocVersion(docx) {
|
|
35747
35747
|
return SuperConverter.getStoredCustomProperty(docx, "SuperdocVersion");
|
|
35748
35748
|
}
|
|
35749
|
-
static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.
|
|
35749
|
+
static setStoredSuperdocVersion(docx = this.convertedXml, version2 = "2.0.0-next.23") {
|
|
35750
35750
|
return SuperConverter.setStoredCustomProperty(docx, "SuperdocVersion", version2, false);
|
|
35751
35751
|
}
|
|
35752
35752
|
/**
|
|
@@ -42903,15 +42903,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
42903
42903
|
/** @type {any} */
|
|
42904
42904
|
eventHandler
|
|
42905
42905
|
);
|
|
42906
|
-
var define_process_default$
|
|
42907
|
-
const isNode = typeof define_process_default$
|
|
42906
|
+
var define_process_default$b = { env: { NODE_ENV: "production" } };
|
|
42907
|
+
const isNode = typeof define_process_default$b !== "undefined" && define_process_default$b.release && /node|io\.js/.test(define_process_default$b.release.name) && Object.prototype.toString.call(typeof define_process_default$b !== "undefined" ? define_process_default$b : 0) === "[object process]";
|
|
42908
42908
|
const isBrowser$4 = typeof window !== "undefined" && typeof document !== "undefined" && !isNode;
|
|
42909
42909
|
let params;
|
|
42910
42910
|
const computeParams = () => {
|
|
42911
42911
|
if (params === void 0) {
|
|
42912
42912
|
if (isNode) {
|
|
42913
42913
|
params = create$4();
|
|
42914
|
-
const pargs = define_process_default$
|
|
42914
|
+
const pargs = define_process_default$b.argv;
|
|
42915
42915
|
let currParamName = null;
|
|
42916
42916
|
for (let i2 = 0; i2 < pargs.length; i2++) {
|
|
42917
42917
|
const parg = pargs[i2];
|
|
@@ -42946,12 +42946,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
42946
42946
|
return params;
|
|
42947
42947
|
};
|
|
42948
42948
|
const hasParam = (name) => computeParams().has(name);
|
|
42949
|
-
const getVariable = (name) => isNode ? undefinedToNull(define_process_default$
|
|
42949
|
+
const getVariable = (name) => isNode ? undefinedToNull(define_process_default$b.env[name.toUpperCase().replaceAll("-", "_")]) : undefinedToNull(varStorage.getItem(name));
|
|
42950
42950
|
const hasConf = (name) => hasParam("--" + name) || getVariable(name) !== null;
|
|
42951
42951
|
hasConf("production");
|
|
42952
|
-
const forceColor = isNode && isOneOf(define_process_default$
|
|
42952
|
+
const forceColor = isNode && isOneOf(define_process_default$b.env.FORCE_COLOR, ["true", "1", "2"]);
|
|
42953
42953
|
forceColor || !hasParam("--no-colors") && // @todo deprecate --no-colors
|
|
42954
|
-
!hasConf("no-color") && (!isNode || define_process_default$
|
|
42954
|
+
!hasConf("no-color") && (!isNode || define_process_default$b.stdout.isTTY) && (!isNode || hasParam("--color") || getVariable("COLORTERM") !== null || (getVariable("TERM") || "").includes("color"));
|
|
42955
42955
|
const doc$1 = (
|
|
42956
42956
|
/** @type {Document} */
|
|
42957
42957
|
typeof document !== "undefined" ? document : {}
|
|
@@ -45110,6 +45110,37 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
45110
45110
|
return new OxmlNode(config2);
|
|
45111
45111
|
}
|
|
45112
45112
|
}
|
|
45113
|
+
class EditorError extends Error {
|
|
45114
|
+
constructor(message) {
|
|
45115
|
+
super(message);
|
|
45116
|
+
this.name = "EditorError";
|
|
45117
|
+
}
|
|
45118
|
+
}
|
|
45119
|
+
class InvalidStateError extends EditorError {
|
|
45120
|
+
constructor(message) {
|
|
45121
|
+
super(message);
|
|
45122
|
+
this.name = "InvalidStateError";
|
|
45123
|
+
}
|
|
45124
|
+
}
|
|
45125
|
+
class NoSourcePathError extends EditorError {
|
|
45126
|
+
constructor(message) {
|
|
45127
|
+
super(message);
|
|
45128
|
+
this.name = "NoSourcePathError";
|
|
45129
|
+
}
|
|
45130
|
+
}
|
|
45131
|
+
class FileSystemNotAvailableError extends EditorError {
|
|
45132
|
+
constructor(message) {
|
|
45133
|
+
super(message);
|
|
45134
|
+
this.name = "FileSystemNotAvailableError";
|
|
45135
|
+
}
|
|
45136
|
+
}
|
|
45137
|
+
class DocumentLoadError extends EditorError {
|
|
45138
|
+
constructor(message, cause) {
|
|
45139
|
+
super(message);
|
|
45140
|
+
this.name = "DocumentLoadError";
|
|
45141
|
+
this.cause = cause;
|
|
45142
|
+
}
|
|
45143
|
+
}
|
|
45113
45144
|
const first = (commands2) => (props) => {
|
|
45114
45145
|
const items = typeof commands2 === "function" ? commands2(props) : commands2;
|
|
45115
45146
|
for (let i2 = 0; i2 < items.length; i2 += 1) {
|
|
@@ -52701,7 +52732,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
52701
52732
|
}
|
|
52702
52733
|
return String(value);
|
|
52703
52734
|
}
|
|
52704
|
-
var define_process_default$
|
|
52735
|
+
var define_process_default$a = { env: { NODE_ENV: "production" } };
|
|
52705
52736
|
let activeEffectScope;
|
|
52706
52737
|
class EffectScope {
|
|
52707
52738
|
constructor(detached = false) {
|
|
@@ -53160,7 +53191,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
53160
53191
|
notify(debugInfo) {
|
|
53161
53192
|
startBatch();
|
|
53162
53193
|
try {
|
|
53163
|
-
if (!!(define_process_default$
|
|
53194
|
+
if (!!(define_process_default$a.env.NODE_ENV !== "production")) ;
|
|
53164
53195
|
for (let link2 = this.subs; link2; link2 = link2.prevSub) {
|
|
53165
53196
|
if (link2.sub.notify()) {
|
|
53166
53197
|
;
|
|
@@ -54308,7 +54339,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
54308
54339
|
}
|
|
54309
54340
|
return value;
|
|
54310
54341
|
}
|
|
54311
|
-
var define_process_default$
|
|
54342
|
+
var define_process_default$9 = { env: { NODE_ENV: "production" } };
|
|
54312
54343
|
const stack$1 = [];
|
|
54313
54344
|
let isWarning = false;
|
|
54314
54345
|
function warn$1$1(msg2, ...args) {
|
|
@@ -54585,7 +54616,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
54585
54616
|
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
|
|
54586
54617
|
const job = queue[flushIndex];
|
|
54587
54618
|
if (job && !(job.flags & 8)) {
|
|
54588
|
-
if (!!(define_process_default$
|
|
54619
|
+
if (!!(define_process_default$9.env.NODE_ENV !== "production") && check(job)) ;
|
|
54589
54620
|
if (job.flags & 4) {
|
|
54590
54621
|
job.flags &= ~1;
|
|
54591
54622
|
}
|
|
@@ -56737,7 +56768,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
56737
56768
|
try {
|
|
56738
56769
|
if (vnode.shapeFlag & 4) {
|
|
56739
56770
|
const proxyToUse = withProxy || proxy;
|
|
56740
|
-
const thisProxy = !!(define_process_default$
|
|
56771
|
+
const thisProxy = !!(define_process_default$9.env.NODE_ENV !== "production") && setupState.__isScriptSetup ? new Proxy(proxyToUse, {
|
|
56741
56772
|
get(target, key2, receiver) {
|
|
56742
56773
|
warn$1$1(
|
|
56743
56774
|
`Property '${String(
|
|
@@ -56752,7 +56783,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
56752
56783
|
thisProxy,
|
|
56753
56784
|
proxyToUse,
|
|
56754
56785
|
renderCache,
|
|
56755
|
-
!!(define_process_default$
|
|
56786
|
+
!!(define_process_default$9.env.NODE_ENV !== "production") ? shallowReadonly(props) : props,
|
|
56756
56787
|
setupState,
|
|
56757
56788
|
data,
|
|
56758
56789
|
ctx2
|
|
@@ -56761,11 +56792,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
56761
56792
|
fallthroughAttrs = attrs;
|
|
56762
56793
|
} else {
|
|
56763
56794
|
const render22 = Component;
|
|
56764
|
-
if (!!(define_process_default$
|
|
56795
|
+
if (!!(define_process_default$9.env.NODE_ENV !== "production") && attrs === props) ;
|
|
56765
56796
|
result = normalizeVNode(
|
|
56766
56797
|
render22.length > 1 ? render22(
|
|
56767
|
-
!!(define_process_default$
|
|
56768
|
-
!!(define_process_default$
|
|
56798
|
+
!!(define_process_default$9.env.NODE_ENV !== "production") ? shallowReadonly(props) : props,
|
|
56799
|
+
!!(define_process_default$9.env.NODE_ENV !== "production") ? {
|
|
56769
56800
|
get attrs() {
|
|
56770
56801
|
markAttrsAccessed();
|
|
56771
56802
|
return shallowReadonly(attrs);
|
|
@@ -56774,7 +56805,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
56774
56805
|
emit: emit2
|
|
56775
56806
|
} : { attrs, slots, emit: emit2 }
|
|
56776
56807
|
) : render22(
|
|
56777
|
-
!!(define_process_default$
|
|
56808
|
+
!!(define_process_default$9.env.NODE_ENV !== "production") ? shallowReadonly(props) : props,
|
|
56778
56809
|
null
|
|
56779
56810
|
)
|
|
56780
56811
|
);
|
|
@@ -57196,7 +57227,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
57196
57227
|
return rawSlot;
|
|
57197
57228
|
}
|
|
57198
57229
|
const normalized = withCtx((...args) => {
|
|
57199
|
-
if (!!(define_process_default$
|
|
57230
|
+
if (!!(define_process_default$9.env.NODE_ENV !== "production") && currentInstance && !(ctx2 === null && currentRenderingInstance) && !(ctx2 && ctx2.root !== currentInstance.root)) ;
|
|
57200
57231
|
return normalizeSlotValue(rawSlot(...args));
|
|
57201
57232
|
}, ctx2);
|
|
57202
57233
|
normalized._c = false;
|
|
@@ -61406,7 +61437,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
61406
61437
|
return false;
|
|
61407
61438
|
}
|
|
61408
61439
|
};
|
|
61409
|
-
const summaryVersion = "2.0.0-next.
|
|
61440
|
+
const summaryVersion = "2.0.0-next.23";
|
|
61410
61441
|
const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
|
|
61411
61442
|
const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
|
|
61412
61443
|
function mapAttributes(attrs) {
|
|
@@ -61888,16 +61919,40 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
61888
61919
|
}
|
|
61889
61920
|
}
|
|
61890
61921
|
}
|
|
61922
|
+
var define_process_default$8 = { env: { NODE_ENV: "production" } };
|
|
61891
61923
|
class Editor extends EventEmitter$1 {
|
|
61892
61924
|
/**
|
|
61893
|
-
* Create a new Editor instance
|
|
61925
|
+
* Create a new Editor instance.
|
|
61926
|
+
*
|
|
61927
|
+
* **Legacy mode (backward compatible):**
|
|
61928
|
+
* When `content` or `fileSource` is provided, the editor initializes synchronously
|
|
61929
|
+
* with the document loaded immediately. This preserves existing behavior where
|
|
61930
|
+
* `editor.view` is available right after construction.
|
|
61931
|
+
*
|
|
61932
|
+
* **New mode (document lifecycle API):**
|
|
61933
|
+
* When no `content` or `fileSource` is provided, only core services (extensions,
|
|
61934
|
+
* commands, schema) are initialized. Call `editor.open()` to load a document.
|
|
61935
|
+
*
|
|
61894
61936
|
* @param options - Editor configuration options
|
|
61937
|
+
*
|
|
61938
|
+
* @example
|
|
61939
|
+
* ```typescript
|
|
61940
|
+
* // Legacy mode (still works)
|
|
61941
|
+
* const editor = new Editor({ content: docx, element: el });
|
|
61942
|
+
* console.log(editor.view.state.doc); // Works immediately
|
|
61943
|
+
*
|
|
61944
|
+
* // New mode
|
|
61945
|
+
* const editor = new Editor({ element: el });
|
|
61946
|
+
* await editor.open('/path/to/doc.docx');
|
|
61947
|
+
* ```
|
|
61895
61948
|
*/
|
|
61896
61949
|
constructor(options) {
|
|
61897
61950
|
super();
|
|
61898
61951
|
this.extensionStorage = {};
|
|
61899
61952
|
this.#renderer = null;
|
|
61900
61953
|
this.#isDestroyed = false;
|
|
61954
|
+
this.#editorLifecycleState = "initialized";
|
|
61955
|
+
this.#sourcePath = null;
|
|
61901
61956
|
this.presentationEditor = null;
|
|
61902
61957
|
this.isFocused = false;
|
|
61903
61958
|
this.fontsImported = [];
|
|
@@ -62010,18 +62065,25 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
62010
62065
|
this.#checkHeadless(resolvedOptions);
|
|
62011
62066
|
this.setOptions(resolvedOptions);
|
|
62012
62067
|
this.#renderer = resolvedOptions.renderer ?? (domAvailable ? new ProseMirrorRenderer() : null);
|
|
62013
|
-
const modes = {
|
|
62014
|
-
docx: () => this.#init(),
|
|
62015
|
-
text: () => this.#initRichText(),
|
|
62016
|
-
html: () => this.#initRichText(),
|
|
62017
|
-
default: () => {
|
|
62018
|
-
console.log("Not implemented.");
|
|
62019
|
-
}
|
|
62020
|
-
};
|
|
62021
|
-
const initMode = modes[this.options.mode] ?? modes.default;
|
|
62022
62068
|
const { setHighContrastMode } = useHighContrastMode$1();
|
|
62023
62069
|
this.setHighContrastMode = setHighContrastMode;
|
|
62024
|
-
|
|
62070
|
+
const useNewApiMode = resolvedOptions.deferDocumentLoad === true;
|
|
62071
|
+
if (useNewApiMode) {
|
|
62072
|
+
this.#initCore();
|
|
62073
|
+
this.#editorLifecycleState = "initialized";
|
|
62074
|
+
} else {
|
|
62075
|
+
const modes = {
|
|
62076
|
+
docx: () => this.#init(),
|
|
62077
|
+
text: () => this.#initRichText(),
|
|
62078
|
+
html: () => this.#initRichText(),
|
|
62079
|
+
default: () => {
|
|
62080
|
+
console.log("Not implemented.");
|
|
62081
|
+
}
|
|
62082
|
+
};
|
|
62083
|
+
const initMode = modes[this.options.mode] ?? modes.default;
|
|
62084
|
+
initMode();
|
|
62085
|
+
this.#editorLifecycleState = "ready";
|
|
62086
|
+
}
|
|
62025
62087
|
}
|
|
62026
62088
|
/**
|
|
62027
62089
|
* Command service for handling editor commands
|
|
@@ -62029,6 +62091,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
62029
62091
|
#commandService;
|
|
62030
62092
|
#renderer;
|
|
62031
62093
|
#isDestroyed;
|
|
62094
|
+
#editorLifecycleState;
|
|
62095
|
+
#sourcePath;
|
|
62032
62096
|
/**
|
|
62033
62097
|
* Getter which indicates if any changes happen in Editor
|
|
62034
62098
|
*/
|
|
@@ -62053,6 +62117,303 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
62053
62117
|
this.emit("create", { editor: this });
|
|
62054
62118
|
}, 0);
|
|
62055
62119
|
}
|
|
62120
|
+
/**
|
|
62121
|
+
* Assert that the editor is in one of the allowed states.
|
|
62122
|
+
* Throws InvalidStateError if not.
|
|
62123
|
+
*/
|
|
62124
|
+
#assertState(...allowed) {
|
|
62125
|
+
if (!allowed.includes(this.#editorLifecycleState)) {
|
|
62126
|
+
throw new InvalidStateError(
|
|
62127
|
+
`Invalid operation: editor is in '${this.#editorLifecycleState}' state, expected one of: ${allowed.join(", ")}`
|
|
62128
|
+
);
|
|
62129
|
+
}
|
|
62130
|
+
}
|
|
62131
|
+
/**
|
|
62132
|
+
* Wraps an async operation with state transitions for safe lifecycle management.
|
|
62133
|
+
*
|
|
62134
|
+
* This method ensures atomic state transitions during async operations:
|
|
62135
|
+
* 1. Sets state to `during` before executing the operation
|
|
62136
|
+
* 2. On success: sets state to `success` and returns the operation result
|
|
62137
|
+
* 3. On error: sets state to `failure` and re-throws the error
|
|
62138
|
+
*
|
|
62139
|
+
* This prevents race conditions and ensures the editor is always in a valid state,
|
|
62140
|
+
* even when operations fail.
|
|
62141
|
+
*
|
|
62142
|
+
* @template T - The return type of the operation
|
|
62143
|
+
* @param during - State to set while the operation is running
|
|
62144
|
+
* @param success - State to set if the operation succeeds
|
|
62145
|
+
* @param failure - State to set if the operation fails
|
|
62146
|
+
* @param operation - Async operation to execute
|
|
62147
|
+
* @returns Promise resolving to the operation's return value
|
|
62148
|
+
* @throws Re-throws any error from the operation after setting failure state
|
|
62149
|
+
*
|
|
62150
|
+
* @example
|
|
62151
|
+
* ```typescript
|
|
62152
|
+
* // Used internally for save operations:
|
|
62153
|
+
* await this.#withState('saving', 'ready', 'ready', async () => {
|
|
62154
|
+
* const data = await this.exportDocument();
|
|
62155
|
+
* await this.#writeToPath(path, data);
|
|
62156
|
+
* });
|
|
62157
|
+
* ```
|
|
62158
|
+
*/
|
|
62159
|
+
async #withState(during, success, failure, operation) {
|
|
62160
|
+
this.#editorLifecycleState = during;
|
|
62161
|
+
try {
|
|
62162
|
+
const result = await operation();
|
|
62163
|
+
this.#editorLifecycleState = success;
|
|
62164
|
+
return result;
|
|
62165
|
+
} catch (error) {
|
|
62166
|
+
this.#editorLifecycleState = failure;
|
|
62167
|
+
throw error;
|
|
62168
|
+
}
|
|
62169
|
+
}
|
|
62170
|
+
/**
|
|
62171
|
+
* Initialize core editor services for new lifecycle API mode.
|
|
62172
|
+
*
|
|
62173
|
+
* When `deferDocumentLoad: true` is set, this method initializes only the
|
|
62174
|
+
* document-independent components:
|
|
62175
|
+
* - Extension service (loads and configures all extensions)
|
|
62176
|
+
* - Command service (registers all editor commands)
|
|
62177
|
+
* - ProseMirror schema (derived from extensions, reusable across documents)
|
|
62178
|
+
*
|
|
62179
|
+
* These services are created once during construction and reused when opening
|
|
62180
|
+
* different documents via the `open()` method. This enables efficient document
|
|
62181
|
+
* switching without recreating the entire editor infrastructure.
|
|
62182
|
+
*
|
|
62183
|
+
* Called exclusively from the constructor when `deferDocumentLoad` is true.
|
|
62184
|
+
*
|
|
62185
|
+
* @remarks
|
|
62186
|
+
* This is part of the new lifecycle API that separates editor initialization
|
|
62187
|
+
* from document loading. The schema and extensions remain constant while
|
|
62188
|
+
* documents can be opened, closed, and reopened.
|
|
62189
|
+
*
|
|
62190
|
+
* @see #loadDocument - Loads document-specific state after core initialization
|
|
62191
|
+
*/
|
|
62192
|
+
#initCore() {
|
|
62193
|
+
if (!this.options.extensions?.length) {
|
|
62194
|
+
this.options.extensions = this.options.mode === "docx" ? getStarterExtensions() : getRichTextExtensions();
|
|
62195
|
+
}
|
|
62196
|
+
this.#createExtensionService();
|
|
62197
|
+
this.#createCommandService();
|
|
62198
|
+
this.#createSchema();
|
|
62199
|
+
this.#registerEventListeners();
|
|
62200
|
+
}
|
|
62201
|
+
/**
|
|
62202
|
+
* Register all event listeners from options.
|
|
62203
|
+
*
|
|
62204
|
+
* Called once during core initialization. These listeners persist across
|
|
62205
|
+
* document open/close cycles since the callbacks are set at construction time.
|
|
62206
|
+
*/
|
|
62207
|
+
#registerEventListeners() {
|
|
62208
|
+
this.on("create", this.options.onCreate);
|
|
62209
|
+
this.on("update", this.options.onUpdate);
|
|
62210
|
+
this.on("selectionUpdate", this.options.onSelectionUpdate);
|
|
62211
|
+
this.on("transaction", this.options.onTransaction);
|
|
62212
|
+
this.on("focus", this.#onFocus.bind(this));
|
|
62213
|
+
this.on("blur", this.options.onBlur);
|
|
62214
|
+
this.on("destroy", this.options.onDestroy);
|
|
62215
|
+
this.on("trackedChangesUpdate", this.options.onTrackedChangesUpdate);
|
|
62216
|
+
this.on("commentsLoaded", this.options.onCommentsLoaded);
|
|
62217
|
+
this.on("commentClick", this.options.onCommentClicked);
|
|
62218
|
+
this.on("commentsUpdate", this.options.onCommentsUpdate);
|
|
62219
|
+
this.on("locked", this.options.onDocumentLocked);
|
|
62220
|
+
this.on("collaborationReady", this.#onCollaborationReady.bind(this));
|
|
62221
|
+
this.on("comment-positions", this.options.onCommentLocationsUpdate);
|
|
62222
|
+
this.on("list-definitions-change", this.options.onListDefinitionsChange);
|
|
62223
|
+
this.on("fonts-resolved", this.options.onFontsResolved);
|
|
62224
|
+
this.on("exception", this.options.onException);
|
|
62225
|
+
}
|
|
62226
|
+
/**
|
|
62227
|
+
* Load a document into the editor from various source types.
|
|
62228
|
+
*
|
|
62229
|
+
* This method handles the complete document loading pipeline:
|
|
62230
|
+
* 1. **Source resolution**: Determines source type (path/File/Blob/Buffer/blank)
|
|
62231
|
+
* 2. **Content loading**:
|
|
62232
|
+
* - String path: Reads file from disk (Node.js) or fetches URL (browser)
|
|
62233
|
+
* - File/Blob: Extracts docx archive data
|
|
62234
|
+
* - Buffer: Processes binary data (Node.js)
|
|
62235
|
+
* - undefined/null: Creates blank document
|
|
62236
|
+
* 3. **Document initialization**: Creates converter, media, fonts, initial state
|
|
62237
|
+
* 4. **View mounting**: Attaches ProseMirror view (unless headless)
|
|
62238
|
+
* 5. **Event wiring**: Connects all lifecycle event handlers
|
|
62239
|
+
*
|
|
62240
|
+
* Called by `open()` after state validation, wrapped in `#withState()` for
|
|
62241
|
+
* atomic state transitions.
|
|
62242
|
+
*
|
|
62243
|
+
* @param source - Document source:
|
|
62244
|
+
* - `string`: File path (Node.js reads from disk, browser fetches as URL)
|
|
62245
|
+
* - `File | Blob`: Browser file object or blob
|
|
62246
|
+
* - `Buffer`: Node.js buffer containing docx data
|
|
62247
|
+
* - `undefined | null`: Creates a blank document
|
|
62248
|
+
* @param options - Document-level options (mode, comments, styles, etc.)
|
|
62249
|
+
* @returns Promise that resolves when document is fully loaded and ready
|
|
62250
|
+
* @throws {DocumentLoadError} If any step of document loading fails. The error
|
|
62251
|
+
* wraps the underlying cause for debugging.
|
|
62252
|
+
*
|
|
62253
|
+
* @remarks
|
|
62254
|
+
* - Sets `#sourcePath` for path-based sources (enables `save()`)
|
|
62255
|
+
* - Sets `#sourcePath = null` for Blob/Buffer sources (requires `saveTo()`)
|
|
62256
|
+
* - In browser, string paths are treated as URLs to fetch
|
|
62257
|
+
* - In Node.js, string paths are read from the filesystem
|
|
62258
|
+
*
|
|
62259
|
+
* @see open - Public API that calls this method
|
|
62260
|
+
* @see #unloadDocument - Cleanup counterpart that reverses this process
|
|
62261
|
+
*/
|
|
62262
|
+
async #loadDocument(source, options) {
|
|
62263
|
+
try {
|
|
62264
|
+
const resolvedMode = options?.mode ?? this.options.mode ?? "docx";
|
|
62265
|
+
const resolvedOptions = {
|
|
62266
|
+
...this.options,
|
|
62267
|
+
mode: resolvedMode,
|
|
62268
|
+
isCommentsEnabled: options?.isCommentsEnabled ?? this.options.isCommentsEnabled,
|
|
62269
|
+
suppressDefaultDocxStyles: options?.suppressDefaultDocxStyles ?? this.options.suppressDefaultDocxStyles,
|
|
62270
|
+
documentMode: options?.documentMode ?? this.options.documentMode ?? "editing",
|
|
62271
|
+
html: options?.html,
|
|
62272
|
+
markdown: options?.markdown,
|
|
62273
|
+
jsonOverride: options?.json ?? null
|
|
62274
|
+
};
|
|
62275
|
+
if (typeof source === "string") {
|
|
62276
|
+
if (typeof define_process_default$8 !== "undefined" && define_process_default$8.versions?.node) {
|
|
62277
|
+
const fs = require("fs");
|
|
62278
|
+
const buffer2 = fs.readFileSync(source);
|
|
62279
|
+
const [docx, _media, mediaFiles, fonts] = await Editor.loadXmlData(buffer2, true);
|
|
62280
|
+
resolvedOptions.content = docx;
|
|
62281
|
+
resolvedOptions.mediaFiles = mediaFiles;
|
|
62282
|
+
resolvedOptions.fonts = fonts;
|
|
62283
|
+
resolvedOptions.fileSource = buffer2;
|
|
62284
|
+
this.#sourcePath = source;
|
|
62285
|
+
} else {
|
|
62286
|
+
const response = await fetch(source);
|
|
62287
|
+
const blob = await response.blob();
|
|
62288
|
+
const [docx, _media, mediaFiles, fonts] = await Editor.loadXmlData(blob);
|
|
62289
|
+
resolvedOptions.content = docx;
|
|
62290
|
+
resolvedOptions.mediaFiles = mediaFiles;
|
|
62291
|
+
resolvedOptions.fonts = fonts;
|
|
62292
|
+
resolvedOptions.fileSource = blob;
|
|
62293
|
+
this.#sourcePath = source.split("/").pop() || null;
|
|
62294
|
+
}
|
|
62295
|
+
} else if (source != null && typeof source === "object") {
|
|
62296
|
+
const isNodeBuffer = typeof Buffer !== "undefined" && (Buffer.isBuffer(source) || source instanceof Buffer);
|
|
62297
|
+
const isBlob = typeof Blob !== "undefined" && source instanceof Blob;
|
|
62298
|
+
const isArrayBuffer = source instanceof ArrayBuffer;
|
|
62299
|
+
const hasArrayBuffer = typeof source === "object" && "buffer" in source && source.buffer instanceof ArrayBuffer;
|
|
62300
|
+
if (isNodeBuffer || isBlob || isArrayBuffer || hasArrayBuffer) {
|
|
62301
|
+
const [docx, _media, mediaFiles, fonts] = await Editor.loadXmlData(
|
|
62302
|
+
source,
|
|
62303
|
+
isNodeBuffer
|
|
62304
|
+
);
|
|
62305
|
+
resolvedOptions.content = docx;
|
|
62306
|
+
resolvedOptions.mediaFiles = mediaFiles;
|
|
62307
|
+
resolvedOptions.fonts = fonts;
|
|
62308
|
+
resolvedOptions.fileSource = source;
|
|
62309
|
+
this.#sourcePath = null;
|
|
62310
|
+
} else {
|
|
62311
|
+
const [docx, _media, mediaFiles, fonts] = await Editor.loadXmlData(source, false);
|
|
62312
|
+
resolvedOptions.content = docx;
|
|
62313
|
+
resolvedOptions.mediaFiles = mediaFiles;
|
|
62314
|
+
resolvedOptions.fonts = fonts;
|
|
62315
|
+
resolvedOptions.fileSource = source;
|
|
62316
|
+
this.#sourcePath = null;
|
|
62317
|
+
}
|
|
62318
|
+
} else {
|
|
62319
|
+
resolvedOptions.content = options?.content ?? [];
|
|
62320
|
+
resolvedOptions.mediaFiles = options?.mediaFiles ?? {};
|
|
62321
|
+
resolvedOptions.fonts = options?.fonts ?? {};
|
|
62322
|
+
resolvedOptions.fileSource = null;
|
|
62323
|
+
resolvedOptions.isNewFile = !options?.content;
|
|
62324
|
+
this.#sourcePath = null;
|
|
62325
|
+
}
|
|
62326
|
+
this.setOptions(resolvedOptions);
|
|
62327
|
+
this.#createConverter();
|
|
62328
|
+
this.#initMedia();
|
|
62329
|
+
const shouldMountRenderer = this.#shouldMountRenderer();
|
|
62330
|
+
if (shouldMountRenderer) {
|
|
62331
|
+
this.#initContainerElement(this.options);
|
|
62332
|
+
this.#initFonts();
|
|
62333
|
+
}
|
|
62334
|
+
this.#createInitialState({ includePlugins: !shouldMountRenderer });
|
|
62335
|
+
if (!shouldMountRenderer) {
|
|
62336
|
+
const tr = this.state.tr.setMeta("forcePluginPass", true).setMeta("addToHistory", false);
|
|
62337
|
+
this.#dispatchTransaction(tr);
|
|
62338
|
+
}
|
|
62339
|
+
if (shouldMountRenderer) {
|
|
62340
|
+
this.mount(this.options.element);
|
|
62341
|
+
this.#configureStateWithExtensionPlugins();
|
|
62342
|
+
}
|
|
62343
|
+
if (!shouldMountRenderer) {
|
|
62344
|
+
this.#emitCreateAsync();
|
|
62345
|
+
}
|
|
62346
|
+
if (shouldMountRenderer) {
|
|
62347
|
+
this.initDefaultStyles();
|
|
62348
|
+
this.#checkFonts();
|
|
62349
|
+
}
|
|
62350
|
+
const shouldMigrateListsOnInit = Boolean(
|
|
62351
|
+
this.options.markdown || this.options.html || this.options.loadFromSchema || this.options.jsonOverride || this.options.mode === "html" || this.options.mode === "text"
|
|
62352
|
+
);
|
|
62353
|
+
if (shouldMigrateListsOnInit) {
|
|
62354
|
+
this.migrateListsToV2();
|
|
62355
|
+
}
|
|
62356
|
+
this.setDocumentMode(this.options.documentMode, "init");
|
|
62357
|
+
this.initializeCollaborationData();
|
|
62358
|
+
if (!this.options.ydoc && !this.options.isChildEditor) {
|
|
62359
|
+
this.#initComments();
|
|
62360
|
+
}
|
|
62361
|
+
if (shouldMountRenderer) {
|
|
62362
|
+
this.#initDevTools();
|
|
62363
|
+
this.#registerCopyHandler();
|
|
62364
|
+
}
|
|
62365
|
+
} catch (error) {
|
|
62366
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
62367
|
+
throw new DocumentLoadError(`Failed to load document: ${err.message}`, err);
|
|
62368
|
+
}
|
|
62369
|
+
}
|
|
62370
|
+
/**
|
|
62371
|
+
* Unload the current document and clean up all document-specific resources.
|
|
62372
|
+
*
|
|
62373
|
+
* This method performs a complete cleanup of document state while preserving
|
|
62374
|
+
* the core editor services (schema, extensions, commands) for reuse:
|
|
62375
|
+
*
|
|
62376
|
+
* **Resources cleaned up:**
|
|
62377
|
+
* - ProseMirror view (unmounted from DOM)
|
|
62378
|
+
* - Header/footer editors (destroyed)
|
|
62379
|
+
* - Document converter instance
|
|
62380
|
+
* - Media references and image storage
|
|
62381
|
+
* - Source path reference
|
|
62382
|
+
* - Document-specific options (content, fileSource, initialState)
|
|
62383
|
+
* - ProseMirror editor state
|
|
62384
|
+
*
|
|
62385
|
+
* **Resources preserved:**
|
|
62386
|
+
* - ProseMirror schema
|
|
62387
|
+
* - Extension service and registered extensions
|
|
62388
|
+
* - Command service and registered commands
|
|
62389
|
+
* - Event listeners (registered once during core init, reused across documents)
|
|
62390
|
+
*
|
|
62391
|
+
* After cleanup, the editor transitions to 'closed' state and can be reopened
|
|
62392
|
+
* with a new document via `open()`.
|
|
62393
|
+
*
|
|
62394
|
+
* Called by `close()` after emitting the `documentClose` event.
|
|
62395
|
+
*
|
|
62396
|
+
* @remarks
|
|
62397
|
+
* This is a critical part of the document lifecycle API that enables efficient
|
|
62398
|
+
* document switching. By preserving schema and extensions, we avoid expensive
|
|
62399
|
+
* reinitialization when opening multiple documents sequentially.
|
|
62400
|
+
*
|
|
62401
|
+
* @see close - Public API that calls this method
|
|
62402
|
+
* @see #loadDocument - Counterpart method that loads document resources
|
|
62403
|
+
*/
|
|
62404
|
+
#unloadDocument() {
|
|
62405
|
+
this.unmount();
|
|
62406
|
+
this.destroyHeaderFooterEditors();
|
|
62407
|
+
this.converter = void 0;
|
|
62408
|
+
if (this.storage.image) {
|
|
62409
|
+
this.storage.image.media = {};
|
|
62410
|
+
}
|
|
62411
|
+
this.#sourcePath = null;
|
|
62412
|
+
this.options.initialState = null;
|
|
62413
|
+
this.options.content = "";
|
|
62414
|
+
this.options.fileSource = null;
|
|
62415
|
+
this._state = void 0;
|
|
62416
|
+
}
|
|
62056
62417
|
/**
|
|
62057
62418
|
* Initialize the editor with the given options
|
|
62058
62419
|
*/
|
|
@@ -62217,6 +62578,25 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
62217
62578
|
get state() {
|
|
62218
62579
|
return this._state;
|
|
62219
62580
|
}
|
|
62581
|
+
/**
|
|
62582
|
+
* Get the current editor lifecycle state.
|
|
62583
|
+
*
|
|
62584
|
+
* @returns The current lifecycle state ('initialized', 'documentLoading', 'ready', 'saving', 'closed', 'destroyed')
|
|
62585
|
+
*/
|
|
62586
|
+
get lifecycleState() {
|
|
62587
|
+
return this.#editorLifecycleState;
|
|
62588
|
+
}
|
|
62589
|
+
/**
|
|
62590
|
+
* Get the source path of the currently opened document.
|
|
62591
|
+
*
|
|
62592
|
+
* Returns the file path if the document was opened from a path (Node.js),
|
|
62593
|
+
* or null if opened from a Blob/Buffer or created as a blank document.
|
|
62594
|
+
*
|
|
62595
|
+
* In browsers, this is only a suggested filename, not an actual filesystem path.
|
|
62596
|
+
*/
|
|
62597
|
+
get sourcePath() {
|
|
62598
|
+
return this.#sourcePath;
|
|
62599
|
+
}
|
|
62220
62600
|
/**
|
|
62221
62601
|
* Replace the editor state entirely.
|
|
62222
62602
|
*
|
|
@@ -62314,19 +62694,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
62314
62694
|
if (this.options.role === "viewer") cleanedMode = "viewing";
|
|
62315
62695
|
if (this.options.role === "suggester" && cleanedMode === "editing") cleanedMode = "suggesting";
|
|
62316
62696
|
if (cleanedMode === "viewing") {
|
|
62317
|
-
this.commands.toggleTrackChangesShowOriginal();
|
|
62697
|
+
this.commands.toggleTrackChangesShowOriginal?.();
|
|
62318
62698
|
this.setEditable(false, false);
|
|
62319
62699
|
this.setOptions({ documentMode: "viewing" });
|
|
62320
62700
|
if (pm) pm.classList.add("view-mode");
|
|
62321
62701
|
} else if (cleanedMode === "suggesting") {
|
|
62322
|
-
this.commands.disableTrackChangesShowOriginal();
|
|
62323
|
-
this.commands.enableTrackChanges();
|
|
62702
|
+
this.commands.disableTrackChangesShowOriginal?.();
|
|
62703
|
+
this.commands.enableTrackChanges?.();
|
|
62324
62704
|
this.setOptions({ documentMode: "suggesting" });
|
|
62325
62705
|
this.setEditable(true, false);
|
|
62326
62706
|
if (pm) pm.classList.remove("view-mode");
|
|
62327
62707
|
} else if (cleanedMode === "editing") {
|
|
62328
|
-
this.commands.disableTrackChangesShowOriginal();
|
|
62329
|
-
this.commands.disableTrackChanges();
|
|
62708
|
+
this.commands.disableTrackChangesShowOriginal?.();
|
|
62709
|
+
this.commands.disableTrackChanges?.();
|
|
62330
62710
|
this.setEditable(true, false);
|
|
62331
62711
|
this.setOptions({ documentMode: "editing" });
|
|
62332
62712
|
if (pm) pm.classList.remove("view-mode");
|
|
@@ -63374,16 +63754,289 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
63374
63754
|
console.error(err);
|
|
63375
63755
|
}
|
|
63376
63756
|
}
|
|
63757
|
+
// ============================================================================
|
|
63758
|
+
// Document Lifecycle API
|
|
63759
|
+
// ============================================================================
|
|
63760
|
+
/**
|
|
63761
|
+
* Open a document in the editor.
|
|
63762
|
+
*
|
|
63763
|
+
* @param source - Document source:
|
|
63764
|
+
* - `string` - File path (Node.js reads from disk, browser fetches URL)
|
|
63765
|
+
* - `File | Blob` - Browser file object
|
|
63766
|
+
* - `Buffer` - Node.js buffer
|
|
63767
|
+
* - `undefined` - Creates a blank document
|
|
63768
|
+
* @param options - Document options (mode, comments, etc.)
|
|
63769
|
+
* @returns Promise that resolves when document is loaded
|
|
63770
|
+
*
|
|
63771
|
+
* @throws {InvalidStateError} If editor is not in 'initialized' or 'closed' state
|
|
63772
|
+
* @throws {DocumentLoadError} If document loading fails
|
|
63773
|
+
*
|
|
63774
|
+
* @example
|
|
63775
|
+
* ```typescript
|
|
63776
|
+
* const editor = new Editor({ element: myDiv });
|
|
63777
|
+
*
|
|
63778
|
+
* // Open from file path (Node.js)
|
|
63779
|
+
* await editor.open('/path/to/document.docx');
|
|
63780
|
+
*
|
|
63781
|
+
* // Open from File object (browser)
|
|
63782
|
+
* await editor.open(fileInput.files[0]);
|
|
63783
|
+
*
|
|
63784
|
+
* // Open blank document
|
|
63785
|
+
* await editor.open();
|
|
63786
|
+
*
|
|
63787
|
+
* // Open with options
|
|
63788
|
+
* await editor.open('/path/to/doc.docx', { isCommentsEnabled: true });
|
|
63789
|
+
* ```
|
|
63790
|
+
*/
|
|
63791
|
+
async open(source, options) {
|
|
63792
|
+
this.#assertState("initialized", "closed");
|
|
63793
|
+
await this.#withState("documentLoading", "ready", "closed", async () => {
|
|
63794
|
+
await this.#loadDocument(source, options);
|
|
63795
|
+
});
|
|
63796
|
+
this.emit("documentOpen", { editor: this, sourcePath: this.#sourcePath });
|
|
63797
|
+
}
|
|
63798
|
+
/**
|
|
63799
|
+
* Static factory method for one-liner document opening.
|
|
63800
|
+
* Creates an Editor instance and opens the document in one call.
|
|
63801
|
+
*
|
|
63802
|
+
* Smart defaults enable minimal configuration:
|
|
63803
|
+
* - No element/selector → headless mode
|
|
63804
|
+
* - No extensions → uses getStarterExtensions() for docx, getRichTextExtensions() for text/html
|
|
63805
|
+
* - No mode → defaults to 'docx'
|
|
63806
|
+
*
|
|
63807
|
+
* @param source - Document source (path, File, Blob, Buffer, or undefined for blank)
|
|
63808
|
+
* @param config - Combined editor and document options (all optional)
|
|
63809
|
+
* @returns Promise resolving to the ready Editor instance
|
|
63810
|
+
*
|
|
63811
|
+
* @example
|
|
63812
|
+
* ```typescript
|
|
63813
|
+
* // Minimal headless usage - just works!
|
|
63814
|
+
* const editor = await Editor.open('/path/to/doc.docx');
|
|
63815
|
+
*
|
|
63816
|
+
* // With options
|
|
63817
|
+
* const editor = await Editor.open('/path/to/doc.docx', {
|
|
63818
|
+
* isCommentsEnabled: true,
|
|
63819
|
+
* });
|
|
63820
|
+
*
|
|
63821
|
+
* // With UI element (automatically not headless)
|
|
63822
|
+
* const editor = await Editor.open('/path/to/doc.docx', {
|
|
63823
|
+
* element: document.getElementById('editor'),
|
|
63824
|
+
* });
|
|
63825
|
+
*
|
|
63826
|
+
* // Blank document
|
|
63827
|
+
* const editor = await Editor.open();
|
|
63828
|
+
* ```
|
|
63829
|
+
*/
|
|
63830
|
+
static async open(source, config2) {
|
|
63831
|
+
const hasElement = config2?.element != null || config2?.selector != null;
|
|
63832
|
+
const resolvedConfig = {
|
|
63833
|
+
mode: "docx",
|
|
63834
|
+
isHeadless: !hasElement,
|
|
63835
|
+
...config2
|
|
63836
|
+
};
|
|
63837
|
+
const {
|
|
63838
|
+
// OpenOptions (document-level)
|
|
63839
|
+
html: html2,
|
|
63840
|
+
markdown,
|
|
63841
|
+
isCommentsEnabled,
|
|
63842
|
+
suppressDefaultDocxStyles,
|
|
63843
|
+
documentMode,
|
|
63844
|
+
content: content2,
|
|
63845
|
+
mediaFiles,
|
|
63846
|
+
fonts,
|
|
63847
|
+
// Everything else is EditorOptions
|
|
63848
|
+
...editorConfig
|
|
63849
|
+
} = resolvedConfig;
|
|
63850
|
+
const openOptions = {
|
|
63851
|
+
mode: resolvedConfig.mode,
|
|
63852
|
+
html: html2,
|
|
63853
|
+
markdown,
|
|
63854
|
+
isCommentsEnabled,
|
|
63855
|
+
suppressDefaultDocxStyles,
|
|
63856
|
+
documentMode,
|
|
63857
|
+
content: content2,
|
|
63858
|
+
mediaFiles,
|
|
63859
|
+
fonts
|
|
63860
|
+
};
|
|
63861
|
+
const editor = new Editor({ ...editorConfig, deferDocumentLoad: true });
|
|
63862
|
+
await editor.open(source, openOptions);
|
|
63863
|
+
return editor;
|
|
63864
|
+
}
|
|
63865
|
+
/**
|
|
63866
|
+
* Close the current document.
|
|
63867
|
+
*
|
|
63868
|
+
* This unloads the document but keeps the editor instance alive.
|
|
63869
|
+
* The editor can be reused by calling `open()` again.
|
|
63870
|
+
*
|
|
63871
|
+
* This method is idempotent - calling it when already closed is a no-op.
|
|
63872
|
+
*
|
|
63873
|
+
* @example
|
|
63874
|
+
* ```typescript
|
|
63875
|
+
* await editor.open('/doc1.docx');
|
|
63876
|
+
* // ... work with document ...
|
|
63877
|
+
* editor.close();
|
|
63878
|
+
*
|
|
63879
|
+
* await editor.open('/doc2.docx'); // Reuse the same editor
|
|
63880
|
+
* ```
|
|
63881
|
+
*/
|
|
63882
|
+
close() {
|
|
63883
|
+
if (this.#editorLifecycleState === "closed" || this.#editorLifecycleState === "initialized") {
|
|
63884
|
+
return;
|
|
63885
|
+
}
|
|
63886
|
+
if (this.#editorLifecycleState === "destroyed") {
|
|
63887
|
+
return;
|
|
63888
|
+
}
|
|
63889
|
+
this.#assertState("ready");
|
|
63890
|
+
this.emit("documentClose", { editor: this });
|
|
63891
|
+
this.#unloadDocument();
|
|
63892
|
+
this.#editorLifecycleState = "closed";
|
|
63893
|
+
}
|
|
63894
|
+
/**
|
|
63895
|
+
* Save the document to the original source path.
|
|
63896
|
+
*
|
|
63897
|
+
* Only works if the document was opened from a file path.
|
|
63898
|
+
* If opened from Blob/Buffer or created blank, use `saveTo()` or `exportDocument()`.
|
|
63899
|
+
*
|
|
63900
|
+
* @param options - Save options (comments, final doc, etc.)
|
|
63901
|
+
* @throws {InvalidStateError} If editor is not in 'ready' state
|
|
63902
|
+
* @throws {NoSourcePathError} If no source path is available
|
|
63903
|
+
* @throws {FileSystemNotAvailableError} If file system access is not available
|
|
63904
|
+
*
|
|
63905
|
+
* @example
|
|
63906
|
+
* ```typescript
|
|
63907
|
+
* const editor = await Editor.open('/path/to/doc.docx');
|
|
63908
|
+
* // ... make changes ...
|
|
63909
|
+
* await editor.save(); // Saves back to /path/to/doc.docx
|
|
63910
|
+
* ```
|
|
63911
|
+
*/
|
|
63912
|
+
async save(options) {
|
|
63913
|
+
this.#assertState("ready");
|
|
63914
|
+
if (!this.#sourcePath) {
|
|
63915
|
+
throw new NoSourcePathError("No source path. Use saveTo(path) or exportDocument() instead.");
|
|
63916
|
+
}
|
|
63917
|
+
await this.#withState("saving", "ready", "ready", async () => {
|
|
63918
|
+
const data = await this.exportDocument(options);
|
|
63919
|
+
await this.#writeToPath(this.#sourcePath, data);
|
|
63920
|
+
});
|
|
63921
|
+
}
|
|
63922
|
+
/**
|
|
63923
|
+
* Save the document to a specific path.
|
|
63924
|
+
*
|
|
63925
|
+
* Updates the source path to the new location after saving.
|
|
63926
|
+
*
|
|
63927
|
+
* @param path - File path to save to
|
|
63928
|
+
* @param options - Save options
|
|
63929
|
+
* @throws {InvalidStateError} If editor is not in 'ready' state
|
|
63930
|
+
* @throws {FileSystemNotAvailableError} If file system access is not available
|
|
63931
|
+
*
|
|
63932
|
+
* @example
|
|
63933
|
+
* ```typescript
|
|
63934
|
+
* const editor = await Editor.open(blobData); // No source path
|
|
63935
|
+
* await editor.saveTo('/path/to/new-doc.docx');
|
|
63936
|
+
* await editor.save(); // Now saves to /path/to/new-doc.docx
|
|
63937
|
+
* ```
|
|
63938
|
+
*/
|
|
63939
|
+
async saveTo(path2, options) {
|
|
63940
|
+
this.#assertState("ready");
|
|
63941
|
+
await this.#withState("saving", "ready", "ready", async () => {
|
|
63942
|
+
const data = await this.exportDocument(options);
|
|
63943
|
+
await this.#writeToPath(path2, data);
|
|
63944
|
+
this.#sourcePath = path2;
|
|
63945
|
+
});
|
|
63946
|
+
}
|
|
63947
|
+
/**
|
|
63948
|
+
* Export the document as a Blob or Buffer.
|
|
63949
|
+
*
|
|
63950
|
+
* This is a convenience wrapper around `exportDocx()` that returns
|
|
63951
|
+
* the document data without writing to a file.
|
|
63952
|
+
*
|
|
63953
|
+
* @param options - Export options
|
|
63954
|
+
* @returns Promise resolving to Blob (browser) or Buffer (Node.js)
|
|
63955
|
+
* @throws {InvalidStateError} If editor is not in 'ready' state
|
|
63956
|
+
*
|
|
63957
|
+
* @example
|
|
63958
|
+
* ```typescript
|
|
63959
|
+
* const blob = await editor.exportDocument();
|
|
63960
|
+
*
|
|
63961
|
+
* // Create download link in browser
|
|
63962
|
+
* const url = URL.createObjectURL(blob);
|
|
63963
|
+
* const a = document.createElement('a');
|
|
63964
|
+
* a.href = url;
|
|
63965
|
+
* a.download = 'document.docx';
|
|
63966
|
+
* a.click();
|
|
63967
|
+
* ```
|
|
63968
|
+
*/
|
|
63969
|
+
async exportDocument(options) {
|
|
63970
|
+
this.#assertState("ready", "saving");
|
|
63971
|
+
const result = await this.exportDocx({
|
|
63972
|
+
isFinalDoc: options?.isFinalDoc,
|
|
63973
|
+
commentsType: options?.commentsType,
|
|
63974
|
+
comments: options?.comments,
|
|
63975
|
+
fieldsHighlightColor: options?.fieldsHighlightColor
|
|
63976
|
+
});
|
|
63977
|
+
return result;
|
|
63978
|
+
}
|
|
63979
|
+
/**
|
|
63980
|
+
* Writes document data to a file path.
|
|
63981
|
+
*
|
|
63982
|
+
* **Browser behavior:**
|
|
63983
|
+
* In browsers, the `path` parameter is only used as a suggested filename.
|
|
63984
|
+
* The File System Access API shows a save dialog and the user chooses the actual location.
|
|
63985
|
+
*
|
|
63986
|
+
* **Node.js behavior:**
|
|
63987
|
+
* The path is an actual filesystem path, written directly.
|
|
63988
|
+
*/
|
|
63989
|
+
async #writeToPath(path2, data) {
|
|
63990
|
+
const isNode2 = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" && globalThis.process.versions?.node != null;
|
|
63991
|
+
const hasNodeBuffer = typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function";
|
|
63992
|
+
if (isNode2 || hasNodeBuffer) {
|
|
63993
|
+
try {
|
|
63994
|
+
const fs = require("fs");
|
|
63995
|
+
const buffer2 = Buffer.isBuffer(data) ? data : Buffer.from(await data.arrayBuffer());
|
|
63996
|
+
fs.writeFileSync(path2, buffer2);
|
|
63997
|
+
return;
|
|
63998
|
+
} catch {
|
|
63999
|
+
}
|
|
64000
|
+
}
|
|
64001
|
+
if (typeof window !== "undefined" && "showSaveFilePicker" in window) {
|
|
64002
|
+
const handle2 = await window.showSaveFilePicker({
|
|
64003
|
+
suggestedName: path2.split("/").pop() || "document.docx",
|
|
64004
|
+
types: [
|
|
64005
|
+
{
|
|
64006
|
+
description: "Word Document",
|
|
64007
|
+
accept: { "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [".docx"] }
|
|
64008
|
+
}
|
|
64009
|
+
]
|
|
64010
|
+
});
|
|
64011
|
+
const writable = await handle2.createWritable();
|
|
64012
|
+
await writable.write(data);
|
|
64013
|
+
await writable.close();
|
|
64014
|
+
return;
|
|
64015
|
+
}
|
|
64016
|
+
throw new FileSystemNotAvailableError(
|
|
64017
|
+
"File System Access API not available. Use exportDocument() to get the document data and handle the download manually."
|
|
64018
|
+
);
|
|
64019
|
+
}
|
|
63377
64020
|
/**
|
|
63378
64021
|
* Destroy the editor and clean up resources
|
|
63379
64022
|
*/
|
|
63380
64023
|
destroy() {
|
|
64024
|
+
if (this.#editorLifecycleState === "ready") {
|
|
64025
|
+
this.close();
|
|
64026
|
+
}
|
|
64027
|
+
if (this.#editorLifecycleState === "destroyed") {
|
|
64028
|
+
return;
|
|
64029
|
+
}
|
|
63381
64030
|
this.#isDestroyed = true;
|
|
63382
64031
|
this.emit("destroy");
|
|
63383
64032
|
this.unmount();
|
|
63384
64033
|
this.destroyHeaderFooterEditors();
|
|
63385
64034
|
this.#endCollaboration();
|
|
63386
64035
|
this.removeAllListeners();
|
|
64036
|
+
this.extensionService = void 0;
|
|
64037
|
+
this.schema = void 0;
|
|
64038
|
+
this.#commandService = void 0;
|
|
64039
|
+
this.#editorLifecycleState = "destroyed";
|
|
63387
64040
|
}
|
|
63388
64041
|
destroyHeaderFooterEditors() {
|
|
63389
64042
|
try {
|
|
@@ -63415,7 +64068,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
63415
64068
|
* Process collaboration migrations
|
|
63416
64069
|
*/
|
|
63417
64070
|
processCollaborationMigrations() {
|
|
63418
|
-
console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.
|
|
64071
|
+
console.debug("[checkVersionMigrations] Current editor version", "2.0.0-next.23");
|
|
63419
64072
|
if (!this.options.ydoc) return;
|
|
63420
64073
|
const metaMap = this.options.ydoc.getMap("meta");
|
|
63421
64074
|
let docVersion = metaMap.get("version");
|
|
@@ -141731,7 +142384,7 @@ ${reason}`);
|
|
|
141731
142384
|
this.config.colors = shuffleArray(this.config.colors);
|
|
141732
142385
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
141733
142386
|
this.colorIndex = 0;
|
|
141734
|
-
this.version = "2.0.0-next.
|
|
142387
|
+
this.version = "2.0.0-next.23";
|
|
141735
142388
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
141736
142389
|
this.superdocId = config2.superdocId || v4();
|
|
141737
142390
|
this.colors = this.config.colors;
|