@docx4j/core-ts 0.1.5 → 0.2.1
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 +81 -0
- package/dist/model/content/Body.d.mts +36 -2
- package/dist/model/content/Body.mjs +79 -4
- package/dist/model/content/Comment.d.mts +15 -5
- package/dist/model/content/Comment.mjs +70 -22
- package/dist/model/content/List.d.mts +13 -2
- package/dist/model/content/List.mjs +48 -9
- package/dist/model/content/Paragraph.d.mts +11 -1
- package/dist/model/content/Paragraph.mjs +37 -21
- package/dist/model/content/Range.d.mts +36 -5
- package/dist/model/content/Range.mjs +97 -26
- package/dist/model/content/binder.d.mts +44 -0
- package/dist/model/content/binder.mjs +128 -0
- package/dist/model/content/comments.d.mts +19 -1
- package/dist/model/content/index.d.mts +5 -3
- package/dist/model/content/index.mjs +3 -1
- package/dist/model/content/search.d.mts +27 -2
- package/dist/model/content/search.mjs +59 -3
- package/dist/model/content/stylesFacade.d.mts +37 -0
- package/dist/model/content/stylesFacade.mjs +114 -0
- package/dist/model/content/tracking.d.mts +57 -2
- package/dist/model/content/tracking.mjs +47 -15
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +7 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +40 -6
- package/dist/model/customxml/xpath.d.mts +18 -3
- package/dist/model/customxml/xpath.mjs +18 -3
- package/dist/office-js/index.d.mts +3 -1
- package/dist/office-js/run.d.mts +12 -2
- package/dist/office-js/run.mjs +8 -1
- package/dist/office-js/shimmed.d.mts +46 -0
- package/dist/office-js/shimmed.mjs +1 -0
- package/dist/opc/exceptions.d.mts +25 -0
- package/dist/opc/exceptions.mjs +20 -0
- package/dist/opc/index.d.mts +1 -1
- package/dist/opc/index.mjs +1 -1
- package/dist/opc/mce/understood.mjs +37 -8
- package/dist/packages/WordprocessingMLPackage.d.mts +105 -3
- package/dist/packages/WordprocessingMLPackage.mjs +165 -2
- package/dist/parts/XmlPart.d.mts +44 -0
- package/dist/parts/XmlPart.mjs +86 -3
- package/dist/parts/sml/index.d.mts +9 -8
- package/dist/parts/sml/index.mjs +23 -19
- package/dist/parts/wml/index.d.mts +10 -2
- package/dist/parts/wml/index.mjs +11 -3
- package/dist/parts/wml/spliceableStyles.d.mts +1 -0
- package/dist/parts/wml/spliceableStyles.mjs +122 -0
- package/dist/xml/dom.d.mts +10 -1
- package/dist/xml/dom.mjs +46 -2
- package/package.json +2 -2
|
@@ -10,7 +10,7 @@ function withRPr(run, rPr) {
|
|
|
10
10
|
import { Font } from './Font.mjs';
|
|
11
11
|
import { runFontSelectorOf } from '../fonts/lookup.mjs';
|
|
12
12
|
import { Range } from './Range.mjs';
|
|
13
|
-
import { searchPattern,
|
|
13
|
+
import { searchPattern, matchesOf, expandReplacement } from './search.mjs';
|
|
14
14
|
import { builtInOf, idOfBuiltIn, styleNameOf, styleIdOf } from './styles.mjs';
|
|
15
15
|
import { cellOf } from './Table.mjs';
|
|
16
16
|
import { ContentControl, collectRunControls } from './ContentControl.mjs';
|
|
@@ -336,7 +336,16 @@ export class Paragraph {
|
|
|
336
336
|
}
|
|
337
337
|
/** Matches within this paragraph. */
|
|
338
338
|
search(text, options) {
|
|
339
|
-
return
|
|
339
|
+
return this.searchMatches(text, options).map((m) => m.range);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* `search`, keeping each match's capture groups, which is what a replacement's `$1` or Word's `\1`
|
|
343
|
+
* expands from (CR-002 section 26). Not an Office JS member; `replaceText` is its only caller here
|
|
344
|
+
* and `Body.replaceText` the other.
|
|
345
|
+
*/
|
|
346
|
+
searchMatches(text, options) {
|
|
347
|
+
return matchesOf(this.text, searchPattern(text, options))
|
|
348
|
+
.map((match) => ({ range: new Range(this, match.index, match.index + match[0].length), match }));
|
|
340
349
|
}
|
|
341
350
|
/**
|
|
342
351
|
* Replaces every match of `find` with `replace`, last match first so that the offsets of the
|
|
@@ -344,9 +353,11 @@ export class Paragraph {
|
|
|
344
353
|
* the package's `changeTrackingMode` is on.
|
|
345
354
|
*/
|
|
346
355
|
replaceText(find, replace, options) {
|
|
347
|
-
const matches = this.
|
|
348
|
-
for (let i = matches.length - 1; i >= 0; i--)
|
|
349
|
-
matches[i]
|
|
356
|
+
const matches = this.searchMatches(find, options);
|
|
357
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
358
|
+
const { range, match } = matches[i];
|
|
359
|
+
range.insertText(expandReplacement(replace, match, options), 'Replace');
|
|
360
|
+
}
|
|
350
361
|
return matches.length;
|
|
351
362
|
}
|
|
352
363
|
/** The tracked changes in this paragraph, in document order (CR-002 phase F). */
|
|
@@ -516,11 +527,8 @@ export class Paragraph {
|
|
|
516
527
|
const value = seg.text.substring(0, from) + middle + seg.text.substring(to);
|
|
517
528
|
if (value === '')
|
|
518
529
|
toRemove.push(seg);
|
|
519
|
-
else
|
|
520
|
-
t
|
|
521
|
-
if (/^\s|\s$|\s\s/.test(value))
|
|
522
|
-
t.space = 'preserve';
|
|
523
|
-
}
|
|
530
|
+
else
|
|
531
|
+
setText(t, value);
|
|
524
532
|
}
|
|
525
533
|
else
|
|
526
534
|
toRemove.push(seg);
|
|
@@ -543,9 +551,7 @@ export class Paragraph {
|
|
|
543
551
|
if (target) {
|
|
544
552
|
const t = target.item.value;
|
|
545
553
|
const at = start - target.start;
|
|
546
|
-
t
|
|
547
|
-
if (/^\s|\s$|\s\s/.test(t.value))
|
|
548
|
-
t.space = 'preserve';
|
|
554
|
+
setText(t, target.text.substring(0, at) + text + target.text.substring(at));
|
|
549
555
|
}
|
|
550
556
|
else {
|
|
551
557
|
// no w:t to extend: a new run next to the segment at `start`, with that run's formatting
|
|
@@ -602,9 +608,7 @@ export class Paragraph {
|
|
|
602
608
|
const t = seg.item.value;
|
|
603
609
|
const head = seg.text.substring(0, at);
|
|
604
610
|
const tail = seg.text.substring(at);
|
|
605
|
-
t
|
|
606
|
-
if (/^\s|\s$|\s\s/.test(head))
|
|
607
|
-
t.space = 'preserve';
|
|
611
|
+
setText(t, head);
|
|
608
612
|
const rest = seg.owner.splice(seg.index + 1);
|
|
609
613
|
const second = runOf([textItem(tail), ...rest], seg.run.rPr ? deepCopy(seg.run.rPr) : undefined);
|
|
610
614
|
seg.runOwner.splice(seg.runIndex + 1, 0, second);
|
|
@@ -672,8 +676,8 @@ export class Paragraph {
|
|
|
672
676
|
return commentApi().commentsOf(this);
|
|
673
677
|
}
|
|
674
678
|
/** Comments the whole paragraph (sugar over `getRange().insertComment`). */
|
|
675
|
-
async insertComment(
|
|
676
|
-
return commentApi().insertComment(this.getRange(),
|
|
679
|
+
async insertComment(content, options) {
|
|
680
|
+
return commentApi().insertComment(this.getRange(), content, options);
|
|
677
681
|
}
|
|
678
682
|
// --- content controls (CR-002 phase E) ---
|
|
679
683
|
/**
|
|
@@ -796,9 +800,7 @@ export class Paragraph {
|
|
|
796
800
|
continue;
|
|
797
801
|
if (seg.editable) {
|
|
798
802
|
const t = seg.item.value;
|
|
799
|
-
t
|
|
800
|
-
if (/^\s|\s$|\s\s/.test(t.value))
|
|
801
|
-
t.space = 'preserve';
|
|
803
|
+
setText(t, side === 'after' ? seg.text + text : text + seg.text);
|
|
802
804
|
}
|
|
803
805
|
else {
|
|
804
806
|
const run = runOf([textItem(text)], copyRPr(seg.run.rPr));
|
|
@@ -916,3 +918,17 @@ function outlineLevelOf(pPr) {
|
|
|
916
918
|
const level = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.outlineLvl) === null || _a === void 0 ? void 0 : _a.val;
|
|
917
919
|
return level === undefined ? 10 : level + 1;
|
|
918
920
|
}
|
|
921
|
+
/**
|
|
922
|
+
* Sets a `w:t`'s text with `xml:space="preserve"` exactly when the text needs it - whitespace at
|
|
923
|
+
* either end, or two whitespace characters together - which is how the builders' `t()` and Word
|
|
924
|
+
* write it. Setting the attribute and never taking it off left a text shortened from "Font styles "
|
|
925
|
+
* to "Font X" still preserving, the same text but not the same bytes as a `w:t` made afresh
|
|
926
|
+
* (CR-002 section 32 item 2).
|
|
927
|
+
*/
|
|
928
|
+
function setText(t, value) {
|
|
929
|
+
t.value = value;
|
|
930
|
+
if (/^\s|\s$|\s\s/.test(value))
|
|
931
|
+
t.space = 'preserve';
|
|
932
|
+
else
|
|
933
|
+
delete t.space;
|
|
934
|
+
}
|
|
@@ -5,6 +5,7 @@ import type { BlockElement } from './Body.mjs';
|
|
|
5
5
|
import { type Element, type TextViewOptions } from './tree.mjs';
|
|
6
6
|
import { ContentControl, type ContentControlType } from './ContentControl.mjs';
|
|
7
7
|
import { type SearchOptions } from './search.mjs';
|
|
8
|
+
import { type CommentContent, type CommentOptions } from './comments.mjs';
|
|
8
9
|
import type { Comment } from './Comment.mjs';
|
|
9
10
|
import type { TrackedChange } from './TrackedChange.mjs';
|
|
10
11
|
/**
|
|
@@ -54,7 +55,11 @@ export declare class Range {
|
|
|
54
55
|
/** Removes the span's text. */
|
|
55
56
|
delete(): void;
|
|
56
57
|
search(text: string, options?: SearchOptions): Range[];
|
|
57
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Replaces every match in this span, last first so the offsets stay valid; returns the count
|
|
60
|
+
* (CR-002 section 3.7). The replacement's `$1` or Word's `\1` expands as it does on a paragraph
|
|
61
|
+
* (section 26; this one was missed there, section 31).
|
|
62
|
+
*/
|
|
58
63
|
replaceText(find: string, replace: string, options?: SearchOptions): number;
|
|
59
64
|
/** The tracked changes this span covers, in document order (CR-002 phase F). */
|
|
60
65
|
getTrackedChanges(): TrackedChange[];
|
|
@@ -68,7 +73,7 @@ export declare class Range {
|
|
|
68
73
|
* boundaries, as `font` does), the comment itself and the side-part entries, creating any of
|
|
69
74
|
* the comment parts the document lacks. Asynchronous because it unmarshals those parts.
|
|
70
75
|
*/
|
|
71
|
-
insertComment(
|
|
76
|
+
insertComment(content: CommentContent, options?: CommentOptions): Promise<Comment>;
|
|
72
77
|
/**
|
|
73
78
|
* Wraps the runs this span covers in a run-level content control (Office JS
|
|
74
79
|
* `Range.insertContentControl`), splitting the runs at the boundaries as `font` does. An empty
|
|
@@ -85,14 +90,40 @@ export declare class Range {
|
|
|
85
90
|
* Setting removes the hyperlinks the range already carries and wraps its runs in one
|
|
86
91
|
* `w:hyperlink`, splitting runs at the boundaries as `font` and `insertContentControl` do;
|
|
87
92
|
* setting `""` removes them and wraps nothing. An external address becomes a relationship of
|
|
88
|
-
* this range's part, which is why the part must exist (CR-002 section 20).
|
|
93
|
+
* this range's part, which is why the part must exist (CR-002 section 20). Only the hyperlinks
|
|
94
|
+
* the range touches are removed; before 0.2.1 every one in the paragraph was (section 25).
|
|
95
|
+
*
|
|
96
|
+
* The runs are styled as Word styles them, measured through Office JS (`test/README.md` check
|
|
97
|
+
* 15, CR-002 section 25): each run a link wraps takes the `Hyperlink` character style, over any
|
|
98
|
+
* character style it had, and loses its direct colour, keeping the rest of its direct formatting;
|
|
99
|
+
* a link removed takes the style off its runs again. The `Hyperlink` definition is added to the
|
|
100
|
+
* styles part when the document lacks it, at the latest when the package is saved - a setter
|
|
101
|
+
* cannot await it - so `await pkg.styles.ensure('Hyperlink')` first where an effective read
|
|
102
|
+
* before the save must see it. Under change tracking the restyle is a formatting revision, as a
|
|
103
|
+
* `font` write is.
|
|
89
104
|
*/
|
|
90
105
|
get hyperlink(): string;
|
|
91
106
|
set hyperlink(value: string);
|
|
92
|
-
/** The `w:hyperlink` this range
|
|
107
|
+
/** The first `w:hyperlink` this range touches, if any. */
|
|
93
108
|
private hyperlinkHolder;
|
|
94
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Unwraps every `w:hyperlink` the range touches, keeping its runs where they are and taking the
|
|
111
|
+
* `Hyperlink` style off them. Until 0.2.1 this unwrapped every hyperlink of the paragraph, so
|
|
112
|
+
* linking one word unlinked the others (CR-002 section 25).
|
|
113
|
+
*/
|
|
95
114
|
private removeHyperlinks;
|
|
115
|
+
/**
|
|
116
|
+
* Whether this range touches a hyperlink's text: overlaps it, or for an empty range lies in it
|
|
117
|
+
* (from its first character up to, not including, its end). A hyperlink holding no text touches
|
|
118
|
+
* nothing.
|
|
119
|
+
*/
|
|
120
|
+
private touches;
|
|
121
|
+
/**
|
|
122
|
+
* The `Hyperlink` character style on every run of a hyperlink, in place of any character style
|
|
123
|
+
* and with the direct colour removed, or off again when the link goes: what Word does (CR-002
|
|
124
|
+
* section 25). A run whose properties are then empty loses its `w:rPr`, as in Word's output.
|
|
125
|
+
*/
|
|
126
|
+
private restyle;
|
|
96
127
|
/** The target of a relationship of this range's part, for the getter. */
|
|
97
128
|
private relationshipTarget;
|
|
98
129
|
/** An external relationship of this range's part for the address, and its id. */
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Font } from './Font.mjs';
|
|
2
2
|
import { runFontSelectorOf } from '../fonts/lookup.mjs';
|
|
3
|
-
import { typeNameOf, linkParents, runItemsOf } from './tree.mjs';
|
|
3
|
+
import { typeNameOf, linkParents, runItemsOf, runsOf } from './tree.mjs';
|
|
4
4
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
5
5
|
import { ContentControl } from './ContentControl.mjs';
|
|
6
|
-
import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/wml';
|
|
6
|
+
import { sdt as sdtOf, nextSdtId, applyRunOptions } from '@docx4j/generated-objects-ts/builders/wml';
|
|
7
7
|
import { hyperlink as hyperlinkOf } from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
|
|
8
8
|
import { Namespaces } from '../../parts/Namespaces.mjs';
|
|
9
9
|
import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
|
|
10
10
|
import { contentOf } from './ooxml.mjs';
|
|
11
|
-
import { searchPattern, findAll } from './search.mjs';
|
|
11
|
+
import { searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
|
|
12
12
|
import { commentApi } from './comments.mjs';
|
|
13
13
|
/**
|
|
14
14
|
* A subset of Office JS `Word.Range`: a span of text within one paragraph, [start, end) in the
|
|
@@ -151,11 +151,19 @@ export class Range {
|
|
|
151
151
|
const base = this.start;
|
|
152
152
|
return findAll(this.text, searchPattern(text, options)).map(([s, e]) => new Range(this.paragraph, base + s, base + e));
|
|
153
153
|
}
|
|
154
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Replaces every match in this span, last first so the offsets stay valid; returns the count
|
|
156
|
+
* (CR-002 section 3.7). The replacement's `$1` or Word's `\1` expands as it does on a paragraph
|
|
157
|
+
* (section 26; this one was missed there, section 31).
|
|
158
|
+
*/
|
|
155
159
|
replaceText(find, replace, options) {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
const base = this.start;
|
|
161
|
+
const matches = matchesOf(this.text, searchPattern(find, options));
|
|
162
|
+
for (let i = matches.length - 1; i >= 0; i--) {
|
|
163
|
+
const match = matches[i];
|
|
164
|
+
new Range(this.paragraph, base + match.index, base + match.index + match[0].length)
|
|
165
|
+
.insertText(expandReplacement(replace, match, options), 'Replace');
|
|
166
|
+
}
|
|
159
167
|
return matches.length;
|
|
160
168
|
}
|
|
161
169
|
/** The tracked changes this span covers, in document order (CR-002 phase F). */
|
|
@@ -188,8 +196,8 @@ export class Range {
|
|
|
188
196
|
* boundaries, as `font` does), the comment itself and the side-part entries, creating any of
|
|
189
197
|
* the comment parts the document lacks. Asynchronous because it unmarshals those parts.
|
|
190
198
|
*/
|
|
191
|
-
async insertComment(
|
|
192
|
-
return commentApi().insertComment(this,
|
|
199
|
+
async insertComment(content, options) {
|
|
200
|
+
return commentApi().insertComment(this, content, options);
|
|
193
201
|
}
|
|
194
202
|
// --- content controls (CR-002 phase E) ---
|
|
195
203
|
/**
|
|
@@ -239,7 +247,17 @@ export class Range {
|
|
|
239
247
|
* Setting removes the hyperlinks the range already carries and wraps its runs in one
|
|
240
248
|
* `w:hyperlink`, splitting runs at the boundaries as `font` and `insertContentControl` do;
|
|
241
249
|
* setting `""` removes them and wraps nothing. An external address becomes a relationship of
|
|
242
|
-
* this range's part, which is why the part must exist (CR-002 section 20).
|
|
250
|
+
* this range's part, which is why the part must exist (CR-002 section 20). Only the hyperlinks
|
|
251
|
+
* the range touches are removed; before 0.2.1 every one in the paragraph was (section 25).
|
|
252
|
+
*
|
|
253
|
+
* The runs are styled as Word styles them, measured through Office JS (`test/README.md` check
|
|
254
|
+
* 15, CR-002 section 25): each run a link wraps takes the `Hyperlink` character style, over any
|
|
255
|
+
* character style it had, and loses its direct colour, keeping the rest of its direct formatting;
|
|
256
|
+
* a link removed takes the style off its runs again. The `Hyperlink` definition is added to the
|
|
257
|
+
* styles part when the document lacks it, at the latest when the package is saved - a setter
|
|
258
|
+
* cannot await it - so `await pkg.styles.ensure('Hyperlink')` first where an effective read
|
|
259
|
+
* before the save must see it. Under change tracking the restyle is a formatting revision, as a
|
|
260
|
+
* `font` write is.
|
|
243
261
|
*/
|
|
244
262
|
get hyperlink() {
|
|
245
263
|
var _a;
|
|
@@ -251,7 +269,7 @@ export class Range {
|
|
|
251
269
|
return anchor === '' ? address : `${address}#${anchor}`;
|
|
252
270
|
}
|
|
253
271
|
set hyperlink(value) {
|
|
254
|
-
var _a;
|
|
272
|
+
var _a, _b, _c;
|
|
255
273
|
const paragraph = this.paragraph;
|
|
256
274
|
this.removeHyperlinks();
|
|
257
275
|
if (value === '')
|
|
@@ -259,7 +277,12 @@ export class Range {
|
|
|
259
277
|
const hash = value.indexOf('#');
|
|
260
278
|
const address = hash === -1 ? value : value.slice(0, hash);
|
|
261
279
|
const location = hash === -1 ? '' : value.slice(hash + 1);
|
|
262
|
-
|
|
280
|
+
// w:history="1" is what Word writes on every hyperlink it makes, and what docx4j writes when
|
|
281
|
+
// it builds one (MainDocumentPart.addHyperlink): "add the target to the viewed hyperlinks"
|
|
282
|
+
// (ECMA-376 17.16.22). Readers do not depend on it, but a document holding one holder from
|
|
283
|
+
// each source should not differ over it. Found by the docx4j-ts-editor session, ED-003
|
|
284
|
+
// section 11.8.
|
|
285
|
+
const holder = hyperlinkOf({ content: [], history: true });
|
|
263
286
|
if (location !== '')
|
|
264
287
|
holder.value.anchor = location;
|
|
265
288
|
if (address !== '')
|
|
@@ -287,35 +310,73 @@ export class Range {
|
|
|
287
310
|
holder.value.content = items;
|
|
288
311
|
owner.splice(at, items.length, holder);
|
|
289
312
|
linkParents(holder, (_a = segments[0].run.PARENT) !== null && _a !== void 0 ? _a : paragraph.p);
|
|
313
|
+
this.restyle(holder.value, true);
|
|
314
|
+
(_c = (_b = paragraph.parentBody.package_) === null || _b === void 0 ? void 0 : _b.requireStyles) === null || _c === void 0 ? void 0 : _c.call(_b, [HYPERLINK_STYLE]);
|
|
290
315
|
}
|
|
291
|
-
/** The `w:hyperlink` this range
|
|
316
|
+
/** The first `w:hyperlink` this range touches, if any. */
|
|
292
317
|
hyperlinkHolder() {
|
|
293
|
-
|
|
294
|
-
if (segment.end <= this.start && this.start !== this.end)
|
|
295
|
-
continue;
|
|
296
|
-
if (segment.start >= this.end && this.start !== this.end)
|
|
297
|
-
break;
|
|
298
|
-
const parent = segment.run.PARENT;
|
|
299
|
-
const found = hyperlinkHolders(this.paragraph).find((h) => h.value === parent);
|
|
300
|
-
if (found)
|
|
301
|
-
return found;
|
|
302
|
-
}
|
|
303
|
-
return undefined;
|
|
318
|
+
return hyperlinkHolders(this.paragraph).find((holder) => this.touches(holder));
|
|
304
319
|
}
|
|
305
|
-
/**
|
|
320
|
+
/**
|
|
321
|
+
* Unwraps every `w:hyperlink` the range touches, keeping its runs where they are and taking the
|
|
322
|
+
* `Hyperlink` style off them. Until 0.2.1 this unwrapped every hyperlink of the paragraph, so
|
|
323
|
+
* linking one word unlinked the others (CR-002 section 25).
|
|
324
|
+
*/
|
|
306
325
|
removeHyperlinks() {
|
|
307
326
|
var _a, _b, _c;
|
|
308
|
-
for (const holder of hyperlinkHolders(this.paragraph)) {
|
|
327
|
+
for (const holder of hyperlinkHolders(this.paragraph).filter((h) => this.touches(h))) {
|
|
309
328
|
const owner = containerOf(holder, this.paragraph);
|
|
310
329
|
const at = owner.indexOf(holder);
|
|
311
330
|
if (at === -1)
|
|
312
331
|
continue;
|
|
332
|
+
this.restyle(holder.value, false);
|
|
313
333
|
owner.splice(at, 1, ...((_a = holder.value.content) !== null && _a !== void 0 ? _a : []));
|
|
314
334
|
for (const item of ((_b = holder.value.content) !== null && _b !== void 0 ? _b : [])) {
|
|
315
335
|
linkParents(item, (_c = holder.PARENT) !== null && _c !== void 0 ? _c : this.paragraph.p);
|
|
316
336
|
}
|
|
317
337
|
}
|
|
318
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Whether this range touches a hyperlink's text: overlaps it, or for an empty range lies in it
|
|
341
|
+
* (from its first character up to, not including, its end). A hyperlink holding no text touches
|
|
342
|
+
* nothing.
|
|
343
|
+
*/
|
|
344
|
+
touches(holder) {
|
|
345
|
+
let start;
|
|
346
|
+
let end = 0;
|
|
347
|
+
for (const segment of this.paragraph.segments()) {
|
|
348
|
+
if (!within(segment.run, holder.value, this.paragraph.p))
|
|
349
|
+
continue;
|
|
350
|
+
start !== null && start !== void 0 ? start : (start = segment.start);
|
|
351
|
+
end = segment.end;
|
|
352
|
+
}
|
|
353
|
+
if (start === undefined)
|
|
354
|
+
return false;
|
|
355
|
+
return this.start === this.end ? start <= this.start && this.start < end : start < this.end && end > this.start;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* The `Hyperlink` character style on every run of a hyperlink, in place of any character style
|
|
359
|
+
* and with the direct colour removed, or off again when the link goes: what Word does (CR-002
|
|
360
|
+
* section 25). A run whose properties are then empty loses its `w:rPr`, as in Word's output.
|
|
361
|
+
*/
|
|
362
|
+
restyle(holder, linked) {
|
|
363
|
+
var _a, _b, _c;
|
|
364
|
+
const tracking = this.paragraph.fontTracking();
|
|
365
|
+
const runs = new Set([...runsOf(holder), ...runsOf(holder, { view: 'original' })].map((r) => r.value));
|
|
366
|
+
for (const run of runs) {
|
|
367
|
+
if (!linked && ((_b = (_a = run.rPr) === null || _a === void 0 ? void 0 : _a.rStyle) === null || _b === void 0 ? void 0 : _b.val) !== HYPERLINK_STYLE)
|
|
368
|
+
continue;
|
|
369
|
+
(_c = run.rPr) !== null && _c !== void 0 ? _c : (run.rPr = { TYPE_NAME: 'org_docx4j_wml.RPr' });
|
|
370
|
+
// the properties as they are now become w:rPrChange, unless this run is our own insertion
|
|
371
|
+
if (tracking && !tracking.ownInsertions.has(run))
|
|
372
|
+
tracking.tracker.recordRPrChange(run.rPr);
|
|
373
|
+
applyRunOptions(run.rPr, linked ? { style: HYPERLINK_STYLE, color: '' } : { style: '' });
|
|
374
|
+
if (Object.keys(run.rPr).every((key) => key === 'TYPE_NAME'))
|
|
375
|
+
delete run.rPr;
|
|
376
|
+
else
|
|
377
|
+
linkParents(run.rPr, run);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
319
380
|
/** The target of a relationship of this range's part, for the getter. */
|
|
320
381
|
relationshipTarget(id) {
|
|
321
382
|
var _a, _b, _c;
|
|
@@ -330,6 +391,16 @@ export class Range {
|
|
|
330
391
|
return part.getRelationshipsPart(true).addExternalRelationship(Namespaces.HYPERLINK, address).id;
|
|
331
392
|
}
|
|
332
393
|
}
|
|
394
|
+
/** The character style Word gives the runs of a hyperlink it makes. */
|
|
395
|
+
const HYPERLINK_STYLE = 'Hyperlink';
|
|
396
|
+
/** Whether `object` is `ancestor` or below it, following `PARENT` no further than `stop`. */
|
|
397
|
+
function within(object, ancestor, stop) {
|
|
398
|
+
for (let o = object; o !== undefined && o !== stop; o = o.PARENT) {
|
|
399
|
+
if (o === ancestor)
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
333
404
|
/** Every `w:hyperlink` of a paragraph, outermost first (they do not nest in practice). */
|
|
334
405
|
function hyperlinkHolders(paragraph) {
|
|
335
406
|
const out = [];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Jsonix } from '@docx4j/generated-objects-ts';
|
|
2
|
+
/** What an XPath selected, and the tree object behind it (CR-006 section 2). */
|
|
3
|
+
export interface Bound {
|
|
4
|
+
/**
|
|
5
|
+
* The DOM node the expression selected. It is in a snapshot marshalled for this call, so changing
|
|
6
|
+
* it changes nothing: edits go through the content API or `setContents`, never here.
|
|
7
|
+
*/
|
|
8
|
+
node: Node;
|
|
9
|
+
/**
|
|
10
|
+
* The tree object: for an element, what a walk of the typed tree would hand you at that path,
|
|
11
|
+
* never a `{ name, value }` wrapper; for an attribute or a text node, the object of the element
|
|
12
|
+
* that owns it. Undefined for an element the model does not build - a wildcard child is its own
|
|
13
|
+
* object, so this is undefined only above the root or for a node the marshal did not report.
|
|
14
|
+
*/
|
|
15
|
+
object: unknown;
|
|
16
|
+
/** Set when an attribute was selected: its qualified name on `object`'s element. */
|
|
17
|
+
attribute?: string;
|
|
18
|
+
/** The node's path from the part's root, `/w:document/w:body/w:p[3]/w:r[2]`. */
|
|
19
|
+
path: string;
|
|
20
|
+
}
|
|
21
|
+
/** A marshalled snapshot and the element-to-object map recorded while it was written. */
|
|
22
|
+
export interface BoundSnapshot {
|
|
23
|
+
root: Element;
|
|
24
|
+
/** The object each element was marshalled from; a wildcard child maps to the original tree node. */
|
|
25
|
+
objects: WeakMap<Element, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Marshals a root element and records what each DOM element came from. One marshal per call: the
|
|
29
|
+
* tree has no change log a cached snapshot could be checked against, and a stale answer is worse
|
|
30
|
+
* than a slow one (docx4j's `refreshXmlFirst`, always true here). The editor measured 349 to 411 ms
|
|
31
|
+
* for a 255-page main document part, against 975 ms for its first unmarshal, and runs a selection
|
|
32
|
+
* on Enter - so no cache is needed, which is what CR-006 section 2 was uncertain about.
|
|
33
|
+
*/
|
|
34
|
+
export declare function bindSnapshot<T>(element: Jsonix.TypedNamedValue<T>): Promise<BoundSnapshot>;
|
|
35
|
+
/** Turns selected nodes into `Bound`s against a snapshot, with one path cache for them all. */
|
|
36
|
+
export declare function boundsOf(nodes: readonly Node[], snapshot: BoundSnapshot): Bound[];
|
|
37
|
+
/**
|
|
38
|
+
* The node's path from the document element, in the prefixed form the part itself uses, with a
|
|
39
|
+
* position on every step: `/w:document/w:body/w:p[3]/w:r[2]`, and `/@w:val` for an attribute. The
|
|
40
|
+
* position counts siblings of the same qualified name, as XPath does, and is written even when
|
|
41
|
+
* there is only one - a path that is stable whether or not a sibling is added later is worth more
|
|
42
|
+
* than a short one, and docx4j's harness records the same form.
|
|
43
|
+
*/
|
|
44
|
+
export declare function pathOf(node: Node): string;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// CR-006: XPath over the WordprocessingML tree, through a read-only binder recorded while marshalling.
|
|
2
|
+
//
|
|
3
|
+
// docx4j answers `getJAXBNodesViaXPath` with a JAXB `Binder<Node>`, which keeps the link between a
|
|
4
|
+
// DOM node and the object it came from in both directions. This runtime has no binder, so CR-002
|
|
5
|
+
// section 3.6 left XPath over the typed tree out; the demand appeared (the editor's Developer
|
|
6
|
+
// perspective selects by XPath) and this is the cheap half - DOM node to object, which is what a
|
|
7
|
+
// selection needs. Nothing is written back through the DOM (CR-006 section 7).
|
|
8
|
+
//
|
|
9
|
+
// The link is recorded by `@docx4j/jsonix` 3.4.0's `onElement` callback, reached through the objects
|
|
10
|
+
// facade's `marshalNode(value, { onElement })` (objects CR-007): the runtime calls it once per
|
|
11
|
+
// class-typed value with the element it was written into, and once per wildcard DOM child with the
|
|
12
|
+
// **imported copy** of that child - `writeNode` does `importNode`, so the element in the snapshot is
|
|
13
|
+
// not the node in the tree and a map keyed on it would miss exactly the content a caller most wants
|
|
14
|
+
// (jsonix-CR-006 section 2, finding 3).
|
|
15
|
+
import { marshalNode } from '@docx4j/generated-objects-ts';
|
|
16
|
+
/**
|
|
17
|
+
* Marshals a root element and records what each DOM element came from. One marshal per call: the
|
|
18
|
+
* tree has no change log a cached snapshot could be checked against, and a stale answer is worse
|
|
19
|
+
* than a slow one (docx4j's `refreshXmlFirst`, always true here). The editor measured 349 to 411 ms
|
|
20
|
+
* for a 255-page main document part, against 975 ms for its first unmarshal, and runs a selection
|
|
21
|
+
* on Enter - so no cache is needed, which is what CR-006 section 2 was uncertain about.
|
|
22
|
+
*/
|
|
23
|
+
export async function bindSnapshot(element) {
|
|
24
|
+
const objects = new WeakMap();
|
|
25
|
+
const root = await marshalNode(element, {
|
|
26
|
+
onElement: (node, value) => {
|
|
27
|
+
if (isElement(node))
|
|
28
|
+
objects.set(node, value);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
return { root, objects };
|
|
32
|
+
}
|
|
33
|
+
/** Turns selected nodes into `Bound`s against a snapshot, with one path cache for them all. */
|
|
34
|
+
export function boundsOf(nodes, snapshot) {
|
|
35
|
+
const paths = new Paths();
|
|
36
|
+
return nodes.map((node) => {
|
|
37
|
+
const owner = owningElement(node);
|
|
38
|
+
const bound = {
|
|
39
|
+
node,
|
|
40
|
+
object: owner === undefined ? undefined : snapshot.objects.get(owner),
|
|
41
|
+
path: paths.of(node),
|
|
42
|
+
};
|
|
43
|
+
if (node.nodeType === 2)
|
|
44
|
+
bound.attribute = node.name;
|
|
45
|
+
return bound;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The element an XPath result belongs to: itself for an element, its owner for an attribute, its
|
|
50
|
+
* parent for a text, comment or processing-instruction node. A document node has none.
|
|
51
|
+
*/
|
|
52
|
+
function owningElement(node) {
|
|
53
|
+
if (node.nodeType === 1)
|
|
54
|
+
return node;
|
|
55
|
+
if (node.nodeType === 2) {
|
|
56
|
+
const owner = node.ownerElement;
|
|
57
|
+
return owner === null ? undefined : owner;
|
|
58
|
+
}
|
|
59
|
+
const parent = node.parentNode;
|
|
60
|
+
return parent !== null && parent.nodeType === 1 ? parent : undefined;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The node's path from the document element, in the prefixed form the part itself uses, with a
|
|
64
|
+
* position on every step: `/w:document/w:body/w:p[3]/w:r[2]`, and `/@w:val` for an attribute. The
|
|
65
|
+
* position counts siblings of the same qualified name, as XPath does, and is written even when
|
|
66
|
+
* there is only one - a path that is stable whether or not a sibling is added later is worth more
|
|
67
|
+
* than a short one, and docx4j's harness records the same form.
|
|
68
|
+
*/
|
|
69
|
+
export function pathOf(node) {
|
|
70
|
+
return new Paths().of(node);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Paths for the nodes of one snapshot. Each parent's children are counted once, on first need,
|
|
74
|
+
* and each element's path is kept for its descendants, so a hit list costs one pass over the
|
|
75
|
+
* parents it touches. Counting a node's preceding siblings afresh for every node and every
|
|
76
|
+
* ancestor was quadratic in a parent's children: the 6,972 hits of `//w:p[w:pPr/w:pStyle]` over a
|
|
77
|
+
* 7,088-paragraph body took 21 s in Chromium, where the marshal took 0.5 s (CR-006 section 10).
|
|
78
|
+
*/
|
|
79
|
+
class Paths {
|
|
80
|
+
constructor() {
|
|
81
|
+
/** For a parent, the position of each element child among its siblings of the same name. */
|
|
82
|
+
this.positions = new Map();
|
|
83
|
+
this.elementPaths = new Map();
|
|
84
|
+
}
|
|
85
|
+
of(node) {
|
|
86
|
+
if (node.nodeType === 2) {
|
|
87
|
+
const owner = node.ownerElement;
|
|
88
|
+
return `${owner === null ? '' : this.of(owner)}/@${node.name}`;
|
|
89
|
+
}
|
|
90
|
+
if (node.nodeType === 3 || node.nodeType === 4) {
|
|
91
|
+
const parent = node.parentNode;
|
|
92
|
+
return `${parent === null ? '' : this.of(parent)}/text()`;
|
|
93
|
+
}
|
|
94
|
+
if (node.nodeType !== 1)
|
|
95
|
+
return '';
|
|
96
|
+
const known = this.elementPaths.get(node);
|
|
97
|
+
if (known !== undefined)
|
|
98
|
+
return known;
|
|
99
|
+
const element = node;
|
|
100
|
+
const parent = element.parentNode;
|
|
101
|
+
const path = parent === null || parent.nodeType !== 1
|
|
102
|
+
? `/${element.nodeName}`
|
|
103
|
+
: `${this.of(parent)}/${element.nodeName}[${this.position(parent, element)}]`;
|
|
104
|
+
this.elementPaths.set(node, path);
|
|
105
|
+
return path;
|
|
106
|
+
}
|
|
107
|
+
position(parent, element) {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
let positions = this.positions.get(parent);
|
|
110
|
+
if (positions === undefined) {
|
|
111
|
+
positions = new Map();
|
|
112
|
+
const counts = new Map();
|
|
113
|
+
for (let sibling = parent.firstChild; sibling; sibling = sibling.nextSibling) {
|
|
114
|
+
if (sibling.nodeType !== 1)
|
|
115
|
+
continue;
|
|
116
|
+
const name = sibling.nodeName;
|
|
117
|
+
const n = ((_a = counts.get(name)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
118
|
+
counts.set(name, n);
|
|
119
|
+
positions.set(sibling, n);
|
|
120
|
+
}
|
|
121
|
+
this.positions.set(parent, positions);
|
|
122
|
+
}
|
|
123
|
+
return (_b = positions.get(element)) !== null && _b !== void 0 ? _b : 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function isElement(node) {
|
|
127
|
+
return typeof node === 'object' && node !== null && node.nodeType === 1;
|
|
128
|
+
}
|
|
@@ -16,6 +16,24 @@ export declare const COMMENT_REFERENCE_STYLE = "CommentReference";
|
|
|
16
16
|
* Who a comment (and, with phase F, a tracked change) is by. `WordprocessingMLPackage.author`;
|
|
17
17
|
* there is no signed-in user here, so the package carries the identity.
|
|
18
18
|
*/
|
|
19
|
+
/**
|
|
20
|
+
* What a comment is made of: the text, or the paragraphs of a comment that was edited rich
|
|
21
|
+
* (CR-002 section 28.3). A string splits on newlines, as it did before this option existed.
|
|
22
|
+
*/
|
|
23
|
+
export type CommentContent = string | Element<wml.P>[];
|
|
24
|
+
/**
|
|
25
|
+
* Who made a comment and when, and its `w:id`, for a caller that knows better than the package does:
|
|
26
|
+
* in a co-editing room the author is the peer who made it and the date is when they made it
|
|
27
|
+
* (CR-002 section 28.3). Anything omitted falls back to what the package would have used.
|
|
28
|
+
*/
|
|
29
|
+
export interface CommentOptions {
|
|
30
|
+
author?: Author | undefined;
|
|
31
|
+
/** Overrides the initials derived from the author's name. */
|
|
32
|
+
initials?: string | undefined;
|
|
33
|
+
date?: Date | undefined;
|
|
34
|
+
/** Checked unused across the comments part and the story's markers; a clash throws. */
|
|
35
|
+
id?: number | undefined;
|
|
36
|
+
}
|
|
19
37
|
export interface Author {
|
|
20
38
|
name: string;
|
|
21
39
|
/** Word's `w:initials`; derived from the name when not given. */
|
|
@@ -69,7 +87,7 @@ export declare function commentPartsAccess(): CommentPartsAccess;
|
|
|
69
87
|
/** How `Body`, `Paragraph` and `Range` reach the `Comment` views; registered by `Comment.mts`. */
|
|
70
88
|
export interface CommentApi {
|
|
71
89
|
commentsOf(scope: Body | Paragraph | Range): Promise<Comment[]>;
|
|
72
|
-
insertComment(range: Range,
|
|
90
|
+
insertComment(range: Range, content: CommentContent, options?: CommentOptions): Promise<Comment>;
|
|
73
91
|
}
|
|
74
92
|
export declare function setCommentApi(implementation: CommentApi): void;
|
|
75
93
|
export declare function commentApi(): CommentApi;
|
|
@@ -4,14 +4,16 @@ export { Range } from './Range.mjs';
|
|
|
4
4
|
export { BUILT_IN_STYLES, builtInOf, idOfBuiltIn, displayNameOf, styleNameOf, styleIdOf, type BuiltInStyle } from './styles.mjs';
|
|
5
5
|
export { Comment } from './Comment.mjs';
|
|
6
6
|
export { List, ListItem, ListItemNotFoundError, NumberingFacade, listsOf, listLabelsOf, numberingEmulatorOf, levelOf, type ListLevelType, type ListNumbering, type ListBullet, type StartListOptions, type ListLabel, } from './List.mjs';
|
|
7
|
-
export { type Author, type CommentParts, type CommentPartsAccess, type CommentsExtensible, type CommentMarker, COMMENT_TEXT_STYLE, COMMENT_REFERENCE_STYLE, markersOf, markersOfParagraph, commentIdsOf } from './comments.mjs';
|
|
7
|
+
export { type Author, type CommentContent, type CommentOptions, type CommentParts, type CommentPartsAccess, type CommentsExtensible, type CommentMarker, COMMENT_TEXT_STYLE, COMMENT_REFERENCE_STYLE, markersOf, markersOfParagraph, commentIdsOf } from './comments.mjs';
|
|
8
8
|
export { Font, type UnderlineType, type RPrHolder, type FontTracking } from './Font.mjs';
|
|
9
9
|
export { Table, TableRow, TableCell, cellOf } from './Table.mjs';
|
|
10
10
|
export { InlinePicture, imageInfoOf, naturalSizeEmu, addImage, writableWidthEmu, type ImageFormat, type ImageInfo, type InlinePictureOptions, type NewPicture } from './InlinePicture.mjs';
|
|
11
11
|
export { ContentControl, collectControls, collectRunControls, W14_NS, W15_NS, type ContentControlType, type ContentControlForm, type ContentControlAppearance } from './ContentControl.mjs';
|
|
12
12
|
export { contentOf, isFlatOpc, rewriteRelationshipIds, type OoxmlOptions } from './ooxml.mjs';
|
|
13
|
-
export { type SearchOptions, searchPattern } from './search.mjs';
|
|
13
|
+
export { type SearchOptions, searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
|
|
14
14
|
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf, type TextSegment, type Located, type TextView, type TextViewOptions, type RevisionKind, type RevisionHolder } from './tree.mjs';
|
|
15
15
|
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext, type TrackedChangeType, type TrackedChangeTarget } from './TrackedChange.mjs';
|
|
16
|
-
export { ChangeTracker, trackerOf, calendarOf, dateOf, copyRPr, markDeleted, markInserted, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, type ChangeTrackingMode, type TrackingHost, } from './tracking.mjs';
|
|
16
|
+
export { ChangeTracker, trackerOf, calendarOf, dateOf, copyRPr, markDeleted, markInserted, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, type ChangeTrackingMode, type TrackingHost, type TrackingScope, } from './tracking.mjs';
|
|
17
17
|
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS, type Element, type Wrapper, type WmlOptions, type Raw, type Interpolated, type RunOptions, type RunFormatting, type ParagraphOptions, type TableOptions, type CellOptions, type SdtKind, type SdtForm, type SdtOptions } from '@docx4j/generated-objects-ts/builders/wml';
|
|
18
|
+
export { StylesFacade, type StylePackageLike } from './stylesFacade.mjs';
|
|
19
|
+
export { bindSnapshot, boundsOf, pathOf, type Bound, type BoundSnapshot } from './binder.mjs';
|
|
@@ -12,10 +12,12 @@ export { Table, TableRow, TableCell, cellOf } from './Table.mjs';
|
|
|
12
12
|
export { InlinePicture, imageInfoOf, naturalSizeEmu, addImage, writableWidthEmu } from './InlinePicture.mjs';
|
|
13
13
|
export { ContentControl, collectControls, collectRunControls, W14_NS, W15_NS } from './ContentControl.mjs';
|
|
14
14
|
export { contentOf, isFlatOpc, rewriteRelationshipIds } from './ooxml.mjs';
|
|
15
|
-
export { searchPattern } from './search.mjs';
|
|
15
|
+
export { searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
|
|
16
16
|
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf } from './tree.mjs';
|
|
17
17
|
// change tracking (CR-002 phase F)
|
|
18
18
|
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext } from './TrackedChange.mjs';
|
|
19
19
|
export { ChangeTracker, trackerOf, calendarOf, dateOf, copyRPr, markDeleted, markInserted, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, } from './tracking.mjs';
|
|
20
20
|
// The objects package's builders, re-exported so that one import serves the content API and the tree it works on.
|
|
21
21
|
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
|
|
22
|
+
export { StylesFacade } from './stylesFacade.mjs';
|
|
23
|
+
export { bindSnapshot, boundsOf, pathOf } from './binder.mjs';
|