@docx4j/core-ts 0.5.0 → 0.7.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/NOTICE +4 -0
- package/README.md +92 -4
- package/dist/html/convert.mjs +2 -1
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +145 -23
- package/dist/model/content/Body.mjs +507 -150
- package/dist/model/content/Comment.d.mts +23 -5
- package/dist/model/content/Comment.mjs +207 -26
- package/dist/model/content/ContentControl.d.mts +198 -19
- package/dist/model/content/ContentControl.mjs +672 -99
- package/dist/model/content/Font.d.mts +70 -17
- package/dist/model/content/Font.mjs +119 -36
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +18 -8
- package/dist/model/content/Paragraph.d.mts +200 -14
- package/dist/model/content/Paragraph.mjs +898 -82
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +135 -49
- package/dist/model/content/TrackedChange.d.mts +174 -15
- package/dist/model/content/TrackedChange.mjs +734 -170
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +10 -3
- package/dist/model/content/index.mjs +10 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/ooxml.mjs +12 -1
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +74 -0
- package/dist/model/content/search.mjs +255 -9
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +47 -0
- package/dist/model/content/story.mjs +95 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +102 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +63 -6
- package/dist/model/content/tracking.mjs +242 -22
- package/dist/model/content/tree.d.mts +172 -24
- package/dist/model/content/tree.mjs +328 -54
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
- package/dist/model/customxml/XmlMapping.d.mts +32 -8
- package/dist/model/customxml/XmlMapping.mjs +64 -10
- package/dist/model/customxml/bindings.d.mts +33 -4
- package/dist/model/customxml/bindings.mjs +171 -45
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +22 -8
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +23 -22
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +3 -0
- package/dist/model/index.mjs +5 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +74 -2
- package/dist/model/properties/PropertyResolver.mjs +133 -5
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +349 -0
- package/dist/model/text/Extractor.mjs +2406 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +542 -0
- package/dist/model/text/TextContext.d.mts +256 -0
- package/dist/model/text/TextContext.mjs +600 -0
- package/dist/model/text/TextOptions.d.mts +233 -0
- package/dist/model/text/TextOptions.mjs +419 -0
- package/dist/model/text/TextResult.d.mts +621 -0
- package/dist/model/text/TextResult.mjs +629 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +936 -0
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +8 -0
- package/dist/model/text/index.mjs +9 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +29 -12
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +32 -0
- package/dist/opc/Save.mjs +110 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +8 -5
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +141 -5
- package/dist/opc/mce/preprocessor.mjs +119 -18
- package/dist/opc/mce/understood.d.mts +3 -11
- package/dist/opc/mce/understood.mjs +27 -23
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +110 -4
- package/dist/packages/OpcPackage.mjs +123 -7
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +158 -21
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +14 -2
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +63 -32
- package/dist/parts/XmlPart.mjs +240 -96
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +37 -1
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { isElement, typeNameOf, runItemsOf, mcBranchOf } from '@docx4j/generated-objects-ts/builders/wml';
|
|
2
|
-
import {
|
|
1
|
+
import { isElement, typeNameOf, runItemsOf, mcBranchOf, sdtProperty } from '@docx4j/generated-objects-ts/builders/wml';
|
|
2
|
+
import { isMath, mathTextOf } from './mathText.mjs';
|
|
3
|
+
import { NotSupportedError } from '../../office-js/errors.mjs';
|
|
3
4
|
export { isElement, typeNameOf, walk, find, linkParents, textOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
|
|
4
5
|
/**
|
|
5
6
|
* Run content that stands in the text and has no text of its own: a `w:drawing` (a picture, a chart, a
|
|
@@ -12,13 +13,14 @@ export const OBJECT_ITEMS = new Set(['drawing', 'pict', 'object']);
|
|
|
12
13
|
export const ALTERNATE_CONTENT = 'org_docx4j_mce.AlternateContent';
|
|
13
14
|
/**
|
|
14
15
|
* The branch of a kept `mc:AlternateContent` the content API reads (docx4j's `McMode.READ`, CR-010
|
|
15
|
-
* phase 3): the objects package's `mcBranchOf`
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* with no branches.
|
|
16
|
+
* phase 3): the objects package's `mcBranchOf`, the first `mc:Choice` whose `Requires` names only namespaces in the
|
|
17
|
+
* understood set, by URI, else the `mc:Fallback`, else nothing (WD REQ-302 to REQ-305, CR-029). So a reader takes the
|
|
18
|
+
* branch the preprocessor resolves the element to. A mutator walks every branch instead (docx4j's `McMode.ALL`). Undefined
|
|
19
|
+
* where nothing is selected, as for an element with no branches. `options` are `mcBranchOf`'s: the text model passes
|
|
20
|
+
* `onNothingSelected` for `mce.nothing_selected`.
|
|
19
21
|
*/
|
|
20
|
-
export function selectedBranchOf(value) {
|
|
21
|
-
return mcBranchOf(value,
|
|
22
|
+
export function selectedBranchOf(value, options) {
|
|
23
|
+
return mcBranchOf(value, options);
|
|
22
24
|
}
|
|
23
25
|
/** True for a kept `mc:AlternateContent`: its element pair, or its value. */
|
|
24
26
|
export function isAlternateContent(value) {
|
|
@@ -52,6 +54,46 @@ function shows(view, kind) {
|
|
|
52
54
|
return view === 'accepted' ? kind === 'ins' || kind === 'moveTo' : kind === 'del' || kind === 'moveFrom';
|
|
53
55
|
}
|
|
54
56
|
export { runItemsOf };
|
|
57
|
+
/**
|
|
58
|
+
* An item's text in Office JS's text, Word's own character stream (CR-012 phase 4; check 48, Word 365):
|
|
59
|
+
* a `w:br` U+000B, of type page U+000C and column U+000E; a `w:cr` U+000D; a `w:ptab` `0`; the
|
|
60
|
+
* non-breaking and optional hyphens U+001E and U+001F; any `w:sym` `(`, whatever its font or code
|
|
61
|
+
* (check 48b); a footnote or endnote reference U+0002, and so the note's own mark (`w:footnoteRef`,
|
|
62
|
+
* `w:endnoteRef`, not measured). Undefined for an item that adds no text: a comment reference, a
|
|
63
|
+
* field's characters and code, a drawing.
|
|
64
|
+
*/
|
|
65
|
+
export function officeItemText(item) {
|
|
66
|
+
var _a;
|
|
67
|
+
const v = item.value;
|
|
68
|
+
switch (item.name.localPart) {
|
|
69
|
+
case 't':
|
|
70
|
+
case 'delText': return String((_a = v.value) !== null && _a !== void 0 ? _a : '');
|
|
71
|
+
case 'tab': return '\t';
|
|
72
|
+
case 'br': return v.type === 'page' ? '\f' : v.type === 'column' ? '\u000E' : '\u000B';
|
|
73
|
+
case 'cr': return '\r';
|
|
74
|
+
case 'ptab': return '0';
|
|
75
|
+
case 'noBreakHyphen': return '\u001E';
|
|
76
|
+
case 'softHyphen': return '\u001F';
|
|
77
|
+
case 'sym': return '(';
|
|
78
|
+
case 'footnoteReference':
|
|
79
|
+
case 'endnoteReference':
|
|
80
|
+
case 'footnoteRef':
|
|
81
|
+
case 'endnoteRef': return '\u0002';
|
|
82
|
+
default: return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** An item a run-level element's selected branch may hold that makes the element one object (CR-012 section 12.2 item 5). */
|
|
86
|
+
function isDrawn(item) {
|
|
87
|
+
return OBJECT_ITEMS.has(item.name.localPart);
|
|
88
|
+
}
|
|
89
|
+
/** The `run` of an equation's segment: it is in no run, and nothing may be written to this one. */
|
|
90
|
+
function standIn(math) {
|
|
91
|
+
return Object.freeze({ TYPE_NAME: 'org_docx4j_wml.R', PARENT: math.value.PARENT });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The item text the revision listings and the text model's plan count (`itemTextOf`): whether a run
|
|
95
|
+
* holds text, in the characters `textOf` gives. Not Office JS's (`officeItemText`).
|
|
96
|
+
*/
|
|
55
97
|
function itemText(item) {
|
|
56
98
|
var _a, _b;
|
|
57
99
|
const t = item.name.localPart;
|
|
@@ -72,53 +114,103 @@ function itemText(item) {
|
|
|
72
114
|
}
|
|
73
115
|
}
|
|
74
116
|
/**
|
|
75
|
-
* The text segments of a paragraph (or any run holder) in order
|
|
76
|
-
* accepted one: the runs of a `w:ins` or `w:moveTo`
|
|
77
|
-
* do not. `{ view: 'original' }` is the other way round
|
|
78
|
-
* lists the drawn objects too, each a segment of no text where
|
|
117
|
+
* The text segments of a paragraph (or any run holder) in order, in Office JS's characters
|
|
118
|
+
* (`officeItemText`). The default view is the accepted one: the runs of a `w:ins` or `w:moveTo`
|
|
119
|
+
* count, those of a `w:del` or `w:moveFrom` do not. `{ view: 'original' }` is the other way round
|
|
120
|
+
* (CR-002 phase F). `{ objects: true }` lists the drawn objects too, each a segment of no text where
|
|
121
|
+
* it stands (CR-002 section 48), and the items of hidden runs (`hidden`).
|
|
79
122
|
*
|
|
80
|
-
* A kept `mc:AlternateContent`
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
123
|
+
* A kept `mc:AlternateContent` reads as its selected branch (CR-012 section 12.2, ED-009): in a run,
|
|
124
|
+
* a branch holding run items reads as those items, at the run's offsets, and one holding a drawing,
|
|
125
|
+
* a picture or an object is one object segment, as a drawing is (CR-010 phase 3); among a paragraph's
|
|
126
|
+
* runs, it reads as the runs its branch holds. Either way the segments carry `alternate`, so that an
|
|
127
|
+
* edit lands in that branch. An equation is one segment of its drawn text (`math`).
|
|
84
128
|
*/
|
|
85
129
|
export function segmentsOf(container, options) {
|
|
86
130
|
var _a;
|
|
87
131
|
const view = (_a = options === null || options === void 0 ? void 0 : options.view) !== null && _a !== void 0 ? _a : 'accepted';
|
|
88
132
|
const objects = (options === null || options === void 0 ? void 0 : options.objects) === true;
|
|
133
|
+
const hiddenRun = options === null || options === void 0 ? void 0 : options.hidden;
|
|
134
|
+
const visit = options === null || options === void 0 ? void 0 : options.visit;
|
|
135
|
+
const office = (options === null || options === void 0 ? void 0 : options.characters) !== 'textOf';
|
|
136
|
+
const charactersOf = office ? officeItemText : itemText;
|
|
89
137
|
const out = [];
|
|
90
138
|
let pos = 0;
|
|
91
|
-
const
|
|
139
|
+
const runContent = (run, runEl, content, runOwner, runIndex, revision, alternate, hidden) => {
|
|
140
|
+
for (let j = 0; j < content.length; j++) {
|
|
141
|
+
const item = content[j];
|
|
142
|
+
const where = { owner: content, index: j, run, runOwner, runIndex };
|
|
143
|
+
if (office && isAlternateContent(item)) {
|
|
144
|
+
const branch = selectedBranchOf(item.value);
|
|
145
|
+
// a branch holding content the model doesn't bind (DOM) is one object, as a drawing is
|
|
146
|
+
if (branch && branch.every(isElement) && !branch.some(isDrawn)) {
|
|
147
|
+
runContent(run, runEl, branch, runOwner, runIndex, revision, { element: item, owner: content, branch, level: 'run' }, hidden);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const text = charactersOf(item);
|
|
152
|
+
if (text === undefined || (hidden && text !== '')) {
|
|
153
|
+
const drawn = OBJECT_ITEMS.has(item.name.localPart) || isAlternateContent(item);
|
|
154
|
+
if (objects && (drawn || (hidden && text !== undefined))) {
|
|
155
|
+
const seg = { item, ...where, text: '', start: pos, end: pos, editable: false, object: true };
|
|
156
|
+
if (hidden)
|
|
157
|
+
seg.hidden = true;
|
|
158
|
+
if (revision)
|
|
159
|
+
seg.revision = revision;
|
|
160
|
+
if (alternate)
|
|
161
|
+
seg.alternate = alternate;
|
|
162
|
+
out.push(seg);
|
|
163
|
+
}
|
|
164
|
+
visit === null || visit === void 0 ? void 0 : visit(item, pos, content, { element: runEl, owner: runOwner });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const seg = { item, ...where, text, start: pos, end: pos + text.length, editable: item.name.localPart === 't' };
|
|
168
|
+
if (revision)
|
|
169
|
+
seg.revision = revision;
|
|
170
|
+
if (alternate)
|
|
171
|
+
seg.alternate = alternate;
|
|
172
|
+
out.push(seg);
|
|
173
|
+
pos += text.length;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const visitRuns = (items, revision, alternate) => {
|
|
92
177
|
var _a;
|
|
93
178
|
if (!items)
|
|
94
179
|
return;
|
|
95
180
|
for (let i = 0; i < items.length; i++) {
|
|
96
181
|
const el = items[i];
|
|
182
|
+
if (!isElement(el))
|
|
183
|
+
continue; // a kept branch's unbound content (DOM)
|
|
184
|
+
visit === null || visit === void 0 ? void 0 : visit(el, pos, items, undefined);
|
|
97
185
|
const tn = typeNameOf(el);
|
|
98
186
|
if (tn === 'org_docx4j_wml.R') {
|
|
99
187
|
const run = el.value;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
188
|
+
runContent(run, el, (_a = run.content) !== null && _a !== void 0 ? _a : [], items, i, revision, alternate, (hiddenRun === null || hiddenRun === void 0 ? void 0 : hiddenRun(run)) === true);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (!office) {
|
|
192
|
+
// textOf's reader: no branch among the runs, no equation
|
|
193
|
+
}
|
|
194
|
+
else if (isAlternateContent(el)) {
|
|
195
|
+
const branch = selectedBranchOf(el.value);
|
|
196
|
+
if (branch)
|
|
197
|
+
visitRuns(branch, revision, { element: el, owner: items, branch, level: 'paragraph' });
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
else if (isMath(el)) {
|
|
201
|
+
const text = mathTextOf(el.value, view);
|
|
202
|
+
if (text === '')
|
|
203
|
+
continue;
|
|
204
|
+
const seg = {
|
|
205
|
+
item: el, owner: items, index: i, run: standIn(el), runOwner: items, runIndex: i, text,
|
|
206
|
+
start: pos, end: pos + text.length, editable: false, math: true,
|
|
207
|
+
};
|
|
208
|
+
if (revision)
|
|
209
|
+
seg.revision = revision;
|
|
210
|
+
if (alternate)
|
|
211
|
+
seg.alternate = alternate;
|
|
212
|
+
out.push(seg);
|
|
213
|
+
pos += text.length;
|
|
122
214
|
continue;
|
|
123
215
|
}
|
|
124
216
|
const kind = revisionKindOf(el);
|
|
@@ -127,21 +219,60 @@ export function segmentsOf(container, options) {
|
|
|
127
219
|
continue;
|
|
128
220
|
const nested = runItemsOf(el.value);
|
|
129
221
|
if (nested)
|
|
130
|
-
visitRuns(nested, { kind, element: el, value: el.value, items: nested, owner: items });
|
|
222
|
+
visitRuns(nested, { kind, element: el, value: el.value, items: nested, owner: items }, alternate);
|
|
131
223
|
}
|
|
132
224
|
else if (tn !== undefined && RUN_HOLDERS.has(tn)) {
|
|
133
|
-
visitRuns(runItemsOf(el.value), revision);
|
|
225
|
+
visitRuns(runItemsOf(el.value), revision, alternate);
|
|
134
226
|
}
|
|
135
227
|
}
|
|
136
228
|
};
|
|
137
|
-
visitRuns(runItemsOf(container), undefined);
|
|
229
|
+
visitRuns(runItemsOf(container), undefined, undefined);
|
|
138
230
|
return out;
|
|
139
231
|
}
|
|
140
|
-
/**
|
|
232
|
+
/**
|
|
233
|
+
* Which of a paragraph's runs are hidden, as the text model's rule has it (REQ-507) and Office JS's text
|
|
234
|
+
* leaves them out (check 48b): a run's own `w:vanish`, else its paragraph style's and character style's.
|
|
235
|
+
* Without a resolver only a run's own counts.
|
|
236
|
+
*/
|
|
237
|
+
export function hiddenRunsOf(resolver, p) {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
const pStyle = (_b = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val;
|
|
240
|
+
return (run) => {
|
|
241
|
+
var _a, _b, _c, _d;
|
|
242
|
+
if (inShowingPlaceholder(run))
|
|
243
|
+
return true;
|
|
244
|
+
const own = (_a = run.rPr) === null || _a === void 0 ? void 0 : _a.vanish;
|
|
245
|
+
if (own !== undefined && own !== null)
|
|
246
|
+
return own.val !== false;
|
|
247
|
+
return (_d = resolver === null || resolver === void 0 ? void 0 : resolver.isVanishedByStyles(pStyle, (_c = (_b = run.rPr) === null || _b === void 0 ? void 0 : _b.rStyle) === null || _c === void 0 ? void 0 : _c.val)) !== null && _d !== void 0 ? _d : false;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Whether a run is in a content control showing its placeholder (`w:showingPlcHdr`), run-level or block-level, up its
|
|
252
|
+
* `PARENT`s. Office JS reads a placeholder as no text, and finds no text there to keep (check 53 cases 34 and 35, check 58
|
|
253
|
+
* cases 11 and 12; CR-012 section 18), so the readers take its runs as they take hidden ones.
|
|
254
|
+
*/
|
|
255
|
+
export function inShowingPlaceholder(run) {
|
|
256
|
+
var _a;
|
|
257
|
+
let o = run.PARENT;
|
|
258
|
+
for (let guard = 0; o && guard < 32; guard++, o = o.PARENT) {
|
|
259
|
+
const v = o;
|
|
260
|
+
if (v.sdtPr === undefined || v.sdtContent === undefined)
|
|
261
|
+
continue;
|
|
262
|
+
const item = sdtProperty(v.sdtPr, 'showingPlcHdr');
|
|
263
|
+
if (item !== undefined && ((_a = item.value) === null || _a === void 0 ? void 0 : _a.val) !== false)
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
/** The text of a paragraph or container in one of the two views, in Office JS's characters (`segmentsOf`). */
|
|
141
269
|
export function textOfView(container, options) {
|
|
142
270
|
return segmentsOf(container, options).map((s) => s.text).join('');
|
|
143
271
|
}
|
|
144
|
-
/**
|
|
272
|
+
/**
|
|
273
|
+
* The runs of a paragraph, direct and nested in hyperlinks, content controls and insertions, in order,
|
|
274
|
+
* and in the selected branch of a kept `mc:AlternateContent` among them (CR-012 section 12.2).
|
|
275
|
+
*/
|
|
145
276
|
export function runsOf(container, options) {
|
|
146
277
|
var _a;
|
|
147
278
|
const view = (_a = options === null || options === void 0 ? void 0 : options.view) !== null && _a !== void 0 ? _a : 'accepted';
|
|
@@ -155,6 +286,10 @@ export function runsOf(container, options) {
|
|
|
155
286
|
out.push(el);
|
|
156
287
|
continue;
|
|
157
288
|
}
|
|
289
|
+
if (isAlternateContent(el)) {
|
|
290
|
+
visit(selectedBranchOf(el.value));
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
158
293
|
const kind = revisionKindOf(el);
|
|
159
294
|
if (kind !== undefined) {
|
|
160
295
|
if (shows(view, kind))
|
|
@@ -167,30 +302,129 @@ export function runsOf(container, options) {
|
|
|
167
302
|
visit(runItemsOf(container));
|
|
168
303
|
return out;
|
|
169
304
|
}
|
|
305
|
+
/** The TYPE_NAMEs of a kept `mc:AlternateContent`'s branches, whose items are their `any`. */
|
|
306
|
+
export const BRANCH_TYPES = new Set(['org_docx4j_mce.AlternateContent.Choice', 'org_docx4j_mce.AlternateContent.Fallback']);
|
|
170
307
|
/**
|
|
171
308
|
* The block-level children of a container: body, header, footer, cell, sdt content, table (rows),
|
|
172
309
|
* row (cells). A content control of any kind (block, row, cell, run) answers with its
|
|
173
|
-
* `sdtContent`'s content, so that a traversal does not have to know the four types.
|
|
310
|
+
* `sdtContent`'s content, so that a traversal does not have to know the four types. A branch of a kept
|
|
311
|
+
* `mc:AlternateContent` (a Choice or the Fallback) answers with its items, so that a locator climbing
|
|
312
|
+
* `PARENT` from a branch's paragraph, row or cell finds the list it is in; the element itself answers
|
|
313
|
+
* in a reader's walk (`'read'`) with its selected branch (CR-013 phase 2), and otherwise not at all.
|
|
174
314
|
*/
|
|
175
|
-
export function childrenOf(value) {
|
|
315
|
+
export function childrenOf(value, mode) {
|
|
176
316
|
const v = value;
|
|
177
317
|
if (v.sdtContent)
|
|
178
318
|
return v.sdtContent.content;
|
|
179
|
-
|
|
319
|
+
if (Array.isArray(v.content))
|
|
320
|
+
return v.content;
|
|
321
|
+
const tn = v.TYPE_NAME;
|
|
322
|
+
if (tn === undefined)
|
|
323
|
+
return undefined;
|
|
324
|
+
if (BRANCH_TYPES.has(tn))
|
|
325
|
+
return v.any;
|
|
326
|
+
if (mode === 'read' && tn === ALTERNATE_CONTENT)
|
|
327
|
+
return selectedBranchOf(v);
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
/** Every branch of a kept `mc:AlternateContent`, the Choices in order, then the Fallback. */
|
|
331
|
+
export function branchesOf(value) {
|
|
332
|
+
var _a, _b;
|
|
333
|
+
const out = [];
|
|
334
|
+
for (const choice of (_a = value.choice) !== null && _a !== void 0 ? _a : [])
|
|
335
|
+
if (choice.any)
|
|
336
|
+
out.push(choice.any);
|
|
337
|
+
if ((_b = value.fallback) === null || _b === void 0 ? void 0 : _b.any)
|
|
338
|
+
out.push(value.fallback.any);
|
|
339
|
+
return out;
|
|
340
|
+
}
|
|
341
|
+
/** How many bulk edits are writing in every branch now (`writingEveryBranch`). */
|
|
342
|
+
let everyBranch = 0;
|
|
343
|
+
/**
|
|
344
|
+
* Runs a bulk edit that reaches every branch of a kept `mc:AlternateContent` (CR-013 phase 3): a
|
|
345
|
+
* `replaceText`, a tracked clear or row deletion, the binding passes. Inside it the views it makes of
|
|
346
|
+
* what is in a branch write, where a caller's view refuses (D4): the edit itself reaches every branch,
|
|
347
|
+
* the selected one and the others alike, as CR-010's rule has mutators do.
|
|
348
|
+
*/
|
|
349
|
+
export function writingEveryBranch(edit) {
|
|
350
|
+
everyBranch++;
|
|
351
|
+
try {
|
|
352
|
+
return edit();
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
everyBranch--;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Refuses a write through a view in a branch of a kept `mc:AlternateContent` at block, row or cell level
|
|
360
|
+
* (CR-013 D4): the view reads the selected branch, and a write would have to reach the element's other
|
|
361
|
+
* branches too, which nothing maps. A bulk edit reaching every branch writes there (`writingEveryBranch`).
|
|
362
|
+
* `className` is Office JS's ('Paragraph', 'Body').
|
|
363
|
+
*/
|
|
364
|
+
export function assertOutsideBranch(value, className, what = `this ${className.toLowerCase()}`) {
|
|
365
|
+
if (everyBranch === 0 && inBranch(value)) {
|
|
366
|
+
throw new NotSupportedError(className, 'edit', `${what} is in a branch of an mc:AlternateContent, which is read-only (CR-013 D4): `
|
|
367
|
+
+ "a write would have to reach the element's other branches too, which nothing maps yet");
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* True for a value inside a branch of a kept `mc:AlternateContent` at block, row or cell level: a
|
|
372
|
+
* paragraph, table, row, cell or content control a reader sees in the selected branch (CR-013 phase 2).
|
|
373
|
+
* A view of one is read-only (D4). From `PARENT` links; a run-level element's content is not reached
|
|
374
|
+
* from a paragraph, which is outside it.
|
|
375
|
+
*/
|
|
376
|
+
export function inBranch(value) {
|
|
377
|
+
let o = value === null || value === void 0 ? void 0 : value.PARENT;
|
|
378
|
+
for (let guard = 0; o && guard < 256; guard++, o = o.PARENT) {
|
|
379
|
+
const tn = o.TYPE_NAME;
|
|
380
|
+
if (tn !== undefined && BRANCH_TYPES.has(tn))
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* True for a value no reader sees: inside a branch of a kept `mc:AlternateContent` other than the one
|
|
387
|
+
* `selectedBranchOf` takes, at any depth (CR-013 phase 3). What a bulk edit writes there it does not
|
|
388
|
+
* count, as resolve-all counts the listed changes: the count is of what a reader sees.
|
|
389
|
+
*/
|
|
390
|
+
export function inUnreadBranch(value) {
|
|
391
|
+
let o = value === null || value === void 0 ? void 0 : value.PARENT;
|
|
392
|
+
for (let guard = 0; o && guard < 256; guard++, o = o.PARENT) {
|
|
393
|
+
const tn = o.TYPE_NAME;
|
|
394
|
+
if (tn === undefined || !BRANCH_TYPES.has(tn))
|
|
395
|
+
continue;
|
|
396
|
+
const ac = o.PARENT;
|
|
397
|
+
if (ac && selectedBranchOf(ac) !== o.any)
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* The lists a walk takes for a kept `mc:AlternateContent` among blocks, rows or cells: a reader's
|
|
404
|
+
* (`'read'`) its selected branch, a mutator's (`'every'`) every branch, the Choices first.
|
|
405
|
+
*/
|
|
406
|
+
export function branchListsOf(value, mode) {
|
|
407
|
+
if (mode === 'every')
|
|
408
|
+
return branchesOf(value);
|
|
409
|
+
const read = selectedBranchOf(value);
|
|
410
|
+
return read ? [read] : [];
|
|
180
411
|
}
|
|
181
412
|
/** w:sdt and w:customXml at row level: they hold the rows of a table (docx4j CTSdtRow, CTCustomXmlRow). */
|
|
182
413
|
const ROW_HOLDERS = new Set(['org_docx4j_wml.CTSdtRow', 'org_docx4j_wml.CTCustomXmlRow']);
|
|
183
414
|
/** The same at cell level. */
|
|
184
415
|
const CELL_HOLDERS = new Set(['org_docx4j_wml.CTSdtCell', 'org_docx4j_wml.CTCustomXmlCell']);
|
|
185
|
-
/**
|
|
186
|
-
|
|
187
|
-
|
|
416
|
+
/**
|
|
417
|
+
* The rows of a table, in order, descending into row-level content controls (an OpenDoPE repeat), and,
|
|
418
|
+
* with a mode, into a row-level `mc:AlternateContent` (`BranchMode`; CR-013 phase 2).
|
|
419
|
+
*/
|
|
420
|
+
export function rowsOf(tbl, mode) {
|
|
421
|
+
return located(childrenOf(tbl), 'org_docx4j_wml.Tr', ROW_HOLDERS, mode);
|
|
188
422
|
}
|
|
189
|
-
/** The cells of a row, in order, descending into cell-level content controls
|
|
190
|
-
export function cellsOf(tr) {
|
|
191
|
-
return located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS);
|
|
423
|
+
/** The cells of a row, in order, descending into cell-level content controls, and with a mode into a cell-level `mc:AlternateContent`. */
|
|
424
|
+
export function cellsOf(tr, mode) {
|
|
425
|
+
return located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS, mode);
|
|
192
426
|
}
|
|
193
|
-
function located(items, typeName, holders) {
|
|
427
|
+
function located(items, typeName, holders, mode, reading) {
|
|
194
428
|
const out = [];
|
|
195
429
|
const visit = (list) => {
|
|
196
430
|
if (!list)
|
|
@@ -201,11 +435,51 @@ function located(items, typeName, holders) {
|
|
|
201
435
|
out.push({ element, container: list });
|
|
202
436
|
else if (tn !== undefined && holders.has(tn) && typeof element.value === 'object' && element.value !== null)
|
|
203
437
|
visit(childrenOf(element.value));
|
|
438
|
+
else if (tn === ALTERNATE_CONTENT && mode !== undefined) {
|
|
439
|
+
if (reading && element.value === reading.ac)
|
|
440
|
+
visit(reading.branch);
|
|
441
|
+
else
|
|
442
|
+
for (const branch of branchListsOf(element.value, mode))
|
|
443
|
+
visit(branch);
|
|
444
|
+
}
|
|
204
445
|
}
|
|
205
446
|
};
|
|
206
447
|
visit(items);
|
|
207
448
|
return out;
|
|
208
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* A row's cells as laid along the grid, one list per reading of the row (docx4j's `Lister.cellLayoutsOf`,
|
|
452
|
+
* its CR-051 phase 2): the selected branches' first (`cellsOf(tr, 'read')`), then, for each cell-level
|
|
453
|
+
* `mc:AlternateContent` and each of its other branches, the row read with that branch in the element's
|
|
454
|
+
* place. Every branch spans the same grid columns, so every cell is in some list at its grid position:
|
|
455
|
+
* what a pass over the grid's columns walks (`collapseGrid`, the column passes; CR-013 phase 3).
|
|
456
|
+
*/
|
|
457
|
+
export function cellLayoutsOf(tr) {
|
|
458
|
+
const out = [cellsOf(tr, 'read')];
|
|
459
|
+
const elements = [];
|
|
460
|
+
const collect = (list) => {
|
|
461
|
+
for (const element of list !== null && list !== void 0 ? list : []) {
|
|
462
|
+
const tn = typeNameOf(element);
|
|
463
|
+
if (tn === ALTERNATE_CONTENT) {
|
|
464
|
+
elements.push(element.value);
|
|
465
|
+
for (const branch of branchesOf(element.value))
|
|
466
|
+
collect(branch);
|
|
467
|
+
}
|
|
468
|
+
else if (tn !== undefined && CELL_HOLDERS.has(tn) && typeof element.value === 'object' && element.value !== null) {
|
|
469
|
+
collect(childrenOf(element.value));
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
collect(childrenOf(tr));
|
|
474
|
+
for (const ac of elements) {
|
|
475
|
+
const read = selectedBranchOf(ac);
|
|
476
|
+
for (const branch of branchesOf(ac)) {
|
|
477
|
+
if (branch !== read)
|
|
478
|
+
out.push(located(childrenOf(tr), 'org_docx4j_wml.Tc', CELL_HOLDERS, 'read', { ac, branch }));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return out;
|
|
482
|
+
}
|
|
209
483
|
/** Content controls: `w:sdt` at block, row, cell and run level, by TYPE_NAME. */
|
|
210
484
|
export const SDT_TYPES = new Set([
|
|
211
485
|
'org_docx4j_wml.SdtBlock', 'org_docx4j_wml.SdtRun', 'org_docx4j_wml.CTSdtRow', 'org_docx4j_wml.CTSdtCell',
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** How Word 365 stores an attribute a setter writes, and the range the setter writes within, in the attribute's unit. */
|
|
2
|
+
export interface WordStorage {
|
|
3
|
+
/** The attribute, as the part writes it. */
|
|
4
|
+
attribute: string;
|
|
5
|
+
/** The attribute's unit, and how many make a point. */
|
|
6
|
+
unit: 'twips' | 'half-points' | 'fiftieths of a percent';
|
|
7
|
+
min: number;
|
|
8
|
+
max: number;
|
|
9
|
+
/** What Word reads a value as, once it is stored: the wrap, as CR-066 measured it (the objects package's `wordIntegerReading`). */
|
|
10
|
+
reads(value: number): string;
|
|
11
|
+
/** Measured by CR-066's rounds 5 and 6: every row is, since round 6 (section 65.6). */
|
|
12
|
+
measured: boolean;
|
|
13
|
+
/** The range Word keeps as written, the objects table's (`keptRange`), before the setter's policy narrows it. */
|
|
14
|
+
stored: readonly [number, number];
|
|
15
|
+
/** Why a value Word would keep as written is refused all the same: the range narrowed below Word's storage. */
|
|
16
|
+
why?: string;
|
|
17
|
+
/** The objects table's entry the row reads: `TYPE_NAME`, property, and the rule beside the attribute where one applies. */
|
|
18
|
+
objects: {
|
|
19
|
+
typeName: string;
|
|
20
|
+
property: string;
|
|
21
|
+
rule?: 'auto' | 'exact' | 'atLeast';
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The attributes the content API's setters write, by Word 365's storage (the objects table; CR-066 sections 3.1 and 3.4),
|
|
26
|
+
* narrowed where Word's own setter stops short of its storage (check 71b, CR-002 section 65.9, D2): there this package
|
|
27
|
+
* refuses where Word does, and no earlier.
|
|
28
|
+
*/
|
|
29
|
+
export declare const WORD_STORAGE: {
|
|
30
|
+
readonly indLeft: WordStorage;
|
|
31
|
+
readonly indRight: WordStorage;
|
|
32
|
+
readonly indFirstLine: WordStorage;
|
|
33
|
+
readonly indHanging: WordStorage;
|
|
34
|
+
readonly lvlIndLeft: WordStorage;
|
|
35
|
+
readonly spacingBefore: WordStorage;
|
|
36
|
+
readonly spacingAfter: WordStorage;
|
|
37
|
+
readonly spacingLineAuto: WordStorage;
|
|
38
|
+
readonly tcWDxa: WordStorage;
|
|
39
|
+
readonly tcWPct: WordStorage;
|
|
40
|
+
readonly sz: WordStorage;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* `points` in the attribute's unit, rounded, where Word stores it as written and the setter's policy allows; else
|
|
44
|
+
* `InvalidArgument`, naming the range and what Word would read, or why the policy stops short of Word's storage (CR-002
|
|
45
|
+
* section 65; the policy section 65.9's). `where` is the setter (`Paragraph.leftIndent`). `units` is the value already
|
|
46
|
+
* in the attribute's unit, where the setter computes it otherwise (a percentage width's fiftieths).
|
|
47
|
+
*/
|
|
48
|
+
export declare function withinWord(where: string, points: number, storage: WordStorage, units?: number): number;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// CR-002 section 65: a measurement setter writes a value only where Word 365 stores it as written. Word keeps each
|
|
2
|
+
// integer attribute in a field of its binary format's width, 16 bits for these, and reads a value past it wrapped, with
|
|
3
|
+
// no error or repair (docx4j CR-065 round 2, CR-066 rounds 5 and 6, run by Jason 2026-10-26): a left indent of 400,000 pt,
|
|
4
|
+
// 8,000,000 twips, opens as 4,608. So the setters refuse such a value, as Office JS refuses an argument it won't take.
|
|
5
|
+
// The width is the attribute's, not its simple type's (CR-066 section 3.1). A file's value is read and kept as written.
|
|
6
|
+
// Since section 65.3 the storage comes from the objects package's table (`WORD_INTEGER_STORAGE`, its CR-016), through
|
|
7
|
+
// `keptRange`, one source for the setters' guards and the out-of-range warnings (CR-017); what each row adds is the
|
|
8
|
+
// setters' own policy, a range narrowed below Word's storage where a value Word keeps is still a caller's mistake.
|
|
9
|
+
import { wordIntegerReading } from '@docx4j/generated-objects-ts/helpers/wml';
|
|
10
|
+
import { keptRange } from '../wordIntegers.mjs';
|
|
11
|
+
import { InvalidArgument } from './generalException.mjs';
|
|
12
|
+
const WML = 'org_docx4j_wml.';
|
|
13
|
+
const WORD_SPACING_LIMIT = "Word's own setter stops at 22 inches, 1584 pt (check 71b); its storage runs to 65535, which its save writes back as -1";
|
|
14
|
+
/**
|
|
15
|
+
* A row from the objects table: the range Word keeps as written there (`keptRange`), narrowed by the setter's policy
|
|
16
|
+
* where `min`, `max` and `why` say so; `reads` through `wordIntegerReading`. A row whose entry the table lacks, or
|
|
17
|
+
* no longer measures, fails here, at load, so a table change announces itself.
|
|
18
|
+
*/
|
|
19
|
+
function row(attribute, unit, typeName, property, policy = {}) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
const range = keptRange(WML + typeName, property, policy.rule);
|
|
22
|
+
if (range === undefined || range === null)
|
|
23
|
+
throw new Error(`wordRange: the objects table has no measured range for ${typeName}.${property}`);
|
|
24
|
+
const name = (p) => (p === 'hanging' ? 'a hanging indent' : 'a first-line indent');
|
|
25
|
+
return {
|
|
26
|
+
attribute, unit, measured: true, stored: range,
|
|
27
|
+
min: (_a = policy.min) !== null && _a !== void 0 ? _a : range[0], max: (_b = policy.max) !== null && _b !== void 0 ? _b : range[1],
|
|
28
|
+
...(policy.why !== undefined ? { why: policy.why } : {}),
|
|
29
|
+
objects: { typeName: WML + typeName, property, ...(policy.rule !== undefined ? { rule: policy.rule } : {}) },
|
|
30
|
+
reads(value) {
|
|
31
|
+
const r = wordIntegerReading(WML + typeName, property, value, policy.rule);
|
|
32
|
+
if (r === undefined || r.value === null)
|
|
33
|
+
return 'not known';
|
|
34
|
+
if (r.attribute !== undefined && r.attribute !== property)
|
|
35
|
+
return `${name(r.attribute)} of ${r.value}`;
|
|
36
|
+
if (r.rule !== undefined && policy.rule !== undefined)
|
|
37
|
+
return `${r.rule} ${r.value}`;
|
|
38
|
+
return String(r.value);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The attributes the content API's setters write, by Word 365's storage (the objects table; CR-066 sections 3.1 and 3.4),
|
|
44
|
+
* narrowed where Word's own setter stops short of its storage (check 71b, CR-002 section 65.9, D2): there this package
|
|
45
|
+
* refuses where Word does, and no earlier.
|
|
46
|
+
*/
|
|
47
|
+
export const WORD_STORAGE = {
|
|
48
|
+
// int16, wraps (w:left measured by round 5, w:right by round 6); Word's own indent setters wrap too, and this package
|
|
49
|
+
// refuses instead (section 65.5, D1)
|
|
50
|
+
indLeft: row('w:ind/@w:left', 'twips', 'PPrBase.Ind', 'left'),
|
|
51
|
+
indRight: row('w:ind/@w:right', 'twips', 'PPrBase.Ind', 'right'),
|
|
52
|
+
// one signed 16-bit field, the binary format's dxaLeft1: a first-line indent as itself, a hanging indent as its negative,
|
|
53
|
+
// so 0 to 32767 and 0 to 32768 (check 71: Word's firstLineIndent setter wrote 1638.4 pt as a hanging indent of 32768;
|
|
54
|
+
// round 6, the file side: a first-line indent of 32768 reads as a hanging indent of 32768)
|
|
55
|
+
indFirstLine: row('w:ind/@w:firstLine', 'twips', 'PPrBase.Ind', 'firstLine'),
|
|
56
|
+
indHanging: row('w:ind/@w:hanging', 'twips', 'PPrBase.Ind', 'hanging'),
|
|
57
|
+
// a list level's text indent, the same int16 field, but Word's own setLevelIndents refuses at 1584 pt either side
|
|
58
|
+
// (check 71b: 1583.95 and -1583.95 written, 1584 and -1584 InvalidArgument), so 31679 twips either way
|
|
59
|
+
lvlIndLeft: row('w:ind/@w:left', 'twips', 'PPrBase.Ind', 'left', { min: -31679, max: 31679, why: "Word's own setLevelIndents stops short of 22 inches, 1584 pt, either way (check 71b)" }),
|
|
60
|
+
// uint16, wraps, and Word's save writes 0xFFFF back as -1; Word's own setters stop at 22 inches, 1584 pt (check 71b: 1584
|
|
61
|
+
// written as 31680, 1584.05 InvalidArgument; a negative refused, the schema's type being unsigned too)
|
|
62
|
+
spacingBefore: row('w:spacing/@w:before', 'twips', 'PPrBase.Spacing', 'before', { max: 31680, why: WORD_SPACING_LIMIT }),
|
|
63
|
+
spacingAfter: row('w:spacing/@w:after', 'twips', 'PPrBase.Spacing', 'after', { max: 31680, why: WORD_SPACING_LIMIT }),
|
|
64
|
+
// Office JS's lineSpacing, in points, is the line as a multiple of 12 pt ("in the Word UI, this value is divided by 12"):
|
|
65
|
+
// Word's own setter writes w:line = 20 × points under w:lineRule="auto" (check 71b: 0.75 pt as w:line="15"
|
|
66
|
+
// w:lineRule="auto", 1584 as 31680), and takes 0.75 to 1584 pt (0.7 and 1584.05 InvalidArgument); int16, wraps
|
|
67
|
+
spacingLineAuto: row('w:spacing/@w:line', 'twips', 'PPrBase.Spacing', 'line', { rule: 'auto', min: 15, max: 31680, why: "Word's own setter takes 0.75 to 1584 pt, 15 to 31680 twips under w:lineRule=\"auto\" (check 71b)" }),
|
|
68
|
+
// int16, wraps, under dxa and under pct; a width is never negative
|
|
69
|
+
tcWDxa: row('w:tcW/@w:w', 'twips', 'TblWidth', 'w', { min: 0, why: "a cell's width is never negative" }),
|
|
70
|
+
tcWPct: row('w:tcW/@w:w', 'fiftieths of a percent', 'TblWidth', 'w', { min: 0, why: "a cell's width is never negative" }),
|
|
71
|
+
// uint16, wraps; Word's own setter takes 1 to 1638 pt, in half-points after rounding (check 71b: 0.9 written as w:sz
|
|
72
|
+
// w:val="2", 1638.05 as 3276, 0.5 and 1638.4 InvalidArgument), where its storage runs to 65535
|
|
73
|
+
sz: row('w:sz/@w:val', 'half-points', 'HpsMeasure', 'val', { min: 2, max: 3276, why: "Word's own setter takes 1 to 1638 pt, 2 to 3276 half-points after rounding (check 71b)" }),
|
|
74
|
+
};
|
|
75
|
+
const PER_POINT = { twips: 20, 'half-points': 2 };
|
|
76
|
+
/**
|
|
77
|
+
* `points` in the attribute's unit, rounded, where Word stores it as written and the setter's policy allows; else
|
|
78
|
+
* `InvalidArgument`, naming the range and what Word would read, or why the policy stops short of Word's storage (CR-002
|
|
79
|
+
* section 65; the policy section 65.9's). `where` is the setter (`Paragraph.leftIndent`). `units` is the value already
|
|
80
|
+
* in the attribute's unit, where the setter computes it otherwise (a percentage width's fiftieths).
|
|
81
|
+
*/
|
|
82
|
+
export function withinWord(where, points, storage, units) {
|
|
83
|
+
if (!Number.isFinite(points))
|
|
84
|
+
throw new InvalidArgument(`${where}: ${points} is not a measurement in points`);
|
|
85
|
+
const unit = storage.unit;
|
|
86
|
+
const value = units !== null && units !== void 0 ? units : Math.round(points * PER_POINT[unit]);
|
|
87
|
+
if (value >= storage.min && value <= storage.max)
|
|
88
|
+
return value;
|
|
89
|
+
const inPoints = unit in PER_POINT
|
|
90
|
+
? `, ${storage.min / PER_POINT[unit]} to ${storage.max / PER_POINT[unit]} pt`
|
|
91
|
+
: '';
|
|
92
|
+
// within Word's storage the value is kept as written, so the refusal is the setter's policy; past it, what Word reads
|
|
93
|
+
const kept = value >= storage.stored[0] && value <= storage.stored[1];
|
|
94
|
+
const reason = kept && storage.why !== undefined ? storage.why : `Word 365 would read it as ${storage.reads(value)}`;
|
|
95
|
+
throw new InvalidArgument(`${where}: ${points} pt is ${value} ${unit} in ${storage.attribute}, outside the range written there `
|
|
96
|
+
+ `(${storage.min} to ${storage.max} ${unit}${inPoints}): ${reason} (CR-002 section 65)`);
|
|
97
|
+
}
|