myrole-docx-editor 0.1.4 → 0.2.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 +59 -0
- package/dist/chunks/{sdk-DZeo_8qT.js → sdk-BM5tI24s.js} +8211 -7688
- package/dist/chunks/sdk-BM5tI24s.js.map +1 -0
- package/dist/chunks/{vars-blockly-EQQZFx30.js → vars-blockly-BQPk_GUT.js} +2 -2
- package/dist/chunks/{vars-blockly-EQQZFx30.js.map → vars-blockly-BQPk_GUT.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/react.js +31 -29
- package/dist/react.js.map +1 -1
- package/dist/types/packages/docx-editor/src/authoring-ui.d.ts +3 -0
- package/dist/types/packages/docx-editor/src/comment-ui.d.ts +4 -0
- package/dist/types/packages/docx-editor/src/comments.d.ts +2 -24
- package/dist/types/packages/docx-editor/src/editor.d.ts +9 -1
- package/dist/types/packages/docx-editor/src/index.d.ts +1 -0
- package/dist/types/packages/docx-editor/src/locking.d.ts +37 -0
- package/dist/types/packages/docx-editor/src/react.d.ts +1 -0
- package/dist/types/packages/docx-editor/src/sdk.d.ts +15 -2
- package/dist/types/packages/docx-model/src/authoring.d.ts +10 -0
- package/dist/types/packages/docx-model/src/comments.d.ts +30 -0
- package/dist/types/packages/docx-model/src/editor.d.ts +1 -1
- package/dist/types/packages/docx-model/src/index.d.ts +2 -0
- package/dist/types/packages/docx-model/src/insert.d.ts +8 -1
- package/dist/types/packages/docx-model/src/paste.d.ts +6 -0
- package/dist/types/packages/docx-model/src/spans.d.ts +2 -0
- package/package.json +3 -3
- package/dist/chunks/sdk-DZeo_8qT.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as s from "blockly";
|
|
2
|
-
import { k as p, T as u, m, n as f, o as g, q as h } from "./sdk-
|
|
2
|
+
import { k as p, T as u, m, n as f, o as g, q as h } from "./sdk-BM5tI24s.js";
|
|
3
3
|
let r = !1;
|
|
4
4
|
function b(o, n, i) {
|
|
5
5
|
r || (p(), r = !0), o.replaceChildren();
|
|
@@ -39,4 +39,4 @@ function b(o, n, i) {
|
|
|
39
39
|
export {
|
|
40
40
|
b as mountBlockly
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=vars-blockly-
|
|
42
|
+
//# sourceMappingURL=vars-blockly-BQPk_GUT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vars-blockly-
|
|
1
|
+
{"version":3,"file":"vars-blockly-BQPk_GUT.js","sources":["../../src/vars-blockly.ts"],"sourcesContent":["import * as Blockly from 'blockly'\nimport {\n decorate, defineBlocks, fieldLibrary, setFields, THEME, TOOLBOX,\n type BlockJson,\n} from '@myrole/docx-vars'\nimport type { Tag } from '@myrole/docx-tags'\n\n/**\n * Le mode Blockly, chargé à la demande.\n *\n * Le canvas ne se replie pas — c'est ce qui a fait choisir le rendu DOM par\n * défaut — mais il sait ce que le DOM ne fait pas encore aussi bien :\n * restructurer librement une expression au glisser-déposer, avec sa poubelle,\n * son annulation et ses connexions typées.\n *\n * Il vit dans son propre module pour ne peser que si on l'ouvre : un\n * mégaoctet et demi qu'un utilisateur qui ne bascule jamais ne télécharge pas.\n */\n\nlet defined = false\n\nexport interface BlocklyView {\n load(tree: BlockJson): void\n read(): BlockJson | null\n resize(): void\n dispose(): void\n}\n\nexport function mountBlockly(\n holder: HTMLElement, onChange: () => void, tags: () => Tag[],\n): BlocklyView {\n if (!defined) { defineBlocks(); defined = true }\n holder.replaceChildren()\n const host = document.createElement('div')\n host.className = 'vp-canvas-host'\n holder.append(host)\n\n const ws = Blockly.inject(host, {\n // La boîte à outils : sans elle, on peut lire une expression et la\n // rebrancher, mais pas y AJOUTER quoi que ce soit — c'est la moitié de ce\n // qu'on vient chercher dans un canvas de blocs.\n toolbox: TOOLBOX,\n theme: THEME,\n renderer: 'geras',\n trashcan: true,\n sounds: false,\n grid: { spacing: 20, length: 1, colour: '#e8e9ed', snap: false },\n zoom: { controls: true, wheel: true, startScale: 0.95, minScale: 0.3, maxScale: 2 },\n move: { scrollbars: true, drag: true, wheel: true },\n })\n ws.addChangeListener((e) => { if (!e.isUiEvent) onChange() })\n\n return {\n load(tree) {\n // `setFields` alimente le sélecteur du bloc « champ » : sans lui, un clic\n // sur un champ n'ouvre rien.\n const groups = fieldLibrary(tags())\n setFields(groups.flatMap((g) => g.fields.map((f) => ({ path: f.path, label: f.label }))))\n Blockly.serialization.workspaces.load({ blocks: { languageVersion: 0, blocks: [tree] } }, ws)\n decorate(ws)\n Blockly.svgResize(ws)\n },\n read() {\n const state = Blockly.serialization.workspaces.save(ws) as {\n blocks?: { blocks?: BlockJson[] }\n }\n return state?.blocks?.blocks?.[0] ?? null\n },\n resize() { Blockly.svgResize(ws) },\n dispose() { ws.dispose() },\n }\n}\n"],"names":["defined","mountBlockly","holder","onChange","tags","defineBlocks","host","ws","Blockly","TOOLBOX","THEME","e","tree","groups","fieldLibrary","setFields","g","f","decorate"],"mappings":";;AAmBA,IAAIA,IAAU;AASP,SAASC,EACdC,GAAqBC,GAAsBC,GAC9B;AACb,EAAKJ,MAAWK,EAAA,GAAgBL,IAAU,KAC1CE,EAAO,gBAAA;AACP,QAAMI,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,kBACjBJ,EAAO,OAAOI,CAAI;AAElB,QAAMC,IAAKC,EAAQ,OAAOF,GAAM;AAAA;AAAA;AAAA;AAAA,IAI9B,SAASG;AAAA,IACT,OAAOC;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,EAAE,SAAS,IAAI,QAAQ,GAAG,QAAQ,WAAW,MAAM,GAAA;AAAA,IACzD,MAAM,EAAE,UAAU,IAAM,OAAO,IAAM,YAAY,MAAM,UAAU,KAAK,UAAU,EAAA;AAAA,IAChF,MAAM,EAAE,YAAY,IAAM,MAAM,IAAM,OAAO,GAAA;AAAA,EAAK,CACnD;AACD,SAAAH,EAAG,kBAAkB,CAACI,MAAM;AAAE,IAAKA,EAAE,aAAWR,EAAA;AAAA,EAAW,CAAC,GAErD;AAAA,IACL,KAAKS,GAAM;AAGT,YAAMC,IAASC,EAAaV,GAAM;AAClC,MAAAW,EAAUF,EAAO,QAAQ,CAACG,MAAMA,EAAE,OAAO,IAAI,CAACC,OAAO,EAAE,MAAMA,EAAE,MAAM,OAAOA,EAAE,MAAA,EAAQ,CAAC,CAAC,GACxFT,EAAQ,cAAc,WAAW,KAAK,EAAE,QAAQ,EAAE,iBAAiB,GAAG,QAAQ,CAACI,CAAI,EAAA,EAAE,GAAKL,CAAE,GAC5FW,EAASX,CAAE,GACXC,EAAQ,UAAUD,CAAE;AAAA,IACtB;AAAA,IACA,OAAO;AAIL,aAHcC,EAAQ,cAAc,WAAW,KAAKD,CAAE,GAGxC,QAAQ,SAAS,CAAC,KAAK;AAAA,IACvC;AAAA,IACA,SAAS;AAAE,MAAAC,EAAQ,UAAUD,CAAE;AAAA,IAAE;AAAA,IACjC,UAAU;AAAE,MAAAA,EAAG,QAAA;AAAA,IAAU;AAAA,EAAA;AAE7B;"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as f, r as m, e as w, f as p, p as u, l as y, a as g, b as h, c as x } from "./chunks/sdk-
|
|
2
|
-
import { d as R, g as b, h as U, j, s as A } from "./chunks/sdk-
|
|
1
|
+
import { i as f, r as m, e as w, f as p, p as u, l as y, a as g, b as h, c as x } from "./chunks/sdk-BM5tI24s.js";
|
|
2
|
+
import { d as R, g as b, h as U, j, s as A } from "./chunks/sdk-BM5tI24s.js";
|
|
3
3
|
async function P(a, o, r = {}) {
|
|
4
4
|
const i = performance.now(), [c] = await Promise.all([
|
|
5
5
|
typeof a == "string" ? fetch(a).then((e) => e.ok ? e.arrayBuffer() : Promise.reject(new Error(`${e.status} ${a}`))) : Promise.resolve(a),
|
package/dist/react.js
CHANGED
|
@@ -1,52 +1,54 @@
|
|
|
1
1
|
import { jsx as h } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as v, useRef as
|
|
3
|
-
import { d as
|
|
4
|
-
const s = v(function({ src: u, className:
|
|
5
|
-
const l =
|
|
6
|
-
|
|
2
|
+
import { forwardRef as v, useRef as o, useEffect as a } from "react";
|
|
3
|
+
import { d as y } from "./chunks/sdk-BM5tI24s.js";
|
|
4
|
+
const s = v(function({ src: u, className: b, style: S, onReady: g, ...e }, f) {
|
|
5
|
+
const l = o(null), c = o(null), n = o(e);
|
|
6
|
+
n.current = e;
|
|
7
7
|
const m = (r) => {
|
|
8
|
-
typeof
|
|
8
|
+
typeof f == "function" ? f(r) : f && (f.current = r);
|
|
9
9
|
};
|
|
10
|
-
return
|
|
11
|
-
const r =
|
|
10
|
+
return a(() => {
|
|
11
|
+
const r = y(l.current, {
|
|
12
12
|
...e,
|
|
13
|
-
onSave: e.onSave ? (
|
|
14
|
-
onError: (
|
|
15
|
-
onSaveState: (
|
|
16
|
-
|
|
13
|
+
onSave: e.onSave ? (t, d) => n.current.onSave(t, d) : void 0,
|
|
14
|
+
onError: (t) => n.current.onError?.(t),
|
|
15
|
+
onSaveState: (t) => n.current.onSaveState?.(t),
|
|
16
|
+
onLockState: (t) => n.current.onLockState?.(t),
|
|
17
|
+
onChange: () => n.current.onChange?.(),
|
|
17
18
|
feedback: typeof e.feedback == "object" ? {
|
|
18
19
|
...e.feedback,
|
|
19
|
-
onSubmit: e.feedback.onSubmit ? (
|
|
20
|
-
const
|
|
21
|
-
if (typeof
|
|
22
|
-
return
|
|
20
|
+
onSubmit: e.feedback.onSubmit ? (t) => {
|
|
21
|
+
const d = n.current.feedback;
|
|
22
|
+
if (typeof d != "object" || !d.onSubmit) throw new Error("Feedback submission handler is no longer configured");
|
|
23
|
+
return d.onSubmit(t);
|
|
23
24
|
} : void 0
|
|
24
25
|
} : e.feedback
|
|
25
26
|
});
|
|
26
|
-
return c.current = r, m(r),
|
|
27
|
+
return c.current = r, m(r), g?.(r), () => {
|
|
27
28
|
r.destroy(), c.current = null, m(null);
|
|
28
29
|
};
|
|
29
|
-
}, [e.draftKey, e.chrome, !!e.onSave]),
|
|
30
|
-
u && c.current && c.current.load(u).catch((r) =>
|
|
31
|
-
}, [u, e.draftKey, e.chrome, !!e.onSave]),
|
|
30
|
+
}, [e.draftKey, e.chrome, !!e.onSave]), a(() => {
|
|
31
|
+
u && c.current && c.current.load(u).catch((r) => n.current.onError?.(r));
|
|
32
|
+
}, [u, e.draftKey, e.chrome, !!e.onSave]), a(() => {
|
|
32
33
|
e.theme && c.current?.setTheme(e.theme);
|
|
33
|
-
}, [e.theme]),
|
|
34
|
+
}, [e.theme]), a(() => {
|
|
34
35
|
c.current?.setReadOnly(e.readOnly ?? !1);
|
|
35
|
-
}, [e.readOnly]),
|
|
36
|
+
}, [e.readOnly]), a(() => {
|
|
36
37
|
e.zoom !== void 0 && c.current?.setZoom(e.zoom);
|
|
37
|
-
}, [e.zoom]),
|
|
38
|
+
}, [e.zoom]), a(() => {
|
|
38
39
|
e.badges !== void 0 && c.current?.variables.setDisplay(e.badges);
|
|
39
|
-
}, [typeof e.badges == "boolean" ? e.badges : e.badges?.variables, typeof e.badges == "boolean" ? e.badges : e.badges?.expressions]), /* @__PURE__ */ h("div", { ref: l, className:
|
|
40
|
+
}, [typeof e.badges == "boolean" ? e.badges : e.badges?.variables, typeof e.badges == "boolean" ? e.badges : e.badges?.expressions]), /* @__PURE__ */ h("div", { ref: l, className: b, style: { height: "100%", minHeight: 320, minWidth: 0, ...S } });
|
|
40
41
|
});
|
|
41
42
|
function D() {
|
|
42
|
-
return
|
|
43
|
+
return o(null);
|
|
43
44
|
}
|
|
44
|
-
const
|
|
45
|
-
return /* @__PURE__ */ h(s, { ...u, ref:
|
|
46
|
-
});
|
|
45
|
+
const O = v(function(u, b) {
|
|
46
|
+
return /* @__PURE__ */ h(s, { ...u, ref: b, chrome: "viewer", readOnly: !0 });
|
|
47
|
+
}), w = 1;
|
|
47
48
|
export {
|
|
49
|
+
w as DOCX_LOCKING_VERSION,
|
|
48
50
|
s as DocxEditor,
|
|
49
|
-
|
|
51
|
+
O as DocxViewer,
|
|
50
52
|
D as useDocxEditor
|
|
51
53
|
};
|
|
52
54
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["/**\n * The React face of the SDK.\n *\n * <DocxEditor src={file} onSave={(bytes) => upload(bytes)} style={{ height: '100vh' }} />\n *\n * The component owns one `createDocxEditor` for its lifetime; `src` changes\n * reload the document in place, every other option is read at mount. React is\n * an optional peer: nothing here runs unless `myrole-docx-editor/react` is\n * imported.\n */\nimport { useEffect, useRef, forwardRef, type CSSProperties } from 'react'\nimport { createDocxEditor, type DocxEditorHandle, type DocxEditorOptions } from './sdk'\n\nexport interface DocxEditorProps extends Omit<DocxEditorOptions, 'onReady'> {\n /** the document: bytes, a Blob/File, or a URL */\n src?: ArrayBuffer | Uint8Array | Blob | string\n className?: string\n style?: CSSProperties\n /** the handle, once mounted */\n onReady?: (editor: DocxEditorHandle) => void\n}\n\nexport const DocxEditor = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxEditor(\n { src, className, style, onReady, ...options }, ref,\n) {\n const host = useRef<HTMLDivElement>(null)\n const handle = useRef<DocxEditorHandle | null>(null)\n // The latest callbacks, without remounting the editor when they change.\n const latest = useRef(options)\n latest.current = options\n\n // The forwarded ref is filled HERE, not by useImperativeHandle: that one\n // runs in the layout phase, before this effect has created anything, and\n // would hand the parent a null for the component's whole life.\n const give = (h: DocxEditorHandle | null) => {\n if (typeof ref === 'function') ref(h)\n else if (ref) ref.current = h\n }\n\n useEffect(() => {\n const h = createDocxEditor(host.current!, {\n ...options,\n onSave: options.onSave ? (b) => latest.current.onSave!(b) : undefined,\n onError: e => latest.current.onError?.(e),\n onSaveState: state => latest.current.onSaveState?.(state),\n onChange: () => latest.current.onChange?.(),\n feedback: typeof options.feedback === 'object' ? {\n ...options.feedback,\n onSubmit: options.feedback.onSubmit ? report => {\n const feedback = latest.current.feedback\n if (typeof feedback !== 'object' || !feedback.onSubmit) throw new Error('Feedback submission handler is no longer configured')\n return feedback.onSubmit(report)\n } : undefined,\n } : options.feedback,\n })\n handle.current = h\n give(h)\n onReady?.(h)\n return () => { h.destroy(); handle.current = null; give(null) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options.draftKey, options.chrome, !!options.onSave])\n\n useEffect(() => {\n if (src && handle.current) void handle.current.load(src).catch(e => latest.current.onError?.(e))\n }, [src, options.draftKey, options.chrome, !!options.onSave])\n useEffect(() => { if (options.theme) handle.current?.setTheme(options.theme) }, [options.theme])\n useEffect(() => { handle.current?.setReadOnly(options.readOnly ?? false) }, [options.readOnly])\n useEffect(() => { if (options.zoom !== undefined) handle.current?.setZoom(options.zoom) }, [options.zoom])\n useEffect(() => { if (options.badges !== undefined) handle.current?.variables.setDisplay(options.badges) }, [typeof options.badges === 'boolean' ? options.badges : options.badges?.variables, typeof options.badges === 'boolean' ? options.badges : options.badges?.expressions])\n\n return <div ref={host} className={className} style={{ height: '100%', minHeight: 320, minWidth: 0, ...style }} />\n})\n\n/** A ref to hand to `<DocxEditor ref={…}>`, and the handle once it exists. */\nexport function useDocxEditor() {\n return useRef<DocxEditorHandle | null>(null)\n}\n\nexport type { DocxEditorHandle, DocxEditorOptions } from './sdk'\n\n/** Read-only companion, with the same rendering and lifecycle as the editor. */\nexport const DocxViewer = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxViewer(props, ref) {\n return <DocxEditor {...props} ref={ref} chrome=\"viewer\" readOnly />\n})\n"],"names":["DocxEditor","forwardRef","src","className","style","onReady","options","ref","host","useRef","handle","latest","give","h","useEffect","createDocxEditor","b","e","state","report","feedback","jsx","useDocxEditor","DocxViewer","props"],"mappings":";;;AAsBO,MAAMA,IAAaC,EAAqD,SAC7E,EAAE,KAAAC,GAAK,WAAAC,GAAW,OAAAC,GAAO,SAAAC,GAAS,GAAGC,EAAA,GAAWC,GAChD;AACA,QAAMC,IAAOC,EAAuB,IAAI,GAClCC,IAASD,EAAgC,IAAI,GAE7CE,IAASF,EAAOH,CAAO;AAC7B,EAAAK,EAAO,UAAUL;AAKjB,QAAMM,IAAO,CAACC,MAA+B;AAC3C,IAAI,OAAON,KAAQ,aAAYA,EAAIM,CAAC,IAC3BN,QAAS,UAAUM;AAAA,EAC9B;AAEA,SAAAC,EAAU,MAAM;AACd,UAAMD,IAAIE,EAAiBP,EAAK,SAAU;AAAA,MACxC,GAAGF;AAAA,MACH,QAAQA,EAAQ,SAAS,CAACU,
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["/**\n * The React face of the SDK.\n *\n * <DocxEditor src={file} onSave={(bytes) => upload(bytes)} style={{ height: '100vh' }} />\n *\n * The component owns one `createDocxEditor` for its lifetime; `src` changes\n * reload the document in place, every other option is read at mount. React is\n * an optional peer: nothing here runs unless `myrole-docx-editor/react` is\n * imported.\n */\nimport { useEffect, useRef, forwardRef, type CSSProperties } from 'react'\nimport { createDocxEditor, type DocxEditorHandle, type DocxEditorOptions } from './sdk'\n\nexport interface DocxEditorProps extends Omit<DocxEditorOptions, 'onReady'> {\n /** the document: bytes, a Blob/File, or a URL */\n src?: ArrayBuffer | Uint8Array | Blob | string\n className?: string\n style?: CSSProperties\n /** the handle, once mounted */\n onReady?: (editor: DocxEditorHandle) => void\n}\n\nexport const DocxEditor = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxEditor(\n { src, className, style, onReady, ...options }, ref,\n) {\n const host = useRef<HTMLDivElement>(null)\n const handle = useRef<DocxEditorHandle | null>(null)\n // The latest callbacks, without remounting the editor when they change.\n const latest = useRef(options)\n latest.current = options\n\n // The forwarded ref is filled HERE, not by useImperativeHandle: that one\n // runs in the layout phase, before this effect has created anything, and\n // would hand the parent a null for the component's whole life.\n const give = (h: DocxEditorHandle | null) => {\n if (typeof ref === 'function') ref(h)\n else if (ref) ref.current = h\n }\n\n useEffect(() => {\n const h = createDocxEditor(host.current!, {\n ...options,\n onSave: options.onSave ? (b, context) => latest.current.onSave!(b, context) : undefined,\n onError: e => latest.current.onError?.(e),\n onSaveState: state => latest.current.onSaveState?.(state),\n onLockState: state => latest.current.onLockState?.(state),\n onChange: () => latest.current.onChange?.(),\n feedback: typeof options.feedback === 'object' ? {\n ...options.feedback,\n onSubmit: options.feedback.onSubmit ? report => {\n const feedback = latest.current.feedback\n if (typeof feedback !== 'object' || !feedback.onSubmit) throw new Error('Feedback submission handler is no longer configured')\n return feedback.onSubmit(report)\n } : undefined,\n } : options.feedback,\n })\n handle.current = h\n give(h)\n onReady?.(h)\n return () => { h.destroy(); handle.current = null; give(null) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options.draftKey, options.chrome, !!options.onSave])\n\n useEffect(() => {\n if (src && handle.current) void handle.current.load(src).catch(e => latest.current.onError?.(e))\n }, [src, options.draftKey, options.chrome, !!options.onSave])\n useEffect(() => { if (options.theme) handle.current?.setTheme(options.theme) }, [options.theme])\n useEffect(() => { handle.current?.setReadOnly(options.readOnly ?? false) }, [options.readOnly])\n useEffect(() => { if (options.zoom !== undefined) handle.current?.setZoom(options.zoom) }, [options.zoom])\n useEffect(() => { if (options.badges !== undefined) handle.current?.variables.setDisplay(options.badges) }, [typeof options.badges === 'boolean' ? options.badges : options.badges?.variables, typeof options.badges === 'boolean' ? options.badges : options.badges?.expressions])\n\n return <div ref={host} className={className} style={{ height: '100%', minHeight: 320, minWidth: 0, ...style }} />\n})\n\n/** A ref to hand to `<DocxEditor ref={…}>`, and the handle once it exists. */\nexport function useDocxEditor() {\n return useRef<DocxEditorHandle | null>(null)\n}\n\nexport type { DocxEditorHandle, DocxEditorOptions } from './sdk'\n\n/** Read-only companion, with the same rendering and lifecycle as the editor. */\nexport const DocxViewer = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxViewer(props, ref) {\n return <DocxEditor {...props} ref={ref} chrome=\"viewer\" readOnly />\n})\n\nexport const DOCX_LOCKING_VERSION = 1\n"],"names":["DocxEditor","forwardRef","src","className","style","onReady","options","ref","host","useRef","handle","latest","give","h","useEffect","createDocxEditor","b","context","e","state","report","feedback","jsx","useDocxEditor","DocxViewer","props","DOCX_LOCKING_VERSION"],"mappings":"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"}
|
|
@@ -1,24 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* `word/comments.xml` holds the comments; the body marks each range with
|
|
5
|
-
* `w:commentRangeStart` / `w:commentRangeEnd` between the runs. The offsets
|
|
6
|
-
* are counted the way `paragraphText` counts — `w:t` text, a tab, a break —
|
|
7
|
-
* so a comment's range is addressable by the editor like any selection.
|
|
8
|
-
*/
|
|
9
|
-
import { type DocxDocument } from '../../docx-model/src/index';
|
|
10
|
-
export interface Comment {
|
|
11
|
-
id: string;
|
|
12
|
-
author: string;
|
|
13
|
-
date?: string;
|
|
14
|
-
text: string;
|
|
15
|
-
}
|
|
16
|
-
export interface CommentRange extends Comment {
|
|
17
|
-
para: number;
|
|
18
|
-
from: number;
|
|
19
|
-
to: number;
|
|
20
|
-
}
|
|
21
|
-
/** The comments, in the order comments.xml declares them. */
|
|
22
|
-
export declare function commentsOf(doc: DocxDocument): Comment[];
|
|
23
|
-
/** Each comment with its range in the body — a comment whose range is not in the flow is left out. */
|
|
24
|
-
export declare function commentRanges(doc: DocxDocument): CommentRange[];
|
|
1
|
+
export { commentsOf, commentRanges } from '../../docx-model/src/index';
|
|
2
|
+
export type { Comment, CommentRange } from '../../docx-model/src/index';
|
|
@@ -169,6 +169,14 @@ export declare function createEditor(setup: EditorSetup): {
|
|
|
169
169
|
from: number;
|
|
170
170
|
to: number;
|
|
171
171
|
} | null;
|
|
172
|
+
addComment(text: string, author?: string): string | null;
|
|
173
|
+
updateComment: (id: string, text: string) => boolean;
|
|
174
|
+
deleteComment: (id: string) => boolean;
|
|
175
|
+
defineStyle(name: string, id?: string): string | null;
|
|
176
|
+
link: () => string | null;
|
|
177
|
+
setLink(target: string | null): boolean;
|
|
178
|
+
setListLevel(level: number): void;
|
|
179
|
+
restartList(start?: number): boolean;
|
|
172
180
|
setList(ordered: boolean | null): void;
|
|
173
181
|
formatCell(patch: CellPatch): boolean;
|
|
174
182
|
mergeNextCell(): boolean;
|
|
@@ -262,7 +270,7 @@ export type Editor = ReturnType<typeof createEditor>;
|
|
|
262
270
|
* déplacement du curseur, `render` après chaque composition, `context` avec
|
|
263
271
|
* l'état complet sous le curseur, `commands` quand le registre bouge.
|
|
264
272
|
*/
|
|
265
|
-
export type EditorEvent = 'change' | 'selection' | 'render' | 'context' | 'commands' | 'load' | 'save' | 'command';
|
|
273
|
+
export type EditorEvent = 'change' | 'selection' | 'render' | 'context' | 'commands' | 'styles' | 'load' | 'save' | 'command';
|
|
266
274
|
/**
|
|
267
275
|
* Une commande ajoutée par l'hôte ou par une extension.
|
|
268
276
|
*
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type DocxLockState = {
|
|
2
|
+
status: 'idle' | 'acquiring' | 'held' | 'blocked' | 'lost' | 'released' | 'releasing';
|
|
3
|
+
owner?: string;
|
|
4
|
+
message?: string;
|
|
5
|
+
};
|
|
6
|
+
export type DocxLockResult = {
|
|
7
|
+
acquired: true;
|
|
8
|
+
ttlMs: number;
|
|
9
|
+
} | {
|
|
10
|
+
acquired: false;
|
|
11
|
+
owner?: string;
|
|
12
|
+
};
|
|
13
|
+
export interface DocxLockAdapter {
|
|
14
|
+
acquire(sessionId: string): Promise<DocxLockResult>;
|
|
15
|
+
renew(sessionId: string): Promise<DocxLockResult>;
|
|
16
|
+
release(sessionId: string): Promise<void>;
|
|
17
|
+
read(sessionId: string): Promise<Uint8Array>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createDocxLock(adapter: DocxLockAdapter, host: {
|
|
20
|
+
dirty(): boolean;
|
|
21
|
+
load(bytes: Uint8Array): Promise<void>;
|
|
22
|
+
save(): Promise<void>;
|
|
23
|
+
changed(state: DocxLockState): void;
|
|
24
|
+
}): {
|
|
25
|
+
id: `${string}-${string}-${string}-${string}-${string}`;
|
|
26
|
+
state: () => {
|
|
27
|
+
status: "idle" | "acquiring" | "held" | "blocked" | "lost" | "released" | "releasing";
|
|
28
|
+
owner?: string;
|
|
29
|
+
message?: string;
|
|
30
|
+
};
|
|
31
|
+
writable: () => boolean;
|
|
32
|
+
acquire: () => Promise<void>;
|
|
33
|
+
release: () => Promise<void>;
|
|
34
|
+
stopRenewing: () => void;
|
|
35
|
+
lost: (message?: string) => void;
|
|
36
|
+
destroy(): Promise<void>;
|
|
37
|
+
};
|
|
@@ -24,3 +24,4 @@ export declare function useDocxEditor(): import("react").RefObject<DocxEditorHan
|
|
|
24
24
|
export type { DocxEditorHandle, DocxEditorOptions } from './sdk';
|
|
25
25
|
/** Read-only companion, with the same rendering and lifecycle as the editor. */
|
|
26
26
|
export declare const DocxViewer: import("react").ForwardRefExoticComponent<DocxEditorProps & import("react").RefAttributes<DocxEditorHandle | null>>;
|
|
27
|
+
export declare const DOCX_LOCKING_VERSION = 1;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DocxLockAdapter, type DocxLockState } from './locking';
|
|
1
2
|
/**
|
|
2
3
|
* The SDK: one call mounts the Word-like editor in an element.
|
|
3
4
|
*
|
|
@@ -23,20 +24,24 @@ import { type FeedbackOptions } from './feedback';
|
|
|
23
24
|
export type ChromeMode = 'full' | 'viewer' | 'none';
|
|
24
25
|
export type Theme = 'light' | 'dark' | 'system';
|
|
25
26
|
export type { DocxEditorUiOptions } from './ui/shell';
|
|
26
|
-
export type DocxEditorEvent = 'load' | 'change' | 'selection' | 'render' | 'save' | 'context' | 'zoom' | 'saveState' | 'error' | 'command';
|
|
27
|
+
export type DocxEditorEvent = 'load' | 'change' | 'selection' | 'render' | 'save' | 'context' | 'zoom' | 'saveState' | 'error' | 'command' | 'lock';
|
|
27
28
|
export interface DocxEditorOptions {
|
|
28
29
|
/** `full`: ribbon, rulers, panels. `viewer`: read-only pages under a slim header. `none`: pages only. */
|
|
29
30
|
/** Development host compatibility only; npm instances expose no window globals or IDs. */
|
|
30
31
|
debug?: boolean;
|
|
31
32
|
chrome?: ChromeMode;
|
|
32
33
|
readOnly?: boolean;
|
|
34
|
+
lock?: DocxLockAdapter;
|
|
35
|
+
onLockState?: (state: DocxLockState) => void;
|
|
33
36
|
theme?: Theme;
|
|
34
37
|
/** directory that holds `ttf/` — see `fonts.ts` */
|
|
35
38
|
fontsUrl?: string | URL;
|
|
36
39
|
/** hard cap on the page count — a guard against a runaway layout, never an alignment */
|
|
37
40
|
maxPages?: number;
|
|
38
41
|
/** the document after a quiet period, and on tab change — where autosave goes */
|
|
39
|
-
onSave?: (bytes: Uint8Array
|
|
42
|
+
onSave?: (bytes: Uint8Array, context: {
|
|
43
|
+
lockId?: string;
|
|
44
|
+
}) => void | Promise<void>;
|
|
40
45
|
onChange?: () => void;
|
|
41
46
|
onError?: (error: Error) => void;
|
|
42
47
|
onSaveState?: (state: string) => void;
|
|
@@ -90,11 +95,19 @@ export interface DocxEditorHandle {
|
|
|
90
95
|
getZoom(): number;
|
|
91
96
|
setTheme(t: Theme): void;
|
|
92
97
|
setReadOnly(on: boolean): void;
|
|
98
|
+
lock: {
|
|
99
|
+
state(): DocxLockState;
|
|
100
|
+
acquire(): Promise<void>;
|
|
101
|
+
release(): Promise<void>;
|
|
102
|
+
} | null;
|
|
93
103
|
showPanel(p: Panel | null): void;
|
|
94
104
|
/** Open the feedback form; requires feedback to be enabled and a loaded document. */
|
|
95
105
|
openFeedback(): void;
|
|
96
106
|
/** Word's comments of the open document, with their ranges */
|
|
97
107
|
comments(): CommentRange[];
|
|
108
|
+
addComment(text: string, author?: string): string | null;
|
|
109
|
+
updateComment(id: string, text: string): boolean;
|
|
110
|
+
deleteComment(id: string): boolean;
|
|
98
111
|
showComments(on: boolean): void;
|
|
99
112
|
variables: {
|
|
100
113
|
tags(): Tag[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type DocxDocument } from './index';
|
|
2
|
+
import { type DocPos } from './editor';
|
|
3
|
+
/** Create a paragraph style from the selection, or update an existing style to match it. */
|
|
4
|
+
export declare function defineParagraphStyle(doc: DocxDocument, at: DocPos, name: string, id?: string): string | null;
|
|
5
|
+
/** Read a link at the caret using the same inline address as its writer. */
|
|
6
|
+
export declare function hyperlinkTarget(doc: DocxDocument, at: DocPos): string | null;
|
|
7
|
+
/** Set or remove a hyperlink in one inline container without flattening its content. */
|
|
8
|
+
export declare function setHyperlink(doc: DocxDocument, a: DocPos, b: DocPos, target: string | null): boolean;
|
|
9
|
+
/** Restart from this paragraph, keeping the following contiguous items in the same new list. */
|
|
10
|
+
export declare function restartList(doc: DocxDocument, at: DocPos, start?: number): number | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word's comments, and where they sit in the text.
|
|
3
|
+
*
|
|
4
|
+
* `word/comments.xml` holds the comments; the body marks each range with
|
|
5
|
+
* `w:commentRangeStart` / `w:commentRangeEnd` between the runs. The offsets
|
|
6
|
+
* are counted the way `paragraphText` counts — `w:t` text, a tab, a break —
|
|
7
|
+
* so a comment's range is addressable by the editor like any selection.
|
|
8
|
+
*/
|
|
9
|
+
import { type DocxDocument } from './index';
|
|
10
|
+
import { type DocPos } from './editor';
|
|
11
|
+
export interface Comment {
|
|
12
|
+
id: string;
|
|
13
|
+
author: string;
|
|
14
|
+
date?: string;
|
|
15
|
+
text: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CommentRange extends Comment {
|
|
18
|
+
para: number;
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
}
|
|
22
|
+
/** The comments, in the order comments.xml declares them. */
|
|
23
|
+
export declare function commentsOf(doc: DocxDocument): Comment[];
|
|
24
|
+
/** Each comment with its range in the body — a comment whose range is not in the flow is left out. */
|
|
25
|
+
export declare function commentRanges(doc: DocxDocument): CommentRange[];
|
|
26
|
+
/** Add a classic Word comment to a nonempty body selection, keeping existing parts intact. */
|
|
27
|
+
export declare function addComment(doc: DocxDocument, a: DocPos, b: DocPos, text: string, author?: string): string | null;
|
|
28
|
+
export declare function updateComment(doc: DocxDocument, id: string, text: string): boolean;
|
|
29
|
+
/** Remove this comment's definition and anchors; unrelated annotations remain intact. */
|
|
30
|
+
export declare function deleteComment(doc: DocxDocument, id: string): boolean;
|
|
@@ -53,7 +53,7 @@ export declare function splitParagraph(doc: DocxDocument, pos: DocPos): DocPos |
|
|
|
53
53
|
*
|
|
54
54
|
* Renvoie la position de la soudure, là où le curseur doit rester.
|
|
55
55
|
*/
|
|
56
|
-
export declare function joinParagraph(doc: DocxDocument, para: number): DocPos | null;
|
|
56
|
+
export declare function joinParagraph(doc: DocxDocument, para: number, part?: string): DocPos | null;
|
|
57
57
|
/**
|
|
58
58
|
* Insère un tableau vide au caret en coupant le paragraphe en deux.
|
|
59
59
|
*
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { type DocxDocument } from './index';
|
|
1
|
+
import { type DocxDocument, type XmlNode } from './index';
|
|
2
2
|
import { type DocPos, type RunPatch } from './editor';
|
|
3
|
+
/** Prochain identifiant de relation libre pour une part. */
|
|
4
|
+
export declare function nextRelId(rels: XmlNode[]): string;
|
|
5
|
+
/** Le tableau des relations d'une part, créé s'il n'existe pas. */
|
|
6
|
+
export declare function relsOf(doc: DocxDocument, part: string): {
|
|
7
|
+
path: string;
|
|
8
|
+
list: XmlNode[];
|
|
9
|
+
};
|
|
3
10
|
export interface InsertedImage {
|
|
4
11
|
/** où le curseur se retrouve, après l'image */
|
|
5
12
|
pos: DocPos;
|
|
@@ -30,6 +30,12 @@ export type PastedBlock = {
|
|
|
30
30
|
widthPt: number;
|
|
31
31
|
heightPt: number;
|
|
32
32
|
};
|
|
33
|
+
/** Déclare une part dans `[Content_Types].xml` par son chemin. */
|
|
34
|
+
export declare function ensureOverride(doc: DocxDocument, part: string, mime: string): void;
|
|
35
|
+
/** Relation du document vers une part interne, créée si elle manque. */
|
|
36
|
+
export declare function ensureRel(doc: DocxDocument, type: string, target: string): void;
|
|
37
|
+
/** Add a missing level to this list instance without changing other lists' abstract definitions. */
|
|
38
|
+
export declare function ensureListLevel(doc: DocxDocument, numId: number, level: number): boolean;
|
|
33
39
|
/**
|
|
34
40
|
* Un `w:numId` bon pour une liste collée — trouvé, ou créé.
|
|
35
41
|
*
|
|
@@ -49,6 +49,8 @@ export interface RunSpan {
|
|
|
49
49
|
start: number;
|
|
50
50
|
end: number;
|
|
51
51
|
}
|
|
52
|
+
/** Keep zero-width markup and objects between text runs when replacing their text. */
|
|
53
|
+
export declare function interveningMarkup(first: RunSpan, last: RunSpan): XmlNode[];
|
|
52
54
|
/**
|
|
53
55
|
* Découpe un paragraphe en runs adressables, dans l'ordre de lecture.
|
|
54
56
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myrole-docx-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Word-faithful .docx editor and renderer on canvas — the MyRole engine as an embeddable SDK, with a React component.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"vite": "^6.4.3",
|
|
48
48
|
"@myrole/docx-model": "0.0.0",
|
|
49
49
|
"@myrole/docx-vars": "0.0.0",
|
|
50
|
-
"@myrole/docx-render": "0.0.0",
|
|
51
50
|
"@myrole/fonts": "0.1.0",
|
|
51
|
+
"@myrole/docx-render": "0.0.0",
|
|
52
52
|
"@myrole/docx-tags": "0.0.0"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"scripts": {
|
|
58
58
|
"fonts": "node scripts/pack-fonts.mjs",
|
|
59
59
|
"build": "node scripts/pack-fonts.mjs && vite build && node scripts/types.mjs",
|
|
60
|
-
"check": "node scripts/pack-fonts.mjs && tsc -p tsconfig.json",
|
|
60
|
+
"check": "node scripts/pack-fonts.mjs && tsc -p tsconfig.json && tsx scripts/locking.test.ts",
|
|
61
61
|
"types": "node scripts/types.mjs"
|
|
62
62
|
},
|
|
63
63
|
"typesVersions": {
|