@docx4j/core-ts 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/model/content/Body.mjs +6 -17
- package/dist/model/content/Comment.d.mts +2 -2
- package/dist/model/content/Comment.mjs +12 -7
- package/dist/model/content/ContentControl.d.mts +1 -1
- package/dist/model/content/ContentControl.mjs +8 -4
- package/dist/model/content/Font.d.mts +4 -1
- package/dist/model/content/Font.mjs +6 -2
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +15 -8
- package/dist/model/content/Paragraph.d.mts +12 -2
- package/dist/model/content/Paragraph.mjs +31 -11
- package/dist/model/content/Table.mjs +26 -16
- package/dist/model/content/TrackedChange.d.mts +2 -2
- package/dist/model/content/TrackedChange.mjs +6 -3
- package/dist/model/content/index.d.mts +3 -1
- package/dist/model/content/index.mjs +4 -1
- package/dist/model/content/ooxml.mjs +12 -1
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/search.d.mts +2 -0
- package/dist/model/content/search.mjs +51 -7
- package/dist/model/content/story.d.mts +5 -2
- package/dist/model/content/story.mjs +6 -3
- package/dist/model/content/tableRules.mjs +2 -0
- package/dist/model/content/tracking.d.mts +35 -6
- package/dist/model/content/tracking.mjs +93 -12
- package/dist/model/content/tree.d.mts +7 -8
- package/dist/model/content/tree.mjs +7 -9
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +22 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +48 -2
- package/dist/model/customxml/XmlMapping.d.mts +31 -7
- package/dist/model/customxml/XmlMapping.mjs +53 -10
- package/dist/model/customxml/bindings.d.mts +12 -2
- package/dist/model/customxml/bindings.mjs +98 -16
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/pictures.mjs +5 -3
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +15 -20
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +1 -0
- package/dist/model/index.mjs +1 -0
- package/dist/model/properties/PropertyResolver.d.mts +14 -1
- package/dist/model/properties/PropertyResolver.mjs +18 -3
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.mjs +2 -2
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +66 -6
- package/dist/model/text/Extractor.mjs +300 -56
- package/dist/model/text/PlainText.mjs +7 -4
- package/dist/model/text/TextContext.d.mts +103 -8
- package/dist/model/text/TextContext.mjs +228 -53
- package/dist/model/text/TextOptions.d.mts +88 -5
- package/dist/model/text/TextOptions.mjs +158 -17
- package/dist/model/text/TextResult.d.mts +126 -9
- package/dist/model/text/TextResult.mjs +115 -12
- package/dist/model/text/WmlToMarkdown.mjs +32 -7
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -0
- package/dist/model/text/index.d.mts +3 -2
- package/dist/model/text/index.mjs +1 -0
- package/dist/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- package/dist/office-js/toApiScript.mjs +8 -7
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +17 -2
- package/dist/opc/Save.mjs +100 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +7 -4
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +121 -10
- package/dist/opc/mce/preprocessor.mjs +122 -21
- package/dist/opc/mce/understood.d.mts +3 -35
- package/dist/opc/mce/understood.mjs +27 -53
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +98 -5
- package/dist/packages/OpcPackage.mjs +122 -7
- package/dist/packages/WordprocessingMLPackage.mjs +3 -1
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/Part.d.mts +5 -1
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +54 -5
- package/dist/parts/XmlPart.mjs +203 -10
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +25 -1
- package/package.json +2 -2
|
@@ -9,8 +9,9 @@ import { Docx4JException } from '../opc/exceptions.mjs';
|
|
|
9
9
|
import { Namespaces } from '../parts/Namespaces.mjs';
|
|
10
10
|
import { Parts } from '../parts/Parts.mjs';
|
|
11
11
|
import { XmlPart } from '../parts/XmlPart.mjs';
|
|
12
|
-
import { RelationshipsPart } from '../parts/RelationshipsPart.mjs';
|
|
12
|
+
import { RelationshipsPart, isExternal } from '../parts/RelationshipsPart.mjs';
|
|
13
13
|
import { DocPropsCorePart, DocPropsExtendedPart } from '../parts/docProps/index.mjs';
|
|
14
|
+
import { assertTimeZone, runtimeTimeZone } from '../model/dateZone.mjs';
|
|
14
15
|
import { mceKeep, mcePreprocess } from '../opc/mce/preprocessor.mjs';
|
|
15
16
|
import { createPackageForContentType, registerGenericPackageClass } from './registry.mjs';
|
|
16
17
|
/**
|
|
@@ -18,6 +19,27 @@ import { createPackageForContentType, registerGenericPackageClass } from './regi
|
|
|
18
19
|
* the content types, the package relationships and the parts reachable from them.
|
|
19
20
|
*/
|
|
20
21
|
export class OpcPackage {
|
|
22
|
+
/**
|
|
23
|
+
* The client's time zone for this package, an IANA id (`Australia/Sydney`), or undefined for the runtime's (CR-018; the
|
|
24
|
+
* portfolio's date rule of 2026-10-28, docx4j's `OpcPackage.setDateTimeZone`). Every instant the package holds is shown
|
|
25
|
+
* in it, and a `w:date` without `dateUtc` read in it: a new revision's or comment's stamp (Word's local wall-clock
|
|
26
|
+
* `w:date`), `TrackedChange.date` and `Comment.creationDate`, and date fields when they are evaluated (CR-012 phase 5).
|
|
27
|
+
* It is the client's for this package, not the document's, and reaches no saved file as such: a server reusing a
|
|
28
|
+
* loaded package sets it per request. Under Office JS the runtime's zone is already the client's. A bound date has no
|
|
29
|
+
* zone (CR-002 section 56) unless `boundDatesConvertedAsWord` asks for Word's conversion in this one. A zone the
|
|
30
|
+
* runtime does not know is refused with a `RangeError` at the set.
|
|
31
|
+
*/
|
|
32
|
+
get dateTimeZone() {
|
|
33
|
+
return this.dateTimeZone_;
|
|
34
|
+
}
|
|
35
|
+
set dateTimeZone(id) {
|
|
36
|
+
this.dateTimeZone_ = id === undefined ? undefined : assertTimeZone(id);
|
|
37
|
+
}
|
|
38
|
+
/** The zone in force: `dateTimeZone`, else the runtime's. */
|
|
39
|
+
effectiveDateTimeZone() {
|
|
40
|
+
var _a;
|
|
41
|
+
return (_a = this.dateTimeZone_) !== null && _a !== void 0 ? _a : runtimeTimeZone();
|
|
42
|
+
}
|
|
21
43
|
constructor() {
|
|
22
44
|
/** The pseudo part name of the package itself: the source of the package relationships. */
|
|
23
45
|
this.partName = PartName.ROOT;
|
|
@@ -26,7 +48,46 @@ export class OpcPackage {
|
|
|
26
48
|
/** Custom XML parts by the (lower-cased) itemID of their properties part. */
|
|
27
49
|
this.customXmlDataStorageParts = new Map();
|
|
28
50
|
/** The options this package was loaded with. */
|
|
51
|
+
/**
|
|
52
|
+
* The names the container held more than one entry of, each read from its first entry under
|
|
53
|
+
* `LoadOptions.repair: 'word'` (WD REQ-206, CR-024); empty for a package loaded without one, or made here.
|
|
54
|
+
*/
|
|
55
|
+
this.duplicateEntries = [];
|
|
29
56
|
this.loadOptions = {};
|
|
57
|
+
/**
|
|
58
|
+
* Whether a save refuses a part holding a child its container never admits (CR-016 D2, docx4j CR-064's rules in the
|
|
59
|
+
* objects facade, its CR-017): a run straight in the body, a table in a paragraph, a cell beside a table's rows, a
|
|
60
|
+
* string in a run, a name and value that disagree. On by default: the save throws `MisplacedContentException` with
|
|
61
|
+
* every such child in the part, its path and docx4j's message naming the fix, and writes nothing, since Word 365
|
|
62
|
+
* refuses such a file or repairs it by dropping content (check 72). Off, the part is written as held and each is on
|
|
63
|
+
* `lastSave.misplaced`. Only a part being marshalled is checked (one unmarshalled, or given contents); a part copied
|
|
64
|
+
* from the source is never refused, so a document read and saved untouched never is. `checkContent()` is the same
|
|
65
|
+
* check on request. A misplaced child read from a file is a `target.misplaced` warning on its part (D7).
|
|
66
|
+
*/
|
|
67
|
+
this.checkContentOnSave = true;
|
|
68
|
+
/**
|
|
69
|
+
* Whether a save refuses to lose what a read dropped (CR-025 sections 2.3 and 2.4, D8): a part holding `part.skipped` content
|
|
70
|
+
* that was changed throws `SaveLossException` and nothing is written. Off, the part is written without those items, each on
|
|
71
|
+
* `lastSave.lost`. A part read and not changed is copied either way, so nothing is lost there. Word's own save drops such
|
|
72
|
+
* content with no message (check 76), so off is Word's behaviour.
|
|
73
|
+
*/
|
|
74
|
+
this.checkLossOnSave = true;
|
|
75
|
+
/**
|
|
76
|
+
* Show bound dates as Word displays them in the package's zone (CR-018, the date rule's point 3; docx4j's
|
|
77
|
+
* `setBoundDatesConvertedAsWord`): off by default, a bound date being the day its fields say wherever it is read
|
|
78
|
+
* (CR-002 section 56). On, a bound value carrying a `Z` or an offset is read as an instant and shown in
|
|
79
|
+
* `effectiveDateTimeZone()`, as Word reads the `Z` as UTC and shows the machine's local time (a day early west of
|
|
80
|
+
* UTC); a value with no marker, or a date alone, stays nominal. Setting `dateTimeZone` does not turn this on.
|
|
81
|
+
*/
|
|
82
|
+
this.boundDatesConvertedAsWord = false;
|
|
83
|
+
/**
|
|
84
|
+
* Write the save's time into the core properties (CR-018, the date rule's point 6; docx4j's `docx4j.dcterms.write`):
|
|
85
|
+
* off by default, a save leaving `dcterms:created` and `dcterms:modified` as they are. On, each save sets
|
|
86
|
+
* `dcterms:modified` to now, UTC to the second (`2026-10-28T03:04:05Z`, the W3CDTF form Office writes), and
|
|
87
|
+
* `dcterms:created` too for a package created here that has none; a loaded package with no core properties part is
|
|
88
|
+
* left without one, as docx4j leaves it.
|
|
89
|
+
*/
|
|
90
|
+
this.writeTimesOnSave = false;
|
|
30
91
|
this.relationshipsPart = RelationshipsPart.createPackageRels();
|
|
31
92
|
this.relationshipsPart.sourceP = this;
|
|
32
93
|
this.relationshipsPart.package = this;
|
|
@@ -73,22 +134,71 @@ export class OpcPackage {
|
|
|
73
134
|
default: return false;
|
|
74
135
|
}
|
|
75
136
|
}
|
|
76
|
-
/** The main part: the target of the officeDocument relationship. */
|
|
137
|
+
/** The main part: the target of the officeDocument relationship, an External one naming none. */
|
|
77
138
|
getMainPart() {
|
|
78
|
-
|
|
79
|
-
const rel =
|
|
80
|
-
return rel ?
|
|
139
|
+
const rels = this.relationshipsPart;
|
|
140
|
+
const rel = [...rels.getRelationshipsByType(Namespaces.DOCUMENT), ...rels.getRelationshipsByType(Namespaces.DOCUMENT_STRICT)].find((r) => !isExternal(r));
|
|
141
|
+
return rel ? rels.getPart(rel) : undefined;
|
|
81
142
|
}
|
|
82
143
|
/**
|
|
83
|
-
* The warnings of every part parsed so far (each XML part's `warnings`, CR-010 phase 1)
|
|
144
|
+
* The warnings of every part parsed so far (each XML part's `warnings`, CR-010 phase 1), after the
|
|
145
|
+
* load's own: a name the container holds twice, and more than one officeDocument relationship, read under
|
|
146
|
+
* `repair: 'word'` (CR-024), and an `External` main relationship dropped under `repair: 'all'` (CR-031). A part
|
|
84
147
|
* is parsed when something reads it, so a reader that wants a whole package's warnings reads its
|
|
85
148
|
* parts first; `unmarshalAll()` does, at the cost of re-marshalling every part on save.
|
|
86
149
|
*/
|
|
87
150
|
get warnings() {
|
|
88
|
-
const out = [];
|
|
151
|
+
const out = [...this.duplicateEntries];
|
|
152
|
+
if (this.multipleMainParts)
|
|
153
|
+
out.push(this.multipleMainParts);
|
|
154
|
+
if (this.externalMainPart)
|
|
155
|
+
out.push(this.externalMainPart);
|
|
89
156
|
for (const part of this.parts)
|
|
90
157
|
if (part instanceof XmlPart)
|
|
91
158
|
out.push(...part.warnings);
|
|
159
|
+
// a relationships part's own, what its read dropped: a child of another local name, an attribute the model doesn't map
|
|
160
|
+
// (CR-025 section 8, D12); after the parts', and outside the save's gate, since none names a part
|
|
161
|
+
for (const rels of [this.relationshipsPart, ...[...this.parts].map((p) => p.relationshipsPart)])
|
|
162
|
+
if (rels)
|
|
163
|
+
out.push(...rels.warnings);
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Each relationships part a load under `repair: 'word'` read by local name, being in a wrong namespace (CR-031 section
|
|
168
|
+
* 2.3): the package's and its parts', in that order.
|
|
169
|
+
*/
|
|
170
|
+
get relationshipsNamespaces() {
|
|
171
|
+
var _a;
|
|
172
|
+
const out = [];
|
|
173
|
+
for (const rels of [this.relationshipsPart, ...[...this.parts].map((p) => p.relationshipsPart)]) {
|
|
174
|
+
for (const w of (_a = rels === null || rels === void 0 ? void 0 : rels.warnings) !== null && _a !== void 0 ? _a : [])
|
|
175
|
+
if (w.code === 'package.relationships_namespace')
|
|
176
|
+
out.push(w);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* What the load repaired (WD REQ-207's `repaired`, CR-031 section 2.4), read from what it recorded, so it reports what the
|
|
182
|
+
* load did whatever the option: `'own'` for a repair of this package's own (an `External` main relationship dropped),
|
|
183
|
+
* `'word'` where only Word's were followed (a duplicated entry, several main relationships, a relationships part read by
|
|
184
|
+
* local name), else `'none'`.
|
|
185
|
+
*/
|
|
186
|
+
get repaired() {
|
|
187
|
+
if (this.externalMainPart)
|
|
188
|
+
return 'own';
|
|
189
|
+
return this.duplicateEntries.length > 0 || this.multipleMainParts || this.relationshipsNamespaces.length > 0 ? 'word' : 'none';
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Every child a part holds that its container never admits (CR-016 D6, the check on request): what a save would
|
|
193
|
+
* refuse for, over every typed XML part, each finding with its part, its path, the rule and docx4j's message naming
|
|
194
|
+
* the fix. Nothing is changed, and an untouched part stays untouched (read privately). `[]` for a package whose
|
|
195
|
+
* content is all in its place.
|
|
196
|
+
*/
|
|
197
|
+
async checkContent() {
|
|
198
|
+
const out = [];
|
|
199
|
+
for (const part of this.parts)
|
|
200
|
+
if (part instanceof XmlPart)
|
|
201
|
+
out.push(...(await part.checkContent()));
|
|
92
202
|
return out;
|
|
93
203
|
}
|
|
94
204
|
/** Unmarshals every XML part, so that `contents` is available synchronously everywhere. */
|
|
@@ -136,6 +246,11 @@ export class OpcPackage {
|
|
|
136
246
|
throw new Docx4JException(`Cloning ${this.constructor.name} produced ${copy.constructor.name}`);
|
|
137
247
|
}
|
|
138
248
|
copy.normaliseOnSave = this.normaliseOnSave;
|
|
249
|
+
copy.checkContentOnSave = this.checkContentOnSave;
|
|
250
|
+
copy.checkLossOnSave = this.checkLossOnSave;
|
|
251
|
+
copy.dateTimeZone = this.dateTimeZone;
|
|
252
|
+
copy.boundDatesConvertedAsWord = this.boundDatesConvertedAsWord;
|
|
253
|
+
copy.writeTimesOnSave = this.writeTimesOnSave;
|
|
139
254
|
this.copyPackageSettingsTo(copy);
|
|
140
255
|
return copy;
|
|
141
256
|
}
|
|
@@ -171,7 +171,8 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
171
171
|
if (landscape)
|
|
172
172
|
pgSz.orient = 'landscape';
|
|
173
173
|
const pgMar = { top: 1440, right: 1440, bottom: 1440, left: 1440, header: 708, footer: 708, gutter: 0 };
|
|
174
|
-
|
|
174
|
+
// typed, as a loaded document is, so the objects facade's walks (its onMisplaced, CR-016) see the body as a container
|
|
175
|
+
const document = { TYPE_NAME: 'org_docx4j_wml.Document', body: { TYPE_NAME: 'org_docx4j_wml.Body', content: [], sectPr: { TYPE_NAME: 'org_docx4j_wml.SectPr', pgSz, pgMar } } };
|
|
175
176
|
const main = new MainDocumentPart();
|
|
176
177
|
main.setContents(document);
|
|
177
178
|
pkg.addTargetPart(main);
|
|
@@ -785,6 +786,7 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
785
786
|
},
|
|
786
787
|
customXmlRelationshipSource: () => this.getMainDocumentPart(),
|
|
787
788
|
xhtmlHost: this,
|
|
789
|
+
getPropertyResolver: () => this.getPropertyResolver(),
|
|
788
790
|
})));
|
|
789
791
|
}
|
|
790
792
|
get progId() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { OpcPackage, type PackageSource } from './OpcPackage.mjs';
|
|
1
|
+
export { OpcPackage, type PackageSource, type PackageWarning, type Repaired } from './OpcPackage.mjs';
|
|
2
2
|
export { WordprocessingMLPackage, type PageSizePaper, type CreatePackageOptions } from './WordprocessingMLPackage.mjs';
|
|
3
3
|
export { PresentationMLPackage, createSlideSize, type SlideSizesWellKnown, type CreatePresentationOptions, } from './PresentationMLPackage.mjs';
|
|
4
4
|
export { SpreadsheetMLPackage } from './SpreadsheetMLPackage.mjs';
|
package/dist/parts/Part.d.mts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { Relationship } from '@docx4j/generated-objects-ts/modules/org_docx4j_relationships';
|
|
2
|
-
import type { Normalisation } from '@docx4j/generated-objects-ts';
|
|
2
|
+
import type { Normalisation, OutOfRange, MisplacedChild } from '@docx4j/generated-objects-ts';
|
|
3
3
|
import { PartName } from '../opc/PartName.mjs';
|
|
4
4
|
import type { RelationshipsPart, AddPartBehaviour } from './RelationshipsPart.mjs';
|
|
5
5
|
import type { OpcPackage } from '../packages/OpcPackage.mjs';
|
|
6
6
|
/** What a save asks of a part's bytes (CR-015 D8): to be told of each value the objects facade's normaliser rewrote. */
|
|
7
7
|
export interface PartBytesOptions {
|
|
8
8
|
onNormalised?(normalisation: Normalisation): void;
|
|
9
|
+
/** Called for each integer attribute value written that Word 365 reads differently (CR-017 P3); the value is written as held. */
|
|
10
|
+
onOutOfRange?(report: OutOfRange): void;
|
|
11
|
+
/** Called for each child its container never admits, as the container is written (CR-016 D2); written as held unless the callback throws. */
|
|
12
|
+
onMisplaced?(report: MisplacedChild): void;
|
|
9
13
|
}
|
|
10
14
|
/** Something that owns a relationships part: a part or the package (docx4j Base). */
|
|
11
15
|
export interface RelationshipSource {
|
|
@@ -2,6 +2,7 @@ import type { Relationships, Relationship } from '@docx4j/generated-objects-ts/m
|
|
|
2
2
|
import { XmlPart } from './XmlPart.mjs';
|
|
3
3
|
import { Part, type RelationshipSource } from './Part.mjs';
|
|
4
4
|
import { PartName } from '../opc/PartName.mjs';
|
|
5
|
+
import type { PartWarning } from '../opc/mce/preprocessor.mjs';
|
|
5
6
|
/** What `addPart` does when a part of the same name is already in the package (docx4j AddPartBehaviour). */
|
|
6
7
|
export type AddPartBehaviour = 'OVERWRITE_IF_NAME_EXISTS' | 'REUSE_EXISTING' | 'RENAME_IF_NAME_EXISTS';
|
|
7
8
|
export declare const RELATIONSHIPS_ROOT: {
|
|
@@ -22,6 +23,20 @@ export declare class RelationshipsPart extends XmlPart<Relationships> {
|
|
|
22
23
|
static createPackageRels(): RelationshipsPart;
|
|
23
24
|
/** A part's own, empty, relationships part. */
|
|
24
25
|
static createRelationshipsPartForPart(source: RelationshipSource): RelationshipsPart;
|
|
26
|
+
/**
|
|
27
|
+
* Set by the load under `LoadOptions.repair` `'word'` or `'all'` (CR-031 section 2.3): a part in a wrong namespace is read
|
|
28
|
+
* as Word's repair reads it, not refused.
|
|
29
|
+
*/
|
|
30
|
+
readsByLocalName: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Refuses a part in another namespace, or in none, on its root or on any `Relationship` (CR-025 section 8, D10), before the
|
|
33
|
+
* runtime drops what it can't bind. Under `readsByLocalName` (`repair: 'word'`, CR-031 section 2.3) the root and every
|
|
34
|
+
* `Relationship` are read by their local names instead, as Word's repair reads them, so the runtime binds them all and a
|
|
35
|
+
* save writes the right namespace, with one `package.relationships_namespace` warning. A root or a child with another
|
|
36
|
+
* local name is left to the runtime, as before: Word is unmeasured on both, and a child is then a `part.skipped` on this
|
|
37
|
+
* part, which `pkg.warnings` gathers (D12).
|
|
38
|
+
*/
|
|
39
|
+
protected readRoot(doc: Document): readonly PartWarning[];
|
|
25
40
|
/** The name of the part these relationships belong to; '/' for the package. */
|
|
26
41
|
get sourceName(): PartName;
|
|
27
42
|
get isPackageRelationshipPart(): boolean;
|
|
@@ -3,7 +3,7 @@ import { setRelationshipsPartFactory } from './Part.mjs';
|
|
|
3
3
|
import { PartName } from '../opc/PartName.mjs';
|
|
4
4
|
import { ContentTypes } from '../opc/ContentTypes.mjs';
|
|
5
5
|
import { Namespaces } from './Namespaces.mjs';
|
|
6
|
-
import { InvalidFormatException } from '../opc/exceptions.mjs';
|
|
6
|
+
import { InvalidFormatException, RelationshipsNamespaceException } from '../opc/exceptions.mjs';
|
|
7
7
|
export const RELATIONSHIPS_ROOT = { namespaceURI: Namespaces.RELATIONSHIPS, localPart: 'Relationships' };
|
|
8
8
|
const RELATIONSHIP_TYPE_NAME = 'org_docx4j_relationships.Relationship';
|
|
9
9
|
/**
|
|
@@ -15,6 +15,11 @@ export class RelationshipsPart extends XmlPart {
|
|
|
15
15
|
constructor(source, partName) {
|
|
16
16
|
super(partName !== null && partName !== void 0 ? partName : (source ? PartName.relsFor(source.partName) : '/_rels/.rels'), ContentTypes.RELATIONSHIPS_PART, '', RELATIONSHIPS_ROOT);
|
|
17
17
|
this.nextId = 1;
|
|
18
|
+
/**
|
|
19
|
+
* Set by the load under `LoadOptions.repair` `'word'` or `'all'` (CR-031 section 2.3): a part in a wrong namespace is read
|
|
20
|
+
* as Word's repair reads it, not refused.
|
|
21
|
+
*/
|
|
22
|
+
this.readsByLocalName = false;
|
|
18
23
|
this.sourceP = source;
|
|
19
24
|
if (source)
|
|
20
25
|
this.package = source.package;
|
|
@@ -31,6 +36,48 @@ export class RelationshipsPart extends XmlPart {
|
|
|
31
36
|
rp.setContents({ relationship: [] });
|
|
32
37
|
return rp;
|
|
33
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Refuses a part in another namespace, or in none, on its root or on any `Relationship` (CR-025 section 8, D10), before the
|
|
41
|
+
* runtime drops what it can't bind. Under `readsByLocalName` (`repair: 'word'`, CR-031 section 2.3) the root and every
|
|
42
|
+
* `Relationship` are read by their local names instead, as Word's repair reads them, so the runtime binds them all and a
|
|
43
|
+
* save writes the right namespace, with one `package.relationships_namespace` warning. A root or a child with another
|
|
44
|
+
* local name is left to the runtime, as before: Word is unmeasured on both, and a child is then a `part.skipped` on this
|
|
45
|
+
* part, which `pkg.warnings` gathers (D12).
|
|
46
|
+
*/
|
|
47
|
+
readRoot(doc) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const root = doc.documentElement;
|
|
50
|
+
if (!root || root.localName !== 'Relationships')
|
|
51
|
+
return [];
|
|
52
|
+
const isRelationship = (c) => c.nodeType === 1 && c.localName === 'Relationship';
|
|
53
|
+
let wrong = root.namespaceURI !== Namespaces.RELATIONSHIPS ? (_a = root.namespaceURI) !== null && _a !== void 0 ? _a : null : undefined;
|
|
54
|
+
for (let c = root.firstChild; c && wrong === undefined; c = c.nextSibling) {
|
|
55
|
+
if (isRelationship(c) && c.namespaceURI !== Namespaces.RELATIONSHIPS)
|
|
56
|
+
wrong = (_b = c.namespaceURI) !== null && _b !== void 0 ? _b : null;
|
|
57
|
+
}
|
|
58
|
+
if (wrong === undefined)
|
|
59
|
+
return [];
|
|
60
|
+
if (!this.readsByLocalName)
|
|
61
|
+
throw new RelationshipsNamespaceException(this.partName.name, wrong);
|
|
62
|
+
const fixed = inRelationshipsNamespace(doc, root);
|
|
63
|
+
let count = 0;
|
|
64
|
+
while (root.firstChild) {
|
|
65
|
+
const c = root.firstChild;
|
|
66
|
+
root.removeChild(c);
|
|
67
|
+
if (isRelationship(c))
|
|
68
|
+
count++;
|
|
69
|
+
fixed.appendChild(isRelationship(c) && c.namespaceURI !== Namespaces.RELATIONSHIPS ? inRelationshipsNamespace(doc, c) : c);
|
|
70
|
+
}
|
|
71
|
+
doc.replaceChild(fixed, root);
|
|
72
|
+
return [{
|
|
73
|
+
code: 'package.relationships_namespace',
|
|
74
|
+
partName: this.partName.name,
|
|
75
|
+
namespace: wrong,
|
|
76
|
+
count,
|
|
77
|
+
message: `${this.partName.name}: a relationships part in ${wrong === null ? 'no namespace' : `another namespace, ${wrong}`}, `
|
|
78
|
+
+ `read as Word's repair reads it, its ${count} relationship${count === 1 ? '' : 's'} by local name (REQ-207)`,
|
|
79
|
+
}];
|
|
80
|
+
}
|
|
34
81
|
/** The name of the part these relationships belong to; '/' for the package. */
|
|
35
82
|
get sourceName() {
|
|
36
83
|
var _a, _b;
|
|
@@ -218,6 +265,24 @@ export class RelationshipsPart extends XmlPart {
|
|
|
218
265
|
}
|
|
219
266
|
}
|
|
220
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* `el` again, in the relationships namespace under its local name, with its attributes but not its namespace declarations,
|
|
270
|
+
* and with what it holds moved across (CR-031 section 2.3).
|
|
271
|
+
*/
|
|
272
|
+
function inRelationshipsNamespace(doc, el) {
|
|
273
|
+
var _a;
|
|
274
|
+
const out = doc.createElementNS(Namespaces.RELATIONSHIPS, (_a = el.localName) !== null && _a !== void 0 ? _a : el.nodeName);
|
|
275
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
276
|
+
const a = el.attributes.item(i);
|
|
277
|
+
if (a.name === 'xmlns' || a.name.startsWith('xmlns:'))
|
|
278
|
+
continue;
|
|
279
|
+
out.setAttributeNS(a.namespaceURI, a.name, a.value);
|
|
280
|
+
}
|
|
281
|
+
if (el.localName === 'Relationship')
|
|
282
|
+
while (el.firstChild)
|
|
283
|
+
out.appendChild(el.firstChild);
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
221
286
|
export function isExternal(rel) {
|
|
222
287
|
return rel.targetMode === 'External';
|
|
223
288
|
}
|
package/dist/parts/XmlPart.d.mts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import { type Jsonix } from '@docx4j/generated-objects-ts';
|
|
1
|
+
import { type Jsonix, type OutOfRange, type MisplacedChild } from '@docx4j/generated-objects-ts';
|
|
2
2
|
import { Part, type PartBytesOptions } from './Part.mjs';
|
|
3
3
|
import { PartName } from '../opc/PartName.mjs';
|
|
4
4
|
import { type Bound } from '../model/content/binder.mjs';
|
|
5
|
-
import type { PartWarning } from '../opc/mce/preprocessor.mjs';
|
|
5
|
+
import type { PartWarning, ValueOutOfRangeWarning, MisplacedContentWarning } from '../opc/mce/preprocessor.mjs';
|
|
6
|
+
import { type ContentSkippedWarning } from '../opc/skipped.mjs';
|
|
7
|
+
/**
|
|
8
|
+
* An integer attribute value Word 365 reads differently, as the objects facade reports it on read or on save, as a
|
|
9
|
+
* warning (CR-017 P2 and P3). The value stays as written; the message says what Word would read, the storage and the
|
|
10
|
+
* range Word keeps as written, from the table entry the report names (`storage`, `property` and `rule`, objects 0.7.0).
|
|
11
|
+
*/
|
|
12
|
+
export declare function valueOutOfRange(report: OutOfRange, partName: string | undefined): ValueOutOfRangeWarning;
|
|
6
13
|
/** What `selectObjects` needs: the engine to evaluate with, and any prefixes beyond the defaults. */
|
|
7
14
|
export interface SelectOptions {
|
|
8
15
|
/** The engine; `pkg.selectObjects` and `Body.select` pass the package's. It is readied on the snapshot. */
|
|
@@ -13,6 +20,13 @@ export interface SelectOptions {
|
|
|
13
20
|
/** Prefixes added to (or overriding) the objects package's own table. */
|
|
14
21
|
namespaces?: Record<string, string> | undefined;
|
|
15
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* A child its container never admits, as the objects facade reports it on read or on save (its CR-017's
|
|
25
|
+
* `onMisplaced`), as a warning (CR-016 D7, D2): docx4j-python's code and fields (`target.misplaced`; `holder` and `item`
|
|
26
|
+
* docx4j's class names), docx4j's message after the part and the place (the path on save; the container, the child's
|
|
27
|
+
* place in its list and the line on read).
|
|
28
|
+
*/
|
|
29
|
+
export declare function misplacedContent(report: MisplacedChild, partName: string | undefined): MisplacedContentWarning;
|
|
16
30
|
/** A qualified name for a part's root element. */
|
|
17
31
|
export interface RootName {
|
|
18
32
|
namespaceURI: string;
|
|
@@ -37,6 +51,8 @@ export declare class XmlPart<T = unknown> extends Part {
|
|
|
37
51
|
/** Runs over the DOM before unmarshalling; the package sets its MCE preprocessor here. */
|
|
38
52
|
preprocessor: DomPreprocessor | undefined;
|
|
39
53
|
private parseWarnings;
|
|
54
|
+
/** The bytes given to `setBytes` that the tree was read from; undefined where it came from the source container. */
|
|
55
|
+
private parsedBytes;
|
|
40
56
|
constructor(partName: PartName | string, contentType: string, relationshipType: string, rootName?: RootName);
|
|
41
57
|
/** True once contents were unmarshalled or set; the part is then re-marshalled on save. */
|
|
42
58
|
get isUnmarshalled(): boolean;
|
|
@@ -49,9 +65,13 @@ export declare class XmlPart<T = unknown> extends Part {
|
|
|
49
65
|
get isUntouched(): boolean;
|
|
50
66
|
/**
|
|
51
67
|
* What the last parse of this part reported: an mc:AlternateContent whose branches' text differs
|
|
52
|
-
* (`mce.branches_differ`, CR-010 phase 1),
|
|
53
|
-
* Word 365 reads it (`value.kept.exact`, `value.kept.invalid`: CR-015 D8
|
|
54
|
-
*
|
|
68
|
+
* (`mce.branches_differ`, CR-010 phase 1), each attribute value its type refuses that was read as
|
|
69
|
+
* Word 365 reads it (`value.kept.exact`, `value.kept.invalid`, `value.truncated`, `value.refused`: CR-015 D8,
|
|
70
|
+
* CR-017 P1), each integer attribute value past what Word stores, kept as written (`value.out_of_range`,
|
|
71
|
+
* CR-017 P2), and each child its container never admits, kept as read but a string the runtime drops
|
|
72
|
+
* (`target.misplaced`, CR-016 D7), and a w:br outside a w:r read as Word reads it (`br.outside_run`, CR-021).
|
|
73
|
+
* Empty until the part is parsed, by `getContents()` or a private read, and again
|
|
74
|
+
* once its contents are set.
|
|
55
75
|
*/
|
|
56
76
|
get warnings(): readonly PartWarning[];
|
|
57
77
|
/** The unmarshalled contents (docx4j getJaxbElement()); throws when not yet unmarshalled. */
|
|
@@ -70,11 +90,40 @@ export declare class XmlPart<T = unknown> extends Part {
|
|
|
70
90
|
* reads the styles and numbering parts of a document nobody has otherwise touched.
|
|
71
91
|
*/
|
|
72
92
|
readContents(): Promise<T>;
|
|
93
|
+
/** `readContents`'s typed element: the live one, else a private tree from the part's bytes. */
|
|
94
|
+
private readElement;
|
|
95
|
+
/**
|
|
96
|
+
* Every child the part holds that its container never admits (CR-016 D6, the check on request): what a save would
|
|
97
|
+
* refuse the part for, each with its path, the rule and docx4j's message naming the fix, found by the objects
|
|
98
|
+
* facade's walk over the tree (a marshal to nothing); the part is not changed, and one never unmarshalled stays
|
|
99
|
+
* untouched, read privately. `[]` for a part whose content is all in its place.
|
|
100
|
+
*/
|
|
101
|
+
checkContent(): Promise<MisplacedContentWarning[]>;
|
|
102
|
+
/**
|
|
103
|
+
* The DOM before unmarshalling: a w:br outside a w:r put in a run, as Word reads it (CR-021: a reading of the file,
|
|
104
|
+
* not an option, so ahead of the package's hook, which sees the repaired DOM), then the hook.
|
|
105
|
+
*/
|
|
73
106
|
private preprocess;
|
|
107
|
+
/**
|
|
108
|
+
* Reads the part's root before anything else meets the DOM; nothing by default. A main document part reads a root other than
|
|
109
|
+
* `w:document` here (WD REQ-318 to REQ-320, CR-028), throwing for one Word refuses.
|
|
110
|
+
*/
|
|
111
|
+
protected readRoot(_doc: Document): readonly PartWarning[];
|
|
112
|
+
private preprocessed;
|
|
74
113
|
/** Replaces the contents (docx4j setJaxbElement / setContents). The root name defaults to the part's. */
|
|
75
114
|
setContents(value: T, rootName?: RootName): void;
|
|
76
115
|
/** Replaces the contents with raw XML bytes; they are unmarshalled on the next getContents(). */
|
|
77
116
|
setBytes(bytes: Uint8Array): void;
|
|
117
|
+
/** What the read of the tree held now dropped (CR-025): nothing for a part not unmarshalled, or given contents. */
|
|
118
|
+
get skippedByRead(): readonly ContentSkippedWarning[];
|
|
119
|
+
/** The bytes the tree held now was read from. */
|
|
120
|
+
bytesRead(): Promise<Uint8Array | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the tree is still what its source reads as (CR-025 section 2.2): the source read again and the two marshalled
|
|
123
|
+
* alike. The save has no change log to ask, so this is for a part that holds skipped content, and only that: such a part,
|
|
124
|
+
* read and not changed, is copied, where a marshal would lose what the read dropped. What can't be compared counts as changed.
|
|
125
|
+
*/
|
|
126
|
+
isUnchangedSinceRead(): Promise<boolean>;
|
|
78
127
|
/** Replaces the contents with XML text (docx4j setContents from a string). */
|
|
79
128
|
setXml(xml: string): void;
|
|
80
129
|
/** The XML as it would be saved (docx4j XmlUtils.marshaltoString on the part). */
|