@docx4j/core-ts 0.4.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 +34 -3
- package/dist/html/convert.mjs +40 -15
- 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 +153 -19
- package/dist/model/content/Body.mjs +570 -131
- package/dist/model/content/Comment.d.mts +21 -3
- package/dist/model/content/Comment.mjs +202 -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 +82 -7
- package/dist/model/content/InlinePicture.mjs +221 -28
- package/dist/model/content/List.mjs +13 -1
- package/dist/model/content/Paragraph.d.mts +213 -14
- package/dist/model/content/Paragraph.mjs +936 -100
- package/dist/model/content/Range.d.mts +242 -11
- package/dist/model/content/Range.mjs +975 -119
- 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 +301 -16
- package/dist/model/content/TrackedChange.mjs +1284 -158
- package/dist/model/content/binder.d.mts +2 -1
- package/dist/model/content/binder.mjs +48 -1
- 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/relationships.d.mts +30 -0
- package/dist/model/content/relationships.mjs +133 -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 +212 -13
- package/dist/model/content/tree.mjs +356 -35
- 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 +9 -5
- package/dist/model/customxml/pictures.mjs +31 -13
- package/dist/model/customxml/xhtml.mjs +8 -2
- package/dist/model/fonts/families.generated.mjs +2 -2
- package/dist/model/fonts/registry.mjs +7 -1
- package/dist/model/fonts/substitutions.generated.mjs +2 -2
- package/dist/model/fonts/themes.generated.mjs +1 -1
- 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/listnumbering/definitions.mjs +18 -0
- package/dist/model/properties/PropertyResolver.d.mts +87 -7
- package/dist/model/properties/PropertyResolver.mjs +197 -17
- package/dist/model/properties/catalogue.d.mts +32 -4
- package/dist/model/properties/catalogue.mjs +115 -36
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/table.d.mts +16 -2
- package/dist/model/properties/table.mjs +17 -5
- 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/Load.d.mts +9 -2
- 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 +2 -2
- package/dist/opc/mce/preprocessor.d.mts +88 -7
- package/dist/opc/mce/preprocessor.mjs +144 -37
- package/dist/opc/mce/understood.d.mts +34 -0
- package/dist/opc/mce/understood.mjs +55 -3
- package/dist/packages/OpcPackage.d.mts +20 -0
- package/dist/packages/OpcPackage.mjs +16 -3
- package/dist/packages/WordprocessingMLPackage.d.mts +77 -7
- package/dist/packages/WordprocessingMLPackage.mjs +242 -11
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +10 -2
- package/dist/parts/XmlPart.d.mts +35 -32
- package/dist/parts/XmlPart.mjs +107 -107
- 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
package/dist/parts/XmlPart.mjs
CHANGED
|
@@ -1,35 +1,43 @@
|
|
|
1
1
|
import { unmarshalNode, marshalNode, NAMESPACE_PREFIXES } from '@docx4j/generated-objects-ts';
|
|
2
2
|
import { Part } from './Part.mjs';
|
|
3
|
-
import { Namespaces } from './Namespaces.mjs';
|
|
4
3
|
import { Docx4JException, PartUnmarshalException } from '../opc/exceptions.mjs';
|
|
5
|
-
import { parseXml, serializeXml, encodeText, decodeXmlText, XML_DECLARATION } from '../xml/dom.mjs';
|
|
6
|
-
import { log } from '../model/properties/log.mjs';
|
|
4
|
+
import { parseXml, serializeXml, encodeText, decodeXmlText, XML_DECLARATION, assertXmlCharacters } from '../xml/dom.mjs';
|
|
7
5
|
import { bindSnapshot, boundsOf } from '../model/content/binder.mjs';
|
|
8
|
-
const XMLNS_NS = 'http://www.w3.org/2000/xmlns/';
|
|
9
|
-
const MC_NS = Namespaces.MARKUP_COMPATIBILITY;
|
|
10
|
-
/** The objects package's prefix table the other way round, prefix to URI, built once. */
|
|
11
|
-
let prefixToUri;
|
|
12
|
-
function knownUriOf(prefix) {
|
|
13
|
-
if (prefixToUri === undefined) {
|
|
14
|
-
prefixToUri = new Map();
|
|
15
|
-
for (const [uri, p] of Object.entries(NAMESPACE_PREFIXES))
|
|
16
|
-
if (p !== '' && !prefixToUri.has(p))
|
|
17
|
-
prefixToUri.set(p, uri);
|
|
18
|
-
}
|
|
19
|
-
return prefixToUri.get(prefix);
|
|
20
|
-
}
|
|
21
|
-
const warnedPrefixes = new Set();
|
|
22
6
|
/**
|
|
23
7
|
* The element or attribute a located runtime error names, out of its message: jsonix writes
|
|
24
8
|
* `w:sz/@w:val (line 7): ...` when it could place the fault and `w:bogus (line 3): ...` for an
|
|
25
9
|
* element, so the location is everything before the position or the colon - and `w:sz` must not be
|
|
26
10
|
* cut at its own prefix separator, which a naive split on `:` does.
|
|
27
11
|
*/
|
|
12
|
+
/** The runtime's located message: `w:sz/@w:val (line 12): reason`, the position optional. */
|
|
13
|
+
const LOCATION_PREFIX = /^(.+?)(?: \(line \d+(?:, column \d+)?\))?: /;
|
|
28
14
|
function locationOf(message, located) {
|
|
29
15
|
var _a;
|
|
30
16
|
if (!located)
|
|
31
17
|
return undefined;
|
|
32
|
-
return (_a =
|
|
18
|
+
return (_a = LOCATION_PREFIX.exec(message)) === null || _a === void 0 ? void 0 : _a[1];
|
|
19
|
+
}
|
|
20
|
+
/** ` (line 12, column 9)`, or as much of it as is known. */
|
|
21
|
+
function positionOf(line, column) {
|
|
22
|
+
if (line === undefined)
|
|
23
|
+
return '';
|
|
24
|
+
return column === undefined ? ` (line ${line})` : ` (line ${line}, column ${column})`;
|
|
25
|
+
}
|
|
26
|
+
/** A value the objects facade read by Word's rule, as a warning on the part (CR-015 D8). */
|
|
27
|
+
function valueKept(reading, partName) {
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
const node = reading.element;
|
|
30
|
+
const name = reading.attribute;
|
|
31
|
+
const attribute = (_c = (_b = (_a = node.getAttributeNodeNS) === null || _a === void 0 ? void 0 : _a.call(node, name.namespaceURI || null, name.localPart)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : name.localPart;
|
|
32
|
+
const value = reading.value;
|
|
33
|
+
const read = value === true ? 'on' : value === undefined ? 'absent' : JSON.stringify(value);
|
|
34
|
+
return {
|
|
35
|
+
code: reading.kind, partName,
|
|
36
|
+
...(typeof node.lineNumber === 'number' ? { line: node.lineNumber } : {}),
|
|
37
|
+
...(typeof node.columnNumber === 'number' ? { column: node.columnNumber } : {}),
|
|
38
|
+
element: node.nodeName, attribute, text: reading.text, value,
|
|
39
|
+
message: `${partName}: ${node.nodeName}/@${attribute}=${JSON.stringify(reading.text)}${positionOf(node.lineNumber, node.columnNumber)} is not a value its type allows; read as ${read}, as Word 365 reads it`,
|
|
40
|
+
};
|
|
33
41
|
}
|
|
34
42
|
/** The objects package's prefix table as XPath wants it, prefix to URI; built once. */
|
|
35
43
|
const NAMESPACE_PREFIXES_BY_PREFIX = (() => {
|
|
@@ -48,6 +56,7 @@ const NAMESPACE_PREFIXES_BY_PREFIX = (() => {
|
|
|
48
56
|
export class XmlPart extends Part {
|
|
49
57
|
constructor(partName, contentType, relationshipType, rootName) {
|
|
50
58
|
super(partName, contentType, relationshipType);
|
|
59
|
+
this.parseWarnings = [];
|
|
51
60
|
this.rootName = rootName;
|
|
52
61
|
}
|
|
53
62
|
/** True once contents were unmarshalled or set; the part is then re-marshalled on save. */
|
|
@@ -65,6 +74,15 @@ export class XmlPart extends Part {
|
|
|
65
74
|
get isUntouched() {
|
|
66
75
|
return this.element === undefined && this.bytes === undefined;
|
|
67
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* What the last parse of this part reported: an mc:AlternateContent whose branches' text differs
|
|
79
|
+
* (`mce.branches_differ`, CR-010 phase 1), and each attribute value its type refuses that was read as
|
|
80
|
+
* Word 365 reads it (`value.kept.exact`, `value.kept.invalid`: CR-015 D8). Empty until the part is
|
|
81
|
+
* parsed, by `getContents()` or a private read, and again once its contents are set.
|
|
82
|
+
*/
|
|
83
|
+
get warnings() {
|
|
84
|
+
return this.parseWarnings;
|
|
85
|
+
}
|
|
68
86
|
/** The unmarshalled contents (docx4j getJaxbElement()); throws when not yet unmarshalled. */
|
|
69
87
|
get contents() {
|
|
70
88
|
if (this.element === undefined)
|
|
@@ -77,16 +95,15 @@ export class XmlPart extends Part {
|
|
|
77
95
|
}
|
|
78
96
|
/** Unmarshals on first call (docx4j getContents()). */
|
|
79
97
|
async getContents() {
|
|
80
|
-
var _a, _b
|
|
98
|
+
var _a, _b;
|
|
81
99
|
if (this.element === undefined) {
|
|
82
100
|
const bytes = (_a = this.bytes) !== null && _a !== void 0 ? _a : (await this.loadSourceBytes());
|
|
83
101
|
if (bytes === undefined)
|
|
84
102
|
throw new Docx4JException(`Part ${this.partName} has no content: set contents or load it from a container`);
|
|
85
|
-
const doc =
|
|
86
|
-
this.
|
|
87
|
-
(_b = this.preprocessor) === null || _b === void 0 ? void 0 : _b.call(this, doc, this);
|
|
103
|
+
const doc = this.parse(bytes);
|
|
104
|
+
this.preprocess(doc);
|
|
88
105
|
this.element = await this.unmarshal(doc);
|
|
89
|
-
(
|
|
106
|
+
(_b = this.rootName) !== null && _b !== void 0 ? _b : (this.rootName = { namespaceURI: this.element.name.namespaceURI, localPart: this.element.name.localPart });
|
|
90
107
|
this.bytes = undefined;
|
|
91
108
|
}
|
|
92
109
|
return this.element.value;
|
|
@@ -101,17 +118,21 @@ export class XmlPart extends Part {
|
|
|
101
118
|
* reads the styles and numbering parts of a document nobody has otherwise touched.
|
|
102
119
|
*/
|
|
103
120
|
async readContents() {
|
|
104
|
-
var _a
|
|
121
|
+
var _a;
|
|
105
122
|
if (this.element !== undefined)
|
|
106
123
|
return this.element.value;
|
|
107
124
|
const bytes = (_a = this.bytes) !== null && _a !== void 0 ? _a : (await this.loadSourceBytes());
|
|
108
125
|
if (bytes === undefined)
|
|
109
126
|
throw new Docx4JException(`Part ${this.partName} has no content: set contents or load it from a container`);
|
|
110
|
-
const doc =
|
|
111
|
-
this.
|
|
112
|
-
(_b = this.preprocessor) === null || _b === void 0 ? void 0 : _b.call(this, doc, this);
|
|
127
|
+
const doc = this.parse(bytes);
|
|
128
|
+
this.preprocess(doc);
|
|
113
129
|
return (await this.unmarshal(doc)).value;
|
|
114
130
|
}
|
|
131
|
+
preprocess(doc) {
|
|
132
|
+
var _a;
|
|
133
|
+
const warnings = (_a = this.preprocessor) === null || _a === void 0 ? void 0 : _a.call(this, doc, this);
|
|
134
|
+
this.parseWarnings = warnings ? [...warnings] : [];
|
|
135
|
+
}
|
|
115
136
|
/** Replaces the contents (docx4j setJaxbElement / setContents). The root name defaults to the part's. */
|
|
116
137
|
setContents(value, rootName) {
|
|
117
138
|
var _a, _b;
|
|
@@ -120,6 +141,7 @@ export class XmlPart extends Part {
|
|
|
120
141
|
throw new Docx4JException(`Part ${this.partName}: no root element name; pass one`);
|
|
121
142
|
this.element = { name: { namespaceURI: name.namespaceURI, localPart: name.localPart }, value };
|
|
122
143
|
this.bytes = undefined;
|
|
144
|
+
this.parseWarnings = [];
|
|
123
145
|
}
|
|
124
146
|
/** Replaces the contents with raw XML bytes; they are unmarshalled on the next getContents(). */
|
|
125
147
|
setBytes(bytes) {
|
|
@@ -135,9 +157,9 @@ export class XmlPart extends Part {
|
|
|
135
157
|
return decodeXmlText(await this.getBytes());
|
|
136
158
|
}
|
|
137
159
|
/** Marshalled bytes when unmarshalled or set, else the source bytes untouched. */
|
|
138
|
-
async getBytes() {
|
|
160
|
+
async getBytes(options) {
|
|
139
161
|
if (this.element !== undefined)
|
|
140
|
-
return encodeText(XML_DECLARATION + serializeXml(await this.marshalToNode()));
|
|
162
|
+
return encodeText(assertXmlCharacters(XML_DECLARATION + serializeXml(await this.marshalToNode(options)), `Part ${this.partName}`));
|
|
141
163
|
if (this.bytes !== undefined)
|
|
142
164
|
return this.bytes;
|
|
143
165
|
const loaded = await this.loadSourceBytes();
|
|
@@ -175,99 +197,77 @@ export class XmlPart extends Part {
|
|
|
175
197
|
const namespaces = { ...NAMESPACE_PREFIXES_BY_PREFIX, ...options.namespaces };
|
|
176
198
|
return boundsOf(engine.select(xpath, snapshot.root, namespaces), snapshot);
|
|
177
199
|
}
|
|
178
|
-
/**
|
|
179
|
-
|
|
200
|
+
/**
|
|
201
|
+
* The root element as a DOM element (docx4j XmlUtils.marshaltoW3CDomDocument). Run properties are written in
|
|
202
|
+
* their normal form unless the package's `normaliseOnSave` (else the objects package's `setNormaliseOnSave`) is
|
|
203
|
+
* false (CR-015 D2, the objects facade's CR-013 phase C): the tree keeps what it read.
|
|
204
|
+
*/
|
|
205
|
+
async marshalToNode(options) {
|
|
206
|
+
var _a;
|
|
180
207
|
if (this.element === undefined)
|
|
181
208
|
await this.getContents();
|
|
182
|
-
const
|
|
183
|
-
this.
|
|
184
|
-
|
|
209
|
+
const marshal = {};
|
|
210
|
+
const normalise = (_a = this.package) === null || _a === void 0 ? void 0 : _a.normaliseOnSave;
|
|
211
|
+
if (normalise !== undefined)
|
|
212
|
+
marshal.normaliseOnSave = normalise;
|
|
213
|
+
if ((options === null || options === void 0 ? void 0 : options.onNormalised) !== undefined)
|
|
214
|
+
marshal.onNormalised = options.onNormalised;
|
|
215
|
+
return marshalNode(this.element, marshal);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Parses the part's bytes, and names the part when the XML is not well-formed. xmldom's error
|
|
219
|
+
* (Node) carries the line and column of the fault; a browser's says them in its text, which
|
|
220
|
+
* `parseXml` passes on.
|
|
221
|
+
*/
|
|
222
|
+
parse(bytes) {
|
|
223
|
+
try {
|
|
224
|
+
return parseXml(decodeXmlText(bytes));
|
|
225
|
+
}
|
|
226
|
+
catch (cause) {
|
|
227
|
+
const at = cause === null || cause === void 0 ? void 0 : cause.locator;
|
|
228
|
+
const line = typeof (at === null || at === void 0 ? void 0 : at.lineNumber) === 'number' ? at.lineNumber : undefined;
|
|
229
|
+
const column = typeof (at === null || at === void 0 ? void 0 : at.columnNumber) === 'number' ? at.columnNumber : undefined;
|
|
230
|
+
const reason = (cause instanceof Error ? cause.message : String(cause)).replace(/^Malformed XML: /, '');
|
|
231
|
+
throw new PartUnmarshalException(`${this.partName}: Malformed XML${positionOf(line, column)}: ${reason}`, this.partName.name, { cause, line, column });
|
|
232
|
+
}
|
|
185
233
|
}
|
|
186
234
|
/**
|
|
187
235
|
* Unmarshals, and names the part when the runtime refuses. The runtime's own message says what is
|
|
188
236
|
* wrong and, since `@docx4j/jsonix` 3.4.0, where - `w:sz/@w:val (line 12): Argument [NaN] must be
|
|
189
237
|
* an integer` - but not which part it was reading, which is the first thing a person editing a
|
|
190
|
-
* part's XML needs (CR-002 section 27)
|
|
191
|
-
*
|
|
192
|
-
*
|
|
238
|
+
* part's XML needs (CR-002 section 27), nor the value it refused. The message names the part, and
|
|
239
|
+
* for an attribute gives the value as written and the column too:
|
|
240
|
+
* `/word/styles.xml: w:sz/@w:val="big" (line 12, column 9): Argument [NaN] must be an integer, ...`.
|
|
241
|
+
* The location it found is lifted onto the exception so a caller does not parse the message; `line`
|
|
242
|
+
* is undefined where the parser supplies no position, which is every browser (only xmldom carries a
|
|
243
|
+
* locator).
|
|
193
244
|
*/
|
|
194
245
|
async unmarshal(doc) {
|
|
195
|
-
var _a, _b;
|
|
246
|
+
var _a, _b, _c, _d, _e, _f;
|
|
247
|
+
const kept = [];
|
|
196
248
|
try {
|
|
197
|
-
|
|
249
|
+
const element = await unmarshalNode(doc, {
|
|
250
|
+
onWordReading: (reading) => kept.push(valueKept(reading, this.partName.name)),
|
|
251
|
+
});
|
|
252
|
+
if (kept.length > 0)
|
|
253
|
+
this.parseWarnings = [...this.parseWarnings, ...kept];
|
|
254
|
+
return element;
|
|
198
255
|
}
|
|
199
256
|
catch (cause) {
|
|
200
257
|
const located = cause;
|
|
201
258
|
const message = typeof (located === null || located === void 0 ? void 0 : located.message) === 'string' ? located.message : String(cause);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
var _a;
|
|
213
|
-
const root = doc.documentElement;
|
|
214
|
-
if (!root)
|
|
215
|
-
return;
|
|
216
|
-
const map = new Map();
|
|
217
|
-
for (const attr of Array.from(root.attributes)) {
|
|
218
|
-
if (attr.name === 'xmlns')
|
|
219
|
-
map.set('', attr.value);
|
|
220
|
-
else if (attr.namespaceURI === XMLNS_NS || attr.name.startsWith('xmlns:'))
|
|
221
|
-
map.set((_a = attr.localName) !== null && _a !== void 0 ? _a : attr.name.slice(6), attr.value);
|
|
222
|
-
}
|
|
223
|
-
this.sourceDeclarations = map;
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Every prefix the marshalled root's `mc:Ignorable` names must be declared on that root
|
|
227
|
-
* (ECMA-376 Part 3 10.1.2; Word and Excel treat an undeclared one as a corrupt part and offer
|
|
228
|
-
* to repair the file). The object model binds only the namespaces it has modules for, so an
|
|
229
|
-
* `mc:Ignorable` prefix whose content was dropped on unmarshal - `xr6`, `xr10` and `xr2` on
|
|
230
|
-
* Excel's `xl/workbook.xml`, for instance - loses its declaration: the runtime declares one
|
|
231
|
-
* prefix per entry of the objects package's table and the facade can only *remove* unused
|
|
232
|
-
* declarations, never add one it never made (CR-001 section 17).
|
|
233
|
-
*
|
|
234
|
-
* So the part re-declares them itself: from what the source root declared, else from the
|
|
235
|
-
* objects package's `NAMESPACE_PREFIXES`. A prefix neither knows is dropped from
|
|
236
|
-
* `mc:Ignorable` - an undeclared prefix is the one thing that must not be written - and warned
|
|
237
|
-
* about once.
|
|
238
|
-
*/
|
|
239
|
-
declareIgnorablePrefixes(root) {
|
|
240
|
-
var _a, _b;
|
|
241
|
-
const attr = Array.from(root.attributes).find((a) => { var _a; return a.namespaceURI === MC_NS && ((_a = a.localName) !== null && _a !== void 0 ? _a : a.name) === 'Ignorable'; });
|
|
242
|
-
if (!attr)
|
|
243
|
-
return;
|
|
244
|
-
const prefixes = attr.value.split(/\s+/).filter((p) => p !== '');
|
|
245
|
-
if (prefixes.length === 0)
|
|
246
|
-
return;
|
|
247
|
-
const kept = [];
|
|
248
|
-
let dropped = false;
|
|
249
|
-
for (const prefix of prefixes) {
|
|
250
|
-
if (root.getAttributeNS(XMLNS_NS, prefix) || root.getAttribute(`xmlns:${prefix}`)) {
|
|
251
|
-
kept.push(prefix);
|
|
252
|
-
continue;
|
|
253
|
-
}
|
|
254
|
-
const uri = (_b = (_a = this.sourceDeclarations) === null || _a === void 0 ? void 0 : _a.get(prefix)) !== null && _b !== void 0 ? _b : knownUriOf(prefix);
|
|
255
|
-
if (uri === undefined) {
|
|
256
|
-
dropped = true;
|
|
257
|
-
if (!warnedPrefixes.has(prefix)) {
|
|
258
|
-
warnedPrefixes.add(prefix);
|
|
259
|
-
log.warn(`${this.partName}: mc:Ignorable names the prefix "${prefix}", which nothing declares; dropping it (an undeclared prefix makes Word and Excel offer to repair the file)`);
|
|
260
|
-
}
|
|
261
|
-
continue;
|
|
259
|
+
const location = locationOf(message, (located === null || located === void 0 ? void 0 : located.jsonixLocated) === true);
|
|
260
|
+
const line = typeof ((_a = located === null || located === void 0 ? void 0 : located.node) === null || _a === void 0 ? void 0 : _a.lineNumber) === 'number' ? located.node.lineNumber : undefined;
|
|
261
|
+
const column = typeof ((_b = located === null || located === void 0 ? void 0 : located.node) === null || _b === void 0 ? void 0 : _b.columnNumber) === 'number' ? located.node.columnNumber : undefined;
|
|
262
|
+
let detail = message;
|
|
263
|
+
if (location !== undefined) {
|
|
264
|
+
const reason = message.slice((_d = (_c = LOCATION_PREFIX.exec(message)) === null || _c === void 0 ? void 0 : _c[0].length) !== null && _d !== void 0 ? _d : 0);
|
|
265
|
+
const name = located === null || located === void 0 ? void 0 : located.attributeName;
|
|
266
|
+
const value = (name === null || name === void 0 ? void 0 : name.localPart) ? (_f = (_e = located === null || located === void 0 ? void 0 : located.node) === null || _e === void 0 ? void 0 : _e.getAttributeNS) === null || _f === void 0 ? void 0 : _f.call(_e, name.namespaceURI || null, name.localPart) : undefined;
|
|
267
|
+
const shown = typeof value === 'string' ? `=${JSON.stringify(value.length > 80 ? `${value.slice(0, 80)}...` : value)}` : '';
|
|
268
|
+
detail = `${location}${shown}${positionOf(line, column)}: ${reason}`;
|
|
262
269
|
}
|
|
263
|
-
|
|
264
|
-
kept.push(prefix);
|
|
270
|
+
throw new PartUnmarshalException(`${this.partName}: ${detail}`, this.partName.name, { cause, location, line, column });
|
|
265
271
|
}
|
|
266
|
-
if (!dropped)
|
|
267
|
-
return;
|
|
268
|
-
if (kept.length === 0)
|
|
269
|
-
root.removeAttributeNode(attr);
|
|
270
|
-
else
|
|
271
|
-
root.setAttributeNS(MC_NS, attr.name, kept.join(' '));
|
|
272
272
|
}
|
|
273
273
|
}
|
|
@@ -47,6 +47,36 @@ class DocumentCommentParts {
|
|
|
47
47
|
this.loadedAll = true;
|
|
48
48
|
return this;
|
|
49
49
|
}
|
|
50
|
+
async loadExisting() {
|
|
51
|
+
var _a, _b, _c;
|
|
52
|
+
const main = this.main;
|
|
53
|
+
if (main.commentsExtendedPart)
|
|
54
|
+
(_a = this.commentsEx) !== null && _a !== void 0 ? _a : (this.commentsEx = await main.commentsExtendedPart.getContents());
|
|
55
|
+
if (main.commentsIdsPart)
|
|
56
|
+
(_b = this.commentsIds) !== null && _b !== void 0 ? _b : (this.commentsIds = await main.commentsIdsPart.getContents());
|
|
57
|
+
(_c = this.extensible) !== null && _c !== void 0 ? _c : (this.extensible = await loadExtensible(main));
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
drop(people) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const main = this.main;
|
|
63
|
+
const parts = [main.commentsPart, main.commentsExtendedPart, main.commentsIdsPart, main.commentsExtensiblePart, people ? main.peoplePart : undefined];
|
|
64
|
+
for (const part of parts) {
|
|
65
|
+
if (!part)
|
|
66
|
+
continue;
|
|
67
|
+
const rels = main.relationshipsPart;
|
|
68
|
+
const rel = rels === null || rels === void 0 ? void 0 : rels.getRel(part.partName);
|
|
69
|
+
if (rel)
|
|
70
|
+
rels.removeRelationship(rel);
|
|
71
|
+
if (part.sourceRelationships.length > 0)
|
|
72
|
+
continue;
|
|
73
|
+
(_a = part.relationshipsPart) === null || _a === void 0 ? void 0 : _a.removeParts();
|
|
74
|
+
(_b = part.package) === null || _b === void 0 ? void 0 : _b.parts.remove(part.partName);
|
|
75
|
+
}
|
|
76
|
+
main.commentsPart = main.commentsExtendedPart = main.commentsIdsPart = main.commentsExtensiblePart = undefined;
|
|
77
|
+
if (people)
|
|
78
|
+
main.peoplePart = undefined;
|
|
79
|
+
}
|
|
50
80
|
}
|
|
51
81
|
/** The document part a body's comments belong to: the body's own part, else the package's main part. */
|
|
52
82
|
function mainPartOf(body) {
|
package/dist/parts/wml/index.mjs
CHANGED
|
@@ -23,6 +23,15 @@ async function ensurePropertyResolver(part) {
|
|
|
23
23
|
const pkg = part.package;
|
|
24
24
|
await ((_a = pkg === null || pkg === void 0 ? void 0 : pkg.getPropertyResolver) === null || _a === void 0 ? void 0 : _a.call(pkg));
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* The glossary's placeholder entries, read privately, which `ContentControl.placeholderText` reads synchronously
|
|
28
|
+
* (CR-002 section 63, D8).
|
|
29
|
+
*/
|
|
30
|
+
async function ensureGlossaryEntries(part) {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
const pkg = part.package;
|
|
33
|
+
await ((_a = pkg === null || pkg === void 0 ? void 0 : pkg.glossaryEntries) === null || _a === void 0 ? void 0 : _a.load((_b = pkg.mainDocumentPart) === null || _b === void 0 ? void 0 : _b.glossaryDocumentPart));
|
|
34
|
+
}
|
|
26
35
|
/** The Body view of a part's block-level container, one per container object. */
|
|
27
36
|
function bodyOf(part, container, prefix) {
|
|
28
37
|
if (!container)
|
|
@@ -124,6 +133,7 @@ export class MainDocumentPart extends DocumentPart {
|
|
|
124
133
|
async getBody() {
|
|
125
134
|
await this.getContents();
|
|
126
135
|
await ensurePropertyResolver(this);
|
|
136
|
+
await ensureGlossaryEntries(this);
|
|
127
137
|
return this.body;
|
|
128
138
|
}
|
|
129
139
|
/**
|
|
@@ -439,6 +449,7 @@ export class HeaderPart extends XmlPart {
|
|
|
439
449
|
async getBody() {
|
|
440
450
|
await this.getContents();
|
|
441
451
|
await ensurePropertyResolver(this);
|
|
452
|
+
await ensureGlossaryEntries(this);
|
|
442
453
|
return this.body;
|
|
443
454
|
}
|
|
444
455
|
}
|
|
@@ -454,6 +465,7 @@ export class FooterPart extends XmlPart {
|
|
|
454
465
|
async getBody() {
|
|
455
466
|
await this.getContents();
|
|
456
467
|
await ensurePropertyResolver(this);
|
|
468
|
+
await ensureGlossaryEntries(this);
|
|
457
469
|
return this.body;
|
|
458
470
|
}
|
|
459
471
|
}
|
package/dist/xml/dom.d.mts
CHANGED
|
@@ -14,6 +14,13 @@ export declare function parseXml(text: string): Document;
|
|
|
14
14
|
/** Serialises a node (document or element) without an XML declaration. */
|
|
15
15
|
export declare function serializeXml(node: Node): string;
|
|
16
16
|
export declare function createDocument(): Document;
|
|
17
|
+
/**
|
|
18
|
+
* The XML, refused where it holds a character XML 1.0 excludes, which no escape can write (CR-002 section 60 D3): the
|
|
19
|
+
* part would not be well-formed, and a conforming parser must refuse it. The content API's writers drop such characters
|
|
20
|
+
* or write them as their elements; this catches what reached the tree some other way (an attribute, a custom XML
|
|
21
|
+
* node's value, a caller's own edit of the tree).
|
|
22
|
+
*/
|
|
23
|
+
export declare function assertXmlCharacters(xml: string, where: string): string;
|
|
17
24
|
/** XML declaration plus the serialised document element, as one string. */
|
|
18
25
|
export declare function serializeXmlPart(node: Node): string;
|
|
19
26
|
/** UTF-8 bytes of a string. */
|
package/dist/xml/dom.mjs
CHANGED
|
@@ -59,6 +59,24 @@ export function serializeXml(node) {
|
|
|
59
59
|
export function createDocument() {
|
|
60
60
|
return DOM.createDocument();
|
|
61
61
|
}
|
|
62
|
+
/** A character XML 1.0 excludes: a C0 control but tab, line feed and carriage return, U+FFFE, U+FFFF, an unpaired surrogate. */
|
|
63
|
+
const NOT_XML = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
64
|
+
/**
|
|
65
|
+
* The XML, refused where it holds a character XML 1.0 excludes, which no escape can write (CR-002 section 60 D3): the
|
|
66
|
+
* part would not be well-formed, and a conforming parser must refuse it. The content API's writers drop such characters
|
|
67
|
+
* or write them as their elements; this catches what reached the tree some other way (an attribute, a custom XML
|
|
68
|
+
* node's value, a caller's own edit of the tree).
|
|
69
|
+
*/
|
|
70
|
+
export function assertXmlCharacters(xml, where) {
|
|
71
|
+
const m = NOT_XML.exec(xml);
|
|
72
|
+
if (m) {
|
|
73
|
+
const code = m[0].charCodeAt(0).toString(16).toUpperCase().padStart(4, '0');
|
|
74
|
+
const before = xml.slice(Math.max(0, m.index - 40), m.index).replace(/[^\x20-\x7e]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
75
|
+
throw new Docx4JException(`${where} holds U+${code}, which XML 1.0 excludes, so it can't be written as well-formed XML `
|
|
76
|
+
+ `(character ${m.index}, after "${before}"); remove it, or write it as the element it stands for (CR-002 section 60)`);
|
|
77
|
+
}
|
|
78
|
+
return xml;
|
|
79
|
+
}
|
|
62
80
|
/** XML declaration plus the serialised document element, as one string. */
|
|
63
81
|
export function serializeXmlPart(node) {
|
|
64
82
|
const el = node.nodeType === 9 ? node.documentElement : node;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docx4j/core-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "docx4j-core for TypeScript: Open Packaging (docx/pptx/xlsx zip and flat OPC), typed parts and relationships, style, numbering and font resolution over @docx4j/generated-objects-ts. Node, browsers, Word add-ins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"license": "Apache-2.0",
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@docx4j/generated-objects-ts": "^0.
|
|
86
|
+
"@docx4j/generated-objects-ts": "^0.5.0",
|
|
87
87
|
"fflate": "^0.8.2"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|