@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/dist/index.d.ts CHANGED
@@ -1,9 +1,205 @@
1
- import { C as CustomNodeDefinition } from './define-custom-node-CkkDPdB0.js';
2
- export { A as ActivatedCustomNode, a as CustomNodesModuleOptions, P as ProLicenseOptions, R as RecognizedCustomNode, b as ReviewModuleOptions, c as customNodesModule, d as defineCustomNode, i as isCustomNodeDefinition, r as recognizeCustomNodes, e as reviewModule } from './define-custom-node-CkkDPdB0.js';
1
+ import { A as AnyCustomNodeDefinition, C as CustomNodeDiagnostic, R as RecognizedCustomNode, S as StandardSchemaV1, I as InferSchemaInput, a as CustomNodeDefinition } from './define-custom-node-BTTX66B3.js';
2
+ export { b as ActivatedCustomNode, c as CustomNode, d as CustomNodeDataRejection, e as CustomNodeDataResult, f as CustomNodePayloadSource, g as CustomNodesModuleOptions, h as InferSchemaOutput, M as MAX_CUSTOM_NODE_DATA_LENGTH, P as ProLicenseOptions, i as RecognizeCustomNodesOptions, j as ReviewModuleOptions, k as StandardSchemaIssue, l as StandardSchemaResult, m as customNodesModule, n as defineCustomNode, o as isCustomNodeDefinition, p as parseCustomNodeData, r as recognizeCustomNodes, q as reviewModule, s as serializeCustomNodeData } from './define-custom-node-BTTX66B3.js';
3
3
  import { Editor, ExecResult } from '@docx-editor.dev/core/contracts/editor';
4
4
  import '@docx-editor.dev/core/editor';
5
5
  import '@docx-editor.dev/core/store';
6
6
 
7
+ /** How {@link customNodesOf} narrows what it answers. */
8
+ interface CustomNodesOfOptions {
9
+ /**
10
+ * Which definitions to recognize. Defaults to everything registered on the editor, which is
11
+ * what a host almost always wants — passing a subset answers only those.
12
+ */
13
+ readonly nodes?: readonly AnyCustomNodeDefinition[];
14
+ /**
15
+ * Told about a node whose payload could not be read.
16
+ *
17
+ * Defaults to the listeners the editor's own modules registered, so a host that passed
18
+ * `onDiagnostic` to `customNodesModule` hears from this call too without repeating itself.
19
+ */
20
+ readonly onDiagnostic?: (diagnostic: CustomNodeDiagnostic) => void;
21
+ }
22
+ /**
23
+ * Every recognized custom node in the editor's body, in document order, with its payload.
24
+ *
25
+ * ```ts
26
+ * for (const node of customNodesOf(editor)) {
27
+ * const citation = Citation.dataOf(node);
28
+ * if (citation) index.add(citation.sourceId);
29
+ * }
30
+ * ```
31
+ *
32
+ * Reads the body story. A node in a header or footer is not answered here — the same limit
33
+ * `recognizeCustomNodes` has, since it takes one part.
34
+ *
35
+ * Derived fresh on every call from the canonical package: there is no cache to go stale, and no
36
+ * change event either, so re-read after an edit rather than holding the array.
37
+ */
38
+ declare function customNodesOf(editor: Editor, options?: CustomNodesOfOptions): readonly RecognizedCustomNode[];
39
+
40
+ /**
41
+ * The exported document, or the reason there is not one.
42
+ *
43
+ * A refusal answers no bytes. "Stripping failed, here are the bytes anyway" is the one outcome
44
+ * that must not be possible: a caller would ship the markup it asked to remove and have been
45
+ * told the export succeeded.
46
+ *
47
+ * @public
48
+ */
49
+ type DocumentExportResult = {
50
+ readonly ok: true;
51
+ readonly bytes: Uint8Array;
52
+ /** Controls unwrapped to their text, and controls removed outright. */
53
+ readonly unwrapped: number;
54
+ readonly removed: number;
55
+ } | {
56
+ readonly ok: false;
57
+ readonly reason: string;
58
+ };
59
+ /**
60
+ * Where this copy of the document is going.
61
+ *
62
+ * The distinction the whole option exists for, made explicit at the call site so a host writes
63
+ * intent rather than remembering which function strips:
64
+ *
65
+ * - `internal` — the copy you keep. Your own storage, your own system, a draft a user will
66
+ * reopen HERE. Nothing is stripped, because a stripped copy reopens as plain text and the
67
+ * chips are gone for good.
68
+ * - `external` — the copy that leaves. A download, an email attachment, a hand-off to someone
69
+ * who does not run this library. `preserveOnExport` decides what travels.
70
+ *
71
+ * A UI with one Download button and a "keep our markup" checkbox drives both from one call.
72
+ *
73
+ * @public
74
+ */
75
+ type DocumentDestination = 'internal' | 'external';
76
+ /** How {@link saveForExport} and {@link prepareForExport} treat this copy. */
77
+ interface DocumentExportOptions {
78
+ /**
79
+ * Defaults to `external`, because that is what calling an export function means.
80
+ *
81
+ * `internal` answers the bytes unchanged — the identity case, present so a caller with one
82
+ * code path and a runtime choice does not need two.
83
+ */
84
+ readonly destination?: DocumentDestination;
85
+ }
86
+ /**
87
+ * Apply every definition's `preserveOnExport` to a document, and answer the bytes to ship.
88
+ *
89
+ * The BYTES form, for a caller with no editor: a request handler, a queue worker, a build step, a
90
+ * document `customNodeXml` authored server-side. In a browser with an editor mounted, reach for
91
+ * {@link saveForExport} instead — it reads the definitions off the editor, so a node cannot leave
92
+ * because the list passed here forgot it.
93
+ *
94
+ * `true` (the default) leaves a node untouched. `'text'` unwraps the control, keeping the words
95
+ * and dropping the tag, the binding and the payload. `false` removes the node with its content.
96
+ * A tag no definition claims is never touched — this is a host applying its own policy to its
97
+ * own markup, not a scrub of the document.
98
+ *
99
+ * ```ts
100
+ * const generated = await renderContract(order);
101
+ * const outgoing = prepareForExport(generated, [Clause, InternalNote]);
102
+ * if (outgoing.ok) await email.attach(outgoing.bytes);
103
+ * ```
104
+ *
105
+ * Applied to EVERY story, so a chip in a header is treated like a chip in the body. The payload
106
+ * stores hang off the main document part, which is where Word enumerates its data store from, so
107
+ * that is the only part they are cleaned up against.
108
+ */
109
+ declare function prepareForExport(bytes: Uint8Array, definitions: readonly AnyCustomNodeDefinition[], options?: DocumentExportOptions): DocumentExportResult;
110
+
111
+ /**
112
+ * How {@link saveForExport} treats this copy.
113
+ *
114
+ * @public
115
+ */
116
+ interface SaveForExportOptions extends DocumentExportOptions {
117
+ /**
118
+ * Which definitions to apply. Defaults to everything registered on the editor, which is the
119
+ * answer a host almost always wants — passing a subset leaves the rest untouched, and an
120
+ * untouched node travels whole.
121
+ */
122
+ readonly nodes?: readonly AnyCustomNodeDefinition[];
123
+ }
124
+ /**
125
+ * Save the document as the copy that leaves your system.
126
+ *
127
+ * NOT THE DEFAULT PATH. A custom node is an ordinary inline content control: Word and Word Online
128
+ * both render its text and hand the tag, binding and payload back unchanged, so `editor.save()`
129
+ * already produces a file that opens correctly for a recipient who has never heard of this
130
+ * library. This is for the narrower case where the recipient should not have the nodes at all —
131
+ * internal annotations that must not leave, markup that means nothing outside your system.
132
+ *
133
+ * `editor.save()` is the copy you keep — every node intact, reopens here with the chips working.
134
+ * This is its pair: the same document with each definition's `preserveOnExport` applied, for a
135
+ * download, an attachment, or a hand-off you want stripped.
136
+ *
137
+ * ```ts
138
+ * await storage.put(docId, new Uint8Array(await editor.save())); // yours
139
+ *
140
+ * const outgoing = await saveForExport(editor); // theirs
141
+ * if (outgoing.ok) download(outgoing.bytes);
142
+ * ```
143
+ *
144
+ * Store the saved bytes, never these. What the export stripped is gone for good: unwrapped text
145
+ * does not become a node again. Produce this copy fresh from the saved one each time you hand
146
+ * one out.
147
+ *
148
+ * Definitions come from the editor's registered modules, so a node cannot leave because a list
149
+ * forgot it. On a server, where there is no editor, use `prepareForExport` with an explicit list.
150
+ *
151
+ * @public
152
+ */
153
+ declare function saveForExport(editor: Editor, options?: SaveForExportOptions): Promise<DocumentExportResult>;
154
+
155
+ /**
156
+ * One field a payload got wrong.
157
+ *
158
+ * `path` is the route to it — `['authors', 0, 'name']` — which is what a form needs to find the
159
+ * input to mark. Empty for an issue about the payload as a whole.
160
+ *
161
+ * @public
162
+ */
163
+ interface CustomNodeIssue {
164
+ readonly message: string;
165
+ readonly path: readonly (string | number)[];
166
+ /** `authors.0.name`, for a log line or a message. Derived from `path`. */
167
+ readonly pointer: string;
168
+ }
169
+ /**
170
+ * What {@link insertCustomNode} and {@link updateCustomNode} answer.
171
+ *
172
+ * The engine's `ExecResult`, plus `issues` when the refusal was a schema failure. A host that
173
+ * only branches on `ok` sees no difference.
174
+ *
175
+ * @public
176
+ */
177
+ type CustomNodeWriteOutcome = (Extract<ExecResult, {
178
+ ok: true;
179
+ }> & {
180
+ /**
181
+ * The control this write authored. A rewrite replaces the control rather than editing it,
182
+ * so the id passed to `updateCustomNode` names nothing afterwards — re-point anything
183
+ * attached to that node at this one.
184
+ */
185
+ readonly nodeId?: string;
186
+ }) | (Extract<ExecResult, {
187
+ ok: false;
188
+ }> & {
189
+ /** Present only for a payload the definition's schema refused. */
190
+ readonly issues?: readonly CustomNodeIssue[];
191
+ });
192
+
193
+ /** The local name of every payload store this library authors. */
194
+ declare const CUSTOM_NODE_STORE_ROOT = "docxEditor";
195
+ /**
196
+ * The namespace a definition's payloads live in.
197
+ *
198
+ * Keyed on `tagPrefix` rather than on `name`, so one integrator's nodes share one store. A
199
+ * document with a citation and a figure carries one customXml part, not two.
200
+ */
201
+ declare function customNodeNamespace(definition: AnyCustomNodeDefinition): string;
202
+
7
203
  /** Word refuses to store more than 64 characters in `w:tag`. */
8
204
  declare const MAX_TAG_LENGTH = 64;
9
205
  /**
@@ -52,46 +248,67 @@ interface DecodedCustomNodeTag {
52
248
  declare function decodeCustomNodeTag(tag: string): DecodedCustomNodeTag | null;
53
249
 
54
250
  /**
55
- * How {@link insertCustomNode} places a node.
251
+ * What a node says and where it goes — one object, so the parts cannot be passed in the wrong
252
+ * order or get out of step.
56
253
  *
57
- * Every field is optional: the ordinary call inserts at the caret with `contentLocked`, which is
58
- * the behaviour that keeps a chip's label from drifting out of sync with its attrs while leaving
59
- * the node deletable as one unit.
254
+ * A definition with `text` needs only `data`: what the document shows is computed from it.
255
+ *
256
+ * ```ts
257
+ * insertCustomNode(editor, Citation, { data: citation }); // text derives
258
+ * insertCustomNode(editor, Tag, { attrs: { id: 'x' }, text: '[tag]' }); // no payload
259
+ * ```
60
260
  *
61
261
  * @public
62
262
  */
63
- interface InsertCustomNodeOptions {
263
+ interface CustomNodeInput<Schema extends StandardSchemaV1 | undefined = any> {
264
+ /**
265
+ * The node's payload: everything that does not fit in 64 characters of `w:tag`.
266
+ *
267
+ * Written into a customXml data part and bound to the control, in the SAME transaction as the
268
+ * control itself. Validated against the definition's `schema` first, so a payload that does
269
+ * not match is refused here — with the failing fields in `issues` — rather than written and
270
+ * rejected on the next open.
271
+ */
272
+ readonly data?: InferSchemaInput<Schema>;
64
273
  /**
65
- * Where to insert. Omitted, the node lands at the current selection HEAD —
66
- * the programmatic mirror of "type a citation at the caret".
274
+ * The `w:tag` attrs. Derived by the definition's `tagAttrs` when it declares one.
275
+ *
276
+ * Word caps the encoded tag at 64 characters, so this is the node's IDENTITY and nothing else.
277
+ */
278
+ readonly attrs?: Readonly<Record<string, string>>;
279
+ /** What the document shows. Derived by the definition's `text` when it declares one. */
280
+ readonly text?: string;
281
+ /**
282
+ * Where to insert. Omitted, the node lands at the current selection HEAD — the programmatic
283
+ * mirror of "type a citation at the caret".
67
284
  */
68
285
  readonly at?: {
69
286
  readonly paragraphId: string;
70
287
  readonly offset: number;
71
288
  };
72
289
  /**
73
- * The `w:lock` written on the control. Defaults to `contentLocked` — the text
74
- * is locked so the label cannot drift out of sync with the attrs by inline
75
- * typing (editing goes through the `onEdit` flow), while the node itself stays
76
- * DELETABLE as one unit, in the editor and in Word alike. `false` writes no
77
- * lock; `sdtContentLocked` also forbids deleting the node.
290
+ * The `w:lock` written on the control. Defaults to `contentLocked` — the text is locked so the
291
+ * label cannot drift out of sync with the attrs by inline typing, while the node itself stays
292
+ * DELETABLE as one unit, in the editor and in Word alike. `false` writes no lock;
293
+ * `sdtContentLocked` also forbids deleting the node.
294
+ *
295
+ * A node carrying a payload is uneditable whatever this says: the engine refuses content edits
296
+ * inside a bound control, and so does Word.
78
297
  */
79
298
  readonly lock?: false | 'sdtLocked' | 'sdtContentLocked' | 'contentLocked';
80
- /**
81
- * `w:alias` — the human title Word shows on the control, and what the
82
- * engine's control chrome uses as its floating label.
83
- */
299
+ /** `w:alias` — the human title Word shows on the control, and the chrome's floating label. */
84
300
  readonly alias?: string;
85
301
  }
86
302
  /**
87
- * Insert one custom node. Returns the engine's typed result: refusals carry the
88
- * engine's own reason (tag overflow, offset out of range, viewing mode, …).
303
+ * Insert one custom node. Returns the engine's typed result: refusals carry the engine's own
304
+ * reason (tag overflow, offset out of range, viewing mode, …), and a payload the schema refused
305
+ * carries the failing fields in `issues`.
89
306
  *
90
307
  * ```ts
91
- * insertCustomNode(editor, citation, { sourceId: 'src_9f3' }, '(Smith 2024)');
308
+ * insertCustomNode(editor, citation, { data: { sourceId: 'src_9f3', year: 2024 } });
92
309
  * ```
93
310
  */
94
- declare function insertCustomNode(editor: Editor, definition: CustomNodeDefinition, attrs: Readonly<Record<string, string>>, text: string, options?: InsertCustomNodeOptions): ExecResult;
311
+ declare function insertCustomNode<Schema extends StandardSchemaV1 | undefined = undefined>(editor: Editor, definition: CustomNodeDefinition<Schema>, input?: CustomNodeInput<Schema>): CustomNodeWriteOutcome;
95
312
 
96
313
  /**
97
314
  * Delete one custom node — wrapper AND content, one undo step.
@@ -99,28 +316,42 @@ declare function insertCustomNode(editor: Editor, definition: CustomNodeDefiniti
99
316
  * The default `contentLocked` chip deletes fine (the lock guards its characters, not its
100
317
  * existence); a `sdtLocked`/`sdtContentLocked` wrapper refuses with the engine's reason.
101
318
  */
102
- declare function removeCustomNode(editor: Editor, nodeId: string): ExecResult;
319
+ declare function removeCustomNode(editor: Editor, nodeId: string): CustomNodeWriteOutcome;
103
320
  /**
104
321
  * How {@link updateCustomNode} rewrites the control it replaces.
105
322
  *
323
+ * The same shape {@link CustomNodeInput} takes, minus `at` — an update happens where the node
324
+ * already is — and with `data` able to be `null`.
325
+ *
106
326
  * @public
107
327
  */
108
- interface UpdateCustomNodeOptions {
109
- /** `w:alias` for the rewritten control. */
110
- readonly alias?: string;
111
- /** `w:lock` for the rewritten control. Defaults to `contentLocked`, like the insert. */
112
- readonly lock?: false | 'sdtLocked' | 'sdtContentLocked' | 'contentLocked';
328
+ interface CustomNodeUpdate<Schema extends StandardSchemaV1 | undefined = undefined> extends Omit<CustomNodeInput<Schema>, 'at' | 'data'> {
329
+ /**
330
+ * The payload the rewritten node carries.
331
+ *
332
+ * Written in the SAME transaction as the label, so an update cannot leave the two
333
+ * disagreeing — which is the one way a bound chip could ever show text its payload does not
334
+ * describe.
335
+ *
336
+ * OMITTING IT KEEPS THE PAYLOAD the node already had. That is the important default: the
337
+ * commonest update is a label edit, and an omission that dropped the citation's authors and
338
+ * year would be data loss the caller never asked for and could not see. Pass `null` to remove
339
+ * the payload deliberately.
340
+ *
341
+ * A definition with `text` re-derives what the document shows from whichever payload ends up
342
+ * being written, so `updateCustomNode(editor, def, id, { data })` rewrites both together.
343
+ */
344
+ readonly data?: InferSchemaInput<Schema> | null;
113
345
  }
114
346
  /**
115
- * Replace one custom node's attrs and text in place: the node is removed and a fresh one
116
- * with the new tag and label is inserted at its own span — ONE transaction, one undo step,
117
- * recognized by construction like `insertCustomNode`.
347
+ * Replace one custom node in place: the node is removed and a fresh one is inserted at its own
348
+ * span — ONE transaction, one undo step, recognized by construction like `insertCustomNode`.
118
349
  *
119
350
  * ```ts
120
- * updateCustomNode(editor, citation, node.nodeId, { sourceId: 'src_2' }, '(Jones 2025)');
351
+ * updateCustomNode(editor, citation, node.nodeId, { data: { ...citation, year: 2025 } });
121
352
  * ```
122
353
  */
123
- declare function updateCustomNode(editor: Editor, definition: CustomNodeDefinition, nodeId: string, attrs: Readonly<Record<string, string>>, text: string, options?: UpdateCustomNodeOptions): ExecResult;
354
+ declare function updateCustomNode<Schema extends StandardSchemaV1 | undefined = undefined>(editor: Editor, definition: CustomNodeDefinition<Schema>, nodeId: string, update?: CustomNodeUpdate<Schema>): CustomNodeWriteOutcome;
124
355
 
125
356
  /**
126
357
  * How {@link customNodeXml} writes the control, for server-side templating where there is no
@@ -128,7 +359,7 @@ declare function updateCustomNode(editor: Editor, definition: CustomNodeDefiniti
128
359
  *
129
360
  * @public
130
361
  */
131
- interface CustomNodeXmlOptions {
362
+ interface CustomNodeXmlOptions<Schema extends StandardSchemaV1 | undefined = undefined> {
132
363
  /** `w:alias` — the human title Word shows on the control. */
133
364
  readonly alias?: string;
134
365
  /** `w:lock`. Defaults to `contentLocked`, matching `insertCustomNode`. `false` omits it. */
@@ -140,6 +371,60 @@ interface CustomNodeXmlOptions {
140
371
  * open, but a caller splicing many copies of the same node can pass distinct ids.
141
372
  */
142
373
  readonly id?: number;
374
+ /**
375
+ * The node's payload — everything past the 64 characters `w:tag` holds.
376
+ *
377
+ * A template engine can splice markup but cannot author a package, so this cannot write the
378
+ * data part itself. It answers the part CONTENTS instead (see {@link CustomNodeXmlStore}) and
379
+ * the caller adds them to the zip it is assembling. The markup and the parts agree by
380
+ * construction: the same `ds:itemID` is minted once and written into both.
381
+ */
382
+ readonly data?: InferSchemaInput<Schema>;
383
+ /**
384
+ * Which `/customXml/itemN.xml` this store claims. Defaults to 1.
385
+ *
386
+ * A caller splicing into a template that ALREADY carries a store — Word's Cover Page
387
+ * Properties rides in most of them — has to pick a free index, and only the caller can see
388
+ * the package to know which one is free.
389
+ */
390
+ readonly storeIndex?: number;
391
+ /**
392
+ * The node's id inside the store, which the binding's xpath quotes. Defaults to `cx1`.
393
+ *
394
+ * Splicing several nodes into one document means several ids: two nodes sharing one makes
395
+ * the xpath ambiguous, and Word resolves an ambiguous xpath to the first match — so the
396
+ * second chip would paint the first one's text forever.
397
+ */
398
+ readonly nodeId?: string;
399
+ }
400
+ /**
401
+ * The package a spliced payload needs, as parts a caller adds to the zip it is assembling.
402
+ *
403
+ * Everything here is required. A control carrying a `w:dataBinding` whose store is missing is a
404
+ * document Word opens and offers to repair, and repairing it throws the control away.
405
+ *
406
+ * @public
407
+ */
408
+ interface CustomNodeXmlStore {
409
+ /** `/customXml/itemN.xml` — the payload itself. Rides the package's `xml` content-type default. */
410
+ readonly itemPartName: string;
411
+ readonly itemXml: string;
412
+ /** `/customXml/itemPropsN.xml` — carries the `ds:itemID` the binding quotes. */
413
+ readonly propsPartName: string;
414
+ readonly propsXml: string;
415
+ /** The `ds:itemID`, which is also the `w:storeItemID` already written into the markup. */
416
+ readonly storeItemId: string;
417
+ /** Relationships the caller must declare, each from the part named to the target named. */
418
+ readonly relationships: readonly {
419
+ readonly from: string;
420
+ readonly type: string;
421
+ readonly target: string;
422
+ }[];
423
+ /** The content-type Override the properties part needs. `itemN.xml` needs none. */
424
+ readonly contentTypeOverride: {
425
+ readonly partName: string;
426
+ readonly contentType: string;
427
+ };
143
428
  }
144
429
  /**
145
430
  * What {@link customNodeXml} answers: the `w:sdt` markup, or a refusal.
@@ -152,6 +437,8 @@ interface CustomNodeXmlOptions {
152
437
  type CustomNodeXmlResult = {
153
438
  readonly ok: true;
154
439
  readonly xml: string;
440
+ /** Present only when `data` was given. Absent means the node carries no payload. */
441
+ readonly store?: CustomNodeXmlStore;
155
442
  } | {
156
443
  readonly ok: false;
157
444
  readonly code: 'invalidArgs';
@@ -170,6 +457,6 @@ type CustomNodeXmlResult = {
170
457
  * if (sdt.ok) template.replace('{{citation}}', sdt.xml);
171
458
  * ```
172
459
  */
173
- declare function customNodeXml(definition: CustomNodeDefinition, attrs: Readonly<Record<string, string>>, text: string, options?: CustomNodeXmlOptions): CustomNodeXmlResult;
460
+ declare function customNodeXml<Schema extends StandardSchemaV1 | undefined = undefined>(definition: CustomNodeDefinition<Schema>, attrs: Readonly<Record<string, string>>, text: string, options?: CustomNodeXmlOptions<Schema>): CustomNodeXmlResult;
174
461
 
175
- export { CustomNodeDefinition, type CustomNodeXmlOptions, type CustomNodeXmlResult, type DecodedCustomNodeTag, type EncodeTagResult, type InsertCustomNodeOptions, MAX_TAG_LENGTH, type UpdateCustomNodeOptions, customNodeXml, decodeCustomNodeTag, encodeCustomNodeTag, insertCustomNode, removeCustomNode, updateCustomNode };
462
+ export { AnyCustomNodeDefinition, CUSTOM_NODE_STORE_ROOT, CustomNodeDefinition, CustomNodeDiagnostic, type CustomNodeInput, type CustomNodeIssue, type CustomNodeUpdate, type CustomNodeWriteOutcome, type CustomNodeXmlOptions, type CustomNodeXmlResult, type CustomNodeXmlStore, type CustomNodesOfOptions, type DecodedCustomNodeTag, type DocumentDestination, type DocumentExportOptions, type DocumentExportResult, type EncodeTagResult, InferSchemaInput, MAX_TAG_LENGTH, RecognizedCustomNode, type SaveForExportOptions, StandardSchemaV1, customNodeNamespace, customNodeXml, customNodesOf, decodeCustomNodeTag, encodeCustomNodeTag, insertCustomNode, prepareForExport, removeCustomNode, saveForExport, updateCustomNode };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import {b,e}from'./chunk-NZOS3H23.js';export{a as MAX_TAG_LENGTH,g as customNodesModule,c as decodeCustomNodeTag,f as defineCustomNode,b as encodeCustomNodeTag,d as isCustomNodeDefinition,h as recognizeCustomNodes,j as removeCustomNode,i as reviewModule,k as updateCustomNode}from'./chunk-NZOS3H23.js';import {fnv1a32}from'@docx-editor.dev/core/store';function x(e){return e.surface??null}function v(e,n,a,t,o={}){let r=x(e);if(!r)return {ok:false,code:"notFound",reason:"no document is mounted"};let s=b(n.tagPrefix,n.name,a);if(!s.ok)return {ok:false,code:"invalidArgs",reason:`the encoded tag is ${s.length} characters; Word caps w:tag at 64 \u2014 shorten the attrs (the customXml data-part escape hatch is not built yet)`};let i=o.at??r.state().selection.head,c=o.lock===void 0?"contentLocked":o.lock,u=r.session.applyTreeOps([{op:"insertInlineContentControl",paragraphId:i.paragraphId,offset:i.offset,tag:s.tag,text:t,...o.alias===void 0?{}:{alias:o.alias},...c===false?{}:{lock:c}}]);return u.committed?{ok:true,changed:true}:{ok:false,code:"unsupported",reason:typeof u.reason=="string"?u.reason:"the insert was refused"}}function m(e){return e.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g,"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function R(e$1,n,a,t={}){if(!e.test(e$1.tagPrefix)||!e.test(e$1.name))return {ok:false,code:"invalidArgs",reason:"the definition identity must match defineCustomNode\u2019s charset ([A-Za-z0-9_.-])"};let o=b(e$1.tagPrefix,e$1.name,n);if(!o.ok)return {ok:false,code:"invalidArgs",reason:`the encoded tag is ${o.length} characters; Word caps w:tag at 64 \u2014 shorten the attrs`};let r=t.lock===void 0?"contentLocked":t.lock,s=t.id!==void 0&&Number.isInteger(t.id)&&t.id>0?t.id:fnv1a32(`${o.tag}\0${a}`)&2147483647||1,i=(t.alias!==void 0?`<w:alias w:val="${m(t.alias)}"/>`:"")+`<w:tag w:val="${m(o.tag)}"/><w:id w:val="${s}"/>`+(r===false?"":`<w:lock w:val="${r}"/>`),c=`<w:r><w:t xml:space="preserve">${m(a)}</w:t></w:r>`;return {ok:true,xml:`<w:sdt><w:sdtPr>${i}</w:sdtPr><w:sdtContent>${c}</w:sdtContent></w:sdt>`}}export{R as customNodeXml,v as insertCustomNode};
1
+ import {j,n,h,k,b as b$1,i,g,c}from'./chunk-FVI3MGO7.js';export{g as CUSTOM_NODE_STORE_ROOT,d as MAX_CUSTOM_NODE_DATA_LENGTH,a as MAX_TAG_LENGTH,h as customNodeNamespace,m as customNodesModule,c as decodeCustomNodeTag,l as defineCustomNode,b as encodeCustomNodeTag,p as insertCustomNode,j as isCustomNodeDefinition,e as parseCustomNodeData,n as recognizeCustomNodes,q as removeCustomNode,o as reviewModule,f as serializeCustomNodeData,r as updateCustomNode}from'./chunk-FVI3MGO7.js';import {customNodePayloadsByControl,readOoxmlPackage,withExportedCustomNodes,writeOoxmlPackage,storyRootsOf,fnv1a32,datastoreItemIdFor,customNodeBinding,CUSTOM_XML_PROPS_TYPE,CUSTOM_XML_REL,CUSTOM_XML_PROPS_REL,DATASTORE_NAMESPACE_URI}from'@docx-editor.dev/core/store';function b(e,o={}){let r=U(e);if(!r)return [];let t=o.nodes??e.getCustomNodeDefinitions().filter(j);if(t.length===0)return [];let s=r.session.part();return n(s,t,{payloads:customNodePayloadsByControl(r.session.currentPackage(),s.name),onDiagnostic:o.onDiagnostic??(d=>{e.reportCustomNodeDiagnostic(d);})})}function U(e){return e.surface??null}function E(e,o,r={}){if(r.destination==="internal")return {ok:true,bytes:e,unwrapped:0,removed:0};let t=readOoxmlPackage(e);if(!t.ok)return {ok:false,reason:`the document could not be read: ${t.reason}`};let s=new Map;for(let i of o)s.set(`${i.tagPrefix}:${i.name}`,i);let d=i=>{let m=c(i);if(!m)return "keep";let x=s.get(`${m.prefix}:${m.name}`);return x?x.preserveOnExport==="text"?"text":x.preserveOnExport===false?"remove":"keep":"keep"},p=[...new Set(o.filter(i=>i.preserveOnExport!==void 0).filter(i=>i.preserveOnExport!==true).map(h))],n=t.package,u=0,c$1=0,g=B(n);for(let i of g){let m=withExportedCustomNodes(n,{storyPartName:i,namespaces:[],decide:d});if(!m.ok)return {ok:false,reason:m.reason};n=m.pkg,u+=m.unwrapped,c$1+=m.removed;}let l=withExportedCustomNodes(n,{storyPartName:n.mainDocumentPart,namespaces:p,decide:()=>"keep"});return l.ok?(n=l.pkg,{ok:true,bytes:writeOoxmlPackage(n),unwrapped:u,removed:c$1}):{ok:false,reason:l.reason}}function B(e){let o=[];for(let[r,t]of e.parts)r!==e.mainDocumentPart&&storyRootsOf(t).length!==0&&o.push(r);return [e.mainDocumentPart,...o]}async function V(e,o={}){let r=o.nodes??e.getCustomNodeDefinitions().filter(j),t=await e.save();return E(new Uint8Array(t),r,{...o.destination===void 0?{}:{destination:o.destination}})}function a(e){return e.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g,"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function J(e,o,r,t={}){if(!k.test(e.tagPrefix)||!k.test(e.name))return {ok:false,code:"invalidArgs",reason:"the definition identity must match defineCustomNode\u2019s charset ([A-Za-z0-9_.-])"};let s=b$1(e.tagPrefix,e.name,o);if(!s.ok)return {ok:false,code:"invalidArgs",reason:`the encoded tag is ${s.length} characters; Word caps w:tag at 64 \u2014 shorten the attrs`};let d=t.lock===void 0?"contentLocked":t.lock,p=t.id!==void 0&&Number.isInteger(t.id)&&t.id>0?t.id:fnv1a32(`${s.tag}\0${r}`)&2147483647||1,n=t.data===void 0?null:K(e,t,r);if(n&&"reason"in n)return {ok:false,code:"invalidArgs",reason:n.reason};let u=(t.alias!==void 0?`<w:alias w:val="${a(t.alias)}"/>`:"")+`<w:tag w:val="${a(s.tag)}"/><w:id w:val="${p}"/>`+(d===false?"":`<w:lock w:val="${d}"/>`)+(n?`<w:dataBinding w:prefixMappings="${a(n.binding.prefixMappings)}" w:xpath="${a(n.binding.xpath)}" w:storeItemID="${a(n.binding.storeItemId)}"/>`:""),c=`<w:r><w:t xml:space="preserve">${a(r)}</w:t></w:r>`;return {ok:true,xml:`<w:sdt><w:sdtPr>${u}</w:sdtPr><w:sdtContent>${c}</w:sdtContent></w:sdt>`,...n?{store:n.store}:{}}}function K(e,o,r){let t=i(e,o.data);if(!t.ok)return {reason:t.reason};let s=h(e),d=o.storeIndex!==void 0&&Number.isInteger(o.storeIndex)&&o.storeIndex>0?o.storeIndex:1,p=o.nodeId??"cx1",n=`/customXml/item${String(d)}.xml`,u=`/customXml/itemProps${String(d)}.xml`,c=datastoreItemIdFor(`${s} ${n} ${p}`),g$1=customNodeBinding({partName:n,propsPartName:u,itemId:c,namespaceUri:s},g,p);if(!g$1)return {reason:`the payload cannot be addressed by an XPath: check nodeId (${p}) and payloadNamespace`};let l=r===r.trim()?`<label>${a(r)}</label>`:`<label xml:space="preserve">${a(r)}</label>`;return {binding:g$1,store:{itemPartName:n,itemXml:`<${g} xmlns="${a(s)}"><node id="${a(p)}">${l}<data>${a(t.data)}</data></node></${g}>`,propsPartName:u,propsXml:`<ds:datastoreItem ds:itemID="${a(c)}" xmlns:ds="${DATASTORE_NAMESPACE_URI}"><ds:schemaRefs><ds:schemaRef ds:uri="${a(s)}"/></ds:schemaRefs></ds:datastoreItem>`,storeItemId:c,relationships:[{from:"/word/document.xml",type:CUSTOM_XML_REL,target:`../customXml/item${String(d)}.xml`},{from:n,type:CUSTOM_XML_PROPS_REL,target:`itemProps${String(d)}.xml`}],contentTypeOverride:{partName:u,contentType:CUSTOM_XML_PROPS_TYPE}}}}export{J as customNodeXml,b as customNodesOf,E as prepareForExport,V as saveForExport};