@docx4j/core-ts 0.5.0 → 0.6.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 +32 -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 +509 -141
- package/dist/model/content/Comment.d.mts +21 -3
- package/dist/model/content/Comment.mjs +195 -19
- package/dist/model/content/ContentControl.d.mts +197 -18
- package/dist/model/content/ContentControl.mjs +664 -95
- package/dist/model/content/Font.d.mts +67 -17
- package/dist/model/content/Font.mjs +114 -35
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.mjs +3 -0
- package/dist/model/content/Paragraph.d.mts +189 -13
- package/dist/model/content/Paragraph.mjs +870 -74
- 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 +109 -33
- package/dist/model/content/TrackedChange.d.mts +172 -13
- package/dist/model/content/TrackedChange.mjs +728 -167
- 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 +8 -3
- package/dist/model/content/index.mjs +7 -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/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -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 +72 -0
- package/dist/model/content/search.mjs +204 -2
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +44 -0
- package/dist/model/content/story.mjs +92 -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 +100 -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 +28 -0
- package/dist/model/content/tracking.mjs +149 -10
- package/dist/model/content/tree.d.mts +171 -22
- package/dist/model/content/tree.mjs +329 -53
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
- package/dist/model/customxml/XmlMapping.d.mts +1 -1
- package/dist/model/customxml/XmlMapping.mjs +11 -0
- package/dist/model/customxml/bindings.d.mts +21 -2
- package/dist/model/customxml/bindings.mjs +76 -32
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- 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 +18 -6
- package/dist/model/customxml/xhtml.mjs +8 -2
- package/dist/model/index.d.mts +2 -0
- package/dist/model/index.mjs +4 -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 +60 -1
- package/dist/model/properties/PropertyResolver.mjs +115 -2
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/Extractor.d.mts +289 -0
- package/dist/model/text/Extractor.mjs +2162 -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 +539 -0
- package/dist/model/text/TextContext.d.mts +161 -0
- package/dist/model/text/TextContext.mjs +425 -0
- package/dist/model/text/TextOptions.d.mts +150 -0
- package/dist/model/text/TextOptions.mjs +278 -0
- package/dist/model/text/TextResult.d.mts +504 -0
- package/dist/model/text/TextResult.mjs +526 -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 +911 -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 +7 -0
- package/dist/model/text/index.mjs +8 -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/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 +21 -5
- package/dist/opc/Save.d.mts +17 -0
- package/dist/opc/Save.mjs +12 -2
- package/dist/opc/index.d.mts +3 -3
- package/dist/opc/index.mjs +1 -1
- package/dist/opc/mce/preprocessor.d.mts +28 -3
- package/dist/opc/mce/preprocessor.mjs +4 -4
- package/dist/opc/mce/understood.d.mts +30 -6
- package/dist/opc/mce/understood.mjs +37 -7
- package/dist/packages/OpcPackage.d.mts +13 -0
- package/dist/packages/OpcPackage.mjs +1 -0
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +155 -20
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +10 -2
- package/dist/parts/XmlPart.d.mts +12 -30
- package/dist/parts/XmlPart.mjs +44 -93
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.mjs +12 -0
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -0,0 +1,2162 @@
|
|
|
1
|
+
import { AlternativeFormatInputPart } from '../../parts/BinaryPart.mjs';
|
|
2
|
+
import { Emulator } from '../listnumbering/Emulator.mjs';
|
|
3
|
+
import { runItemsOf, selectedBranchOf, segmentsOf, hiddenRunsOf, SDT_TYPES } from '../content/tree.mjs';
|
|
4
|
+
import { TextBlock, TextRun, TextRow, TextCell, TextField, TextNumbering, TextRevision, TextWarning, TextComment, TextImage, TextResult, } from './TextResult.mjs';
|
|
5
|
+
import { calendarText } from './TextContext.mjs';
|
|
6
|
+
import { normalize } from './normalize.mjs';
|
|
7
|
+
const W_NS = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
8
|
+
const R_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
|
9
|
+
/**
|
|
10
|
+
* Fonts whose glyphs are all one width, for the block model's `monospace` and Markdown's code. The WD's
|
|
11
|
+
* definition of a monospaced font (1.3.2) is this list, docx4j's: a change goes to the specification first.
|
|
12
|
+
*/
|
|
13
|
+
const MONOSPACE = new Set([
|
|
14
|
+
'courier new', 'courier', 'consolas', 'lucida console', 'lucida sans typewriter', 'menlo', 'monaco',
|
|
15
|
+
'cascadia mono', 'cascadia code', 'source code pro', 'dejavu sans mono', 'liberation mono',
|
|
16
|
+
'andale mono', 'fira code', 'fira mono', 'inconsolata', 'roboto mono', 'ubuntu mono', 'jetbrains mono',
|
|
17
|
+
'noto sans mono', 'ocr a extended', 'letter gothic', 'pt mono', 'sf mono', 'ibm plex mono',
|
|
18
|
+
]);
|
|
19
|
+
const DECORATIVE_EXT = '{C183D7F6-B498-43B3-948B-1728B52AA6E4}';
|
|
20
|
+
/** The extension Office 2016 writes an SVG picture's SVG in, beside the PNG copy `a:blip/@r:embed` names. */
|
|
21
|
+
const SVG_BLIP_EXTENSION = '{96DAC541-7B7A-43D3-8B79-37D633B846F1}';
|
|
22
|
+
/** The run items that open, divide, close or instruct a complex field: all `fieldsAtBlocks` reads of a run. */
|
|
23
|
+
const FIELD_ITEMS = new Set(['fldChar', 'instrText', 'delInstrText']);
|
|
24
|
+
/** A list member's value: an element pair's, else the member. docx4j `unwrap`. */
|
|
25
|
+
function unwrap(item) {
|
|
26
|
+
return typeof item === 'object' && item !== null && 'value' in item && 'name' in item ? item.value : item;
|
|
27
|
+
}
|
|
28
|
+
/** A list member's element name, or ''. docx4j `name`. */
|
|
29
|
+
function nameOf(item) {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
return typeof item === 'object' && item !== null && 'name' in item ? ((_b = (_a = item.name) === null || _a === void 0 ? void 0 : _a.localPart) !== null && _b !== void 0 ? _b : '') : '';
|
|
32
|
+
}
|
|
33
|
+
function typeOf(v) {
|
|
34
|
+
return typeof v === 'object' && v !== null ? v.TYPE_NAME : undefined;
|
|
35
|
+
}
|
|
36
|
+
const P = 'org_docx4j_wml.P';
|
|
37
|
+
const R = 'org_docx4j_wml.R';
|
|
38
|
+
const TBL = 'org_docx4j_wml.Tbl';
|
|
39
|
+
const TR = 'org_docx4j_wml.Tr';
|
|
40
|
+
const TC = 'org_docx4j_wml.Tc';
|
|
41
|
+
const AC = 'org_docx4j_mce.AlternateContent';
|
|
42
|
+
const REVISION_TYPES = new Set(['org_docx4j_wml.RunIns', 'org_docx4j_wml.RunDel', 'org_docx4j_wml.RunTrackChange']);
|
|
43
|
+
const isSdt = (v) => { var _a; return SDT_TYPES.has((_a = typeOf(v)) !== null && _a !== void 0 ? _a : ''); };
|
|
44
|
+
const isMath = (v) => typeOf(v) === 'org_docx4j_math.CTOMath' || typeOf(v) === 'org_docx4j_math.CTOMathPara';
|
|
45
|
+
const on = (b) => b !== undefined && b !== null && b.val !== false;
|
|
46
|
+
/** The `w:ins`, `w:del`, `w:moveFrom` or `w:moveTo` a list member is, or undefined. */
|
|
47
|
+
function revisionHolder(item) {
|
|
48
|
+
var _a;
|
|
49
|
+
const v = unwrap(item);
|
|
50
|
+
return REVISION_TYPES.has((_a = typeOf(v)) !== null && _a !== void 0 ? _a : '') ? v : undefined;
|
|
51
|
+
}
|
|
52
|
+
const isInsertionName = (name) => name === 'ins' || name === 'moveTo';
|
|
53
|
+
/** Run-level content a holder keeps (docx4j `runItemsOf`); not a paragraph's. */
|
|
54
|
+
function runItemsOfValue(v) {
|
|
55
|
+
if (typeof v !== 'object' || v === null || typeOf(v) === P)
|
|
56
|
+
return undefined;
|
|
57
|
+
return runItemsOf(v);
|
|
58
|
+
}
|
|
59
|
+
/** Block-level content a container keeps (docx4j `blockItems`). */
|
|
60
|
+
function blockItems(v) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
var _c;
|
|
63
|
+
if (typeof v !== 'object' || v === null)
|
|
64
|
+
return undefined;
|
|
65
|
+
switch (typeOf(v)) {
|
|
66
|
+
case 'org_docx4j_wml.Body':
|
|
67
|
+
case 'org_docx4j_wml.Hdr':
|
|
68
|
+
case 'org_docx4j_wml.Ftr':
|
|
69
|
+
case 'org_docx4j_wml.CTFtnEdn':
|
|
70
|
+
case 'org_docx4j_wml.Comments.Comment':
|
|
71
|
+
case TC:
|
|
72
|
+
case 'org_docx4j_wml.CTTxbxContent':
|
|
73
|
+
case 'org_docx4j_wml.CTCustomXmlBlock':
|
|
74
|
+
case 'org_docx4j_wml.CTCustomXmlRow':
|
|
75
|
+
case 'org_docx4j_wml.CTCustomXmlCell':
|
|
76
|
+
return ((_a = (_c = v).content) !== null && _a !== void 0 ? _a : (_c.content = []));
|
|
77
|
+
case 'org_docx4j_wml.Document': {
|
|
78
|
+
const body = v.body;
|
|
79
|
+
return body ? ((_b = body.content) !== null && _b !== void 0 ? _b : []) : undefined;
|
|
80
|
+
}
|
|
81
|
+
default: return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** A range marker, bookmark, permission or proofing mark: a join passes over it. */
|
|
85
|
+
function isMarker(item) {
|
|
86
|
+
const name = nameOf(item);
|
|
87
|
+
return name.endsWith('RangeStart') || name.endsWith('RangeEnd') || name === 'bookmarkStart' || name === 'bookmarkEnd'
|
|
88
|
+
|| name === 'permStart' || name === 'permEnd' || name === 'proofErr';
|
|
89
|
+
}
|
|
90
|
+
const isBookmarkMarker = (item) => nameOf(item) === 'bookmarkStart' || nameOf(item) === 'bookmarkEnd';
|
|
91
|
+
/** The `w:sdtPr` child of a name, or undefined. */
|
|
92
|
+
function sdtPrChild(pr, local) {
|
|
93
|
+
var _a;
|
|
94
|
+
return (_a = pr === null || pr === void 0 ? void 0 : pr.rPrOrAliasOrLock) === null || _a === void 0 ? void 0 : _a.find((o) => nameOf(o) === local && o.name.namespaceURI === W_NS);
|
|
95
|
+
}
|
|
96
|
+
function showingPlaceholder(pr) {
|
|
97
|
+
const e = sdtPrChild(pr, 'showingPlcHdr');
|
|
98
|
+
return e !== undefined && on(e.value);
|
|
99
|
+
}
|
|
100
|
+
/** A walk of the typed objects under `value`, in property and list order; DOM is not entered. docx4j `walk`. */
|
|
101
|
+
function walk(value, depth, visitor) {
|
|
102
|
+
if (typeof value !== 'object' || value === null || depth > 200 || typeOf(value) === undefined)
|
|
103
|
+
return;
|
|
104
|
+
if (visitor.enter && !visitor.enter(value))
|
|
105
|
+
return;
|
|
106
|
+
for (const key of Object.keys(value)) {
|
|
107
|
+
if (key === 'PARENT' || key === 'TYPE_NAME')
|
|
108
|
+
continue;
|
|
109
|
+
const fv = value[key];
|
|
110
|
+
if (Array.isArray(fv)) {
|
|
111
|
+
for (const o of [...fv]) {
|
|
112
|
+
if (typeof o !== 'object' || o === null)
|
|
113
|
+
continue;
|
|
114
|
+
if (visitor.item && !visitor.item(o))
|
|
115
|
+
continue;
|
|
116
|
+
walk(unwrap(o), depth + 1, visitor);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else if (typeof fv === 'object' && fv !== null) {
|
|
120
|
+
if (visitor.item && !visitor.item(fv))
|
|
121
|
+
continue;
|
|
122
|
+
walk(unwrap(fv), depth + 1, visitor);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** The typed objects directly under `value`: its list members and object properties. docx4j `children`. */
|
|
127
|
+
function children(value) {
|
|
128
|
+
const out = [];
|
|
129
|
+
if (typeof value !== 'object' || value === null || typeOf(value) === undefined)
|
|
130
|
+
return out;
|
|
131
|
+
for (const key of Object.keys(value)) {
|
|
132
|
+
if (key === 'PARENT' || key === 'TYPE_NAME')
|
|
133
|
+
continue;
|
|
134
|
+
const fv = value[key];
|
|
135
|
+
if (Array.isArray(fv))
|
|
136
|
+
out.push(...fv.filter((o) => typeof o === 'object' && o !== null));
|
|
137
|
+
else if (typeof fv === 'object' && fv !== null)
|
|
138
|
+
out.push(fv);
|
|
139
|
+
}
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
function isMonospace(font) {
|
|
143
|
+
return font !== undefined && MONOSPACE.has(font.trim().toLowerCase());
|
|
144
|
+
}
|
|
145
|
+
function asciiFont(rPr) {
|
|
146
|
+
var _a;
|
|
147
|
+
return (_a = rPr === null || rPr === void 0 ? void 0 : rPr.rFonts) === null || _a === void 0 ? void 0 : _a.ascii;
|
|
148
|
+
}
|
|
149
|
+
function revisionOf(tc, type) {
|
|
150
|
+
return new TextRevision(type, tc.author, calendarText(tc.date));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Each item's place in `Paragraph.text` (CR-012 D2, section 4.4): the content API's own reader since phase 4
|
|
154
|
+
* (`segmentsOf`, Office JS's characters, hidden runs left out by the same rule), so an item that adds a
|
|
155
|
+
* character there has its offset, and one it leaves out (hidden text, a comment reference) has none.
|
|
156
|
+
*/
|
|
157
|
+
function officeSpans(p, resolver) {
|
|
158
|
+
const out = new Map();
|
|
159
|
+
for (const seg of segmentsOf(p, { hidden: hiddenRunsOf(resolver, p) })) {
|
|
160
|
+
if (!seg.math)
|
|
161
|
+
out.set(seg.item, { offset: seg.start, length: seg.end - seg.start });
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
/** An open complex field. */
|
|
166
|
+
class FieldState {
|
|
167
|
+
constructor() {
|
|
168
|
+
this.instr = '';
|
|
169
|
+
this.result = '';
|
|
170
|
+
this.separated = false;
|
|
171
|
+
/** `w:fldLock` on its beginning: never recomputed (REQ-506). */
|
|
172
|
+
this.locked = false;
|
|
173
|
+
/** A table of contents under `toc: false` (D12): nothing of it is read. */
|
|
174
|
+
this.toc = false;
|
|
175
|
+
this.codeStart = 0;
|
|
176
|
+
this.previousFloor = 0;
|
|
177
|
+
}
|
|
178
|
+
/** The field as a block after the one it began in starts inside it: its code's block and paragraph left behind. */
|
|
179
|
+
copy() {
|
|
180
|
+
const f = new FieldState();
|
|
181
|
+
f.instr = this.instr;
|
|
182
|
+
f.result = this.result;
|
|
183
|
+
f.separated = this.separated;
|
|
184
|
+
f.locked = this.locked;
|
|
185
|
+
f.computed = this.computed;
|
|
186
|
+
f.link = this.link;
|
|
187
|
+
f.toc = this.toc;
|
|
188
|
+
return f;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** The state of a run-level walk: the revision and the control the runs are in. */
|
|
192
|
+
class RunState {
|
|
193
|
+
constructor(
|
|
194
|
+
/** markup: the innermost revision; else undefined. */
|
|
195
|
+
revision,
|
|
196
|
+
/** accepted, original: inside a revision holder the view keeps (its runs are text whatever their elements). */
|
|
197
|
+
kept, placeholder) {
|
|
198
|
+
this.revision = revision;
|
|
199
|
+
this.kept = kept;
|
|
200
|
+
this.placeholder = placeholder;
|
|
201
|
+
}
|
|
202
|
+
withRevision(r, kept) {
|
|
203
|
+
return new RunState(r, kept, this.placeholder);
|
|
204
|
+
}
|
|
205
|
+
withPlaceholder() {
|
|
206
|
+
return new RunState(this.revision, this.kept, true);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const PLAIN = new RunState(undefined, false, false);
|
|
210
|
+
/** The walk of one story. */
|
|
211
|
+
class Story {
|
|
212
|
+
constructor(x, kind, prefix, part) {
|
|
213
|
+
this.x = x;
|
|
214
|
+
this.kind = kind;
|
|
215
|
+
this.prefix = prefix;
|
|
216
|
+
this.part = part;
|
|
217
|
+
/** Open complex fields; [0] is the innermost (docx4j's deque head). */
|
|
218
|
+
this.fields = [];
|
|
219
|
+
/** What was anchored since the last flush, to follow its anchor (or its table). */
|
|
220
|
+
this.pending = [];
|
|
221
|
+
this.tableDepth = 0;
|
|
222
|
+
this.noteNumber = 0;
|
|
223
|
+
}
|
|
224
|
+
/** The resolver the walk reads styles with, for `officeSpans`' hidden rule. */
|
|
225
|
+
get resolver() {
|
|
226
|
+
return this.x.resolver;
|
|
227
|
+
}
|
|
228
|
+
numbering() {
|
|
229
|
+
var _a;
|
|
230
|
+
(_a = this.numberingState) !== null && _a !== void 0 ? _a : (this.numberingState = this.part === undefined ? this.x.context.numberingStates.main() : this.x.context.numberingStates.forPart(this.part));
|
|
231
|
+
return this.numberingState;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/** A paragraph being read: the block its runs go to, its address, what it anchored so far. */
|
|
235
|
+
class ParagraphState {
|
|
236
|
+
constructor(block, p, address, story) {
|
|
237
|
+
this.block = block;
|
|
238
|
+
this.p = p;
|
|
239
|
+
this.address = address;
|
|
240
|
+
this.story = story;
|
|
241
|
+
this.boxes = 0;
|
|
242
|
+
this.charts = 0;
|
|
243
|
+
this.smartArts = 0;
|
|
244
|
+
this.objects = 0;
|
|
245
|
+
/** An equation being written, and whether it is a display one. */
|
|
246
|
+
this.math = false;
|
|
247
|
+
this.displayMath = false;
|
|
248
|
+
/** Whether a table of contents left out (D12) is in the paragraph. */
|
|
249
|
+
this.toc = false;
|
|
250
|
+
/** The first of the block's runs a run may be merged into: a field's code starts a run of its own where it may be taken out. */
|
|
251
|
+
this.mergeFloor = 0;
|
|
252
|
+
}
|
|
253
|
+
/** Where an item's text is in this paragraph's `Paragraph.text`. */
|
|
254
|
+
officeSpan(item) {
|
|
255
|
+
var _a;
|
|
256
|
+
(_a = this.office) !== null && _a !== void 0 ? _a : (this.office = officeSpans(this.p, this.story.resolver));
|
|
257
|
+
return this.office.get(item);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The text model's walk (CR-046 section 2.3): `scope(view(resolve(package)))` in one pass over the
|
|
262
|
+
* unresolved tree, producing the block model. docx4j `Extractor`, over trees read before it starts.
|
|
263
|
+
*/
|
|
264
|
+
export class Extractor {
|
|
265
|
+
constructor(trees, options, mode, context) {
|
|
266
|
+
this.trees = trees;
|
|
267
|
+
this.options = options;
|
|
268
|
+
this.context = context;
|
|
269
|
+
this.warnings = [];
|
|
270
|
+
this.warned = new Set();
|
|
271
|
+
/** What every address this extraction makes starts with. */
|
|
272
|
+
this.root = '';
|
|
273
|
+
/** The run properties a paragraph style and character style give, by their ids. */
|
|
274
|
+
this.styleRPrCache = new Map();
|
|
275
|
+
/** Bookmarks open in the walk, by id (REQ-506's REF, phase 5a). */
|
|
276
|
+
this.openBookmarks = new Map();
|
|
277
|
+
/** `fieldsAtBlocks`' walk: paragraphs read for their field characters and instructions alone, nothing emitted. */
|
|
278
|
+
this.fieldsOnly = false;
|
|
279
|
+
this.view = options.view;
|
|
280
|
+
this.mode = trees.pkg === undefined && mode === 'view' ? 'planless' : mode;
|
|
281
|
+
this.plan = this.mode === 'view' && this.view !== 'markup' ? context.plan(this.view === 'accepted') : undefined;
|
|
282
|
+
this.resolver = trees.resolver;
|
|
283
|
+
}
|
|
284
|
+
// --- the package ------------------------------------------------------------------------------
|
|
285
|
+
extract() {
|
|
286
|
+
var _a;
|
|
287
|
+
const out = [];
|
|
288
|
+
const comments = new Map();
|
|
289
|
+
const metadata = this.metadata();
|
|
290
|
+
const main = this.trees.main;
|
|
291
|
+
const body = main === null || main === void 0 ? void 0 : main.document.body;
|
|
292
|
+
if (!main || !body)
|
|
293
|
+
return new TextResult(out, comments, this.warnings, metadata, this.options);
|
|
294
|
+
// the main story, each text box after its anchor; sections recorded as they end
|
|
295
|
+
const story = new Story(this, 'MAIN', `${this.root}body`, main.part);
|
|
296
|
+
story.sections = [];
|
|
297
|
+
const mainBlocks = [];
|
|
298
|
+
this.blocks((_a = body.content) !== null && _a !== void 0 ? _a : [], `${this.root}body`, story, mainBlocks);
|
|
299
|
+
story.sections.push(body.sectPr);
|
|
300
|
+
this.context.mainRead = true;
|
|
301
|
+
const headers = this.options.includes.has('headers');
|
|
302
|
+
const footers = this.options.includes.has('footers');
|
|
303
|
+
if (headers || footers)
|
|
304
|
+
this.sectionsWithHeaders(story.sections, mainBlocks, headers, footers, out);
|
|
305
|
+
else
|
|
306
|
+
out.push(...mainBlocks);
|
|
307
|
+
// the notes, in reference order (REQ-501, REQ-503)
|
|
308
|
+
if (this.options.notes) {
|
|
309
|
+
this.notes('footnote', out);
|
|
310
|
+
this.notes('endnote', out);
|
|
311
|
+
}
|
|
312
|
+
// the glossary, last (REQ-501, REQ-516)
|
|
313
|
+
if (this.options.includes.has('glossary'))
|
|
314
|
+
this.glossary(out);
|
|
315
|
+
// comments, rendered at their references (REQ-504)
|
|
316
|
+
if (this.commentsIncluded())
|
|
317
|
+
this.comments(comments);
|
|
318
|
+
return new TextResult(out, comments, this.warnings, metadata, this.options);
|
|
319
|
+
}
|
|
320
|
+
/** The result's metadata: `fields_update_on_open` and the document properties (REQ-801, REQ-515). */
|
|
321
|
+
metadata() {
|
|
322
|
+
var _a;
|
|
323
|
+
const metadata = { [TextResult.FIELDS_UPDATE_ON_OPEN]: this.fieldsUpdateOnOpen() };
|
|
324
|
+
Object.assign(metadata, (_a = this.trees.properties) !== null && _a !== void 0 ? _a : {});
|
|
325
|
+
return metadata;
|
|
326
|
+
}
|
|
327
|
+
fieldsUpdateOnOpen() {
|
|
328
|
+
var _a;
|
|
329
|
+
return on((_a = this.trees.settings) === null || _a === void 0 ? void 0 : _a.updateFields);
|
|
330
|
+
}
|
|
331
|
+
commentsIncluded() {
|
|
332
|
+
return this.view === 'markup' || this.options.comments;
|
|
333
|
+
}
|
|
334
|
+
/** A part's or object's content as one story (`Texts.of(part)`, `Texts.of(pkg, content)`). */
|
|
335
|
+
extractContent(content, kind, prefix, part) {
|
|
336
|
+
const out = [];
|
|
337
|
+
const story = new Story(this, kind, prefix, part);
|
|
338
|
+
const v = unwrap(content);
|
|
339
|
+
const items = blockItems(v);
|
|
340
|
+
if (items !== undefined && typeOf(v) !== P)
|
|
341
|
+
this.blocks(items, prefix, story, out);
|
|
342
|
+
else
|
|
343
|
+
this.blocks([content], prefix, story, out);
|
|
344
|
+
if (kind === 'MAIN' && prefix === 'body')
|
|
345
|
+
this.context.mainRead = true;
|
|
346
|
+
const metadata = {};
|
|
347
|
+
if (this.trees.pkg !== undefined)
|
|
348
|
+
metadata[TextResult.FIELDS_UPDATE_ON_OPEN] = this.fieldsUpdateOnOpen();
|
|
349
|
+
return new TextResult(out, new Map(), this.warnings, metadata, this.options);
|
|
350
|
+
}
|
|
351
|
+
/** The notes of one kind, in the context's reference order (`Texts.of(notesPart)`). */
|
|
352
|
+
extractNotes(type) {
|
|
353
|
+
const out = [];
|
|
354
|
+
this.notes(type, out);
|
|
355
|
+
return new TextResult(out, new Map(), this.warnings, { [TextResult.FIELDS_UPDATE_ON_OPEN]: this.fieldsUpdateOnOpen() }, this.options);
|
|
356
|
+
}
|
|
357
|
+
/** The comments (`Texts.of(commentsPart)`): what the view includes, in the comments part's order. */
|
|
358
|
+
extractComments() {
|
|
359
|
+
const comments = new Map();
|
|
360
|
+
this.comments(comments);
|
|
361
|
+
return new TextResult([], comments, this.warnings, { [TextResult.FIELDS_UPDATE_ON_OPEN]: this.fieldsUpdateOnOpen() }, this.options);
|
|
362
|
+
}
|
|
363
|
+
// --- the glossary (REQ-516) -------------------------------------------------------------------
|
|
364
|
+
glossary(out) {
|
|
365
|
+
var _a, _b, _c;
|
|
366
|
+
const g = this.trees.glossary;
|
|
367
|
+
const parts = (_b = (_a = g === null || g === void 0 ? void 0 : g.tree.docParts) === null || _a === void 0 ? void 0 : _a.docPart) !== null && _b !== void 0 ? _b : [];
|
|
368
|
+
for (let i = 0; i < parts.length; i++) {
|
|
369
|
+
const body = parts[i].docPartBody;
|
|
370
|
+
if (!body)
|
|
371
|
+
continue;
|
|
372
|
+
const prefix = `${this.root}glossary:${i}`;
|
|
373
|
+
this.blocks((_c = body.content) !== null && _c !== void 0 ? _c : [], prefix, new Story(this, 'GLOSSARY', prefix, g.part), out);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// --- block level ------------------------------------------------------------------------------
|
|
377
|
+
/** Block-level content into `sink`: paragraphs (joined in a view), tables, and what is transparent. */
|
|
378
|
+
blocks(items, prefix, story, sink, state = PLAIN) {
|
|
379
|
+
if (!items)
|
|
380
|
+
return;
|
|
381
|
+
for (let i = 0; i < items.length; i++)
|
|
382
|
+
i = this.block(items, i, prefix, story, sink, state);
|
|
383
|
+
}
|
|
384
|
+
/** The block at `items[i]` into `sink`, with the paragraphs a view joins to it; the index of the last item it took. */
|
|
385
|
+
block(items, i, prefix, story, sink, state) {
|
|
386
|
+
var _a, _b, _c;
|
|
387
|
+
const item = items[i];
|
|
388
|
+
if (this.removes(item))
|
|
389
|
+
return i;
|
|
390
|
+
const v = unwrap(item);
|
|
391
|
+
const address = `${prefix}/${i}`;
|
|
392
|
+
const tn = typeOf(v);
|
|
393
|
+
if (tn === P) {
|
|
394
|
+
const chain = [v];
|
|
395
|
+
const addresses = [address];
|
|
396
|
+
let j = i;
|
|
397
|
+
while (this.joinsNext(chain[chain.length - 1])) {
|
|
398
|
+
const k = this.nextParagraph(items, j);
|
|
399
|
+
if (k < 0)
|
|
400
|
+
break; // no paragraph next: only the mark goes, or what the plan says
|
|
401
|
+
chain.push(unwrap(items[k]));
|
|
402
|
+
addresses.push(`${prefix}/${k}`);
|
|
403
|
+
j = k;
|
|
404
|
+
}
|
|
405
|
+
if (this.pendingTableJoin) {
|
|
406
|
+
// the paragraph before the table whose content joins this one, its first cell's first paragraph
|
|
407
|
+
chain.unshift(...this.pendingTableJoin.chain);
|
|
408
|
+
addresses.unshift(...this.pendingTableJoin.addresses);
|
|
409
|
+
this.pendingTableJoin = undefined;
|
|
410
|
+
}
|
|
411
|
+
if ((_a = this.plan) === null || _a === void 0 ? void 0 : _a.joinsIntoTable(chain[chain.length - 1])) {
|
|
412
|
+
// a deleted mark with a table next and text left: into the table's first cell (docx4j CR-043 section 17)
|
|
413
|
+
this.pendingTableJoin = { chain, addresses };
|
|
414
|
+
return j;
|
|
415
|
+
}
|
|
416
|
+
this.paragraph(chain, addresses, story, sink, state);
|
|
417
|
+
return j;
|
|
418
|
+
}
|
|
419
|
+
if (tn === TBL) {
|
|
420
|
+
this.table(v, address, story, sink, state);
|
|
421
|
+
if (this.pendingTableJoin) {
|
|
422
|
+
// the table had no paragraph to take it after all: on its own
|
|
423
|
+
const { chain, addresses } = this.pendingTableJoin;
|
|
424
|
+
this.pendingTableJoin = undefined;
|
|
425
|
+
this.paragraph(chain, addresses, story, sink, state);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
else if (isSdt(v) && this.unwraps(item)) {
|
|
429
|
+
// an inserted control rejected: its content in its place, its properties gone
|
|
430
|
+
this.blocks(sdtContentOf(v), address, story, sink, state);
|
|
431
|
+
}
|
|
432
|
+
else if (isSdt(v)) {
|
|
433
|
+
const sdt = v;
|
|
434
|
+
const bound = this.bound(sdt, address);
|
|
435
|
+
if (bound !== undefined) {
|
|
436
|
+
// a plain-text control bound at block level: its bound value as one paragraph (REQ-509)
|
|
437
|
+
const block = paragraphBlock(story.kind, address, bound);
|
|
438
|
+
block.section = (_c = (_b = story.sections) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
|
|
439
|
+
block.source = sdt;
|
|
440
|
+
sink.push(block);
|
|
441
|
+
this.flushIfOutsideTable(story, sink);
|
|
442
|
+
return i;
|
|
443
|
+
}
|
|
444
|
+
const placeholder = showingPlaceholder(sdt.sdtPr);
|
|
445
|
+
if (placeholder && !this.options.placeholders)
|
|
446
|
+
return i;
|
|
447
|
+
this.blocks(sdtContentOf(v), address, story, sink, placeholder ? state.withPlaceholder() : state);
|
|
448
|
+
}
|
|
449
|
+
else if (tn === 'org_docx4j_wml.CTAltChunk') {
|
|
450
|
+
this.altChunk(v, address, story);
|
|
451
|
+
}
|
|
452
|
+
else if (isBookmarkMarker(item)) {
|
|
453
|
+
this.bookmark(item);
|
|
454
|
+
}
|
|
455
|
+
else if (tn === AC) {
|
|
456
|
+
const ac = v;
|
|
457
|
+
this.compareBranches(ac, address);
|
|
458
|
+
this.blocks(selectedBranchOf(ac), address, story, sink, state);
|
|
459
|
+
}
|
|
460
|
+
else if (revisionHolder(item) !== undefined) {
|
|
461
|
+
this.blocks(runItemsOfValue(v), address, story, sink, this.holderState(item, state));
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
const inner = blockItems(v);
|
|
465
|
+
if (inner)
|
|
466
|
+
this.blocks(inner, address, story, sink, state);
|
|
467
|
+
}
|
|
468
|
+
return i;
|
|
469
|
+
}
|
|
470
|
+
// --- some of a container's blocks (CR-012 section 17.13) -----------------------------------------
|
|
471
|
+
/**
|
|
472
|
+
* Some of a container's blocks, by their indices, each as `extractContent` reads it in the whole: a
|
|
473
|
+
* paragraph the view joins to one before it gives nothing (its text is in that one's block), and each
|
|
474
|
+
* block starts inside the complex fields open where it begins (`starts`, from `fieldsAtBlocks`), so that
|
|
475
|
+
* a table of contents left out (D12) is left out here too. Each block is read as a story of its own.
|
|
476
|
+
*/
|
|
477
|
+
extractBlocks(content, kind, prefix, part, indices, starts) {
|
|
478
|
+
var _a, _b;
|
|
479
|
+
const out = [];
|
|
480
|
+
const items = (_a = blockItems(unwrap(content))) !== null && _a !== void 0 ? _a : [];
|
|
481
|
+
for (const i of [...new Set(indices)].sort((a, b) => a - b)) {
|
|
482
|
+
if (!(i >= 0 && i < items.length) || this.joinedFromBefore(items, i))
|
|
483
|
+
continue;
|
|
484
|
+
const story = new Story(this, kind, prefix, part);
|
|
485
|
+
for (const f of (_b = starts.get(i)) !== null && _b !== void 0 ? _b : [])
|
|
486
|
+
story.fields.push(f.copy());
|
|
487
|
+
this.block(items, i, prefix, story, out, PLAIN);
|
|
488
|
+
}
|
|
489
|
+
return new TextResult(out, new Map(), this.warnings, { [TextResult.FIELDS_UPDATE_ON_OPEN]: this.fieldsUpdateOnOpen() }, this.options);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* The complex fields open where each of a container's blocks begins, for `extractBlocks`: a walk of the
|
|
493
|
+
* blocks reading field characters and instructions alone (`fieldsOnly`), as the whole walk reads them.
|
|
494
|
+
* Blocks with none open are not in the map. Its own context and warnings, so the reading leaves no trace.
|
|
495
|
+
*/
|
|
496
|
+
static fieldsAtBlocks(trees, options, mode, context, content, kind, prefix, part) {
|
|
497
|
+
var _a;
|
|
498
|
+
const x = new Extractor(trees, options, mode, context.sibling());
|
|
499
|
+
x.fieldsOnly = true;
|
|
500
|
+
const starts = new Map();
|
|
501
|
+
const items = (_a = blockItems(unwrap(content))) !== null && _a !== void 0 ? _a : [];
|
|
502
|
+
const story = new Story(x, kind, prefix, part);
|
|
503
|
+
const sink = [];
|
|
504
|
+
for (let i = 0; i < items.length; i++) {
|
|
505
|
+
if (story.fields.length > 0)
|
|
506
|
+
starts.set(i, story.fields.map((f) => f.copy()));
|
|
507
|
+
i = x.block(items, i, prefix, story, sink, PLAIN);
|
|
508
|
+
sink.length = 0;
|
|
509
|
+
}
|
|
510
|
+
return starts;
|
|
511
|
+
}
|
|
512
|
+
/** Whether the view joins the paragraph at `items[i]` to one before it: the item before it, past markers and what the view removes, is a paragraph whose mark goes. */
|
|
513
|
+
joinedFromBefore(items, i) {
|
|
514
|
+
if (typeOf(unwrap(items[i])) !== P)
|
|
515
|
+
return false;
|
|
516
|
+
for (let k = i - 1; k >= 0; k--) {
|
|
517
|
+
const item = items[k];
|
|
518
|
+
if (isMarker(item) || this.removes(item))
|
|
519
|
+
continue;
|
|
520
|
+
const v = unwrap(item);
|
|
521
|
+
return typeOf(v) === P && this.joinsNext(v);
|
|
522
|
+
}
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
/** The index of the paragraph a paragraph joins: the next in the list past markers and what the view removes, or -1. */
|
|
526
|
+
nextParagraph(items, from) {
|
|
527
|
+
for (let k = from + 1; k < items.length; k++) {
|
|
528
|
+
const item = items[k];
|
|
529
|
+
if (isMarker(item) || this.removes(item))
|
|
530
|
+
continue;
|
|
531
|
+
return typeOf(unwrap(item)) === P ? k : -1;
|
|
532
|
+
}
|
|
533
|
+
return -1;
|
|
534
|
+
}
|
|
535
|
+
paragraph(chain, addresses, story, sink, state) {
|
|
536
|
+
var _a, _b, _c, _d;
|
|
537
|
+
const first = chain[0];
|
|
538
|
+
const last = chain[chain.length - 1];
|
|
539
|
+
const block = new TextBlock('PARAGRAPH', story.kind, addresses[0]);
|
|
540
|
+
if (this.fieldsOnly) {
|
|
541
|
+
for (let c = 0; c < chain.length; c++)
|
|
542
|
+
this.runs(chain[c].content, new ParagraphState(block, chain[c], addresses[c], story), state);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
if (chain.length > 1)
|
|
546
|
+
block.joined = addresses.slice(1);
|
|
547
|
+
block.paraId = first.paraId;
|
|
548
|
+
block.source = first;
|
|
549
|
+
// a joined paragraph keeps the last one's properties (CR-043's join); under a plan, a paragraph whose mark is gone
|
|
550
|
+
// with no paragraph next takes what Word gives it (docx4j CR-043 section 17)
|
|
551
|
+
block.style = (_b = (_a = this.viewPPr(last)) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val;
|
|
552
|
+
block.noteType = story.noteType;
|
|
553
|
+
block.noteNumber = story.noteNumber;
|
|
554
|
+
block.noteId = story.noteId;
|
|
555
|
+
let monospace;
|
|
556
|
+
let toc = false;
|
|
557
|
+
for (let c = 0; c < chain.length; c++) {
|
|
558
|
+
const p = chain[c];
|
|
559
|
+
block.revisions += markRevisions(p);
|
|
560
|
+
const para = new ParagraphState(block, p, addresses[c], story);
|
|
561
|
+
const startsInToc = inToc(story);
|
|
562
|
+
this.runs(p.content, para, state);
|
|
563
|
+
if (startsInToc || para.toc || inToc(story))
|
|
564
|
+
toc = true;
|
|
565
|
+
if (para.monospace !== undefined)
|
|
566
|
+
monospace = monospace === undefined ? para.monospace : monospace && para.monospace;
|
|
567
|
+
}
|
|
568
|
+
for (const b of this.openBookmarks.values())
|
|
569
|
+
b.paragraphEnded = true;
|
|
570
|
+
block.monospace = monospace === true;
|
|
571
|
+
this.properties(block, last);
|
|
572
|
+
const markHidden = this.isHiddenMark(last.pPr);
|
|
573
|
+
const anyVisible = block.runs.some((r) => !r.hidden);
|
|
574
|
+
const hiddenParagraph = markHidden && !anyVisible;
|
|
575
|
+
if (hiddenParagraph && !this.options.hidden) {
|
|
576
|
+
// runs and mark hidden: no line at all (REQ-507)
|
|
577
|
+
block.runs.length = 0;
|
|
578
|
+
this.flushIfOutsideTable(story, sink);
|
|
579
|
+
this.endSection(last, story);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
block.hidden = hiddenParagraph;
|
|
583
|
+
if (!this.options.hidden) {
|
|
584
|
+
for (let k = block.runs.length - 1; k >= 0; k--)
|
|
585
|
+
if (block.runs[k].hidden)
|
|
586
|
+
block.runs.splice(k, 1);
|
|
587
|
+
}
|
|
588
|
+
if (toc && block.runs.length === 0) {
|
|
589
|
+
// a table of contents' paragraph, under toc: false (D12): no line at all
|
|
590
|
+
this.flushIfOutsideTable(story, sink);
|
|
591
|
+
this.endSection(last, story);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
// one count per paragraph: the label (list_labels) and the numbering's value come from it
|
|
595
|
+
if (this.trees.pkg !== undefined && (this.options.listLabels || block.numbering !== undefined)) {
|
|
596
|
+
const counted = this.count(last, story);
|
|
597
|
+
if (this.options.listLabels)
|
|
598
|
+
block.listLabel = listLabel(counted);
|
|
599
|
+
if (block.numbering !== undefined && counted !== undefined && !counted.notNumbered)
|
|
600
|
+
block.numbering.value = counted.count;
|
|
601
|
+
}
|
|
602
|
+
block.section = (_d = (_c = story.sections) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
|
|
603
|
+
sink.push(block);
|
|
604
|
+
this.flushIfOutsideTable(story, sink);
|
|
605
|
+
this.endSection(last, story);
|
|
606
|
+
}
|
|
607
|
+
endSection(last, story) {
|
|
608
|
+
var _a;
|
|
609
|
+
if (story.sections && story.tableDepth === 0 && ((_a = last.pPr) === null || _a === void 0 ? void 0 : _a.sectPr))
|
|
610
|
+
story.sections.push(last.pPr.sectPr);
|
|
611
|
+
}
|
|
612
|
+
flushIfOutsideTable(story, sink) {
|
|
613
|
+
var _a, _b;
|
|
614
|
+
if (story.tableDepth > 0 || story.pending.length === 0)
|
|
615
|
+
return;
|
|
616
|
+
const items = story.pending.splice(0);
|
|
617
|
+
for (const item of items) {
|
|
618
|
+
const blocks = [];
|
|
619
|
+
item.emit(this, story, blocks);
|
|
620
|
+
const section = (_b = (_a = story.sections) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
621
|
+
for (const b of blocks)
|
|
622
|
+
b.section = section;
|
|
623
|
+
sink.push(...blocks);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
// --- altChunk (REQ-513) -----------------------------------------------------------------------
|
|
627
|
+
/** An `altChunk`: not expanded until CR-012 phase 5e, which raises `altchunk.not_expanded` with its content type. */
|
|
628
|
+
altChunk(chunk, address, story) {
|
|
629
|
+
var _a;
|
|
630
|
+
const part = related(story.part, chunk.id);
|
|
631
|
+
if (!(part instanceof AlternativeFormatInputPart))
|
|
632
|
+
return;
|
|
633
|
+
const ct = (_a = part.contentType) !== null && _a !== void 0 ? _a : '';
|
|
634
|
+
const semi = ct.indexOf(';');
|
|
635
|
+
this.warn(new TextWarning(TextWarning.ALTCHUNK_NOT_EXPANDED, address, undefined, (semi >= 0 ? ct.slice(0, semi) : ct).trim()));
|
|
636
|
+
}
|
|
637
|
+
// --- bound values (REQ-509) -------------------------------------------------------------------
|
|
638
|
+
/**
|
|
639
|
+
* A plain-text control's bound value where its binding resolves and is what Word shows: not where the
|
|
640
|
+
* value is empty and the control shows its placeholder, nor under `bindings: surface`. Undefined to read
|
|
641
|
+
* the surface. Raises `sdt.binding_differs` where the two differ.
|
|
642
|
+
*/
|
|
643
|
+
bound(sdt, address) {
|
|
644
|
+
var _a;
|
|
645
|
+
const pr = sdt.sdtPr;
|
|
646
|
+
if (this.trees.pkg === undefined || !pr || sdtPrChild(pr, 'text') === undefined)
|
|
647
|
+
return undefined;
|
|
648
|
+
const binding = (_a = sdtPrChild(pr, 'dataBinding')) === null || _a === void 0 ? void 0 : _a.value;
|
|
649
|
+
if (!binding)
|
|
650
|
+
return undefined;
|
|
651
|
+
const value = this.trees.boundValue(binding);
|
|
652
|
+
if (value === undefined)
|
|
653
|
+
return undefined;
|
|
654
|
+
const placeholder = showingPlaceholder(pr);
|
|
655
|
+
if (value === '' && placeholder)
|
|
656
|
+
return undefined;
|
|
657
|
+
const surface = placeholder ? undefined : this.surfaceText(sdt);
|
|
658
|
+
if (value !== surface)
|
|
659
|
+
this.warn(new TextWarning(TextWarning.SDT_BINDING_DIFFERS, address));
|
|
660
|
+
return this.options.bindings === 'surface' ? undefined : value;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* A control's surface in the view: its `w:t`, tabs and breaks, what the view removes left out, and of an
|
|
664
|
+
* mc:AlternateContent the selected branch only, as the reading takes it (CR-013: every branch's text
|
|
665
|
+
* made a surface no binding could match, and a false `sdt.binding_differs`).
|
|
666
|
+
*/
|
|
667
|
+
surfaceText(sdt) {
|
|
668
|
+
let out = '';
|
|
669
|
+
// every item, a branch's own included (a branch in a w:r holds w:t directly), goes through item()
|
|
670
|
+
const item = (o) => {
|
|
671
|
+
var _a;
|
|
672
|
+
if (this.removes(o))
|
|
673
|
+
return false;
|
|
674
|
+
const name = nameOf(o);
|
|
675
|
+
const v = unwrap(o);
|
|
676
|
+
if (typeOf(v) === AC) {
|
|
677
|
+
visit(selectedBranchOf(v));
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
680
|
+
if (name === 't' && typeOf(v) === 'org_docx4j_wml.Text')
|
|
681
|
+
out += String((_a = v.value) !== null && _a !== void 0 ? _a : '');
|
|
682
|
+
else if (name === 'tab')
|
|
683
|
+
out += '\t';
|
|
684
|
+
else if (name === 'br' || name === 'cr')
|
|
685
|
+
out += '\n';
|
|
686
|
+
return name !== 'instrText';
|
|
687
|
+
};
|
|
688
|
+
const visit = (items) => {
|
|
689
|
+
for (const o of items !== null && items !== void 0 ? items : [])
|
|
690
|
+
if (item(o))
|
|
691
|
+
walk(unwrap(o), 0, { item });
|
|
692
|
+
};
|
|
693
|
+
visit(sdtContentOf(sdt));
|
|
694
|
+
return out;
|
|
695
|
+
}
|
|
696
|
+
// --- bookmarks, for REF under fields: update (REQ-506) -----------------------------------------
|
|
697
|
+
bookmark(item) {
|
|
698
|
+
if (this.options.fields !== 'update')
|
|
699
|
+
return; // phase 5a
|
|
700
|
+
const v = unwrap(item);
|
|
701
|
+
if (nameOf(item) === 'bookmarkStart') {
|
|
702
|
+
if (v.id !== undefined && v.name !== undefined)
|
|
703
|
+
this.openBookmarks.set(String(v.id), { name: v.name, text: '', paragraphEnded: false });
|
|
704
|
+
}
|
|
705
|
+
else if (v.id !== undefined) {
|
|
706
|
+
const b = this.openBookmarks.get(String(v.id));
|
|
707
|
+
this.openBookmarks.delete(String(v.id));
|
|
708
|
+
if (b)
|
|
709
|
+
this.context.bookmarks.set(b.name.toLowerCase(), b.text);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
properties(block, p) {
|
|
713
|
+
var _a, _b, _c, _d, _e, _f;
|
|
714
|
+
const own = this.viewPPr(p);
|
|
715
|
+
block.bottomBorder = ((_a = own === null || own === void 0 ? void 0 : own.pBdr) === null || _a === void 0 ? void 0 : _a.bottom) !== undefined;
|
|
716
|
+
let effective = own;
|
|
717
|
+
if (this.resolver) {
|
|
718
|
+
try {
|
|
719
|
+
effective = this.resolver.getEffectivePPr(own);
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
// not resolved: the paragraph's own properties
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (!effective)
|
|
726
|
+
return;
|
|
727
|
+
const ind = effective.ind;
|
|
728
|
+
if (ind) {
|
|
729
|
+
block.indentLeft = twips((_b = ind.left) !== null && _b !== void 0 ? _b : ind.start);
|
|
730
|
+
block.indentHanging = twips(ind.hanging);
|
|
731
|
+
block.indentFirstLine = twips(ind.firstLine);
|
|
732
|
+
}
|
|
733
|
+
if (((_c = effective.jc) === null || _c === void 0 ? void 0 : _c.val) !== undefined)
|
|
734
|
+
block.alignment = String(effective.jc.val);
|
|
735
|
+
const level = (_d = effective.outlineLvl) === null || _d === void 0 ? void 0 : _d.val;
|
|
736
|
+
if (level !== undefined && level !== null) {
|
|
737
|
+
const n = Number(level);
|
|
738
|
+
if (n >= 0 && n <= 8)
|
|
739
|
+
block.outlineLevel = n; // 9 is body text
|
|
740
|
+
}
|
|
741
|
+
if (effective.contextualSpacing !== undefined)
|
|
742
|
+
block.contextualSpacing = on(effective.contextualSpacing);
|
|
743
|
+
const directNumId = ((_e = own === null || own === void 0 ? void 0 : own.numPr) === null || _e === void 0 ? void 0 : _e.numId) !== undefined;
|
|
744
|
+
block.numbering = this.numbering(effective.numPr, directNumId, (_f = own === null || own === void 0 ? void 0 : own.pStyle) === null || _f === void 0 ? void 0 : _f.val);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* A paragraph's numbering from its effective `w:numPr` and the numbering definitions; undefined for none,
|
|
748
|
+
* for `w:numId` 0, and where Word gives the paragraph no number: a `w:numId` its style brought, whose
|
|
749
|
+
* level belongs to another paragraph style (`Emulator.levelStyleId`, REQ-510).
|
|
750
|
+
*/
|
|
751
|
+
numbering(numPr, directNumId, pStyle) {
|
|
752
|
+
var _a, _b, _c, _d, _e;
|
|
753
|
+
const numIdValue = (_a = numPr === null || numPr === void 0 ? void 0 : numPr.numId) === null || _a === void 0 ? void 0 : _a.val;
|
|
754
|
+
if (numIdValue === undefined || numIdValue === null)
|
|
755
|
+
return undefined;
|
|
756
|
+
const numId = String(numIdValue);
|
|
757
|
+
if (Number(numIdValue) === 0)
|
|
758
|
+
return undefined;
|
|
759
|
+
const ilvlValue = (_b = numPr === null || numPr === void 0 ? void 0 : numPr.ilvl) === null || _b === void 0 ? void 0 : _b.val;
|
|
760
|
+
const ilvl = ilvlValue === undefined || ilvlValue === null ? 0 : Number(ilvlValue);
|
|
761
|
+
let format;
|
|
762
|
+
let text;
|
|
763
|
+
let abstractNumId;
|
|
764
|
+
let start = 1;
|
|
765
|
+
const part = this.trees.numberingPart;
|
|
766
|
+
const definitions = this.trees.numbering;
|
|
767
|
+
try {
|
|
768
|
+
if (part && !directNumId && this.linkedElsewhere(part, numId, String(ilvl), pStyle))
|
|
769
|
+
return undefined;
|
|
770
|
+
const list = definitions === null || definitions === void 0 ? void 0 : definitions.list(numId);
|
|
771
|
+
abstractNumId = (_c = list === null || list === void 0 ? void 0 : list.abstractDefinition) === null || _c === void 0 ? void 0 : _c.id;
|
|
772
|
+
// the instance's level, its w:lvlOverride applied
|
|
773
|
+
const level = (_d = list === null || list === void 0 ? void 0 : list.level(ilvl)) !== null && _d !== void 0 ? _d : (_e = list === null || list === void 0 ? void 0 : list.abstractDefinition) === null || _e === void 0 ? void 0 : _e.levels.get(String(ilvl));
|
|
774
|
+
if (level) {
|
|
775
|
+
format = level.numFmt === undefined ? (level.isBullet ? 'bullet' : undefined) : String(level.numFmt);
|
|
776
|
+
text = level.lvlText;
|
|
777
|
+
start = level.startValue + 1;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch {
|
|
781
|
+
// the definitions could not be read
|
|
782
|
+
}
|
|
783
|
+
const numbering = new TextNumbering(numId, ilvl, format, text, start);
|
|
784
|
+
numbering.abstractNumId = abstractNumId;
|
|
785
|
+
return numbering;
|
|
786
|
+
}
|
|
787
|
+
/** Whether the level belongs to a paragraph style that is neither the paragraph's nor one its style is based on. */
|
|
788
|
+
linkedElsewhere(part, numId, ilvl, pStyle) {
|
|
789
|
+
var _a, _b, _c, _d;
|
|
790
|
+
const linked = Emulator.levelStyleId(part, numId, ilvl);
|
|
791
|
+
if (linked === undefined || linked === '')
|
|
792
|
+
return false;
|
|
793
|
+
// a paragraph naming no style is in the default paragraph style, which can own a level
|
|
794
|
+
let id = pStyle !== null && pStyle !== void 0 ? pStyle : (_a = this.resolver) === null || _a === void 0 ? void 0 : _a.getDefaultParagraphStyleId();
|
|
795
|
+
const seen = new Set();
|
|
796
|
+
while (id !== undefined && !seen.has(id)) {
|
|
797
|
+
seen.add(id);
|
|
798
|
+
if (linked === id)
|
|
799
|
+
return false;
|
|
800
|
+
id = (_d = (_c = (_b = this.resolver) === null || _b === void 0 ? void 0 : _b.getStyle(id)) === null || _c === void 0 ? void 0 : _c.basedOn) === null || _d === void 0 ? void 0 : _d.val;
|
|
801
|
+
}
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
/** The paragraph counted in its story's numbering state; undefined where it is not numbered. */
|
|
805
|
+
count(p, story) {
|
|
806
|
+
const pkg = this.trees.pkg;
|
|
807
|
+
if (!pkg || !this.trees.numberingPart)
|
|
808
|
+
return undefined;
|
|
809
|
+
try {
|
|
810
|
+
return Emulator.getNumber(pkg, p.pPr, story.numbering());
|
|
811
|
+
}
|
|
812
|
+
catch {
|
|
813
|
+
return undefined;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
// --- tables -----------------------------------------------------------------------------------
|
|
817
|
+
table(tbl, address, story, sink, state) {
|
|
818
|
+
var _a, _b;
|
|
819
|
+
const block = new TextBlock('TABLE', story.kind, address);
|
|
820
|
+
block.section = (_b = (_a = story.sections) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
821
|
+
block.source = tbl;
|
|
822
|
+
story.tableDepth++;
|
|
823
|
+
try {
|
|
824
|
+
this.rows(tbl.content, address, story, block, state);
|
|
825
|
+
}
|
|
826
|
+
finally {
|
|
827
|
+
story.tableDepth--;
|
|
828
|
+
}
|
|
829
|
+
if (block.rows.length > 0)
|
|
830
|
+
sink.push(block); // a table left with no rows goes (CR-043)
|
|
831
|
+
this.flushIfOutsideTable(story, sink);
|
|
832
|
+
}
|
|
833
|
+
rows(items, prefix, story, table, state) {
|
|
834
|
+
var _a;
|
|
835
|
+
if (!items)
|
|
836
|
+
return;
|
|
837
|
+
for (let i = 0; i < items.length; i++) {
|
|
838
|
+
const item = items[i];
|
|
839
|
+
if (this.removes(item))
|
|
840
|
+
continue;
|
|
841
|
+
const v = unwrap(item);
|
|
842
|
+
const address = `${prefix}/${i}`;
|
|
843
|
+
if (typeOf(v) === TR) {
|
|
844
|
+
const tr = v;
|
|
845
|
+
const row = new TextRow(address);
|
|
846
|
+
const trPr = tr.trPr;
|
|
847
|
+
let rowState = state;
|
|
848
|
+
if (trPr) {
|
|
849
|
+
for (const e of ((_a = trPr.cnfStyleOrDivIdOrGridBefore) !== null && _a !== void 0 ? _a : [])) {
|
|
850
|
+
if (nameOf(e) === 'tblHeader')
|
|
851
|
+
row.header = on(e.value);
|
|
852
|
+
}
|
|
853
|
+
if (this.view === 'markup' && this.mode === 'view') {
|
|
854
|
+
if (trPr.ins)
|
|
855
|
+
rowState = state.withRevision(revisionOf(trPr.ins, 'INSERTION'), false);
|
|
856
|
+
if (trPr.del)
|
|
857
|
+
rowState = state.withRevision(revisionOf(trPr.del, 'DELETION'), false);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
this.cells(tr.content, address, story, row, rowState);
|
|
861
|
+
table.rows.push(row);
|
|
862
|
+
}
|
|
863
|
+
else if (isSdt(v)) {
|
|
864
|
+
this.rows(sdtContentOf(v), address, story, table, state);
|
|
865
|
+
}
|
|
866
|
+
else if (typeOf(v) === AC) {
|
|
867
|
+
// a row-level mc:AlternateContent: its selected branch's rows, addressed from the element (CR-013)
|
|
868
|
+
const ac = v;
|
|
869
|
+
this.compareBranches(ac, address);
|
|
870
|
+
this.rows(selectedBranchOf(ac), address, story, table, state);
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
const inner = blockItems(v);
|
|
874
|
+
if (inner && typeOf(v) !== TC)
|
|
875
|
+
this.rows(inner, address, story, table, state);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
cells(items, prefix, story, row, state) {
|
|
880
|
+
var _a;
|
|
881
|
+
if (!items)
|
|
882
|
+
return;
|
|
883
|
+
for (let i = 0; i < items.length; i++) {
|
|
884
|
+
const item = items[i];
|
|
885
|
+
if (this.removes(item))
|
|
886
|
+
continue;
|
|
887
|
+
const v = unwrap(item);
|
|
888
|
+
const address = `${prefix}/${i}`;
|
|
889
|
+
if (typeOf(v) === TC) {
|
|
890
|
+
const tc = v;
|
|
891
|
+
const cell = new TextCell(address);
|
|
892
|
+
const tcPr = tc.tcPr;
|
|
893
|
+
let cellState = state;
|
|
894
|
+
if (tcPr) {
|
|
895
|
+
const span = (_a = tcPr.gridSpan) === null || _a === void 0 ? void 0 : _a.val;
|
|
896
|
+
if (span !== undefined && span !== null)
|
|
897
|
+
cell.gridSpan = Number(span);
|
|
898
|
+
if (tcPr.vMerge !== undefined) {
|
|
899
|
+
if (tcPr.vMerge.val === 'restart')
|
|
900
|
+
cell.mergeRestart = true;
|
|
901
|
+
else
|
|
902
|
+
cell.mergeContinue = true;
|
|
903
|
+
}
|
|
904
|
+
if (this.view === 'markup' && this.mode === 'view') {
|
|
905
|
+
if (tcPr.cellIns)
|
|
906
|
+
cellState = state.withRevision(revisionOf(tcPr.cellIns, 'INSERTION'), false);
|
|
907
|
+
if (tcPr.cellDel)
|
|
908
|
+
cellState = state.withRevision(revisionOf(tcPr.cellDel, 'DELETION'), false);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
this.blocks(tc.content, address, story, cell.blocks, cellState);
|
|
912
|
+
row.cells.push(cell);
|
|
913
|
+
}
|
|
914
|
+
else if (isSdt(v)) {
|
|
915
|
+
this.cells(sdtContentOf(v), address, story, row, state);
|
|
916
|
+
}
|
|
917
|
+
else if (typeOf(v) === AC) {
|
|
918
|
+
// a cell-level mc:AlternateContent: its selected branch's cells, addressed from the element (CR-013)
|
|
919
|
+
const ac = v;
|
|
920
|
+
this.compareBranches(ac, address);
|
|
921
|
+
this.cells(selectedBranchOf(ac), address, story, row, state);
|
|
922
|
+
}
|
|
923
|
+
else {
|
|
924
|
+
const inner = blockItems(v);
|
|
925
|
+
if (inner)
|
|
926
|
+
this.cells(inner, address, story, row, state);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
// --- run level --------------------------------------------------------------------------------
|
|
931
|
+
runs(items, para, state) {
|
|
932
|
+
if (!items)
|
|
933
|
+
return;
|
|
934
|
+
for (const item of items) {
|
|
935
|
+
if (this.removes(item))
|
|
936
|
+
continue;
|
|
937
|
+
const v = unwrap(item);
|
|
938
|
+
const tn = typeOf(v);
|
|
939
|
+
if (revisionHolder(item) !== undefined) {
|
|
940
|
+
para.block.revisions++;
|
|
941
|
+
this.runs(runItemsOfValue(v), para, this.holderState(item, state));
|
|
942
|
+
}
|
|
943
|
+
else if (tn === R) {
|
|
944
|
+
this.run(v, para, state);
|
|
945
|
+
}
|
|
946
|
+
else if (tn === AC) {
|
|
947
|
+
const ac = v;
|
|
948
|
+
this.compareBranches(ac, para.block.address);
|
|
949
|
+
this.runs(selectedBranchOf(ac), para, state);
|
|
950
|
+
}
|
|
951
|
+
else if (isSdt(v) && this.unwraps(item)) {
|
|
952
|
+
this.runs(sdtContentOf(v), para, state);
|
|
953
|
+
}
|
|
954
|
+
else if (isSdt(v)) {
|
|
955
|
+
const sdt = v;
|
|
956
|
+
const bound = this.bound(sdt, para.block.address);
|
|
957
|
+
if (bound !== undefined) {
|
|
958
|
+
this.text(para, bound, false, state);
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
const placeholder = showingPlaceholder(sdt.sdtPr);
|
|
962
|
+
if (placeholder && !this.options.placeholders)
|
|
963
|
+
continue;
|
|
964
|
+
this.runs(sdtContentOf(v), para, placeholder ? state.withPlaceholder() : state);
|
|
965
|
+
}
|
|
966
|
+
else if (isBookmarkMarker(item)) {
|
|
967
|
+
this.bookmark(item);
|
|
968
|
+
}
|
|
969
|
+
else if (tn === 'org_docx4j_wml.CTSimpleField') {
|
|
970
|
+
this.simpleField(v, para, state);
|
|
971
|
+
}
|
|
972
|
+
else if (isMath(v)) {
|
|
973
|
+
this.math(v, para, state);
|
|
974
|
+
}
|
|
975
|
+
else if (tn === 'org_docx4j_wml.P.Hyperlink') {
|
|
976
|
+
const saved = para.link;
|
|
977
|
+
const target = hyperlinkTarget(v, para.story);
|
|
978
|
+
if (target !== undefined)
|
|
979
|
+
para.link = target;
|
|
980
|
+
try {
|
|
981
|
+
this.runs(v.content, para, state);
|
|
982
|
+
}
|
|
983
|
+
finally {
|
|
984
|
+
para.link = saved;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
const inner = runItemsOfValue(v);
|
|
989
|
+
if (inner)
|
|
990
|
+
this.runs(inner, para, state);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
holderState(item, state) {
|
|
995
|
+
if (this.view === 'markup' && this.mode === 'view') {
|
|
996
|
+
const tc = revisionHolder(item);
|
|
997
|
+
return state.withRevision(revisionOf(tc, isInsertionName(nameOf(item)) ? 'INSERTION' : 'DELETION'), false);
|
|
998
|
+
}
|
|
999
|
+
return state.withRevision(undefined, true);
|
|
1000
|
+
}
|
|
1001
|
+
run(r, para, state) {
|
|
1002
|
+
var _a, _b;
|
|
1003
|
+
if (this.fieldsOnly) {
|
|
1004
|
+
for (const item of ((_a = r.content) !== null && _a !== void 0 ? _a : []))
|
|
1005
|
+
if (FIELD_ITEMS.has(nameOf(item)))
|
|
1006
|
+
this.runItem(item, r, false, para, state);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
const hidden = this.isHiddenRun(r, para.p);
|
|
1010
|
+
const before = textLength(para.block);
|
|
1011
|
+
const saved = para.format;
|
|
1012
|
+
para.format = this.formatOf(r, para.p);
|
|
1013
|
+
try {
|
|
1014
|
+
for (const item of ((_b = r.content) !== null && _b !== void 0 ? _b : []))
|
|
1015
|
+
this.runItem(item, r, hidden, para, state);
|
|
1016
|
+
}
|
|
1017
|
+
finally {
|
|
1018
|
+
para.format = saved;
|
|
1019
|
+
}
|
|
1020
|
+
if (textLength(para.block) > before) {
|
|
1021
|
+
const mono = isMonospace(this.runFont(r, para.p));
|
|
1022
|
+
para.monospace = para.monospace === undefined ? mono : para.monospace && mono;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
runItem(item, r, hidden, para, state) {
|
|
1026
|
+
var _a, _b;
|
|
1027
|
+
const v = unwrap(item);
|
|
1028
|
+
const name = nameOf(item);
|
|
1029
|
+
const source = { run: r, item };
|
|
1030
|
+
switch (name) {
|
|
1031
|
+
case 'fldChar': {
|
|
1032
|
+
const fc = v;
|
|
1033
|
+
const fields = para.story.fields;
|
|
1034
|
+
if (fc.fldCharType === 'begin') {
|
|
1035
|
+
const f = new FieldState();
|
|
1036
|
+
f.locked = fc.fldLock === true;
|
|
1037
|
+
f.codeBlock = para.block;
|
|
1038
|
+
f.codeStart = para.block.runs.length;
|
|
1039
|
+
if (!this.options.toc && this.options.fieldCodes) {
|
|
1040
|
+
f.floorParagraph = para;
|
|
1041
|
+
f.previousFloor = para.mergeFloor;
|
|
1042
|
+
para.mergeFloor = para.block.runs.length;
|
|
1043
|
+
}
|
|
1044
|
+
fields.unshift(f);
|
|
1045
|
+
}
|
|
1046
|
+
else if (fc.fldCharType === 'separate') {
|
|
1047
|
+
const f = fields[0];
|
|
1048
|
+
if (f) {
|
|
1049
|
+
f.separated = true;
|
|
1050
|
+
f.link = fieldHyperlinkTarget(f.instr);
|
|
1051
|
+
if (!this.options.toc && !suppressed(para.story) && isTocField(f.instr)) {
|
|
1052
|
+
f.toc = true;
|
|
1053
|
+
para.toc = true;
|
|
1054
|
+
removeFieldCode(f, para);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
else if (fc.fldCharType === 'end') {
|
|
1059
|
+
const f = fields.shift();
|
|
1060
|
+
if (f) {
|
|
1061
|
+
// a field inside a computed field's cached result is not read, nor recorded
|
|
1062
|
+
if (suppressed(para.story))
|
|
1063
|
+
return;
|
|
1064
|
+
if (f.toc || (!this.options.toc && isTocField(f.instr))) {
|
|
1065
|
+
if (!f.toc)
|
|
1066
|
+
removeFieldCode(f, para);
|
|
1067
|
+
para.toc = true;
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
if (f.computed !== undefined)
|
|
1071
|
+
para.block.fields.push(new TextField(f.instr, f.computed, true));
|
|
1072
|
+
else
|
|
1073
|
+
this.endField(f.instr, f.separated ? f.result : undefined, para);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
case 'instrText':
|
|
1079
|
+
case 'delInstrText': {
|
|
1080
|
+
if (name === 'delInstrText' && !state.kept && state.revision === undefined && this.view === 'accepted')
|
|
1081
|
+
return;
|
|
1082
|
+
const s = v === null || v === void 0 ? void 0 : v.value;
|
|
1083
|
+
if (s === undefined || s === null)
|
|
1084
|
+
return;
|
|
1085
|
+
const f = para.story.fields[0];
|
|
1086
|
+
if (f)
|
|
1087
|
+
f.instr += s;
|
|
1088
|
+
if (this.options.fieldCodes && !suppressed(para.story))
|
|
1089
|
+
this.addText(para, s, 'FIELD_CODE', hidden, state);
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
case 't':
|
|
1093
|
+
this.text(para, v === null || v === void 0 ? void 0 : v.value, hidden, state, source);
|
|
1094
|
+
return;
|
|
1095
|
+
case 'delText': {
|
|
1096
|
+
// the holder decides; outside one, the element: no text after Accept All (REQ-404)
|
|
1097
|
+
if (!state.kept && state.revision === undefined) {
|
|
1098
|
+
if (this.view === 'accepted')
|
|
1099
|
+
return;
|
|
1100
|
+
if (this.view === 'markup' && this.mode === 'view')
|
|
1101
|
+
state = state.withRevision(new TextRevision('DELETION', undefined, undefined), false);
|
|
1102
|
+
}
|
|
1103
|
+
this.text(para, v === null || v === void 0 ? void 0 : v.value, hidden, state, source);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
case 'tab':
|
|
1107
|
+
case 'ptab':
|
|
1108
|
+
this.text(para, '\t', hidden, state, source);
|
|
1109
|
+
return;
|
|
1110
|
+
case 'br':
|
|
1111
|
+
case 'cr':
|
|
1112
|
+
this.text(para, '\n', hidden, state, source);
|
|
1113
|
+
return;
|
|
1114
|
+
case 'noBreakHyphen':
|
|
1115
|
+
this.text(para, '\u2011', hidden, state, source);
|
|
1116
|
+
return;
|
|
1117
|
+
case 'softHyphen':
|
|
1118
|
+
this.text(para, '\u00AD', hidden, state, source);
|
|
1119
|
+
return;
|
|
1120
|
+
case 'sym': {
|
|
1121
|
+
const code = v === null || v === void 0 ? void 0 : v._char;
|
|
1122
|
+
if (typeof code === 'string' && /^[0-9A-Fa-f]{1,6}$/.test(code)) {
|
|
1123
|
+
const cp = parseInt(code, 16);
|
|
1124
|
+
if (cp <= 0x10FFFF && !(cp >= 0xD800 && cp <= 0xDFFF))
|
|
1125
|
+
this.text(para, String.fromCodePoint(cp), hidden, state, source);
|
|
1126
|
+
}
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
case 'footnoteReference':
|
|
1130
|
+
case 'endnoteReference': {
|
|
1131
|
+
// in a computed field's cached result, a copy of a reference: neither written nor numbered
|
|
1132
|
+
if (inCode(para.story) || suppressed(para.story))
|
|
1133
|
+
return;
|
|
1134
|
+
const foot = name === 'footnoteReference';
|
|
1135
|
+
const ref = v;
|
|
1136
|
+
const id = ref.id === undefined || ref.id === null ? '' : String(ref.id);
|
|
1137
|
+
const run = new TextRun('NOTE_REFERENCE', '', state.revision);
|
|
1138
|
+
run.hidden = hidden;
|
|
1139
|
+
run.noteType = foot ? 'footnote' : 'endnote';
|
|
1140
|
+
run.noteId = id;
|
|
1141
|
+
run.source = { run: r, paragraph: para.p };
|
|
1142
|
+
if (!(hidden && !this.options.hidden)) {
|
|
1143
|
+
// a reference carrying a custom mark is given no number (REQ-503); its note is still read
|
|
1144
|
+
run.noteNumber = this.context.noteNumber(run.noteType, id, ref.customMarkFollows === true);
|
|
1145
|
+
}
|
|
1146
|
+
para.block.runs.push(run);
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
case 'footnoteRef':
|
|
1150
|
+
case 'endnoteRef': {
|
|
1151
|
+
if (para.story.noteType === undefined)
|
|
1152
|
+
return;
|
|
1153
|
+
const run = new TextRun('NOTE_MARK', '', state.revision);
|
|
1154
|
+
run.noteType = para.story.noteType;
|
|
1155
|
+
run.noteNumber = para.story.noteNumber;
|
|
1156
|
+
run.noteId = para.story.noteId;
|
|
1157
|
+
para.block.runs.push(run);
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
case 'commentReference': {
|
|
1161
|
+
if (!this.commentsIncluded() || inCode(para.story) || suppressed(para.story))
|
|
1162
|
+
return;
|
|
1163
|
+
const id = v.id;
|
|
1164
|
+
if ((_a = this.plan) === null || _a === void 0 ? void 0 : _a.removesComment(id))
|
|
1165
|
+
return; // gone with the revision it was on
|
|
1166
|
+
const run = new TextRun('COMMENT_REFERENCE', '', state.revision);
|
|
1167
|
+
run.hidden = hidden;
|
|
1168
|
+
run.commentId = id === undefined || id === null ? '' : String(id);
|
|
1169
|
+
run.source = { run: r, paragraph: para.p };
|
|
1170
|
+
para.block.runs.push(run);
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
case 'drawing':
|
|
1174
|
+
case 'pict':
|
|
1175
|
+
case 'object':
|
|
1176
|
+
if (!inCode(para.story) && !suppressed(para.story) && !(hidden && !this.options.hidden))
|
|
1177
|
+
this.anchored(v, para, state);
|
|
1178
|
+
return;
|
|
1179
|
+
case 'lastRenderedPageBreak': {
|
|
1180
|
+
if (para.story.kind !== 'MAIN' || inCode(para.story) || (hidden && !this.options.hidden))
|
|
1181
|
+
return;
|
|
1182
|
+
if (suppressed(para.story))
|
|
1183
|
+
return;
|
|
1184
|
+
const run = new TextRun('PAGE_MARKER', '', state.revision);
|
|
1185
|
+
run.pageNumber = ++this.context.pageMarkers + 1;
|
|
1186
|
+
para.block.runs.push(run);
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
case 'AlternateContent': {
|
|
1190
|
+
const ac = v;
|
|
1191
|
+
this.compareBranches(ac, para.block.address);
|
|
1192
|
+
for (const o of (_b = selectedBranchOf(ac)) !== null && _b !== void 0 ? _b : [])
|
|
1193
|
+
this.runItem(o, r, hidden, para, state);
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
case 'ruby': {
|
|
1197
|
+
const base = v.rubyBase;
|
|
1198
|
+
this.runs(base === null || base === void 0 ? void 0 : base.egRubyContent, para, state);
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
default:
|
|
1202
|
+
// a run within a run (w:r in m:r, a ruby base's) or nothing that is text
|
|
1203
|
+
if (typeOf(v) === R)
|
|
1204
|
+
this.run(v, para, state);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
/** Document text: a field's code where a field is in its code (shown only under `field_codes`), else text. */
|
|
1208
|
+
text(para, s, hidden, state, source) {
|
|
1209
|
+
if (s === undefined || s === null || s === '')
|
|
1210
|
+
return;
|
|
1211
|
+
if (inCode(para.story)) {
|
|
1212
|
+
if (this.options.fieldCodes)
|
|
1213
|
+
this.addText(para, s, 'FIELD_CODE', hidden, state);
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
if (suppressed(para.story))
|
|
1217
|
+
return;
|
|
1218
|
+
if (!(hidden && !this.options.hidden)) {
|
|
1219
|
+
for (const f of para.story.fields)
|
|
1220
|
+
f.result += s;
|
|
1221
|
+
for (const b of this.openBookmarks.values()) {
|
|
1222
|
+
if (b.paragraphEnded && b.text.length > 0)
|
|
1223
|
+
b.text += '\n';
|
|
1224
|
+
b.paragraphEnded = false;
|
|
1225
|
+
b.text += s;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
this.addText(para, s, 'TEXT', hidden, state, source);
|
|
1229
|
+
}
|
|
1230
|
+
addText(para, s, kind, hidden, state, source) {
|
|
1231
|
+
var _a, _b;
|
|
1232
|
+
const run = new TextRun(kind, s, state.revision);
|
|
1233
|
+
run.hidden = hidden;
|
|
1234
|
+
run.placeholder = state.placeholder;
|
|
1235
|
+
if (kind === 'TEXT') {
|
|
1236
|
+
if (para.format)
|
|
1237
|
+
run.copyFormat(para.format);
|
|
1238
|
+
run.link = linkOf(para);
|
|
1239
|
+
run.math = para.math;
|
|
1240
|
+
run.displayMath = para.displayMath;
|
|
1241
|
+
if (source) {
|
|
1242
|
+
run.source = { run: source.run, paragraph: para.p };
|
|
1243
|
+
const span = para.officeSpan(source.item);
|
|
1244
|
+
if (span !== undefined && span.length === s.length)
|
|
1245
|
+
run.officeOffset = span.offset;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
const runs = para.block.runs;
|
|
1249
|
+
if (runs.length > para.mergeFloor && !run.math) {
|
|
1250
|
+
const last = runs[runs.length - 1];
|
|
1251
|
+
// one run as long as its text and Paragraph.text's agree character for character (CR-012 section 4.4)
|
|
1252
|
+
const contiguous = last.officeOffset === undefined ? run.officeOffset === undefined
|
|
1253
|
+
: run.officeOffset === last.officeOffset + last.text.length && ((_a = last.source) === null || _a === void 0 ? void 0 : _a.paragraph) === ((_b = run.source) === null || _b === void 0 ? void 0 : _b.paragraph);
|
|
1254
|
+
if (last.kind === kind && last.hidden === hidden && last.placeholder === state.placeholder
|
|
1255
|
+
&& sameRevision(last.revision, state.revision) && last.sameFormat(run) && contiguous) {
|
|
1256
|
+
const merged = new TextRun(kind, last.text + s, last.revision);
|
|
1257
|
+
merged.hidden = hidden;
|
|
1258
|
+
merged.placeholder = last.placeholder;
|
|
1259
|
+
merged.copyFormat(last);
|
|
1260
|
+
merged.officeOffset = last.officeOffset;
|
|
1261
|
+
merged.source = last.source;
|
|
1262
|
+
runs[runs.length - 1] = merged;
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
runs.push(run);
|
|
1267
|
+
}
|
|
1268
|
+
endField(instr, result, para) {
|
|
1269
|
+
para.block.fields.push(new TextField(instr, result));
|
|
1270
|
+
if (result === undefined)
|
|
1271
|
+
this.warn(new TextWarning(TextWarning.FIELD_NO_RESULT, para.block.address));
|
|
1272
|
+
}
|
|
1273
|
+
simpleField(field, para, state) {
|
|
1274
|
+
var _a;
|
|
1275
|
+
if (suppressed(para.story))
|
|
1276
|
+
return; // inside a computed field's cached result
|
|
1277
|
+
const instr = (_a = field.instr) !== null && _a !== void 0 ? _a : '';
|
|
1278
|
+
if (!this.options.toc && isTocField(instr)) {
|
|
1279
|
+
para.toc = true; // a table of contents left out (D12)
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
if (this.options.fieldCodes && !inCode(para.story))
|
|
1283
|
+
this.addText(para, instr, 'FIELD_CODE', false, state);
|
|
1284
|
+
const before = para.block.runs.length;
|
|
1285
|
+
const text = this.resultOf(field.content, para, state, fieldHyperlinkTarget(instr));
|
|
1286
|
+
const hasResult = text !== '' || para.block.runs.length > before;
|
|
1287
|
+
para.block.fields.push(new TextField(instr, hasResult ? text : undefined));
|
|
1288
|
+
if (!hasResult)
|
|
1289
|
+
this.warn(new TextWarning(TextWarning.FIELD_NO_RESULT, para.block.address));
|
|
1290
|
+
}
|
|
1291
|
+
/** The runs of a simple field's result, added to the paragraph; their text. */
|
|
1292
|
+
resultOf(content, para, state, link) {
|
|
1293
|
+
const capture = new FieldState();
|
|
1294
|
+
capture.separated = true;
|
|
1295
|
+
capture.link = link;
|
|
1296
|
+
para.story.fields.push(capture);
|
|
1297
|
+
try {
|
|
1298
|
+
this.runs(content, para, state);
|
|
1299
|
+
}
|
|
1300
|
+
finally {
|
|
1301
|
+
const fields = para.story.fields;
|
|
1302
|
+
const at = fields.lastIndexOf(capture);
|
|
1303
|
+
if (at >= 0)
|
|
1304
|
+
fields.splice(at, 1);
|
|
1305
|
+
}
|
|
1306
|
+
return capture.result;
|
|
1307
|
+
}
|
|
1308
|
+
// --- math (REQ-604) ---------------------------------------------------------------------------
|
|
1309
|
+
/**
|
|
1310
|
+
* An equation, `$...$` (`$$...$$` for an `m:oMathPara`). Until CR-012 phase 5b ports a LaTeX converter
|
|
1311
|
+
* it is its `m:t` text in document order inside the delimiters, REQ-604's form for an equation that
|
|
1312
|
+
* can't be converted. In markup, an equation with tracked changes is its Reject All form deleted and
|
|
1313
|
+
* its Accept All form inserted, each as the plan for that view leaves it.
|
|
1314
|
+
*/
|
|
1315
|
+
math(v, para, state) {
|
|
1316
|
+
const display = typeOf(v) === 'org_docx4j_math.CTOMathPara';
|
|
1317
|
+
const savedMath = para.math;
|
|
1318
|
+
const savedDisplay = para.displayMath;
|
|
1319
|
+
para.math = true;
|
|
1320
|
+
para.displayMath = display;
|
|
1321
|
+
try {
|
|
1322
|
+
this.mathText(v, display, para, state);
|
|
1323
|
+
}
|
|
1324
|
+
finally {
|
|
1325
|
+
para.math = savedMath;
|
|
1326
|
+
para.displayMath = savedDisplay;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
mathText(v, display, para, state) {
|
|
1330
|
+
var _a, _b;
|
|
1331
|
+
if (this.view === 'markup' && this.mode === 'view') {
|
|
1332
|
+
const revisions = mathRevisions(v);
|
|
1333
|
+
if (revisions[0] !== undefined || revisions[1] !== undefined) {
|
|
1334
|
+
const original = this.context.plan(false);
|
|
1335
|
+
const accepted = this.context.plan(true);
|
|
1336
|
+
const before = mathRunsText(v, (o) => !original.removes(o));
|
|
1337
|
+
const after = mathRunsText(v, (o) => !accepted.removes(o));
|
|
1338
|
+
if (before !== after) {
|
|
1339
|
+
if (before !== '')
|
|
1340
|
+
this.text(para, delimit(before, display), false, state.withRevision((_a = revisions[0]) !== null && _a !== void 0 ? _a : new TextRevision('DELETION', undefined, undefined), false));
|
|
1341
|
+
if (after !== '')
|
|
1342
|
+
this.text(para, delimit(after, display), false, state.withRevision((_b = revisions[1]) !== null && _b !== void 0 ? _b : new TextRevision('INSERTION', undefined, undefined), false));
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
if (after !== '')
|
|
1346
|
+
this.text(para, delimit(after, display), false, state);
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
const text = mathRunsText(v, (o) => this.keepMathInView(o));
|
|
1351
|
+
if (text !== '')
|
|
1352
|
+
this.text(para, delimit(text, display), false, state);
|
|
1353
|
+
}
|
|
1354
|
+
/** The view's rule for an equation's list members: what the plan removes goes; without a plan, a revision by its type. */
|
|
1355
|
+
keepMathInView(o) {
|
|
1356
|
+
if (this.removes(o))
|
|
1357
|
+
return false;
|
|
1358
|
+
if (this.mode !== 'planless' || this.view === 'markup')
|
|
1359
|
+
return true;
|
|
1360
|
+
const ins = mathRevisionType(o);
|
|
1361
|
+
return ins === undefined || ins === (this.view === 'accepted');
|
|
1362
|
+
}
|
|
1363
|
+
// --- what a run anchors: text boxes (REQ-518), WordArt, pictures (REQ-514), objects (REQ-512) ---
|
|
1364
|
+
/**
|
|
1365
|
+
* What a run's drawing, picture or object holds, in document order, branches selected: text boxes and
|
|
1366
|
+
* WordArt to follow the paragraph; pictures and objects as runs where they are. A chart or SmartArt
|
|
1367
|
+
* contributes nothing until CR-012 phase 5c.
|
|
1368
|
+
*/
|
|
1369
|
+
anchored(v, para, state) {
|
|
1370
|
+
const visitor = {
|
|
1371
|
+
enter: (value) => {
|
|
1372
|
+
var _a, _b;
|
|
1373
|
+
switch (value.TYPE_NAME) {
|
|
1374
|
+
case 'org_docx4j_wml.CTTxbxContent':
|
|
1375
|
+
if (this.options.textBoxes)
|
|
1376
|
+
para.story.pending.push(new Box(value, `${para.address}/textbox:${para.boxes++}`));
|
|
1377
|
+
return false;
|
|
1378
|
+
case AC: {
|
|
1379
|
+
const ac = value;
|
|
1380
|
+
this.compareBranches(ac, para.block.address);
|
|
1381
|
+
for (const o of (_a = selectedBranchOf(ac)) !== null && _a !== void 0 ? _a : [])
|
|
1382
|
+
walk(unwrap(o), 1, visitor);
|
|
1383
|
+
return false;
|
|
1384
|
+
}
|
|
1385
|
+
case 'org_docx4j_wml.CTObject':
|
|
1386
|
+
this.object(value, para, state);
|
|
1387
|
+
return false;
|
|
1388
|
+
case 'org_docx4j_wml.CTControl':
|
|
1389
|
+
objectRun(para, undefined, state);
|
|
1390
|
+
return false;
|
|
1391
|
+
case 'org_docx4j_dml_wordprocessingDrawing.Inline':
|
|
1392
|
+
case 'org_docx4j_dml_wordprocessingDrawing.Anchor':
|
|
1393
|
+
return this.graphic(value, para, state);
|
|
1394
|
+
case 'org_docx4j_dml_picture.Pic': {
|
|
1395
|
+
const pic = value;
|
|
1396
|
+
this.image((_b = pic.nvPicPr) === null || _b === void 0 ? void 0 : _b.cNvPr, blipPart(value, para), false, value, para, state);
|
|
1397
|
+
return false;
|
|
1398
|
+
}
|
|
1399
|
+
case 'org_docx4j_vml.CTShape':
|
|
1400
|
+
return this.vmlShape(value, para, state);
|
|
1401
|
+
default:
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
};
|
|
1406
|
+
walk(v, 0, visitor);
|
|
1407
|
+
}
|
|
1408
|
+
/** A `wp:inline` or `wp:anchor`: a chart, SmartArt, a picture, or a shape to walk into. */
|
|
1409
|
+
graphic(anchor, para, state) {
|
|
1410
|
+
var _a, _b;
|
|
1411
|
+
const graphic = anchor.graphic;
|
|
1412
|
+
const docPr = anchor.docPr;
|
|
1413
|
+
if (!(graphic === null || graphic === void 0 ? void 0 : graphic.graphicData))
|
|
1414
|
+
return false;
|
|
1415
|
+
const uri = (_a = graphic.graphicData.uri) !== null && _a !== void 0 ? _a : '';
|
|
1416
|
+
// a chart (c:chart, cx:chart): CR-012 phase 5c
|
|
1417
|
+
if (uri === 'http://schemas.openxmlformats.org/drawingml/2006/chart' || uri.startsWith('http://schemas.microsoft.com/office/drawing/2014/chartex'))
|
|
1418
|
+
return false;
|
|
1419
|
+
for (const o of (_b = graphic.graphicData.any) !== null && _b !== void 0 ? _b : []) {
|
|
1420
|
+
const v = unwrap(o);
|
|
1421
|
+
const tn = typeOf(v);
|
|
1422
|
+
if (tn === 'org_docx4j_dml_chart.CTRelId' || tn === 'org_docx4j_com_microsoft_schemas_office_drawing_x2014_chartex.CTRelId')
|
|
1423
|
+
return false;
|
|
1424
|
+
if (tn === 'org_docx4j_dml_diagram.CTRelIds')
|
|
1425
|
+
return false; // SmartArt: CR-012 phase 5c
|
|
1426
|
+
if (tn === 'org_docx4j_dml_picture.Pic') {
|
|
1427
|
+
this.image(docPr, blipPart(v, para), false, anchor, para, state);
|
|
1428
|
+
return false;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return true; // a shape, group or canvas: its text boxes and pictures
|
|
1432
|
+
}
|
|
1433
|
+
/** A VML shape: legacy WordArt, a picture, or a shape to walk into for its text box. */
|
|
1434
|
+
vmlShape(shape, para, state) {
|
|
1435
|
+
var _a;
|
|
1436
|
+
let imageData;
|
|
1437
|
+
for (const e of ((_a = shape.pathOrFormulasOrHandles) !== null && _a !== void 0 ? _a : [])) {
|
|
1438
|
+
const v = unwrap(e);
|
|
1439
|
+
const tn = typeOf(v);
|
|
1440
|
+
if (tn === 'org_docx4j_vml.CTTextPath') {
|
|
1441
|
+
const s = v.string;
|
|
1442
|
+
if (s !== undefined && s !== '') {
|
|
1443
|
+
if (this.options.textBoxes)
|
|
1444
|
+
para.story.pending.push(new WordArt(s, `${para.address}/textbox:${para.boxes++}`));
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
else if (tn === 'org_docx4j_vml.CTImageData') {
|
|
1449
|
+
imageData = v;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
if (imageData) {
|
|
1453
|
+
this.imageOf(shape.alt, undefined, undefined, false, true, related(para.story.part, imageData.id), shape, para, state);
|
|
1454
|
+
}
|
|
1455
|
+
return true;
|
|
1456
|
+
}
|
|
1457
|
+
/** A `w:object`: an object run with its ProgID (REQ-512); its package is read under `embedded: true`, phase 5d. */
|
|
1458
|
+
object(object, para, state) {
|
|
1459
|
+
var _a;
|
|
1460
|
+
if (object.control) {
|
|
1461
|
+
objectRun(para, undefined, state);
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
for (const o of ((_a = object.anyAndAny) !== null && _a !== void 0 ? _a : [])) {
|
|
1465
|
+
const v = unwrap(o);
|
|
1466
|
+
const tn = typeOf(v);
|
|
1467
|
+
if (tn === 'org_docx4j_vml_officedrawing.CTOLEObject') {
|
|
1468
|
+
objectRun(para, v.progID, state);
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
if (tn === 'org_docx4j_wml.CTControl') {
|
|
1472
|
+
objectRun(para, undefined, state);
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* A DrawingML picture: its `wp:docPr` (or a nested picture's `pic:cNvPr`). `descr` and `title` are the
|
|
1479
|
+
* schema's default, `''`, where the element doesn't give them, as docx4j's JAXB getters read them (CR-012
|
|
1480
|
+
* section 20).
|
|
1481
|
+
*/
|
|
1482
|
+
image(nv, part, vml, source, para, state) {
|
|
1483
|
+
var _a, _b;
|
|
1484
|
+
this.imageOf(nv ? (_a = nv.descr) !== null && _a !== void 0 ? _a : '' : undefined, nv === null || nv === void 0 ? void 0 : nv.name, nv ? (_b = nv.title) !== null && _b !== void 0 ? _b : '' : undefined, decorative(nv), vml, part, source, para, state);
|
|
1485
|
+
}
|
|
1486
|
+
imageOf(descr, name, title, isDecorative, vml, part, source, para, state) {
|
|
1487
|
+
const image = new TextImage(descr, name, title, isDecorative, vml, part, source);
|
|
1488
|
+
const run = new TextRun('IMAGE', '', state.revision);
|
|
1489
|
+
run.image = image;
|
|
1490
|
+
try {
|
|
1491
|
+
run.description = this.options.imageDescriber(image);
|
|
1492
|
+
}
|
|
1493
|
+
catch {
|
|
1494
|
+
this.warn(new TextWarning(TextWarning.IMAGE_NOT_DESCRIBED, para.block.address, undefined, undefined, part === null || part === void 0 ? void 0 : part.partName.name));
|
|
1495
|
+
}
|
|
1496
|
+
run.placeholder = state.placeholder;
|
|
1497
|
+
para.block.runs.push(run);
|
|
1498
|
+
}
|
|
1499
|
+
// --- markup compatibility: REQ-307 ------------------------------------------------------------
|
|
1500
|
+
/**
|
|
1501
|
+
* `mce.branches_differ` (REQ-307): where the selected branch and another both hold text, and the texts
|
|
1502
|
+
* differ after REQ-1201's normalisation. A branch's text is every `w:t`, `m:t` and `a:t` in it, whatever
|
|
1503
|
+
* the view and hidden or not, as docx4j reads it: a comparison made at load knows no view, and a branch
|
|
1504
|
+
* that differs only in hidden or deleted text is one an agent should hear of (Jason, 2026-10-21, for WD
|
|
1505
|
+
* 0.29; CR-012 section 15.6).
|
|
1506
|
+
*/
|
|
1507
|
+
compareBranches(ac, address) {
|
|
1508
|
+
var _a, _b, _c, _d;
|
|
1509
|
+
if (!this.options.warnings || this.fieldsOnly)
|
|
1510
|
+
return;
|
|
1511
|
+
const selected = selectedBranchOf(ac);
|
|
1512
|
+
if (selected === undefined)
|
|
1513
|
+
return;
|
|
1514
|
+
const mine = branchText(selected);
|
|
1515
|
+
if (mine === '')
|
|
1516
|
+
return;
|
|
1517
|
+
const branches = [...((_a = ac.choice) !== null && _a !== void 0 ? _a : [])];
|
|
1518
|
+
if (ac.fallback)
|
|
1519
|
+
branches.push(ac.fallback);
|
|
1520
|
+
for (const other of branches) {
|
|
1521
|
+
if (((_b = other.any) !== null && _b !== void 0 ? _b : []) === selected)
|
|
1522
|
+
continue;
|
|
1523
|
+
const theirs = branchText((_c = other.any) !== null && _c !== void 0 ? _c : []);
|
|
1524
|
+
if (theirs !== '' && theirs !== mine) {
|
|
1525
|
+
const chosen = ((_d = ac.choice) !== null && _d !== void 0 ? _d : []).find((c) => { var _a; return ((_a = c.any) !== null && _a !== void 0 ? _a : []) === selected; });
|
|
1526
|
+
const branch = chosen ? `mc:Choice Requires="${chosen.requires}"` : 'mc:Fallback';
|
|
1527
|
+
this.warn(new TextWarning(TextWarning.MCE_BRANCHES_DIFFER, address, branch));
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
warn(w) {
|
|
1533
|
+
if (this.warned.has(w.key))
|
|
1534
|
+
return;
|
|
1535
|
+
this.warned.add(w.key);
|
|
1536
|
+
this.warnings.push(w);
|
|
1537
|
+
}
|
|
1538
|
+
// --- headers and footers by section (REQ-502) ---------------------------------------------------
|
|
1539
|
+
sectionsWithHeaders(sections, mainBlocks, headers, footers, out) {
|
|
1540
|
+
var _a, _b;
|
|
1541
|
+
const evenAndOdd = on((_a = this.trees.settings) === null || _a === void 0 ? void 0 : _a.evenAndOddHeaders);
|
|
1542
|
+
const emitted = new Set();
|
|
1543
|
+
const lastHeader = new Map();
|
|
1544
|
+
const lastFooter = new Map();
|
|
1545
|
+
let b = 0;
|
|
1546
|
+
for (let s = 0; s < sections.length; s++) {
|
|
1547
|
+
const sectPr = sections[s];
|
|
1548
|
+
let titlePg = false;
|
|
1549
|
+
if (sectPr) {
|
|
1550
|
+
for (const ref of ((_b = sectPr.egHdrFtrReferences) !== null && _b !== void 0 ? _b : [])) {
|
|
1551
|
+
const v = unwrap(ref);
|
|
1552
|
+
if (v.TYPE_NAME === 'org_docx4j_wml.HeaderReference' && v.type !== undefined && v.id !== undefined)
|
|
1553
|
+
lastHeader.set(v.type, v.id);
|
|
1554
|
+
else if (v.TYPE_NAME === 'org_docx4j_wml.FooterReference' && v.type !== undefined && v.id !== undefined)
|
|
1555
|
+
lastFooter.set(v.type, v.id);
|
|
1556
|
+
}
|
|
1557
|
+
titlePg = on(sectPr.titlePg);
|
|
1558
|
+
}
|
|
1559
|
+
const shown = [];
|
|
1560
|
+
if (titlePg)
|
|
1561
|
+
shown.push('first');
|
|
1562
|
+
shown.push('default');
|
|
1563
|
+
if (evenAndOdd)
|
|
1564
|
+
shown.push('even');
|
|
1565
|
+
if (headers)
|
|
1566
|
+
for (const type of shown)
|
|
1567
|
+
this.headerOrFooter(lastHeader.get(type), 'HEADER', emitted, out);
|
|
1568
|
+
while (b < mainBlocks.length && mainBlocks[b].section <= s)
|
|
1569
|
+
out.push(mainBlocks[b++]);
|
|
1570
|
+
if (s === sections.length - 1)
|
|
1571
|
+
while (b < mainBlocks.length)
|
|
1572
|
+
out.push(mainBlocks[b++]);
|
|
1573
|
+
if (footers)
|
|
1574
|
+
for (const type of shown)
|
|
1575
|
+
this.headerOrFooter(lastFooter.get(type), 'FOOTER', emitted, out);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
headerOrFooter(rId, kind, emitted, out) {
|
|
1579
|
+
if (rId === undefined || emitted.has(rId))
|
|
1580
|
+
return;
|
|
1581
|
+
emitted.add(rId);
|
|
1582
|
+
const main = this.trees.main;
|
|
1583
|
+
const part = main ? related(main.part, rId) : undefined;
|
|
1584
|
+
const content = part ? this.trees.headersAndFooters.get(part) : undefined;
|
|
1585
|
+
if (!content)
|
|
1586
|
+
return;
|
|
1587
|
+
const prefix = `${this.root}${kind === 'HEADER' ? 'header:' : 'footer:'}${rId}`;
|
|
1588
|
+
const story = new Story(this, kind, prefix, part);
|
|
1589
|
+
this.blocks(blockItems(content), prefix, story, out);
|
|
1590
|
+
}
|
|
1591
|
+
/** A header or footer part's content as its own story (`Texts.of(headerPart)`). */
|
|
1592
|
+
headerOrFooterPart(part, kind, rId) {
|
|
1593
|
+
const out = [];
|
|
1594
|
+
const content = this.trees.headersAndFooters.get(part);
|
|
1595
|
+
const prefix = `${this.root}${kind === 'HEADER' ? 'header:' : 'footer:'}${rId}`;
|
|
1596
|
+
if (content)
|
|
1597
|
+
this.blocks(blockItems(content), prefix, new Story(this, kind, prefix, part), out);
|
|
1598
|
+
return new TextResult(out, new Map(), this.warnings, { [TextResult.FIELDS_UPDATE_ON_OPEN]: this.fieldsUpdateOnOpen() }, this.options);
|
|
1599
|
+
}
|
|
1600
|
+
// --- notes (REQ-503) ------------------------------------------------------------------------
|
|
1601
|
+
notes(type, out) {
|
|
1602
|
+
var _a;
|
|
1603
|
+
const holder = type === 'footnote' ? this.trees.footnotes : this.trees.endnotes;
|
|
1604
|
+
const numbers = type === 'footnote' ? this.context.footnotes : this.context.endnotes;
|
|
1605
|
+
if (!holder || numbers.size === 0)
|
|
1606
|
+
return;
|
|
1607
|
+
const notes = ((_a = (type === 'footnote' ? holder.tree.footnote : holder.tree.endnote)) !== null && _a !== void 0 ? _a : []);
|
|
1608
|
+
const byId = new Map();
|
|
1609
|
+
for (const note of notes)
|
|
1610
|
+
if (note.id !== undefined && note.id !== null)
|
|
1611
|
+
byId.set(String(note.id), note);
|
|
1612
|
+
for (const [id, number] of numbers) {
|
|
1613
|
+
const note = byId.get(id);
|
|
1614
|
+
if (!note)
|
|
1615
|
+
continue;
|
|
1616
|
+
if (note.type !== undefined && note.type !== 'normal')
|
|
1617
|
+
continue;
|
|
1618
|
+
const prefix = `${this.root}${type}:${id}`;
|
|
1619
|
+
const story = new Story(this, type === 'footnote' ? 'FOOTNOTE' : 'ENDNOTE', prefix, holder.part);
|
|
1620
|
+
story.noteType = type;
|
|
1621
|
+
story.noteNumber = number;
|
|
1622
|
+
story.noteId = id;
|
|
1623
|
+
const blocks = [];
|
|
1624
|
+
this.blocks(note.content, prefix, story, blocks);
|
|
1625
|
+
if (blocks.length === 0)
|
|
1626
|
+
continue;
|
|
1627
|
+
// the note is prefixed [n]: its own mark, or one added at its start
|
|
1628
|
+
const marked = blocks.some((b) => b.runs.some((r) => r.kind === 'NOTE_MARK'));
|
|
1629
|
+
if (!marked) {
|
|
1630
|
+
const first = blocks.find((b) => b.kind === 'PARAGRAPH');
|
|
1631
|
+
if (first) {
|
|
1632
|
+
const mark = new TextRun('NOTE_MARK', '', undefined);
|
|
1633
|
+
mark.noteType = type;
|
|
1634
|
+
mark.noteNumber = number;
|
|
1635
|
+
mark.noteId = id;
|
|
1636
|
+
first.runs.unshift(mark);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
// every block of the note says whose it is, a table's too
|
|
1640
|
+
for (const b of blocks) {
|
|
1641
|
+
if (b.noteType !== undefined)
|
|
1642
|
+
continue;
|
|
1643
|
+
b.noteType = type;
|
|
1644
|
+
b.noteNumber = number;
|
|
1645
|
+
b.noteId = id;
|
|
1646
|
+
}
|
|
1647
|
+
out.push(...blocks);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
// --- comments (REQ-504) ---------------------------------------------------------------------
|
|
1651
|
+
comments(out) {
|
|
1652
|
+
var _a, _b, _c, _d, _e;
|
|
1653
|
+
const part = this.trees.comments;
|
|
1654
|
+
if (!part)
|
|
1655
|
+
return;
|
|
1656
|
+
const extended = new Map();
|
|
1657
|
+
for (const ex of ((_b = (_a = this.trees.commentsExtended) === null || _a === void 0 ? void 0 : _a.commentEx) !== null && _b !== void 0 ? _b : [])) {
|
|
1658
|
+
if (ex.paraId)
|
|
1659
|
+
extended.set(ex.paraId.toUpperCase(), ex);
|
|
1660
|
+
}
|
|
1661
|
+
const idByParaId = new Map();
|
|
1662
|
+
const anchored = this.trees.anchoredComments();
|
|
1663
|
+
for (const c of ((_c = part.tree.comment) !== null && _c !== void 0 ? _c : [])) {
|
|
1664
|
+
if ((_d = this.plan) === null || _d === void 0 ? void 0 : _d.removesComment(c.id))
|
|
1665
|
+
continue;
|
|
1666
|
+
const id = c.id === undefined || c.id === null ? '' : String(c.id);
|
|
1667
|
+
// a comment with no anchor in the document is none of its text: Word drops it on save (REQ-504)
|
|
1668
|
+
if (!anchored.has(id))
|
|
1669
|
+
continue;
|
|
1670
|
+
const comment = new TextComment(id);
|
|
1671
|
+
comment.author = c.author;
|
|
1672
|
+
comment.initials = c.initials;
|
|
1673
|
+
comment.date = calendarText(c.date);
|
|
1674
|
+
const prefix = `${this.root}comment:${id}`;
|
|
1675
|
+
this.blocks(c.content, prefix, new Story(this, 'COMMENT', prefix, part.part), comment.blocks);
|
|
1676
|
+
const paraId = lastParaId(c.content);
|
|
1677
|
+
if (paraId !== undefined) {
|
|
1678
|
+
idByParaId.set(paraId.toUpperCase(), id);
|
|
1679
|
+
const ex = extended.get(paraId.toUpperCase());
|
|
1680
|
+
if (ex) {
|
|
1681
|
+
comment.resolved = ex.done === true || ex.done === 1 || ex.done === '1' || ex.done === 'true';
|
|
1682
|
+
comment.parentId = ex.paraIdParent;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
out.set(id, comment);
|
|
1686
|
+
}
|
|
1687
|
+
for (const comment of out.values()) {
|
|
1688
|
+
if (comment.parentId === undefined)
|
|
1689
|
+
continue;
|
|
1690
|
+
const parent = idByParaId.get(comment.parentId.toUpperCase());
|
|
1691
|
+
comment.parentId = parent;
|
|
1692
|
+
if (parent !== undefined)
|
|
1693
|
+
(_e = out.get(parent)) === null || _e === void 0 ? void 0 : _e.replies.push(comment);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
// --- the view -------------------------------------------------------------------------------
|
|
1697
|
+
/** Whether the view removes a list member (always false in markup and on a resolved copy). */
|
|
1698
|
+
removes(item) {
|
|
1699
|
+
if (this.plan)
|
|
1700
|
+
return this.plan.removes(item);
|
|
1701
|
+
if (this.mode === 'planless' && this.view !== 'markup') {
|
|
1702
|
+
if (revisionHolder(item) === undefined)
|
|
1703
|
+
return false;
|
|
1704
|
+
return isInsertionName(nameOf(item)) !== (this.view === 'accepted');
|
|
1705
|
+
}
|
|
1706
|
+
return false;
|
|
1707
|
+
}
|
|
1708
|
+
/** Whether the view takes a content control away and leaves its content (an inserted one, rejected). */
|
|
1709
|
+
unwraps(item) {
|
|
1710
|
+
return this.plan !== undefined && this.plan.unwraps(item);
|
|
1711
|
+
}
|
|
1712
|
+
joinsNext(p) {
|
|
1713
|
+
return this.plan !== undefined && this.plan.removesMark(p);
|
|
1714
|
+
}
|
|
1715
|
+
/** The paragraph's properties in the view: its own, or what the plan gives a paragraph whose mark is gone with no paragraph next. */
|
|
1716
|
+
viewPPr(p) {
|
|
1717
|
+
return this.plan ? this.plan.paragraphPropertiesOf(p) : p.pPr;
|
|
1718
|
+
}
|
|
1719
|
+
// --- hidden text (REQ-507) and formatting -----------------------------------------------------
|
|
1720
|
+
isHiddenRun(r, p) {
|
|
1721
|
+
var _a, _b, _c, _d;
|
|
1722
|
+
const own = (_a = r.rPr) === null || _a === void 0 ? void 0 : _a.vanish;
|
|
1723
|
+
if (own !== undefined)
|
|
1724
|
+
return on(own);
|
|
1725
|
+
return on((_d = this.styleRPr((_c = (_b = r.rPr) === null || _b === void 0 ? void 0 : _b.rStyle) === null || _c === void 0 ? void 0 : _c.val, p)) === null || _d === void 0 ? void 0 : _d.vanish);
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* A run's formatting beyond its paragraph style's (CR-046 phase 3): bold, italic, struck through,
|
|
1729
|
+
* monospaced, each as the run's own property gives it, else its styles', where the paragraph style
|
|
1730
|
+
* alone doesn't give it. A run carrying only that.
|
|
1731
|
+
*/
|
|
1732
|
+
formatOf(r, p) {
|
|
1733
|
+
var _a;
|
|
1734
|
+
const own = r.rPr;
|
|
1735
|
+
const styles = this.styleRPr((_a = own === null || own === void 0 ? void 0 : own.rStyle) === null || _a === void 0 ? void 0 : _a.val, p);
|
|
1736
|
+
const paragraph = this.styleRPr(undefined, p);
|
|
1737
|
+
const f = new TextRun('TEXT', '', undefined);
|
|
1738
|
+
f.bold = onOf(own === null || own === void 0 ? void 0 : own.b, styles === null || styles === void 0 ? void 0 : styles.b) && !on(paragraph === null || paragraph === void 0 ? void 0 : paragraph.b);
|
|
1739
|
+
f.italic = onOf(own === null || own === void 0 ? void 0 : own.i, styles === null || styles === void 0 ? void 0 : styles.i) && !on(paragraph === null || paragraph === void 0 ? void 0 : paragraph.i);
|
|
1740
|
+
f.strike = onOf(own === null || own === void 0 ? void 0 : own.strike, styles === null || styles === void 0 ? void 0 : styles.strike) && !on(paragraph === null || paragraph === void 0 ? void 0 : paragraph.strike);
|
|
1741
|
+
f.monospace = isMonospace(this.runFont(r, p)) && !isMonospace(asciiFont(paragraph));
|
|
1742
|
+
return f;
|
|
1743
|
+
}
|
|
1744
|
+
/** The run's font for `monospace`: its own `w:rFonts/@w:ascii`, else its styles'. */
|
|
1745
|
+
runFont(r, p) {
|
|
1746
|
+
var _a, _b, _c;
|
|
1747
|
+
return (_a = asciiFont(r.rPr)) !== null && _a !== void 0 ? _a : asciiFont(this.styleRPr((_c = (_b = r.rPr) === null || _b === void 0 ? void 0 : _b.rStyle) === null || _c === void 0 ? void 0 : _c.val, p));
|
|
1748
|
+
}
|
|
1749
|
+
/** The effective run properties of the paragraph's style and a character style, cached by their ids; undefined without styles. */
|
|
1750
|
+
styleRPr(rStyle, p) {
|
|
1751
|
+
var _a, _b;
|
|
1752
|
+
if (!this.resolver)
|
|
1753
|
+
return undefined;
|
|
1754
|
+
const pStyle = (_b = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val;
|
|
1755
|
+
const key = `${String(pStyle)}|${String(rStyle)}`;
|
|
1756
|
+
if (this.styleRPrCache.has(key))
|
|
1757
|
+
return this.styleRPrCache.get(key);
|
|
1758
|
+
let effective;
|
|
1759
|
+
try {
|
|
1760
|
+
const styleOnly = rStyle === undefined ? undefined : { TYPE_NAME: 'org_docx4j_wml.RPr', rStyle: { TYPE_NAME: 'org_docx4j_wml.RStyle', val: rStyle } };
|
|
1761
|
+
const pPrStyle = pStyle === undefined ? undefined : { TYPE_NAME: 'org_docx4j_wml.PPr', pStyle: { TYPE_NAME: 'org_docx4j_wml.PPrBase.PStyle', val: pStyle } };
|
|
1762
|
+
effective = this.resolver.getEffectiveRPr(styleOnly, pPrStyle);
|
|
1763
|
+
}
|
|
1764
|
+
catch {
|
|
1765
|
+
effective = undefined;
|
|
1766
|
+
}
|
|
1767
|
+
this.styleRPrCache.set(key, effective);
|
|
1768
|
+
return effective;
|
|
1769
|
+
}
|
|
1770
|
+
isHiddenMark(pPr) {
|
|
1771
|
+
var _a, _b;
|
|
1772
|
+
const own = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.rPr) === null || _a === void 0 ? void 0 : _a.vanish;
|
|
1773
|
+
if (own !== undefined)
|
|
1774
|
+
return on(own);
|
|
1775
|
+
if (!this.resolver)
|
|
1776
|
+
return false;
|
|
1777
|
+
try {
|
|
1778
|
+
return on((_b = this.resolver.getEffectiveParagraphMarkRPr(pPr)) === null || _b === void 0 ? void 0 : _b.vanish);
|
|
1779
|
+
}
|
|
1780
|
+
catch {
|
|
1781
|
+
return false;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
// --- the anchored items ---------------------------------------------------------------------------
|
|
1786
|
+
/** A text box: its content, read as a story of its own. */
|
|
1787
|
+
class Box {
|
|
1788
|
+
constructor(content, prefix) {
|
|
1789
|
+
this.content = content;
|
|
1790
|
+
this.prefix = prefix;
|
|
1791
|
+
}
|
|
1792
|
+
emit(x, anchoring, sink) {
|
|
1793
|
+
const inner = new Story(x, 'TEXT_BOX', this.prefix, anchoring.part);
|
|
1794
|
+
inner.noteType = anchoring.noteType;
|
|
1795
|
+
inner.noteNumber = anchoring.noteNumber;
|
|
1796
|
+
inner.noteId = anchoring.noteId;
|
|
1797
|
+
x.blocks(this.content.content, this.prefix, inner, sink);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
/** Legacy VML WordArt: a one-paragraph text box holding its `v:textpath/@string` (REQ-511). */
|
|
1801
|
+
class WordArt {
|
|
1802
|
+
constructor(text, prefix) {
|
|
1803
|
+
this.text = text;
|
|
1804
|
+
this.prefix = prefix;
|
|
1805
|
+
}
|
|
1806
|
+
emit(_x, _anchoring, sink) {
|
|
1807
|
+
sink.push(paragraphBlock('TEXT_BOX', `${this.prefix}/0`, this.text));
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
// --- helpers ----------------------------------------------------------------------------------------
|
|
1811
|
+
/** A paragraph block of one text run (docx4j `Embedded.paragraph`). */
|
|
1812
|
+
function paragraphBlock(story, address, text) {
|
|
1813
|
+
const b = new TextBlock('PARAGRAPH', story, address);
|
|
1814
|
+
if (text !== '')
|
|
1815
|
+
b.runs.push(new TextRun('TEXT', text, undefined));
|
|
1816
|
+
return b;
|
|
1817
|
+
}
|
|
1818
|
+
/** A content control's content list, whatever its level. */
|
|
1819
|
+
function sdtContentOf(v) {
|
|
1820
|
+
const content = v === null || v === void 0 ? void 0 : v.sdtContent;
|
|
1821
|
+
return content === null || content === void 0 ? void 0 : content.content;
|
|
1822
|
+
}
|
|
1823
|
+
function textLength(block) {
|
|
1824
|
+
let n = 0;
|
|
1825
|
+
for (const run of block.runs)
|
|
1826
|
+
if (run.kind === 'TEXT')
|
|
1827
|
+
n += run.text.length;
|
|
1828
|
+
return n;
|
|
1829
|
+
}
|
|
1830
|
+
function sameRevision(a, b) {
|
|
1831
|
+
return a === undefined ? b === undefined : a.equals(b);
|
|
1832
|
+
}
|
|
1833
|
+
/** An on/off property: the run's own where it has one, else its styles'. */
|
|
1834
|
+
function onOf(own, styles) {
|
|
1835
|
+
if (own !== undefined)
|
|
1836
|
+
return on(own);
|
|
1837
|
+
return on(styles);
|
|
1838
|
+
}
|
|
1839
|
+
function twips(value) {
|
|
1840
|
+
if (value === undefined || value === null)
|
|
1841
|
+
return undefined;
|
|
1842
|
+
const n = Number(value);
|
|
1843
|
+
return Number.isFinite(n) ? Math.trunc(n) : undefined;
|
|
1844
|
+
}
|
|
1845
|
+
function markRevisions(p) {
|
|
1846
|
+
var _a;
|
|
1847
|
+
const rPr = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.rPr;
|
|
1848
|
+
if (!rPr)
|
|
1849
|
+
return 0;
|
|
1850
|
+
return (rPr.ins ? 1 : 0) + (rPr.del ? 1 : 0) + (rPr.moveFrom ? 1 : 0) + (rPr.moveTo ? 1 : 0);
|
|
1851
|
+
}
|
|
1852
|
+
function listLabel(result) {
|
|
1853
|
+
var _a, _b;
|
|
1854
|
+
if (!result || result.notNumbered)
|
|
1855
|
+
return undefined;
|
|
1856
|
+
let label = result.numString;
|
|
1857
|
+
if (label === undefined || label === '')
|
|
1858
|
+
label = result.bullet;
|
|
1859
|
+
if (label === undefined)
|
|
1860
|
+
return undefined;
|
|
1861
|
+
const suff = (_b = (_a = result.lvl) === null || _a === void 0 ? void 0 : _a.suff) === null || _b === void 0 ? void 0 : _b.val;
|
|
1862
|
+
const suffix = suff === 'space' ? ' ' : suff === 'nothing' ? '' : '\t';
|
|
1863
|
+
return label + suffix;
|
|
1864
|
+
}
|
|
1865
|
+
function inCode(story) {
|
|
1866
|
+
return story.fields.some((f) => !f.separated);
|
|
1867
|
+
}
|
|
1868
|
+
/** Inside the cached result of a field whose result was computed (REQ-506), or a table of contents left out. */
|
|
1869
|
+
function suppressed(story) {
|
|
1870
|
+
return story.fields.some((f) => f.computed !== undefined || f.toc);
|
|
1871
|
+
}
|
|
1872
|
+
/** Inside a table of contents left out (D12). */
|
|
1873
|
+
function inToc(story) {
|
|
1874
|
+
return story.fields.some((f) => f.toc);
|
|
1875
|
+
}
|
|
1876
|
+
/** A TOC field's instruction: a table of contents, of figures (`\c`), of anything it collects. */
|
|
1877
|
+
export function isTocField(instr) {
|
|
1878
|
+
const tokens = fieldTokens(instr);
|
|
1879
|
+
return tokens.length > 0 && tokens[0].toUpperCase() === 'TOC';
|
|
1880
|
+
}
|
|
1881
|
+
/** A table of contents' code, shown under `field_codes` until it was known to be one, taken out again. */
|
|
1882
|
+
function removeFieldCode(f, para) {
|
|
1883
|
+
// what follows the field may merge with what preceded it, as it would with no field codes
|
|
1884
|
+
if (f.floorParagraph)
|
|
1885
|
+
f.floorParagraph.mergeFloor = f.previousFloor;
|
|
1886
|
+
if (f.codeBlock) {
|
|
1887
|
+
const runs = f.codeBlock.runs;
|
|
1888
|
+
for (let k = runs.length - 1; k >= Math.min(f.codeStart, runs.length); k--)
|
|
1889
|
+
if (runs[k].kind === 'FIELD_CODE')
|
|
1890
|
+
runs.splice(k, 1);
|
|
1891
|
+
}
|
|
1892
|
+
if (para.block !== f.codeBlock) {
|
|
1893
|
+
// a code over more than one paragraph: this one's code too
|
|
1894
|
+
const runs = para.block.runs;
|
|
1895
|
+
for (let k = runs.length - 1; k >= 0; k--)
|
|
1896
|
+
if (runs[k].kind === 'FIELD_CODE')
|
|
1897
|
+
runs.splice(k, 1);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
/** The link text being read is in: the `w:hyperlink`'s, else the innermost HYPERLINK field's whose result it is. */
|
|
1901
|
+
function linkOf(para) {
|
|
1902
|
+
if (para.link !== undefined)
|
|
1903
|
+
return para.link;
|
|
1904
|
+
for (const f of para.story.fields)
|
|
1905
|
+
if (f.separated && f.link !== undefined)
|
|
1906
|
+
return f.link;
|
|
1907
|
+
return undefined;
|
|
1908
|
+
}
|
|
1909
|
+
/** The part a relationship of `host` names. */
|
|
1910
|
+
function related(host, rId) {
|
|
1911
|
+
if (!host || !rId)
|
|
1912
|
+
return undefined;
|
|
1913
|
+
const rels = host.getRelationshipsPart(false);
|
|
1914
|
+
if (!rels)
|
|
1915
|
+
return undefined;
|
|
1916
|
+
try {
|
|
1917
|
+
return rels.getPart(rId);
|
|
1918
|
+
}
|
|
1919
|
+
catch {
|
|
1920
|
+
return undefined;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
/** A `w:hyperlink`'s target: its relationship's target, and `#` and its anchor; else `#` and its anchor. */
|
|
1924
|
+
function hyperlinkTarget(h, story) {
|
|
1925
|
+
var _a;
|
|
1926
|
+
let target;
|
|
1927
|
+
if (h.id && story.part) {
|
|
1928
|
+
const rel = (_a = story.part.getRelationshipsPart(false)) === null || _a === void 0 ? void 0 : _a.getRelationshipById(h.id);
|
|
1929
|
+
if (rel === null || rel === void 0 ? void 0 : rel.target)
|
|
1930
|
+
target = rel.target;
|
|
1931
|
+
}
|
|
1932
|
+
const anchor = h.anchor === undefined || h.anchor === '' ? undefined : h.anchor;
|
|
1933
|
+
if (anchor !== undefined)
|
|
1934
|
+
return target === undefined ? `#${anchor}` : `${target}#${anchor}`;
|
|
1935
|
+
return target;
|
|
1936
|
+
}
|
|
1937
|
+
/**
|
|
1938
|
+
* A HYPERLINK field's target from its instruction (WD REQ-703): its address, and `#` and the bookmark its
|
|
1939
|
+
* `\l` names; undefined for any other field, or one with neither.
|
|
1940
|
+
*/
|
|
1941
|
+
export function fieldHyperlinkTarget(instr) {
|
|
1942
|
+
const tokens = fieldTokens(instr);
|
|
1943
|
+
if (tokens.length === 0 || tokens[0].toUpperCase() !== 'HYPERLINK')
|
|
1944
|
+
return undefined;
|
|
1945
|
+
let address;
|
|
1946
|
+
let bookmark;
|
|
1947
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
1948
|
+
const t = tokens[i];
|
|
1949
|
+
if (t.length === 2 && t[0] === '\\') {
|
|
1950
|
+
const sw = t[1].toLowerCase();
|
|
1951
|
+
// \l, \o, \t take an argument; \m and \n don't
|
|
1952
|
+
if ((sw === 'l' || sw === 'o' || sw === 't') && i + 1 < tokens.length) {
|
|
1953
|
+
const arg = tokens[++i];
|
|
1954
|
+
if (sw === 'l')
|
|
1955
|
+
bookmark = arg;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
else if (address === undefined) {
|
|
1959
|
+
address = t;
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
if (address === '')
|
|
1963
|
+
address = undefined;
|
|
1964
|
+
if (bookmark === '')
|
|
1965
|
+
bookmark = undefined;
|
|
1966
|
+
if (bookmark !== undefined)
|
|
1967
|
+
return address === undefined ? `#${bookmark}` : `${address}#${bookmark}`;
|
|
1968
|
+
return address;
|
|
1969
|
+
}
|
|
1970
|
+
const isJavaWhitespace = (c) => /[\t\n\x0B\f\r\x1C-\x1F \u1680\u2000-\u2006\u2008-\u200A\u2028\u2029\u205F\u3000]/.test(c);
|
|
1971
|
+
/** A field instruction's words: a quoted argument is one, its quotes removed and `\\` and `\"` unescaped. */
|
|
1972
|
+
function fieldTokens(instr) {
|
|
1973
|
+
const tokens = [];
|
|
1974
|
+
if (!instr)
|
|
1975
|
+
return tokens;
|
|
1976
|
+
let i = 0;
|
|
1977
|
+
const n = instr.length;
|
|
1978
|
+
while (i < n) {
|
|
1979
|
+
const c = instr[i];
|
|
1980
|
+
if (isJavaWhitespace(c)) {
|
|
1981
|
+
i++;
|
|
1982
|
+
}
|
|
1983
|
+
else if (c === '"') {
|
|
1984
|
+
let out = '';
|
|
1985
|
+
i++;
|
|
1986
|
+
while (i < n && instr[i] !== '"') {
|
|
1987
|
+
let d = instr[i];
|
|
1988
|
+
if (d === '\\' && i + 1 < n && (instr[i + 1] === '\\' || instr[i + 1] === '"'))
|
|
1989
|
+
d = instr[++i];
|
|
1990
|
+
out += d;
|
|
1991
|
+
i++;
|
|
1992
|
+
}
|
|
1993
|
+
i++; // the closing quote
|
|
1994
|
+
tokens.push(out);
|
|
1995
|
+
}
|
|
1996
|
+
else {
|
|
1997
|
+
let j = i;
|
|
1998
|
+
while (j < n && !isJavaWhitespace(instr[j]) && instr[j] !== '"')
|
|
1999
|
+
j++;
|
|
2000
|
+
tokens.push(instr.slice(i, j));
|
|
2001
|
+
i = j;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
return tokens;
|
|
2005
|
+
}
|
|
2006
|
+
function objectRun(para, progId, state) {
|
|
2007
|
+
const run = new TextRun('OBJECT', '', state.revision);
|
|
2008
|
+
run.progId = progId;
|
|
2009
|
+
para.block.runs.push(run);
|
|
2010
|
+
}
|
|
2011
|
+
/** `adec:decorative val="1"` among the properties' extensions. */
|
|
2012
|
+
function decorative(nv) {
|
|
2013
|
+
var _a, _b, _c, _d;
|
|
2014
|
+
for (const ext of (_b = (_a = nv === null || nv === void 0 ? void 0 : nv.extLst) === null || _a === void 0 ? void 0 : _a.ext) !== null && _b !== void 0 ? _b : []) {
|
|
2015
|
+
if (((_c = ext.uri) !== null && _c !== void 0 ? _c : '').toUpperCase() !== DECORATIVE_EXT)
|
|
2016
|
+
continue;
|
|
2017
|
+
const any = ext.any;
|
|
2018
|
+
let val;
|
|
2019
|
+
if (typeof any === 'object' && any !== null && typeof any.getAttribute === 'function') {
|
|
2020
|
+
val = any.getAttribute('val');
|
|
2021
|
+
}
|
|
2022
|
+
else {
|
|
2023
|
+
val = (_d = unwrap(any)) === null || _d === void 0 ? void 0 : _d.val;
|
|
2024
|
+
}
|
|
2025
|
+
if (val === true || val === 1 || val === '1' || String(val).toLowerCase() === 'true')
|
|
2026
|
+
return true;
|
|
2027
|
+
}
|
|
2028
|
+
return false;
|
|
2029
|
+
}
|
|
2030
|
+
function blipPart(pic, para) {
|
|
2031
|
+
var _a, _b;
|
|
2032
|
+
const blip = (_a = pic.blipFill) === null || _a === void 0 ? void 0 : _a.blip;
|
|
2033
|
+
if (!blip)
|
|
2034
|
+
return undefined;
|
|
2035
|
+
// an SVG picture with no PNG copy: its svgBlip's (REQ-514, docx4j #699)
|
|
2036
|
+
return (_b = related(para.story.part, blip.embed)) !== null && _b !== void 0 ? _b : related(para.story.part, svgBlipEmbed(blip));
|
|
2037
|
+
}
|
|
2038
|
+
/** An `a:blip`'s `asvg:svgBlip/@r:embed`. */
|
|
2039
|
+
function svgBlipEmbed(blip) {
|
|
2040
|
+
var _a, _b, _c;
|
|
2041
|
+
for (const ext of (_b = (_a = blip.extLst) === null || _a === void 0 ? void 0 : _a.ext) !== null && _b !== void 0 ? _b : []) {
|
|
2042
|
+
if (((_c = ext.uri) !== null && _c !== void 0 ? _c : '').toUpperCase() !== SVG_BLIP_EXTENSION)
|
|
2043
|
+
continue;
|
|
2044
|
+
const any = ext.any;
|
|
2045
|
+
if (typeof any === 'object' && any !== null && typeof any.getAttributeNS === 'function') {
|
|
2046
|
+
const id = any.getAttributeNS(R_NS, 'embed');
|
|
2047
|
+
if (id)
|
|
2048
|
+
return id;
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
const v = unwrap(any);
|
|
2052
|
+
if (v === null || v === void 0 ? void 0 : v.embed)
|
|
2053
|
+
return v.embed;
|
|
2054
|
+
}
|
|
2055
|
+
return undefined;
|
|
2056
|
+
}
|
|
2057
|
+
/** A branch's text (`w:t`, `m:t`, `a:t`), normalised as REQ-1201 normalises. docx4j `normalized`. */
|
|
2058
|
+
function branchText(branch) {
|
|
2059
|
+
let out = '';
|
|
2060
|
+
const visitor = {
|
|
2061
|
+
item: (item) => {
|
|
2062
|
+
var _a, _b, _c;
|
|
2063
|
+
const v = unwrap(item);
|
|
2064
|
+
const tn = typeOf(v);
|
|
2065
|
+
if (tn === 'org_docx4j_wml.Text' && nameOf(item) === 't')
|
|
2066
|
+
out += String((_a = v.value) !== null && _a !== void 0 ? _a : '');
|
|
2067
|
+
else if (tn === 'org_docx4j_math.CTText')
|
|
2068
|
+
out += String((_b = v.value) !== null && _b !== void 0 ? _b : '');
|
|
2069
|
+
else if (tn === 'org_docx4j_dml.CTRegularTextRun')
|
|
2070
|
+
out += String((_c = v.t) !== null && _c !== void 0 ? _c : '');
|
|
2071
|
+
return true;
|
|
2072
|
+
},
|
|
2073
|
+
};
|
|
2074
|
+
// each member as an item first: a run-level element's branch holds bare w:t
|
|
2075
|
+
for (const o of branch)
|
|
2076
|
+
if (visitor.item(o) !== false)
|
|
2077
|
+
walk(unwrap(o), 0, visitor);
|
|
2078
|
+
return normalize(out);
|
|
2079
|
+
}
|
|
2080
|
+
/** The last paragraph's `w14:paraId` in a comment's content (a branch's too). */
|
|
2081
|
+
function lastParaId(content) {
|
|
2082
|
+
let id;
|
|
2083
|
+
for (const o of content !== null && content !== void 0 ? content : []) {
|
|
2084
|
+
const v = unwrap(o);
|
|
2085
|
+
if (typeOf(v) === P && v.paraId)
|
|
2086
|
+
id = v.paraId;
|
|
2087
|
+
else if (typeOf(v) === AC) {
|
|
2088
|
+
const inner = lastParaId(selectedBranchOf(v));
|
|
2089
|
+
if (inner !== undefined)
|
|
2090
|
+
id = inner;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
return id;
|
|
2094
|
+
}
|
|
2095
|
+
function delimit(text, display) {
|
|
2096
|
+
return display ? `$$${text}$$` : `$${text}$`;
|
|
2097
|
+
}
|
|
2098
|
+
/** For a `w:ins` or `w:del` in an equation's run, whether it is an insertion; else undefined. */
|
|
2099
|
+
function mathRevisionType(o) {
|
|
2100
|
+
if (typeOf(unwrap(o)) === 'org_docx4j_wml.CTMathRunTrackChange')
|
|
2101
|
+
return nameOf(o) === 'ins';
|
|
2102
|
+
return undefined;
|
|
2103
|
+
}
|
|
2104
|
+
/** The first deletion's and the first insertion's revision in an equation. */
|
|
2105
|
+
function mathRevisions(v) {
|
|
2106
|
+
const out = [undefined, undefined];
|
|
2107
|
+
walk(v, 0, {
|
|
2108
|
+
item: (item) => {
|
|
2109
|
+
var _a;
|
|
2110
|
+
const ins = mathRevisionType(item);
|
|
2111
|
+
if (ins !== undefined) {
|
|
2112
|
+
const tc = unwrap(item);
|
|
2113
|
+
const i = ins ? 1 : 0;
|
|
2114
|
+
(_a = out[i]) !== null && _a !== void 0 ? _a : (out[i] = revisionOf(tc, ins ? 'INSERTION' : 'DELETION'));
|
|
2115
|
+
}
|
|
2116
|
+
return true;
|
|
2117
|
+
},
|
|
2118
|
+
});
|
|
2119
|
+
return out;
|
|
2120
|
+
}
|
|
2121
|
+
/** An equation's runs' text (`m:t`, `w:t`), what `keep` refuses left out: REQ-604's text for an equation not converted. */
|
|
2122
|
+
function mathRunsText(v, keep) {
|
|
2123
|
+
let out = '';
|
|
2124
|
+
const item = (o) => {
|
|
2125
|
+
var _a, _b;
|
|
2126
|
+
const ov = unwrap(o);
|
|
2127
|
+
const tn = typeOf(ov);
|
|
2128
|
+
if (tn === 'org_docx4j_math.CTText')
|
|
2129
|
+
out += String((_a = ov.value) !== null && _a !== void 0 ? _a : '');
|
|
2130
|
+
else if (tn === 'org_docx4j_wml.Text' && nameOf(o) === 't')
|
|
2131
|
+
out += String((_b = ov.value) !== null && _b !== void 0 ? _b : '');
|
|
2132
|
+
};
|
|
2133
|
+
const visit = (value, depth) => {
|
|
2134
|
+
var _a, _b;
|
|
2135
|
+
if (value === undefined || value === null || depth > 64)
|
|
2136
|
+
return;
|
|
2137
|
+
const tn = typeOf(value);
|
|
2138
|
+
if (tn === 'org_docx4j_math.CTR') {
|
|
2139
|
+
for (const o of ((_a = value.content) !== null && _a !== void 0 ? _a : [])) {
|
|
2140
|
+
if (!keep(o))
|
|
2141
|
+
continue;
|
|
2142
|
+
const ov = unwrap(o);
|
|
2143
|
+
if (typeOf(ov) === 'org_docx4j_wml.CTMathRunTrackChange') {
|
|
2144
|
+
for (const inner of ((_b = ov.rest) !== null && _b !== void 0 ? _b : []))
|
|
2145
|
+
item(inner);
|
|
2146
|
+
continue;
|
|
2147
|
+
}
|
|
2148
|
+
item(o);
|
|
2149
|
+
}
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
if (tn === 'org_docx4j_math.CTCtrlPr')
|
|
2153
|
+
return;
|
|
2154
|
+
for (const child of children(value)) {
|
|
2155
|
+
if (!keep(child))
|
|
2156
|
+
continue;
|
|
2157
|
+
visit(unwrap(child), depth + 1);
|
|
2158
|
+
}
|
|
2159
|
+
};
|
|
2160
|
+
visit(v, 0);
|
|
2161
|
+
return out;
|
|
2162
|
+
}
|