@docx-editor.dev/pro 2.0.0 → 2.1.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 +6 -6
- package/dist/chunk-FVI3MGO7.js +1 -0
- package/dist/chunk-MNK6DXJQ.cjs +1 -0
- package/dist/define-custom-node-BTTX66B3.d.cts +500 -0
- package/dist/define-custom-node-BTTX66B3.d.ts +500 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +323 -36
- package/dist/index.d.ts +323 -36
- package/dist/index.js +1 -1
- package/dist/react/index.cjs +2 -2
- package/dist/react/index.d.cts +31 -16
- package/dist/react/index.d.ts +31 -16
- package/dist/react/index.js +2 -2
- package/package.json +5 -4
- package/dist/chunk-NZOS3H23.js +0 -1
- package/dist/chunk-TNSHSAA4.cjs +0 -1
- package/dist/define-custom-node-CkkDPdB0.d.cts +0 -191
- package/dist/define-custom-node-CkkDPdB0.d.ts +0 -191
package/dist/chunk-TNSHSAA4.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
'use strict';var store=require('@docx-editor.dev/core/store'),layout=require('@docx-editor.dev/core/layout');function f(e){}var z=64,I=new Set(["__proto__","constructor","prototype"]);function p(e,i,r){let s=new URLSearchParams;for(let[o,d]of Object.entries(r))s.set(o,d);let a=s.toString(),t=a.length>0?`${e}:${i}?${a}`:`${e}:${i}`;return t.length>64?{ok:false,reason:"tag-overflow",length:t.length}:{ok:true,tag:t}}function g(e){if(e.length>64)return null;let i=e.indexOf(":");if(i<=0)return null;let r=e.slice(0,i),s=e.slice(i+1),a=s.indexOf("?"),t=a===-1?s:s.slice(0,a);if(t.length===0)return null;let o=Object.create(null);if(a!==-1)for(let[d,n]of new URLSearchParams(s.slice(a+1))){if(I.has(d))return null;o[d]=n;}return {prefix:r,name:t,attrs:o}}function x(e){return typeof e=="object"&&e!==null&&typeof e.name=="string"&&typeof e.tagPrefix=="string"}var y=/^[A-Za-z0-9_.-]+$/;function U(e){if(!y.test(e.name??""))throw new Error(`defineCustomNode: invalid name ${JSON.stringify(e.name)}`);if(!y.test(e.tagPrefix??""))throw new Error(`defineCustomNode: invalid tagPrefix ${JSON.stringify(e.tagPrefix)}`);return Object.freeze({...e})}function F(e){return f(e.licenseKey),{id:"custom-nodes",customNodes:e.nodes}}function k(e){for(let i of e.children)if(!(i.kind==="textValue"||i.localName!=="sdtPr")){for(let r of i.children)if(!(r.kind==="textValue"||r.localName!=="tag")){for(let s of r.attributes)if(s.localName==="val")return s.value}}}function v(e){if(e.kind==="textValue")return e.value;let i="";for(let r of e.children)i+=v(r);return i}function N(e,i){if(i.length===0)return [];let r=new Map;for(let t of i){let o=`${t.tagPrefix}:${t.name}`;if(r.has(o))throw new Error(`recognizeCustomNodes: duplicate definition for ${JSON.stringify(o)}`);r.set(o,t);}let s=[],a=(t,o)=>{if(!(t.kind==="textValue"||o>64)){if(t.kind==="contentControl"){let d=k(t),n=d!==void 0?g(d):null,l=n?r.get(`${n.prefix}:${n.name}`):void 0;if(n&&l&&d!==void 0){let c=v(t),u=l.fromDocx?l.fromDocx({attrs:n.attrs,text:c}):n.attrs;if(u!==null){s.push({name:l.name,attrs:u,text:c,nodeId:t.id,tag:d});return}}}for(let d of t.children)a(d,o+1);}};return a(e.root,0),s}function R(e,i){let r=store.findNode(e,i);return !r||r.kind!=="paragraph"?[]:store.revisionItemsOf({id:e.id,name:e.name,contentType:e.contentType,root:r})}function b(e,i){let r=i.filter(o=>o.reviewCard);if(r.length===0)return [];let s=N(e,r);if(s.length===0)return [];let a=store.locateSites(e),t=[];for(let o of s){let d=r.find(c=>c.name===o.name&&o.tag.startsWith(`${c.tagPrefix}:`));if(!d)continue;let n=d.reviewCard({attrs:o.attrs,text:o.text});if(n===null)continue;let l=a.get(o.nodeId);t.push({kind:"custom",id:o.nodeId,name:o.name,tag:o.tag,attrs:o.attrs,text:o.text,title:n.title,...n.detail!==void 0?{detail:n.detail}:{},range:l?{partName:e.name,start:{paragraphId:l.paragraphId,offset:l.start},end:{paragraphId:l.paragraphId,offset:l.end}}:null});}return t}function O(e){let i=store.collectReviewItems(e),r=(e.customNodes??[]).filter(x);if(r.length===0)return i;let s=[e.storyPart],a=new Set([e.storyPart.name]);for(let n of e.furnitureParts??[])a.has(n.name)||(a.add(n.name),s.push(n));let t=[],o=new Map;for(let n of s){t.push(...b(n,r));let l=o.size;for(let[c,u]of store.paragraphOrderOfPart(n))o.has(c)||o.set(c,l+u);}return t.length===0?i:[...i,...t].sort((n,l)=>layout.reviewItemPositionRank(n,o)-layout.reviewItemPositionRank(l,o))}function se(e={}){return f(e.licenseKey),{id:"review",review:{displayModes:["all-markup","proposed","original"],collectReviewItems:O,revisionItemsOfParagraph:R}}}function w(e){return e.surface??null}function _(e,i){let r=null,s=t=>t.id===i?true:t.kind==="textValue"?false:t.children.some(s),a=(t,o)=>{if(!(r||t.kind==="textValue"||o>64)){if(t.kind==="paragraph"){s(t)&&(r=t);return}for(let d of t.children)a(d,o+1);}};return a(e.root,0),r}function A(e,i){let r=new Set,s=n=>{if(r.add(n.id),n.kind!=="textValue")for(let l of n.children)s(l);},a=n=>{if(n.id===i)return n;if(n.kind==="textValue")return null;for(let l of n.children){let c=a(l);if(c)return c}return null},t=a(e);if(!t)return null;s(t);let o=Number.MAX_SAFE_INTEGER,d=-1;for(let n of store.segmentsOf(e))r.has(n.runId)&&(n.start<o&&(o=n.start),n.end>d&&(d=n.end));return d<0?null:{start:o,end:d}}function ce(e,i){let r=w(e);if(!r)return {ok:false,code:"notFound",reason:"no document is mounted"};let s=r.session.applyTreeOps([{op:"removeContentControl",controlId:i,keepContent:false}]);return s.committed?{ok:true,changed:true}:{ok:false,code:"unsupported",reason:typeof s.reason=="string"?s.reason:"the removal was refused"}}function ue(e,i,r,s,a,t={}){let o=w(e);if(!o)return {ok:false,code:"notFound",reason:"no document is mounted"};let d=p(i.tagPrefix,i.name,s);if(!d.ok)return {ok:false,code:"invalidArgs",reason:`the encoded tag is ${d.length} characters; Word caps w:tag at 64 \u2014 shorten the attrs`};let n=o.session.part(),l=_(n,r),c=l?A(l,r):null;if(!l||!c)return {ok:false,code:"notFound",reason:"no custom node with that id"};let u=t.lock===void 0?"contentLocked":t.lock,m=o.session.applyTreeOps([{op:"removeContentControl",controlId:r,keepContent:false},{op:"insertInlineContentControl",paragraphId:l.id,offset:c.start,tag:d.tag,text:a,...t.alias===void 0?{}:{alias:t.alias},...u===false?{}:{lock:u}}]);return m.committed?{ok:true,changed:true}:{ok:false,code:"unsupported",reason:typeof m.reason=="string"?m.reason:"the update was refused"}}exports.a=z;exports.b=p;exports.c=g;exports.d=x;exports.e=y;exports.f=U;exports.g=F;exports.h=N;exports.i=se;exports.j=ce;exports.k=ue;
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { EditorModule } from '@docx-editor.dev/core/editor';
|
|
2
|
-
import { OoxmlPart } from '@docx-editor.dev/core/store';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Licensing, v1: honor system.
|
|
6
|
-
*
|
|
7
|
-
* The key is accepted and remembered so that adding offline (Ed25519)
|
|
8
|
-
* verification later is not a breaking change — but nothing validates it,
|
|
9
|
-
* nothing warns, nothing renders differently, and NOTHING EVER LEAVES THE
|
|
10
|
-
* PROCESS: no network request is made for licensing, ever. That last property
|
|
11
|
-
* is a spec requirement (`pro-licensing`), not an implementation detail.
|
|
12
|
-
*/
|
|
13
|
-
/** Accepted by every pro entry point. */
|
|
14
|
-
interface ProLicenseOptions {
|
|
15
|
-
/**
|
|
16
|
-
* Your license key from docx-editor.dev. Optional in v1: unlicensed use in
|
|
17
|
-
* development and evaluation is permitted, production use requires a
|
|
18
|
-
* license (see LICENSE.md) — the package trusts you either way.
|
|
19
|
-
*/
|
|
20
|
-
readonly licenseKey?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The review module: comments, tracked changes, and markup rendering as an
|
|
25
|
-
* `EditorModule` for `createDocxEditor({ modules })`.
|
|
26
|
-
*
|
|
27
|
-
* Registering it is the whole enablement story: the review chrome slots light
|
|
28
|
-
* up through the same `toolbarCommandState` they were disabled by, suggesting
|
|
29
|
-
* mode becomes reachable, and the editor renders revisions in markup rather
|
|
30
|
-
* than the free tier's final-state projection.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* How {@link reviewModule} is configured. Carries only the licence key today, so
|
|
35
|
-
* `reviewModule()` with no argument is the ordinary call.
|
|
36
|
-
*
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
39
|
-
interface ReviewModuleOptions extends ProLicenseOptions {
|
|
40
|
-
}
|
|
41
|
-
/** Build the review module. Construction never validates the key and never touches the network. */
|
|
42
|
-
declare function reviewModule(options?: ReviewModuleOptions): EditorModule;
|
|
43
|
-
|
|
44
|
-
/** A recognized custom node: one inline SDT whose tag matched a definition. */
|
|
45
|
-
interface RecognizedCustomNode {
|
|
46
|
-
/** The definition's `name`. */
|
|
47
|
-
readonly name: string;
|
|
48
|
-
/** Attrs after the definition's `fromDocx` had its say. Untrusted input. */
|
|
49
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
50
|
-
/** The SDT's literal content text — what Word users see and may have edited. */
|
|
51
|
-
readonly text: string;
|
|
52
|
-
/** The SDT node's stable id in the canonical tree. */
|
|
53
|
-
readonly nodeId: string;
|
|
54
|
-
/** The raw `w:tag` the node was recognized from. */
|
|
55
|
-
readonly tag: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* One integrator-defined inline node, anchored on a run-level SDT whose `w:tag` carries its
|
|
59
|
-
* identity.
|
|
60
|
-
*
|
|
61
|
-
* A definition claims a tag PREFIX, so `acme` recognizes every `acme:*` tag. An SDT whose prefix
|
|
62
|
-
* no definition claims stays literal — which is also what the free tier and Word itself render,
|
|
63
|
-
* so an unrecognized node never loses content or locks editing.
|
|
64
|
-
*
|
|
65
|
-
* Build one with {@link defineCustomNode}, which validates the shape, then register it through
|
|
66
|
-
* {@link customNodesModule}.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```ts
|
|
70
|
-
* const citation = defineCustomNode({
|
|
71
|
-
* name: 'citation',
|
|
72
|
-
* tagPrefix: 'acme',
|
|
73
|
-
* chrome: { color: '#2563eb' },
|
|
74
|
-
* onClick: (node) => openCitation(node.attrs.key),
|
|
75
|
-
* });
|
|
76
|
-
* ```
|
|
77
|
-
*
|
|
78
|
-
* @public
|
|
79
|
-
*/
|
|
80
|
-
interface CustomNodeDefinition {
|
|
81
|
-
/** Node type name — the second segment of the tag (`<prefix>:<name>?…`). */
|
|
82
|
-
readonly name: string;
|
|
83
|
-
/** Tag prefix this definition claims (`acme` claims `acme:*`). No colons. */
|
|
84
|
-
readonly tagPrefix: string;
|
|
85
|
-
/**
|
|
86
|
-
* Recognition hook. Receives the decoded attrs and the SDT's literal text
|
|
87
|
-
* (so label drift from Word edits is visible) and returns the attrs the node
|
|
88
|
-
* should carry — or null to leave this SDT unrecognized and literal.
|
|
89
|
-
*
|
|
90
|
-
* Every input value originates in a file an attacker controls; treat it as
|
|
91
|
-
* untrusted and never build DOM or URLs from it without sanitizing.
|
|
92
|
-
*/
|
|
93
|
-
readonly fromDocx?: (input: {
|
|
94
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
95
|
-
readonly text: string;
|
|
96
|
-
}) => Readonly<Record<string, string>> | null;
|
|
97
|
-
/**
|
|
98
|
-
* Chip appearance, HOST-authored (never file data). `color` tints the chip
|
|
99
|
-
* and its border; applied by `CustomNodeChrome` from `@docx-editor.dev/pro/react`.
|
|
100
|
-
*/
|
|
101
|
-
readonly chrome?: {
|
|
102
|
-
readonly color?: string;
|
|
103
|
-
};
|
|
104
|
-
/** Click on the painted chip. UI state belongs in `CustomNodeChrome`'s `onNodeClick`. */
|
|
105
|
-
readonly onClick?: (node: ActivatedCustomNode) => void;
|
|
106
|
-
/** Pointer enters the painted chip. */
|
|
107
|
-
readonly onHover?: (node: ActivatedCustomNode) => void;
|
|
108
|
-
/**
|
|
109
|
-
* Contribute a card to the review sidebar for every recognized node of this
|
|
110
|
-
* definition, anchored at the node's range. Return null to skip one node.
|
|
111
|
-
*
|
|
112
|
-
* `attrs` and `text` originate in the file — untrusted; the returned strings
|
|
113
|
-
* are rendered as TEXT by the pane, never markup. The context-menu section
|
|
114
|
-
* reuses this hook for its info block and may invoke it with `text: ''` when
|
|
115
|
-
* no review module is registered (the DOM decode alone cannot see the text).
|
|
116
|
-
*/
|
|
117
|
-
readonly reviewCard?: (node: {
|
|
118
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
119
|
-
readonly text: string;
|
|
120
|
-
}) => {
|
|
121
|
-
readonly title: string;
|
|
122
|
-
readonly detail?: string;
|
|
123
|
-
} | null;
|
|
124
|
-
/**
|
|
125
|
-
* The "Edit {label}" row the context menu shows at the top when the
|
|
126
|
-
* right-click lands on the node's chip. The HOST owns the dialog.
|
|
127
|
-
*
|
|
128
|
-
* HONEST LIMIT: there is no in-place update call yet — re-authoring is
|
|
129
|
-
* `removeContentControl` + `insertCustomNode` at the node's range (the
|
|
130
|
-
* activation carries `nodeId` and, when a review module is registered, the
|
|
131
|
-
* current `text` to prefill a form). Schema-driven edit forms are the planned
|
|
132
|
-
* follow-up.
|
|
133
|
-
*/
|
|
134
|
-
readonly onEdit?: (node: ActivatedCustomNode) => void;
|
|
135
|
-
/**
|
|
136
|
-
* Display name for chrome — the "Edit {label}" context-menu row. Defaults to
|
|
137
|
-
* `name`. Host-authored, never file data; provide a localized string.
|
|
138
|
-
*/
|
|
139
|
-
readonly label?: string;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* A chip activation: identity + attrs, plus where it sits.
|
|
143
|
-
*
|
|
144
|
-
* `attrs` are the definition's OWN shape — the raw tag decode has already been
|
|
145
|
-
* through `fromDocx`, exactly as the review derivation runs it, so every
|
|
146
|
-
* surface (click, hover, edit, cards) sees one attrs vocabulary. `text` and
|
|
147
|
-
* `nodeId` are present when the surface could resolve them (a registered
|
|
148
|
-
* review module resolves both).
|
|
149
|
-
*/
|
|
150
|
-
interface ActivatedCustomNode {
|
|
151
|
-
readonly name: string;
|
|
152
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
153
|
-
readonly tag: string;
|
|
154
|
-
/** Viewport-relative rect of the chip's boundary, for anchoring host UI. */
|
|
155
|
-
readonly rect: DOMRect;
|
|
156
|
-
/** The SDT node's canonical id — the address `removeContentControl` takes. */
|
|
157
|
-
readonly nodeId?: string;
|
|
158
|
-
/** The node's literal content text, when resolvable. */
|
|
159
|
-
readonly text?: string;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Whether an opaque registry value is a custom-node definition.
|
|
163
|
-
*
|
|
164
|
-
* The engine carries registered definitions as unknowns (`getCustomNodeDefinitions`), so
|
|
165
|
-
* every pro surface that reads them back narrows through this ONE guard.
|
|
166
|
-
*/
|
|
167
|
-
declare function isCustomNodeDefinition(candidate: unknown): candidate is CustomNodeDefinition;
|
|
168
|
-
/** Validate and freeze a definition. Throws on a shape mistake — author error, not file input. */
|
|
169
|
-
declare function defineCustomNode(definition: CustomNodeDefinition): CustomNodeDefinition;
|
|
170
|
-
/**
|
|
171
|
-
* How {@link customNodesModule} is configured.
|
|
172
|
-
*
|
|
173
|
-
* @public
|
|
174
|
-
*/
|
|
175
|
-
interface CustomNodesModuleOptions extends ProLicenseOptions {
|
|
176
|
-
/** The definitions this editor recognizes. A tag prefix no definition claims stays literal. */
|
|
177
|
-
readonly nodes: readonly CustomNodeDefinition[];
|
|
178
|
-
}
|
|
179
|
-
/** Register custom node definitions with `createDocxEditor({ modules })`. */
|
|
180
|
-
declare function customNodesModule(options: CustomNodesModuleOptions): EditorModule;
|
|
181
|
-
/**
|
|
182
|
-
* Every recognized custom node in one story, in document order.
|
|
183
|
-
*
|
|
184
|
-
* Tag-prefix keyed, exactly as the change specifies: an inline SDT whose tag
|
|
185
|
-
* decodes to a registered `<prefix>:<name>` pair is offered to that
|
|
186
|
-
* definition's `fromDocx`; everything else — foreign tags, unregistered
|
|
187
|
-
* prefixes, a `fromDocx` veto — stays a literal SDT.
|
|
188
|
-
*/
|
|
189
|
-
declare function recognizeCustomNodes(part: OoxmlPart, definitions: readonly CustomNodeDefinition[]): RecognizedCustomNode[];
|
|
190
|
-
|
|
191
|
-
export { type ActivatedCustomNode as A, type CustomNodeDefinition as C, type ProLicenseOptions as P, type RecognizedCustomNode as R, type CustomNodesModuleOptions as a, type ReviewModuleOptions as b, customNodesModule as c, defineCustomNode as d, reviewModule as e, isCustomNodeDefinition as i, recognizeCustomNodes as r };
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { EditorModule } from '@docx-editor.dev/core/editor';
|
|
2
|
-
import { OoxmlPart } from '@docx-editor.dev/core/store';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Licensing, v1: honor system.
|
|
6
|
-
*
|
|
7
|
-
* The key is accepted and remembered so that adding offline (Ed25519)
|
|
8
|
-
* verification later is not a breaking change — but nothing validates it,
|
|
9
|
-
* nothing warns, nothing renders differently, and NOTHING EVER LEAVES THE
|
|
10
|
-
* PROCESS: no network request is made for licensing, ever. That last property
|
|
11
|
-
* is a spec requirement (`pro-licensing`), not an implementation detail.
|
|
12
|
-
*/
|
|
13
|
-
/** Accepted by every pro entry point. */
|
|
14
|
-
interface ProLicenseOptions {
|
|
15
|
-
/**
|
|
16
|
-
* Your license key from docx-editor.dev. Optional in v1: unlicensed use in
|
|
17
|
-
* development and evaluation is permitted, production use requires a
|
|
18
|
-
* license (see LICENSE.md) — the package trusts you either way.
|
|
19
|
-
*/
|
|
20
|
-
readonly licenseKey?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The review module: comments, tracked changes, and markup rendering as an
|
|
25
|
-
* `EditorModule` for `createDocxEditor({ modules })`.
|
|
26
|
-
*
|
|
27
|
-
* Registering it is the whole enablement story: the review chrome slots light
|
|
28
|
-
* up through the same `toolbarCommandState` they were disabled by, suggesting
|
|
29
|
-
* mode becomes reachable, and the editor renders revisions in markup rather
|
|
30
|
-
* than the free tier's final-state projection.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* How {@link reviewModule} is configured. Carries only the licence key today, so
|
|
35
|
-
* `reviewModule()` with no argument is the ordinary call.
|
|
36
|
-
*
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
39
|
-
interface ReviewModuleOptions extends ProLicenseOptions {
|
|
40
|
-
}
|
|
41
|
-
/** Build the review module. Construction never validates the key and never touches the network. */
|
|
42
|
-
declare function reviewModule(options?: ReviewModuleOptions): EditorModule;
|
|
43
|
-
|
|
44
|
-
/** A recognized custom node: one inline SDT whose tag matched a definition. */
|
|
45
|
-
interface RecognizedCustomNode {
|
|
46
|
-
/** The definition's `name`. */
|
|
47
|
-
readonly name: string;
|
|
48
|
-
/** Attrs after the definition's `fromDocx` had its say. Untrusted input. */
|
|
49
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
50
|
-
/** The SDT's literal content text — what Word users see and may have edited. */
|
|
51
|
-
readonly text: string;
|
|
52
|
-
/** The SDT node's stable id in the canonical tree. */
|
|
53
|
-
readonly nodeId: string;
|
|
54
|
-
/** The raw `w:tag` the node was recognized from. */
|
|
55
|
-
readonly tag: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* One integrator-defined inline node, anchored on a run-level SDT whose `w:tag` carries its
|
|
59
|
-
* identity.
|
|
60
|
-
*
|
|
61
|
-
* A definition claims a tag PREFIX, so `acme` recognizes every `acme:*` tag. An SDT whose prefix
|
|
62
|
-
* no definition claims stays literal — which is also what the free tier and Word itself render,
|
|
63
|
-
* so an unrecognized node never loses content or locks editing.
|
|
64
|
-
*
|
|
65
|
-
* Build one with {@link defineCustomNode}, which validates the shape, then register it through
|
|
66
|
-
* {@link customNodesModule}.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```ts
|
|
70
|
-
* const citation = defineCustomNode({
|
|
71
|
-
* name: 'citation',
|
|
72
|
-
* tagPrefix: 'acme',
|
|
73
|
-
* chrome: { color: '#2563eb' },
|
|
74
|
-
* onClick: (node) => openCitation(node.attrs.key),
|
|
75
|
-
* });
|
|
76
|
-
* ```
|
|
77
|
-
*
|
|
78
|
-
* @public
|
|
79
|
-
*/
|
|
80
|
-
interface CustomNodeDefinition {
|
|
81
|
-
/** Node type name — the second segment of the tag (`<prefix>:<name>?…`). */
|
|
82
|
-
readonly name: string;
|
|
83
|
-
/** Tag prefix this definition claims (`acme` claims `acme:*`). No colons. */
|
|
84
|
-
readonly tagPrefix: string;
|
|
85
|
-
/**
|
|
86
|
-
* Recognition hook. Receives the decoded attrs and the SDT's literal text
|
|
87
|
-
* (so label drift from Word edits is visible) and returns the attrs the node
|
|
88
|
-
* should carry — or null to leave this SDT unrecognized and literal.
|
|
89
|
-
*
|
|
90
|
-
* Every input value originates in a file an attacker controls; treat it as
|
|
91
|
-
* untrusted and never build DOM or URLs from it without sanitizing.
|
|
92
|
-
*/
|
|
93
|
-
readonly fromDocx?: (input: {
|
|
94
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
95
|
-
readonly text: string;
|
|
96
|
-
}) => Readonly<Record<string, string>> | null;
|
|
97
|
-
/**
|
|
98
|
-
* Chip appearance, HOST-authored (never file data). `color` tints the chip
|
|
99
|
-
* and its border; applied by `CustomNodeChrome` from `@docx-editor.dev/pro/react`.
|
|
100
|
-
*/
|
|
101
|
-
readonly chrome?: {
|
|
102
|
-
readonly color?: string;
|
|
103
|
-
};
|
|
104
|
-
/** Click on the painted chip. UI state belongs in `CustomNodeChrome`'s `onNodeClick`. */
|
|
105
|
-
readonly onClick?: (node: ActivatedCustomNode) => void;
|
|
106
|
-
/** Pointer enters the painted chip. */
|
|
107
|
-
readonly onHover?: (node: ActivatedCustomNode) => void;
|
|
108
|
-
/**
|
|
109
|
-
* Contribute a card to the review sidebar for every recognized node of this
|
|
110
|
-
* definition, anchored at the node's range. Return null to skip one node.
|
|
111
|
-
*
|
|
112
|
-
* `attrs` and `text` originate in the file — untrusted; the returned strings
|
|
113
|
-
* are rendered as TEXT by the pane, never markup. The context-menu section
|
|
114
|
-
* reuses this hook for its info block and may invoke it with `text: ''` when
|
|
115
|
-
* no review module is registered (the DOM decode alone cannot see the text).
|
|
116
|
-
*/
|
|
117
|
-
readonly reviewCard?: (node: {
|
|
118
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
119
|
-
readonly text: string;
|
|
120
|
-
}) => {
|
|
121
|
-
readonly title: string;
|
|
122
|
-
readonly detail?: string;
|
|
123
|
-
} | null;
|
|
124
|
-
/**
|
|
125
|
-
* The "Edit {label}" row the context menu shows at the top when the
|
|
126
|
-
* right-click lands on the node's chip. The HOST owns the dialog.
|
|
127
|
-
*
|
|
128
|
-
* HONEST LIMIT: there is no in-place update call yet — re-authoring is
|
|
129
|
-
* `removeContentControl` + `insertCustomNode` at the node's range (the
|
|
130
|
-
* activation carries `nodeId` and, when a review module is registered, the
|
|
131
|
-
* current `text` to prefill a form). Schema-driven edit forms are the planned
|
|
132
|
-
* follow-up.
|
|
133
|
-
*/
|
|
134
|
-
readonly onEdit?: (node: ActivatedCustomNode) => void;
|
|
135
|
-
/**
|
|
136
|
-
* Display name for chrome — the "Edit {label}" context-menu row. Defaults to
|
|
137
|
-
* `name`. Host-authored, never file data; provide a localized string.
|
|
138
|
-
*/
|
|
139
|
-
readonly label?: string;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* A chip activation: identity + attrs, plus where it sits.
|
|
143
|
-
*
|
|
144
|
-
* `attrs` are the definition's OWN shape — the raw tag decode has already been
|
|
145
|
-
* through `fromDocx`, exactly as the review derivation runs it, so every
|
|
146
|
-
* surface (click, hover, edit, cards) sees one attrs vocabulary. `text` and
|
|
147
|
-
* `nodeId` are present when the surface could resolve them (a registered
|
|
148
|
-
* review module resolves both).
|
|
149
|
-
*/
|
|
150
|
-
interface ActivatedCustomNode {
|
|
151
|
-
readonly name: string;
|
|
152
|
-
readonly attrs: Readonly<Record<string, string>>;
|
|
153
|
-
readonly tag: string;
|
|
154
|
-
/** Viewport-relative rect of the chip's boundary, for anchoring host UI. */
|
|
155
|
-
readonly rect: DOMRect;
|
|
156
|
-
/** The SDT node's canonical id — the address `removeContentControl` takes. */
|
|
157
|
-
readonly nodeId?: string;
|
|
158
|
-
/** The node's literal content text, when resolvable. */
|
|
159
|
-
readonly text?: string;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Whether an opaque registry value is a custom-node definition.
|
|
163
|
-
*
|
|
164
|
-
* The engine carries registered definitions as unknowns (`getCustomNodeDefinitions`), so
|
|
165
|
-
* every pro surface that reads them back narrows through this ONE guard.
|
|
166
|
-
*/
|
|
167
|
-
declare function isCustomNodeDefinition(candidate: unknown): candidate is CustomNodeDefinition;
|
|
168
|
-
/** Validate and freeze a definition. Throws on a shape mistake — author error, not file input. */
|
|
169
|
-
declare function defineCustomNode(definition: CustomNodeDefinition): CustomNodeDefinition;
|
|
170
|
-
/**
|
|
171
|
-
* How {@link customNodesModule} is configured.
|
|
172
|
-
*
|
|
173
|
-
* @public
|
|
174
|
-
*/
|
|
175
|
-
interface CustomNodesModuleOptions extends ProLicenseOptions {
|
|
176
|
-
/** The definitions this editor recognizes. A tag prefix no definition claims stays literal. */
|
|
177
|
-
readonly nodes: readonly CustomNodeDefinition[];
|
|
178
|
-
}
|
|
179
|
-
/** Register custom node definitions with `createDocxEditor({ modules })`. */
|
|
180
|
-
declare function customNodesModule(options: CustomNodesModuleOptions): EditorModule;
|
|
181
|
-
/**
|
|
182
|
-
* Every recognized custom node in one story, in document order.
|
|
183
|
-
*
|
|
184
|
-
* Tag-prefix keyed, exactly as the change specifies: an inline SDT whose tag
|
|
185
|
-
* decodes to a registered `<prefix>:<name>` pair is offered to that
|
|
186
|
-
* definition's `fromDocx`; everything else — foreign tags, unregistered
|
|
187
|
-
* prefixes, a `fromDocx` veto — stays a literal SDT.
|
|
188
|
-
*/
|
|
189
|
-
declare function recognizeCustomNodes(part: OoxmlPart, definitions: readonly CustomNodeDefinition[]): RecognizedCustomNode[];
|
|
190
|
-
|
|
191
|
-
export { type ActivatedCustomNode as A, type CustomNodeDefinition as C, type ProLicenseOptions as P, type RecognizedCustomNode as R, type CustomNodesModuleOptions as a, type ReviewModuleOptions as b, customNodesModule as c, defineCustomNode as d, reviewModule as e, isCustomNodeDefinition as i, recognizeCustomNodes as r };
|