@docx4j/core-ts 0.3.1 → 0.3.2
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/model/content/Body.mjs +2 -1
- package/dist/model/content/ContentControl.d.mts +5 -1
- package/dist/model/content/ContentControl.mjs +18 -5
- package/dist/model/content/Paragraph.d.mts +11 -11
- package/dist/model/content/Paragraph.mjs +30 -43
- package/dist/model/content/Range.mjs +3 -2
- package/dist/model/content/stylesFacade.mjs +7 -4
- package/dist/model/content/tracking.d.mts +14 -0
- package/dist/model/content/tracking.mjs +19 -10
- package/dist/model/customxml/XmlMapping.d.mts +20 -4
- package/dist/model/customxml/XmlMapping.mjs +44 -6
- package/dist/model/customxml/bindings.d.mts +9 -2
- package/dist/model/customxml/bindings.mjs +18 -2
- package/dist/model/customxml/index.d.mts +1 -1
- package/dist/model/customxml/index.mjs +1 -1
- package/dist/model/customxml/insert.d.mts +10 -0
- package/dist/model/customxml/insert.mjs +13 -0
- package/dist/model/fonts/RunFontSelector.d.mts +8 -1
- package/dist/model/fonts/RunFontSelector.mjs +6 -5
- package/dist/model/properties/PropertyResolver.d.mts +110 -10
- package/dist/model/properties/PropertyResolver.mjs +300 -31
- package/dist/model/properties/index.d.mts +3 -0
- package/dist/model/properties/index.mjs +2 -0
- package/dist/model/properties/table.d.mts +155 -0
- package/dist/model/properties/table.mjs +315 -0
- package/dist/model/properties/tableStyleConditions.d.mts +101 -0
- package/dist/model/properties/tableStyleConditions.mjs +296 -0
- package/dist/parts/wml/placeholderStyle.d.mts +3 -0
- package/dist/parts/wml/placeholderStyle.mjs +13 -0
- package/package.json +2 -2
|
@@ -6,7 +6,7 @@ import { Paragraph } from './Paragraph.mjs';
|
|
|
6
6
|
import { Table } from './Table.mjs';
|
|
7
7
|
import { ContentControl, collectControls } from './ContentControl.mjs';
|
|
8
8
|
import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/wml';
|
|
9
|
-
import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
|
|
9
|
+
import { controlIdScope, sdtKindFor, declareSdtExtensions } from '../customxml/insert.mjs';
|
|
10
10
|
import { InlinePicture, addImage, writableWidthEmu } from './InlinePicture.mjs';
|
|
11
11
|
import { contentOf } from './ooxml.mjs';
|
|
12
12
|
import { expandReplacement } from './search.mjs';
|
|
@@ -748,6 +748,7 @@ export class Body {
|
|
|
748
748
|
this.content.length = 0;
|
|
749
749
|
this.content.push(sdt);
|
|
750
750
|
linkParents(sdt, this.container);
|
|
751
|
+
declareSdtExtensions(this, sdt);
|
|
751
752
|
// under tracking the control itself is the insertion, its content what it was (check 30)
|
|
752
753
|
const tracker = this.changeTracker;
|
|
753
754
|
if (tracker)
|
|
@@ -140,7 +140,11 @@ export declare class ContentControl {
|
|
|
140
140
|
get repeatingSectionContentControl(): RepeatingSectionContentControl | undefined;
|
|
141
141
|
/** The group view, for a `w:group` control (Office JS: an object with no members of its own). */
|
|
142
142
|
get groupContentControl(): GroupContentControl | undefined;
|
|
143
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* Adds or replaces a `w:sdtPr` child (extension). A `w15` element (`w15:appearance`, `w15:color`,
|
|
145
|
+
* `w15:dataBinding`, the repeating section) puts `w15` in the part's `mc:Ignorable`, as Word's own
|
|
146
|
+
* files have it: Word 2010 opens a part holding one only then (CR-002 section 40).
|
|
147
|
+
*/
|
|
144
148
|
putProperty(element: Element): void;
|
|
145
149
|
/** Removes a `w:sdtPr` child (extension). */
|
|
146
150
|
removeProperty(localPart: string, namespaceURI?: string): void;
|
|
@@ -6,7 +6,8 @@ import { marshalString, deepCopy } from '@docx4j/generated-objects-ts';
|
|
|
6
6
|
// nothing from here at run time (types only), so this direction is the only one.
|
|
7
7
|
import { XmlMapping } from '../customxml/XmlMapping.mjs';
|
|
8
8
|
import { CheckboxContentControl, DatePickerContentControl, ListContentControl, PictureContentControl, RepeatingSectionContentControl, GroupContentControl, checkboxRun, CHECKBOX_FONT, } from '../customxml/kinds.mjs';
|
|
9
|
-
import { runsForValue, updateFromControl, PLACEHOLDER_TEXT } from '../customxml/bindings.mjs';
|
|
9
|
+
import { runsForValue, updateFromControl, PLACEHOLDER_TEXT, PLACEHOLDER_STYLE } from '../customxml/bindings.mjs';
|
|
10
|
+
import { declareIgnorable } from './tracking.mjs';
|
|
10
11
|
import { sdtProperty, sdtKindOf, t as textItem } from '@docx4j/generated-objects-ts/builders/wml';
|
|
11
12
|
import { typeNameOf, childrenOf, textOf, runItemsOf, segmentsOf, linkParents, runOf, SDT_TYPES } from './tree.mjs';
|
|
12
13
|
import { Range } from './Range.mjs';
|
|
@@ -429,7 +430,11 @@ export class ContentControl {
|
|
|
429
430
|
get groupContentControl() {
|
|
430
431
|
return sdtProperty(this.sdt.sdtPr, 'group') ? new GroupContentControl() : undefined;
|
|
431
432
|
}
|
|
432
|
-
/**
|
|
433
|
+
/**
|
|
434
|
+
* Adds or replaces a `w:sdtPr` child (extension). A `w15` element (`w15:appearance`, `w15:color`,
|
|
435
|
+
* `w15:dataBinding`, the repeating section) puts `w15` in the part's `mc:Ignorable`, as Word's own
|
|
436
|
+
* files have it: Word 2010 opens a part holding one only then (CR-002 section 40).
|
|
437
|
+
*/
|
|
433
438
|
putProperty(element) {
|
|
434
439
|
var _a, _b;
|
|
435
440
|
var _c;
|
|
@@ -441,6 +446,8 @@ export class ContentControl {
|
|
|
441
446
|
items[at] = element;
|
|
442
447
|
else
|
|
443
448
|
items.push(element);
|
|
449
|
+
if (element.name.namespaceURI === W15_NS)
|
|
450
|
+
declareIgnorable(this.parentBody.part, 'w15');
|
|
444
451
|
}
|
|
445
452
|
/** Removes a `w:sdtPr` child (extension). */
|
|
446
453
|
removeProperty(localPart, namespaceURI) {
|
|
@@ -481,11 +488,11 @@ export class ContentControl {
|
|
|
481
488
|
* the runs of a run-level one.
|
|
482
489
|
*/
|
|
483
490
|
setBoundContent(runs, showingPlaceholder = false) {
|
|
484
|
-
var _a, _b;
|
|
485
|
-
var
|
|
491
|
+
var _a, _b, _c, _d;
|
|
492
|
+
var _e;
|
|
486
493
|
const sdt = this.sdt;
|
|
487
494
|
(_a = sdt.sdtContent) !== null && _a !== void 0 ? _a : (sdt.sdtContent = {});
|
|
488
|
-
const content = ((_b = (
|
|
495
|
+
const content = ((_b = (_e = sdt.sdtContent).content) !== null && _b !== void 0 ? _b : (_e.content = []));
|
|
489
496
|
const first = content.find((e) => typeNameOf(e) !== undefined);
|
|
490
497
|
if (this.form === 'Run' || (first && typeNameOf(first) === 'org_docx4j_wml.R')) {
|
|
491
498
|
content.length = 0;
|
|
@@ -505,6 +512,12 @@ export class ContentControl {
|
|
|
505
512
|
}
|
|
506
513
|
}
|
|
507
514
|
this.isShowingPlaceholder = showingPlaceholder;
|
|
515
|
+
// The placeholder run names the PlaceholderText style, which a document made here lacks: the
|
|
516
|
+
// package splices the definition in when it is saved, as it does a new hyperlink's style. Word
|
|
517
|
+
// 2010 drops a w:rStyle naming a style the part does not define (CR-002 section 40).
|
|
518
|
+
if (showingPlaceholder) {
|
|
519
|
+
(_d = (_c = this.parentBody.package_) === null || _c === void 0 ? void 0 : _c.requireStyles) === null || _d === void 0 ? void 0 : _d.call(_c, [PLACEHOLDER_STYLE]);
|
|
520
|
+
}
|
|
508
521
|
}
|
|
509
522
|
/** Shows a checkbox's glyph, as Word writes it: one run in the checkbox font (docx4j checkboxRun). */
|
|
510
523
|
setCheckboxGlyph(symbol) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
|
+
import type { CellContext } from '../properties/table.mjs';
|
|
2
3
|
import { type Element, W_NS, type TextSegment, type TextViewOptions } from './tree.mjs';
|
|
3
4
|
import { Font, type FontTracking } from './Font.mjs';
|
|
4
5
|
import { Range } from './Range.mjs';
|
|
@@ -95,6 +96,16 @@ export declare class Paragraph {
|
|
|
95
96
|
get effectivePPr(): wml.PPr;
|
|
96
97
|
/** The paragraph mark's effective run properties (docx4j `getEffectiveParagraphMarkRPr`). */
|
|
97
98
|
get effectiveParagraphMarkRPr(): wml.RPr;
|
|
99
|
+
/**
|
|
100
|
+
* Where this paragraph sits in a table, as far as its formatting goes (docx4j
|
|
101
|
+
* `PropertyResolver.cellContextOf`; CR-007): the table style its table resolves to and the
|
|
102
|
+
* conditional formats it is under. Undefined outside a table, and in a text box, note or comment
|
|
103
|
+
* reached from a cell. Every effective read of the paragraph and of its runs passes it, so a run
|
|
104
|
+
* in a header row the table style makes bold reads bold. Each read walks the table's rows; code
|
|
105
|
+
* resolving every paragraph of a large table should walk with a `TableContextTracker` instead.
|
|
106
|
+
* Needs the package's resolver, as the effective reads do.
|
|
107
|
+
*/
|
|
108
|
+
get cellContext(): CellContext | undefined;
|
|
98
109
|
/** The `w:pPr` a formatting read works from: the resolved one, or this paragraph's own. */
|
|
99
110
|
private readPPr;
|
|
100
111
|
/**
|
|
@@ -195,17 +206,6 @@ export declare class Paragraph {
|
|
|
195
206
|
*/
|
|
196
207
|
delete(): void;
|
|
197
208
|
private trackedDelete;
|
|
198
|
-
/**
|
|
199
|
-
* A paragraph mark deleted under tracking gives the next paragraph this paragraph's properties,
|
|
200
|
-
* as a `w:pPrChange` on it recording its own: Word, at Delete at the end of a Heading 2 with a
|
|
201
|
-
* Normal paragraph after it, wrote the next paragraph `w:pStyle Heading2` with
|
|
202
|
-
* `<w:pPrChange><w:pPr/></w:pPrChange>`, and No Markup reads the joined line as a heading
|
|
203
|
-
* throughout (the editor's `measure-word15.docx`, 2026-09-30; CR-002 section 38). The Delete
|
|
204
|
-
* counterpart of check 29's Enter. Nothing where the two paragraphs' properties are the same
|
|
205
|
-
* (check 22's deleted marks). Accepting the mark then joins into a paragraph with these
|
|
206
|
-
* properties, and rejecting puts the next paragraph's back.
|
|
207
|
-
*/
|
|
208
|
-
private giveMarkPropertiesToNext;
|
|
209
209
|
/**
|
|
210
210
|
* The paragraph's content and its mark marked deleted, the paragraph element itself kept:
|
|
211
211
|
* what the cells of a deleted table row need (a `w:tc` must keep a block-level child, and Word
|
|
@@ -15,11 +15,11 @@ import { builtInOf, idOfBuiltIn, styleNameOf, styleIdOf } from './styles.mjs';
|
|
|
15
15
|
import { cellOf } from './Table.mjs';
|
|
16
16
|
import { ContentControl, collectRunControls } from './ContentControl.mjs';
|
|
17
17
|
import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/wml';
|
|
18
|
-
import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
|
|
18
|
+
import { controlIdScope, sdtKindFor, declareSdtExtensions } from '../customxml/insert.mjs';
|
|
19
19
|
import { InlinePicture, addImage, writableWidthEmu } from './InlinePicture.mjs';
|
|
20
20
|
import { contentOf } from './ooxml.mjs';
|
|
21
21
|
import { commentApi } from './comments.mjs';
|
|
22
|
-
import { ChangeTracker, copyRPr, markDeleted, toDeletedText, highestAnnotationId, canonical, restorePPr, wrapInsertedRuns, markHolderInserted } from './tracking.mjs';
|
|
22
|
+
import { ChangeTracker, copyRPr, markDeleted, toDeletedText, highestAnnotationId, canonical, restorePPr, wrapInsertedRuns, markHolderInserted, pruneParagraphProperties } from './tracking.mjs';
|
|
23
23
|
import { trackedChangesOfParagraph } from './TrackedChange.mjs';
|
|
24
24
|
import { isListItem, listOf, listOrNullObjectOf, listItemOf, listItemOrNullObjectOf, startNewList, attachToList, detachFromList, } from './List.mjs';
|
|
25
25
|
const TWIPS_PER_POINT = 20;
|
|
@@ -125,11 +125,23 @@ export class Paragraph {
|
|
|
125
125
|
* changing it. Needs the package's resolver; see `Body.propertyResolver`.
|
|
126
126
|
*/
|
|
127
127
|
get effectivePPr() {
|
|
128
|
-
return this.parentBody.propertyResolver.getEffectivePPr(this.p.pPr);
|
|
128
|
+
return this.parentBody.propertyResolver.getEffectivePPr(this.p.pPr, this.cellContext);
|
|
129
129
|
}
|
|
130
130
|
/** The paragraph mark's effective run properties (docx4j `getEffectiveParagraphMarkRPr`). */
|
|
131
131
|
get effectiveParagraphMarkRPr() {
|
|
132
|
-
return this.parentBody.propertyResolver.getEffectiveParagraphMarkRPr(this.p.pPr);
|
|
132
|
+
return this.parentBody.propertyResolver.getEffectiveParagraphMarkRPr(this.p.pPr, this.cellContext);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Where this paragraph sits in a table, as far as its formatting goes (docx4j
|
|
136
|
+
* `PropertyResolver.cellContextOf`; CR-007): the table style its table resolves to and the
|
|
137
|
+
* conditional formats it is under. Undefined outside a table, and in a text box, note or comment
|
|
138
|
+
* reached from a cell. Every effective read of the paragraph and of its runs passes it, so a run
|
|
139
|
+
* in a header row the table style makes bold reads bold. Each read walks the table's rows; code
|
|
140
|
+
* resolving every paragraph of a large table should walk with a `TableContextTracker` instead.
|
|
141
|
+
* Needs the package's resolver, as the effective reads do.
|
|
142
|
+
*/
|
|
143
|
+
get cellContext() {
|
|
144
|
+
return this.parentBody.propertyResolver.cellContextOf(this.p);
|
|
133
145
|
}
|
|
134
146
|
/** The `w:pPr` a formatting read works from: the resolved one, or this paragraph's own. */
|
|
135
147
|
readPPr(options) {
|
|
@@ -157,6 +169,7 @@ export class Paragraph {
|
|
|
157
169
|
else
|
|
158
170
|
pPr.jc = { val };
|
|
159
171
|
this.settleFormatting();
|
|
172
|
+
pruneParagraphProperties(this.p); // no empty w:pPr left (the editor's finding on 0.3.1)
|
|
160
173
|
}
|
|
161
174
|
/**
|
|
162
175
|
* The alignment the paragraph resolves to with no `w:jc` of its own: its style's, else the
|
|
@@ -172,7 +185,8 @@ export class Paragraph {
|
|
|
172
185
|
if (!resolver)
|
|
173
186
|
return undefined;
|
|
174
187
|
const { jc: _jc, pPrChange: _change, PARENT: _parent, ...rest } = this.p.pPr;
|
|
175
|
-
|
|
188
|
+
// in a table cell what is inherited includes the table style's (CR-007)
|
|
189
|
+
return alignmentOf(resolver.getEffectivePPr(rest, resolver.cellContextOf(this.p)), true);
|
|
176
190
|
}
|
|
177
191
|
/** Indents and spacing in points, as Office JS; the effective values (CR-001 Phase B step 2). */
|
|
178
192
|
get leftIndent() { var _a, _b; return ((_b = (_a = this.effectivePPr.ind) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
|
|
@@ -222,7 +236,7 @@ export class Paragraph {
|
|
|
222
236
|
const holders = () => runsOf(this.p).map((r) => r.value);
|
|
223
237
|
if ((options === null || options === void 0 ? void 0 : options.direct) === true)
|
|
224
238
|
return new Font(holders, () => this.fontTracking());
|
|
225
|
-
return new Font(holders, () => this.fontTracking(), (rPr) => this.parentBody.propertyResolver.getEffectiveRPr(rPr, this.p.pPr), (rPr) => { var _a; return (_a = runFontSelectorOf(this.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
|
|
239
|
+
return new Font(holders, () => this.fontTracking(), (rPr) => this.parentBody.propertyResolver.getEffectiveRPr(rPr, this.p.pPr, this.cellContext), (rPr) => { var _a; return (_a = runFontSelectorOf(this.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
|
|
226
240
|
}
|
|
227
241
|
/** w14:paraId, the stable address Word gives paragraphs. */
|
|
228
242
|
get paraId() {
|
|
@@ -426,42 +440,13 @@ export class Paragraph {
|
|
|
426
440
|
return;
|
|
427
441
|
}
|
|
428
442
|
tracker.markParagraphDeleted(this.p);
|
|
429
|
-
this
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
* throughout (the editor's `measure-word15.docx`, 2026-09-30; CR-002 section 38). The Delete
|
|
437
|
-
* counterpart of check 29's Enter. Nothing where the two paragraphs' properties are the same
|
|
438
|
-
* (check 22's deleted marks). Accepting the mark then joins into a paragraph with these
|
|
439
|
-
* properties, and rejecting puts the next paragraph's back.
|
|
440
|
-
*/
|
|
441
|
-
giveMarkPropertiesToNext(tracker) {
|
|
442
|
-
const i = this.index;
|
|
443
|
-
const next = i >= 0 ? this.container[i + 1] : undefined;
|
|
444
|
-
if (!next || typeNameOf(next) !== 'org_docx4j_wml.P')
|
|
445
|
-
return;
|
|
446
|
-
const base = (pPr) => {
|
|
447
|
-
const out = {};
|
|
448
|
-
for (const [key, value] of Object.entries(pPr !== null && pPr !== void 0 ? pPr : {})) {
|
|
449
|
-
if (key !== 'TYPE_NAME' && key !== 'PARENT' && key !== 'rPr' && key !== 'sectPr' && key !== 'pPrChange' && value !== undefined)
|
|
450
|
-
out[key] = value;
|
|
451
|
-
}
|
|
452
|
-
return out;
|
|
453
|
-
};
|
|
454
|
-
const source = base(this.p.pPr);
|
|
455
|
-
const nextP = next.value;
|
|
456
|
-
if (canonical(source) === canonical(base(nextP.pPr)))
|
|
457
|
-
return;
|
|
458
|
-
const target = new Paragraph(next, this.container, this.parentBody).pPr();
|
|
459
|
-
tracker.recordPPrChange(target);
|
|
460
|
-
for (const key of Object.keys(base(target)))
|
|
461
|
-
delete target[key];
|
|
462
|
-
for (const [key, value] of Object.entries(source))
|
|
463
|
-
target[key] = deepCopy(value);
|
|
464
|
-
linkParents(target, nextP);
|
|
443
|
+
// Word, deleting a paragraph mark ALONE under tracking, gives the next paragraph this one's
|
|
444
|
+
// properties as a w:pPrChange (CR-002 section 38 item 2, the editor's measure-word15.docx), so
|
|
445
|
+
// that the joined line reads in them. This method deletes the whole paragraph, text and mark - the
|
|
446
|
+
// engine's only mark deletion, a Range being within one paragraph - and what Word writes for that
|
|
447
|
+
// is not measured (test/README.md check 33). 0.3.1 carried the properties here too, which turned
|
|
448
|
+
// an agent's new heading, put in after a paragraph it then deleted, into body text once accepted
|
|
449
|
+
// (the editor's finding on 0.3.1); until the check, nothing is carried.
|
|
465
450
|
}
|
|
466
451
|
/**
|
|
467
452
|
* The paragraph's content and its mark marked deleted, the paragraph element itself kept:
|
|
@@ -533,8 +518,9 @@ export class Paragraph {
|
|
|
533
518
|
if (!same) {
|
|
534
519
|
const rest = (props) => canonical(Object.fromEntries(Object.entries(props).filter(([key]) => !FORMATTING_MEMBERS.has(key))));
|
|
535
520
|
const resolver = (_b = this.parentBody.package_) === null || _b === void 0 ? void 0 : _b.propertyResolverOrUndefined;
|
|
521
|
+
const cell = resolver === null || resolver === void 0 ? void 0 : resolver.cellContextOf(this.p);
|
|
536
522
|
same = resolver !== undefined && rest(current) === rest(before)
|
|
537
|
-
&& canonical(formattingOf(resolver.getEffectivePPr(current), true)) === canonical(formattingOf(resolver.getEffectivePPr(before), true));
|
|
523
|
+
&& canonical(formattingOf(resolver.getEffectivePPr(current, cell), true)) === canonical(formattingOf(resolver.getEffectivePPr(before, cell), true));
|
|
538
524
|
}
|
|
539
525
|
if (same)
|
|
540
526
|
restorePPr(this.p, recorded);
|
|
@@ -826,6 +812,7 @@ export class Paragraph {
|
|
|
826
812
|
const sdt = sdtOf([this.element], { kind: sdtKindFor(kind), id: nextSdtId(controlIdScope(this.parentBody)), form: 'block' });
|
|
827
813
|
this.container.splice(at, 1, sdt);
|
|
828
814
|
linkParents(sdt, (_a = this.p.PARENT) !== null && _a !== void 0 ? _a : this.parentBody.container);
|
|
815
|
+
declareSdtExtensions(this.parentBody, sdt);
|
|
829
816
|
// under tracking the control itself is the insertion, the paragraph what it was (check 30)
|
|
830
817
|
const tracker = this.changeTracker;
|
|
831
818
|
if (tracker)
|
|
@@ -6,7 +6,7 @@ import { ContentControl } from './ContentControl.mjs';
|
|
|
6
6
|
import { sdt as sdtOf, nextSdtId, applyRunOptions, t as textElement } 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
|
-
import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
|
|
9
|
+
import { controlIdScope, sdtKindFor, declareSdtExtensions } from '../customxml/insert.mjs';
|
|
10
10
|
import { contentOf } from './ooxml.mjs';
|
|
11
11
|
import { markHolderInserted } from './tracking.mjs';
|
|
12
12
|
import { searchPattern, findAll, matchesOf, expandReplacement } from './search.mjs';
|
|
@@ -74,7 +74,7 @@ export class Range {
|
|
|
74
74
|
};
|
|
75
75
|
if ((options === null || options === void 0 ? void 0 : options.direct) === true)
|
|
76
76
|
return new Font(holders, () => this.paragraph.fontTracking());
|
|
77
|
-
return new Font(holders, () => this.paragraph.fontTracking(), (rPr) => this.paragraph.parentBody.propertyResolver.getEffectiveRPr(rPr, this.paragraph.p.pPr), (rPr) => { var _a; return (_a = runFontSelectorOf(this.paragraph.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
|
|
77
|
+
return new Font(holders, () => this.paragraph.fontTracking(), (rPr) => this.paragraph.parentBody.propertyResolver.getEffectiveRPr(rPr, this.paragraph.p.pPr, this.paragraph.cellContext), (rPr) => { var _a; return (_a = runFontSelectorOf(this.paragraph.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
|
|
78
78
|
}
|
|
79
79
|
/** The runs the span covers (a run partly inside counts). */
|
|
80
80
|
get runs() {
|
|
@@ -215,6 +215,7 @@ export class Range {
|
|
|
215
215
|
// The control is built empty first: `sdt` refuses a kind that cannot be run-level (a repeating
|
|
216
216
|
// section), and that refusal must come before any run is split.
|
|
217
217
|
const sdt = sdtOf([], { kind: sdtKindFor(kind), id: nextSdtId(controlIdScope(body)), form: 'run' });
|
|
218
|
+
declareSdtExtensions(body, sdt);
|
|
218
219
|
if (this.start === this.end) {
|
|
219
220
|
paragraph.insertItemsAt(this.start, [sdt]);
|
|
220
221
|
return new ContentControl(sdt, containerOf(sdt, paragraph), body);
|
|
@@ -4,12 +4,14 @@ import { parseXml } from '../../xml/dom.mjs';
|
|
|
4
4
|
import { DEFAULT_STYLES_XML } from '../../parts/wml/defaultStyles.mjs';
|
|
5
5
|
import { SPLICEABLE_STYLES_XML } from '../../parts/wml/spliceableStyles.mjs';
|
|
6
6
|
import { commentStyles } from '../../parts/wml/commentStyles.mjs';
|
|
7
|
+
import { placeholderStyle } from '../../parts/wml/placeholderStyle.mjs';
|
|
7
8
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
8
9
|
/**
|
|
9
10
|
* Where a definition is looked up, unmarshalled once and never handed out (a copy is spliced in):
|
|
10
11
|
* the defaults `createPackage()` writes, and then the nine styles docx4j's own `styles.xml` carries
|
|
11
12
|
* **commented out** - which is why a created document has no `FootnoteText` although the file
|
|
12
|
-
* appears to contain one, and why this facade exists (CR-002 section 22.2)
|
|
13
|
+
* appears to contain one, and why this facade exists (CR-002 section 22.2) - with Word's two comment
|
|
14
|
+
* styles and its `PlaceholderText` after them.
|
|
13
15
|
*/
|
|
14
16
|
let sources;
|
|
15
17
|
function styleSources() {
|
|
@@ -17,8 +19,9 @@ function styleSources() {
|
|
|
17
19
|
const read = async (xml) => { var _a; return (_a = (await unmarshalNode(parseXml(xml))).value.style) !== null && _a !== void 0 ? _a : []; };
|
|
18
20
|
const defaults = await read(DEFAULT_STYLES_XML);
|
|
19
21
|
// and Word's two comment styles, which the comment parts add when they are made, for a caller
|
|
20
|
-
// that makes the comment itself (CR-002 section 37)
|
|
21
|
-
|
|
22
|
+
// that makes the comment itself (CR-002 section 37), and Word's PlaceholderText, which a
|
|
23
|
+
// placeholder run names (CR-002 section 40)
|
|
24
|
+
return { defaults, all: [...defaults, ...(await read(SPLICEABLE_STYLES_XML)), ...commentStyles(), placeholderStyle()] };
|
|
22
25
|
})()));
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
@@ -102,7 +105,7 @@ function closureOf(wanted, present, source) {
|
|
|
102
105
|
seen.add(id);
|
|
103
106
|
const template = source.find((s) => s.styleId === id);
|
|
104
107
|
if (template === undefined) {
|
|
105
|
-
throw new Docx4JException(`No definition to splice for the style ${id}: neither docx4j's default styles, the nine it comments out
|
|
108
|
+
throw new Docx4JException(`No definition to splice for the style ${id}: neither docx4j's default styles, the nine it comments out, the two comment styles nor PlaceholderText carry one. Define it yourself on the styles part.`);
|
|
106
109
|
}
|
|
107
110
|
// what it is based on and linked to must be there too, and before it reads better in the part
|
|
108
111
|
for (const dependency of [(_a = template.basedOn) === null || _a === void 0 ? void 0 : _a.val, (_b = template.link) === null || _b === void 0 ? void 0 : _b.val]) {
|
|
@@ -92,6 +92,20 @@ export declare function canonical(value: unknown): string;
|
|
|
92
92
|
export interface TrackedPart {
|
|
93
93
|
readonly contents?: unknown;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Makes sure the part's root lists a prefix in `mc:Ignorable`, appending it when absent, so that
|
|
97
|
+
* content in that prefix's namespace may be written in it; the facade then declares the prefix.
|
|
98
|
+
* This is docx4j's pattern - the writer of the content adds its prefix
|
|
99
|
+
* (`Paginate.declareW14Ignorable`) - and Jason's decision (CR-002 section 29). Since objects 0.3.1
|
|
100
|
+
* (its CR-008) the marshaller does it for every writer as well; these calls stay as the writer's
|
|
101
|
+
* own statement. False when there is no unmarshalled root to put it on. Every part a
|
|
102
|
+
* `Body` is over (document, header, footer, notes, comments) has a root that binds `mc:Ignorable`.
|
|
103
|
+
*
|
|
104
|
+
* The prefix must be the facade's conventional one for its namespace (`w15`, `w16du`): an
|
|
105
|
+
* application that does not know the namespace (Word 2010 and `w15`) opens the part only when the
|
|
106
|
+
* prefix is ignorable, as Word's own files declare it (CR-002 section 40).
|
|
107
|
+
*/
|
|
108
|
+
export declare function declareIgnorable(part: TrackedPart | undefined, prefix: string): boolean;
|
|
95
109
|
/**
|
|
96
110
|
* The per-package writer of revision markup. Created by the package while
|
|
97
111
|
* `changeTrackingMode` is not `Off`; every content-API mutation asks its `Body` for one and,
|
|
@@ -105,24 +105,33 @@ export function canonical(value) {
|
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
-
* Makes sure the part's root lists
|
|
109
|
-
*
|
|
110
|
-
* pattern - the writer of the content adds its prefix
|
|
111
|
-
* decision (CR-002 section 29)
|
|
112
|
-
*
|
|
113
|
-
*
|
|
108
|
+
* Makes sure the part's root lists a prefix in `mc:Ignorable`, appending it when absent, so that
|
|
109
|
+
* content in that prefix's namespace may be written in it; the facade then declares the prefix.
|
|
110
|
+
* This is docx4j's pattern - the writer of the content adds its prefix
|
|
111
|
+
* (`Paginate.declareW14Ignorable`) - and Jason's decision (CR-002 section 29). Since objects 0.3.1
|
|
112
|
+
* (its CR-008) the marshaller does it for every writer as well; these calls stay as the writer's
|
|
113
|
+
* own statement. False when there is no unmarshalled root to put it on. Every part a
|
|
114
|
+
* `Body` is over (document, header, footer, notes, comments) has a root that binds `mc:Ignorable`.
|
|
115
|
+
*
|
|
116
|
+
* The prefix must be the facade's conventional one for its namespace (`w15`, `w16du`): an
|
|
117
|
+
* application that does not know the namespace (Word 2010 and `w15`) opens the part only when the
|
|
118
|
+
* prefix is ignorable, as Word's own files declare it (CR-002 section 40).
|
|
114
119
|
*/
|
|
115
|
-
function
|
|
120
|
+
export function declareIgnorable(part, prefix) {
|
|
116
121
|
var _a;
|
|
117
122
|
const contents = part === null || part === void 0 ? void 0 : part.contents;
|
|
118
123
|
if (!contents || typeof contents !== 'object')
|
|
119
124
|
return false;
|
|
120
125
|
const root = (contents.value && typeof contents.value === 'object' ? contents.value : contents);
|
|
121
|
-
const prefixes = ((_a = root.ignorable) !== null && _a !== void 0 ? _a : '').split(/\s+/).filter((
|
|
122
|
-
if (!prefixes.includes(
|
|
123
|
-
root.ignorable = [...prefixes,
|
|
126
|
+
const prefixes = ((_a = root.ignorable) !== null && _a !== void 0 ? _a : '').split(/\s+/).filter((p) => p.length > 0);
|
|
127
|
+
if (!prefixes.includes(prefix))
|
|
128
|
+
root.ignorable = [...prefixes, prefix].join(' ');
|
|
124
129
|
return true;
|
|
125
130
|
}
|
|
131
|
+
/** `w16du` in the part's `mc:Ignorable`, so that `w16du:dateUtc` may be written in it. */
|
|
132
|
+
function declareDateUtc(part) {
|
|
133
|
+
return declareIgnorable(part, 'w16du');
|
|
134
|
+
}
|
|
126
135
|
function element(localPart, value) {
|
|
127
136
|
return { name: { namespaceURI: W_NS, localPart }, value };
|
|
128
137
|
}
|
|
@@ -8,7 +8,9 @@ export interface CustomXmlPartLookup {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* A subset of Office JS `Word.XmlMapping`: the content control's data binding. `isMapped` is
|
|
11
|
-
* whether the control has a `w:dataBinding
|
|
11
|
+
* whether the control has a `w:dataBinding` (or, on a rich text control or a repeating section,
|
|
12
|
+
* the `w15:dataBinding` Word writes there, which is what `setMapping` writes on one: CR-002
|
|
13
|
+
* section 40); `customXmlNode` evaluates the XPath now, so it needs
|
|
12
14
|
* the XPath engine to be warm (`await pkg.customXmlParts.load()` once, CR-002 section 3.6).
|
|
13
15
|
*/
|
|
14
16
|
export declare class XmlMapping {
|
|
@@ -33,13 +35,27 @@ export declare class XmlMapping {
|
|
|
33
35
|
* Binds the control to what the XPath selects, as Word's own mapping does: the part is the one
|
|
34
36
|
* given, else the one the control is already bound to, else the first custom XML part (the
|
|
35
37
|
* built-in property stores last) in which the XPath selects a node. Returns false and changes
|
|
36
|
-
* nothing when nothing is selected, which is what Word reports.
|
|
38
|
+
* nothing when nothing is selected, which is what Word reports. **The node's value then goes into
|
|
39
|
+
* the control**, whatever text it held: Office JS's `setMapping` on a plain text control holding
|
|
40
|
+
* "quick brown", on an empty one and on one already holding the value, and Word's XML Mapping
|
|
41
|
+
* Pane mapping an existing control, each showed the node's "Ann" and left the part unchanged
|
|
42
|
+
* (`test/README.md` check 34, 2026-10-03; CR-002 section 39). Before, only the binding was
|
|
43
|
+
* written and the values stayed apart until `applyBindings`.
|
|
37
44
|
*/
|
|
38
45
|
setMapping(xpath: string, prefixMappings?: string, part?: CustomXmlPart): boolean;
|
|
39
|
-
/** Binds to a node: its canonical XPath and the prefixes that path needs, as Word writes them. */
|
|
46
|
+
/** Binds to a node: its canonical XPath and the prefixes that path needs, as Word writes them; the node's value goes into the control (check 34). */
|
|
40
47
|
setMappingByNode(node: CustomXmlNode): boolean;
|
|
41
|
-
/** Removes the binding (`w:dataBinding`); the control keeps the content it shows. */
|
|
48
|
+
/** Removes the binding (`w:dataBinding` and `w15:dataBinding`); the control keeps the content it shows. */
|
|
42
49
|
delete(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the control's binding is `w15:dataBinding`, as Word 2013 and later write it: on a rich
|
|
52
|
+
* text control (one with `w:richText`, or with no kind element at all) and on a repeating
|
|
53
|
+
* section. `w:dataBinding` on a rich text control makes it a plain text control to Word 15 and
|
|
54
|
+
* Word 2010 alike - shown from its node on open, given `<w:text/>` on saving, an edit written
|
|
55
|
+
* back as text (`test/README.md` check 35, 1f; CR-002 section 40).
|
|
56
|
+
*/
|
|
57
|
+
get usesW15(): boolean;
|
|
58
|
+
/** Writes the binding in the element the control's kind takes, replacing one in the other namespace where it stood. */
|
|
43
59
|
private write;
|
|
44
60
|
/** The parts to try, the customer's data before Word's property stores. */
|
|
45
61
|
private candidates;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import * as el from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
|
|
2
|
+
import * as w15el from '@docx4j/generated-objects-ts/el/org_docx4j_w15';
|
|
2
3
|
import { sdtProperty } from '@docx4j/generated-objects-ts/builders/wml';
|
|
3
4
|
import { canonicalXPathOf } from './xpath.mjs';
|
|
5
|
+
import { applyBindingTo } from './bindings.mjs';
|
|
4
6
|
/** The Word 2012 (w15) namespace; not imported from `ContentControl`, which imports this module. */
|
|
5
7
|
const W15_NS = 'http://schemas.microsoft.com/office/word/2012/wordml';
|
|
8
|
+
const W_NS = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
6
9
|
/**
|
|
7
10
|
* A subset of Office JS `Word.XmlMapping`: the content control's data binding. `isMapped` is
|
|
8
|
-
* whether the control has a `w:dataBinding
|
|
11
|
+
* whether the control has a `w:dataBinding` (or, on a rich text control or a repeating section,
|
|
12
|
+
* the `w15:dataBinding` Word writes there, which is what `setMapping` writes on one: CR-002
|
|
13
|
+
* section 40); `customXmlNode` evaluates the XPath now, so it needs
|
|
9
14
|
* the XPath engine to be warm (`await pkg.customXmlParts.load()` once, CR-002 section 3.6).
|
|
10
15
|
*/
|
|
11
16
|
export class XmlMapping {
|
|
@@ -58,7 +63,12 @@ export class XmlMapping {
|
|
|
58
63
|
* Binds the control to what the XPath selects, as Word's own mapping does: the part is the one
|
|
59
64
|
* given, else the one the control is already bound to, else the first custom XML part (the
|
|
60
65
|
* built-in property stores last) in which the XPath selects a node. Returns false and changes
|
|
61
|
-
* nothing when nothing is selected, which is what Word reports.
|
|
66
|
+
* nothing when nothing is selected, which is what Word reports. **The node's value then goes into
|
|
67
|
+
* the control**, whatever text it held: Office JS's `setMapping` on a plain text control holding
|
|
68
|
+
* "quick brown", on an empty one and on one already holding the value, and Word's XML Mapping
|
|
69
|
+
* Pane mapping an existing control, each showed the node's "Ann" and left the part unchanged
|
|
70
|
+
* (`test/README.md` check 34, 2026-10-03; CR-002 section 39). Before, only the binding was
|
|
71
|
+
* written and the values stayed apart until `applyBindings`.
|
|
62
72
|
*/
|
|
63
73
|
setMapping(xpath, prefixMappings, part) {
|
|
64
74
|
const candidates = part ? [part] : this.candidates();
|
|
@@ -67,25 +77,53 @@ export class XmlMapping {
|
|
|
67
77
|
if (!node)
|
|
68
78
|
continue;
|
|
69
79
|
this.write(xpath, prefixMappings !== null && prefixMappings !== void 0 ? prefixMappings : '', candidate.id);
|
|
80
|
+
applyBindingTo(this.contentControl);
|
|
70
81
|
return true;
|
|
71
82
|
}
|
|
72
83
|
return false;
|
|
73
84
|
}
|
|
74
|
-
/** Binds to a node: its canonical XPath and the prefixes that path needs, as Word writes them. */
|
|
85
|
+
/** Binds to a node: its canonical XPath and the prefixes that path needs, as Word writes them; the node's value goes into the control (check 34). */
|
|
75
86
|
setMappingByNode(node) {
|
|
76
87
|
const { xpath, prefixMappings } = canonicalXPathOf(node.node);
|
|
77
88
|
this.write(xpath, prefixMappings, node.ownerPart.id);
|
|
89
|
+
applyBindingTo(this.contentControl);
|
|
78
90
|
return true;
|
|
79
91
|
}
|
|
80
|
-
/** Removes the binding (`w:dataBinding`); the control keeps the content it shows. */
|
|
92
|
+
/** Removes the binding (`w:dataBinding` and `w15:dataBinding`); the control keeps the content it shows. */
|
|
81
93
|
delete() {
|
|
82
|
-
this.contentControl.removeProperty('dataBinding');
|
|
94
|
+
this.contentControl.removeProperty('dataBinding', W_NS);
|
|
95
|
+
this.contentControl.removeProperty('dataBinding', W15_NS);
|
|
83
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether the control's binding is `w15:dataBinding`, as Word 2013 and later write it: on a rich
|
|
99
|
+
* text control (one with `w:richText`, or with no kind element at all) and on a repeating
|
|
100
|
+
* section. `w:dataBinding` on a rich text control makes it a plain text control to Word 15 and
|
|
101
|
+
* Word 2010 alike - shown from its node on open, given `<w:text/>` on saving, an edit written
|
|
102
|
+
* back as text (`test/README.md` check 35, 1f; CR-002 section 40).
|
|
103
|
+
*/
|
|
104
|
+
get usesW15() {
|
|
105
|
+
const type = this.contentControl.type;
|
|
106
|
+
return type === 'RichText' || type === 'RepeatingSection';
|
|
107
|
+
}
|
|
108
|
+
/** Writes the binding in the element the control's kind takes, replacing one in the other namespace where it stood. */
|
|
84
109
|
write(xpath, prefixMappings, storeItemID) {
|
|
110
|
+
var _a, _b;
|
|
85
111
|
const binding = { TYPE_NAME: 'org_docx4j_wml.CTDataBinding', xpath, storeItemID };
|
|
86
112
|
if (prefixMappings !== '')
|
|
87
113
|
binding.prefixMappings = prefixMappings;
|
|
88
|
-
this.
|
|
114
|
+
const w15 = this.usesW15;
|
|
115
|
+
const element = (w15 ? w15el.dataBinding(binding) : el.dataBinding(binding));
|
|
116
|
+
const items = (_a = this.contentControl.sdt.sdtPr) === null || _a === void 0 ? void 0 : _a.rPrOrAliasOrLock;
|
|
117
|
+
const other = w15 ? W_NS : W15_NS;
|
|
118
|
+
const at = (_b = items === null || items === void 0 ? void 0 : items.findIndex((i) => i.name.localPart === 'dataBinding' && i.name.namespaceURI === other)) !== null && _b !== void 0 ? _b : -1;
|
|
119
|
+
if (items && at >= 0) {
|
|
120
|
+
if (items.some((i) => i.name.localPart === 'dataBinding' && i.name.namespaceURI === element.name.namespaceURI))
|
|
121
|
+
items.splice(at, 1);
|
|
122
|
+
else
|
|
123
|
+
items[at] = element;
|
|
124
|
+
}
|
|
125
|
+
// putProperty also lists w15 in the part's mc:Ignorable when the element is a w15 one
|
|
126
|
+
this.contentControl.putProperty(element);
|
|
89
127
|
}
|
|
90
128
|
/** The parts to try, the customer's data before Word's property stores. */
|
|
91
129
|
candidates() {
|
|
@@ -13,6 +13,13 @@ export interface BindingResult {
|
|
|
13
13
|
/** Controls left alone: the part is missing, the XPath selects nothing, or the kind is not handled. */
|
|
14
14
|
skipped: number;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether a node's value is a Flat OPC package: what Word writes into the node of a mapped rich
|
|
18
|
+
* text control when its content is edited, a whole `pkg:package` as escaped text (`test/README.md`
|
|
19
|
+
* check 35). It is content, never a control's text - Word 2010 shows it as raw XML in a plain text
|
|
20
|
+
* control bound to the same node - so neither direction moves it as text (CR-002 section 40).
|
|
21
|
+
*/
|
|
22
|
+
export declare function holdsFlatOpc(value: string): boolean;
|
|
16
23
|
/** docx4j ValueInserterPlainTextImpl: the runs for a value, with the w:sdtPr run properties. */
|
|
17
24
|
export declare function runsForValue(value: string, rPr: wml.RPr | undefined, multiLine: boolean): Element[];
|
|
18
25
|
/**
|
|
@@ -24,8 +31,8 @@ export declare function runsForValue(value: string, rPr: wml.RPr | undefined, mu
|
|
|
24
31
|
export declare function formatDate(pattern: string, date: Date, locale?: string): string;
|
|
25
32
|
/**
|
|
26
33
|
* Pushes the custom XML value into one control (docx4j BindingHandler's per-sdt work). Returns
|
|
27
|
-
* false when nothing was written: no binding, no part, an XPath that selects nothing,
|
|
28
|
-
* this phase does not handle (pictures, explicit rich text).
|
|
34
|
+
* false when nothing was written: no binding, no part, an XPath that selects nothing, a kind
|
|
35
|
+
* this phase does not handle (pictures, explicit rich text), or a node holding a Flat OPC package.
|
|
29
36
|
*/
|
|
30
37
|
export declare function applyBindingTo(control: ContentControl): boolean;
|
|
31
38
|
/** `applyBindings` over a list of controls. */
|
|
@@ -4,6 +4,16 @@ import { sdtProperty } from '@docx4j/generated-objects-ts/builders/wml';
|
|
|
4
4
|
/** The style Word gives placeholder text, and the text docx4j's placeholder.xml carries. */
|
|
5
5
|
export const PLACEHOLDER_STYLE = 'PlaceholderText';
|
|
6
6
|
export const PLACEHOLDER_TEXT = 'Click here to enter text.';
|
|
7
|
+
/**
|
|
8
|
+
* Whether a node's value is a Flat OPC package: what Word writes into the node of a mapped rich
|
|
9
|
+
* text control when its content is edited, a whole `pkg:package` as escaped text (`test/README.md`
|
|
10
|
+
* check 35). It is content, never a control's text - Word 2010 shows it as raw XML in a plain text
|
|
11
|
+
* control bound to the same node - so neither direction moves it as text (CR-002 section 40).
|
|
12
|
+
*/
|
|
13
|
+
export function holdsFlatOpc(value) {
|
|
14
|
+
return /^\s*(<\?[^>]*\?>\s*)*<([\w.-]+:)?package[\s>]/.test(value)
|
|
15
|
+
&& value.includes('http://schemas.microsoft.com/office/2006/xmlPackage');
|
|
16
|
+
}
|
|
7
17
|
function isTrue(value) {
|
|
8
18
|
const v = value.trim().toLowerCase();
|
|
9
19
|
return v === 'true' || v === '1' || v === 'on' || v === 'yes';
|
|
@@ -103,8 +113,8 @@ function dateOf(value) {
|
|
|
103
113
|
}
|
|
104
114
|
/**
|
|
105
115
|
* Pushes the custom XML value into one control (docx4j BindingHandler's per-sdt work). Returns
|
|
106
|
-
* false when nothing was written: no binding, no part, an XPath that selects nothing,
|
|
107
|
-
* this phase does not handle (pictures, explicit rich text).
|
|
116
|
+
* false when nothing was written: no binding, no part, an XPath that selects nothing, a kind
|
|
117
|
+
* this phase does not handle (pictures, explicit rich text), or a node holding a Flat OPC package.
|
|
108
118
|
*/
|
|
109
119
|
export function applyBindingTo(control) {
|
|
110
120
|
var _a;
|
|
@@ -123,6 +133,9 @@ export function applyBindingTo(control) {
|
|
|
123
133
|
return false;
|
|
124
134
|
if (isContainer(control))
|
|
125
135
|
return false;
|
|
136
|
+
// A Flat OPC package is a rich text control's content, not text: no control is filled with it.
|
|
137
|
+
if (holdsFlatOpc(value))
|
|
138
|
+
return false;
|
|
126
139
|
if (control.type === 'CheckBox') {
|
|
127
140
|
const checkbox = control.checkboxContentControl;
|
|
128
141
|
if (!checkbox)
|
|
@@ -190,6 +203,9 @@ export function updateFromControl(control) {
|
|
|
190
203
|
// A control showing its placeholder holds no value.
|
|
191
204
|
if (control.isShowingPlaceholder)
|
|
192
205
|
return false;
|
|
206
|
+
// The node holds a rich text control's content as Flat OPC: text is not written over it.
|
|
207
|
+
if (holdsFlatOpc(node.text))
|
|
208
|
+
return false;
|
|
193
209
|
let value = control.text;
|
|
194
210
|
if (control.type === 'CheckBox') {
|
|
195
211
|
const checkbox = control.checkboxContentControl;
|
|
@@ -3,5 +3,5 @@ export { CustomXmlPart, CustomXmlNode, CustomXmlPrefixMappingCollection, type Cu
|
|
|
3
3
|
export { CustomXmlPartCollection, type CustomXmlHost } from './CustomXmlPartCollection.mjs';
|
|
4
4
|
export { XmlMapping, type CustomXmlPartLookup } from './XmlMapping.mjs';
|
|
5
5
|
export { CheckboxContentControl, DatePickerContentControl, ListContentControl, ContentControlListItem, PictureContentControl, RepeatingSectionContentControl, GroupContentControl, checkboxRun, CHECKED_SYMBOL, UNCHECKED_SYMBOL, CHECKBOX_FONT, } from './kinds.mjs';
|
|
6
|
-
export { applyBindingsTo, applyBindingTo, updateFromControls, updateFromControl, runsForValue, formatDate, PLACEHOLDER_STYLE, PLACEHOLDER_TEXT, type BindingResult } from './bindings.mjs';
|
|
6
|
+
export { applyBindingsTo, applyBindingTo, updateFromControls, updateFromControl, runsForValue, formatDate, holdsFlatOpc, PLACEHOLDER_STYLE, PLACEHOLDER_TEXT, type BindingResult } from './bindings.mjs';
|
|
7
7
|
export { controlIdScope, sdtKindFor, isRunLevel } from './insert.mjs';
|
|
@@ -5,5 +5,5 @@ export { CustomXmlPart, CustomXmlNode, CustomXmlPrefixMappingCollection } from '
|
|
|
5
5
|
export { CustomXmlPartCollection } from './CustomXmlPartCollection.mjs';
|
|
6
6
|
export { XmlMapping } from './XmlMapping.mjs';
|
|
7
7
|
export { CheckboxContentControl, DatePickerContentControl, ListContentControl, ContentControlListItem, PictureContentControl, RepeatingSectionContentControl, GroupContentControl, checkboxRun, CHECKED_SYMBOL, UNCHECKED_SYMBOL, CHECKBOX_FONT, } from './kinds.mjs';
|
|
8
|
-
export { applyBindingsTo, applyBindingTo, updateFromControls, updateFromControl, runsForValue, formatDate, PLACEHOLDER_STYLE, PLACEHOLDER_TEXT } from './bindings.mjs';
|
|
8
|
+
export { applyBindingsTo, applyBindingTo, updateFromControls, updateFromControl, runsForValue, formatDate, holdsFlatOpc, PLACEHOLDER_STYLE, PLACEHOLDER_TEXT } from './bindings.mjs';
|
|
9
9
|
export { controlIdScope, sdtKindFor, isRunLevel } from './insert.mjs';
|