@docx4j/core-ts 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -0
- package/README.md +92 -4
- package/dist/html/convert.mjs +2 -1
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +145 -23
- package/dist/model/content/Body.mjs +507 -150
- package/dist/model/content/Comment.d.mts +23 -5
- package/dist/model/content/Comment.mjs +207 -26
- package/dist/model/content/ContentControl.d.mts +198 -19
- package/dist/model/content/ContentControl.mjs +672 -99
- package/dist/model/content/Font.d.mts +70 -17
- package/dist/model/content/Font.mjs +119 -36
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +18 -8
- package/dist/model/content/Paragraph.d.mts +200 -14
- package/dist/model/content/Paragraph.mjs +898 -82
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +135 -49
- package/dist/model/content/TrackedChange.d.mts +174 -15
- package/dist/model/content/TrackedChange.mjs +734 -170
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +10 -3
- package/dist/model/content/index.mjs +10 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/ooxml.mjs +12 -1
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +74 -0
- package/dist/model/content/search.mjs +255 -9
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +47 -0
- package/dist/model/content/story.mjs +95 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +102 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +63 -6
- package/dist/model/content/tracking.mjs +242 -22
- package/dist/model/content/tree.d.mts +172 -24
- package/dist/model/content/tree.mjs +328 -54
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
- package/dist/model/customxml/XmlMapping.d.mts +32 -8
- package/dist/model/customxml/XmlMapping.mjs +64 -10
- package/dist/model/customxml/bindings.d.mts +33 -4
- package/dist/model/customxml/bindings.mjs +171 -45
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +22 -8
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +23 -22
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +3 -0
- package/dist/model/index.mjs +5 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +74 -2
- package/dist/model/properties/PropertyResolver.mjs +133 -5
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +349 -0
- package/dist/model/text/Extractor.mjs +2406 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +542 -0
- package/dist/model/text/TextContext.d.mts +256 -0
- package/dist/model/text/TextContext.mjs +600 -0
- package/dist/model/text/TextOptions.d.mts +233 -0
- package/dist/model/text/TextOptions.mjs +419 -0
- package/dist/model/text/TextResult.d.mts +621 -0
- package/dist/model/text/TextResult.mjs +629 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +936 -0
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +8 -0
- package/dist/model/text/index.mjs +9 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +29 -12
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +32 -0
- package/dist/opc/Save.mjs +110 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +8 -5
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +141 -5
- package/dist/opc/mce/preprocessor.mjs +119 -18
- package/dist/opc/mce/understood.d.mts +3 -11
- package/dist/opc/mce/understood.mjs +27 -23
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +110 -4
- package/dist/packages/OpcPackage.mjs +123 -7
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +158 -21
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +14 -2
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +63 -32
- package/dist/parts/XmlPart.mjs +240 -96
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +37 -1
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -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. */
|
|
@@ -135,6 +245,12 @@ export class OpcPackage {
|
|
|
135
245
|
if (copy.constructor !== this.constructor) {
|
|
136
246
|
throw new Docx4JException(`Cloning ${this.constructor.name} produced ${copy.constructor.name}`);
|
|
137
247
|
}
|
|
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;
|
|
138
254
|
this.copyPackageSettingsTo(copy);
|
|
139
255
|
return copy;
|
|
140
256
|
}
|
|
@@ -4,6 +4,7 @@ import type { Part } from '../parts/Part.mjs';
|
|
|
4
4
|
import { MainDocumentPart, StyleDefinitionsPart, type NumberingDefinitionsPart } from '../parts/wml/index.mjs';
|
|
5
5
|
import { type FontSettings, type DefaultThemeValue } from '../model/fonts/defaultTheme.mjs';
|
|
6
6
|
import { Body, type Address, type Outline, type OutlineParagraph, type OutlineTable } from '../model/content/Body.mjs';
|
|
7
|
+
import { type TrackedChangeSelection } from '../model/content/trackedChangeFilter.mjs';
|
|
7
8
|
import type { Paragraph } from '../model/content/Paragraph.mjs';
|
|
8
9
|
import type { Author } from '../model/content/comments.mjs';
|
|
9
10
|
import { CustomXmlPartCollection } from '../model/customxml/CustomXmlPartCollection.mjs';
|
|
@@ -11,6 +12,7 @@ import { type XPathEngine } from '../model/customxml/xpath.mjs';
|
|
|
11
12
|
import { ChangeTracker, type ChangeTrackingMode, type TrackingHost, type TrackingScope } from '../model/content/tracking.mjs';
|
|
12
13
|
import { NumberingFacade } from '../model/content/List.mjs';
|
|
13
14
|
import { StylesFacade } from '../model/content/stylesFacade.mjs';
|
|
15
|
+
import { GlossaryEntries } from '../model/content/placeholders.mjs';
|
|
14
16
|
import type { Bound } from '../model/content/binder.mjs';
|
|
15
17
|
import { PropertyResolver } from '../model/properties/PropertyResolver.mjs';
|
|
16
18
|
import type { Emulator } from '../model/listnumbering/Emulator.mjs';
|
|
@@ -19,6 +21,9 @@ import { type RelationshipRemovals } from '../model/content/relationships.mjs';
|
|
|
19
21
|
import { XmlPart } from '../parts/XmlPart.mjs';
|
|
20
22
|
import type { PartSink } from '../opc/PartStore.mjs';
|
|
21
23
|
import '../parts/wml/comments.mjs';
|
|
24
|
+
import '../model/text/outline.mjs';
|
|
25
|
+
import type { TextContext } from '../model/text/TextContext.mjs';
|
|
26
|
+
import type { TextOptions, TextOptionsInit } from '../model/text/TextOptions.mjs';
|
|
22
27
|
/** The outline of a document: the body's paragraphs and tables, then each header's and footer's (loaded ones only). */
|
|
23
28
|
export interface DocumentOutline extends Outline {
|
|
24
29
|
headers: {
|
|
@@ -102,6 +107,12 @@ export declare class WordprocessingMLPackage extends OpcPackage implements Track
|
|
|
102
107
|
* 47). Settled on save, not at once, so a picture cut and pasted back keeps its image. An extension.
|
|
103
108
|
*/
|
|
104
109
|
readonly pendingRelationshipRemovals: RelationshipRemovals;
|
|
110
|
+
/**
|
|
111
|
+
* The glossary's placeholder entries: read privately when a body is first read (`getBody`, `Word.run`), and those a
|
|
112
|
+
* placeholder written since names, which go into the glossary when the package is saved, the glossary made where the
|
|
113
|
+
* file has none (CR-002 section 63, D8 and D9). An extension.
|
|
114
|
+
*/
|
|
115
|
+
readonly glossaryEntries: GlossaryEntries;
|
|
105
116
|
/**
|
|
106
117
|
* The parts `seedAnnotationIds()` has read, with what it read: `true` for a part still holding its
|
|
107
118
|
* source, whose bytes cannot change, and otherwise the bytes that were set, which stay the same
|
|
@@ -212,10 +223,24 @@ export declare class WordprocessingMLPackage extends OpcPackage implements Track
|
|
|
212
223
|
private settingsPart;
|
|
213
224
|
/**
|
|
214
225
|
* Office JS `document.getTrackedChanges()`: every tracked change in the main document part,
|
|
215
|
-
* in document order (headers and footers have their own `Body`
|
|
216
|
-
* unmarshalled, as `body` needs it to be.
|
|
226
|
+
* in document order (headers and footers have their own `Body`; `getAllTrackedChanges` lists
|
|
227
|
+
* every story). The part must be unmarshalled, as `body` needs it to be.
|
|
217
228
|
*/
|
|
218
229
|
getTrackedChanges(): TrackedChange[];
|
|
230
|
+
/**
|
|
231
|
+
* Every tracked change in every story, in docx4j's order (its CR-043 `TrackedChanges.in`, CR-011):
|
|
232
|
+
* the main document, each footnote, each endnote, each comment, then the headers and footers in the
|
|
233
|
+
* order the sections reference them; a text box's after the story it is in. Each story's are its
|
|
234
|
+
* `Body.getTrackedChanges()`, grouped as Office JS groups them, so changes never group across two
|
|
235
|
+
* stories. `TrackedChange.part` says which part each is in.
|
|
236
|
+
*
|
|
237
|
+
* With a filter, the changes with a piece it matches, each whole (docx4j's `in(pkg, filter)`).
|
|
238
|
+
*
|
|
239
|
+
* A story part whose source holds no revision markup is not read, so it keeps its bytes; one that
|
|
240
|
+
* does is unmarshalled, since the views returned must be resolvable, and so is re-marshalled on save.
|
|
241
|
+
* An extension: Office JS lists one body at a time.
|
|
242
|
+
*/
|
|
243
|
+
getAllTrackedChanges(filter?: TrackedChangeSelection): Promise<TrackedChange[]>;
|
|
219
244
|
/**
|
|
220
245
|
* Accepts every tracked change in every story: the main document, the footnotes, the endnotes and
|
|
221
246
|
* the comments, the headers and footers, and the text boxes in each. Word's
|
|
@@ -223,15 +248,19 @@ export declare class WordprocessingMLPackage extends OpcPackage implements Track
|
|
|
223
248
|
* revision in any story; `Body.acceptAll` resolves its own story only, as Office JS's `body` does
|
|
224
249
|
* (CR-002 section 49). A story part with no revision markup is not read, so it keeps its bytes.
|
|
225
250
|
* Returns how many changes were listed, story by story. An extension, named after Word's verb.
|
|
251
|
+
*
|
|
252
|
+
* With a filter (CR-011), only the single changes it matches are accepted, as `Body.acceptAll`
|
|
253
|
+
* takes one, and the count is of the listed changes with a matching piece.
|
|
226
254
|
*/
|
|
227
|
-
acceptAllRevisions(): Promise<number>;
|
|
255
|
+
acceptAllRevisions(filter?: TrackedChangeSelection): Promise<number>;
|
|
228
256
|
/** Rejects every tracked change in every story, as `acceptAllRevisions` accepts them (Word's `Document.RejectAllRevisions`). */
|
|
229
|
-
rejectAllRevisions(): Promise<number>;
|
|
257
|
+
rejectAllRevisions(filter?: TrackedChangeSelection): Promise<number>;
|
|
230
258
|
private resolveEveryStory;
|
|
231
259
|
/**
|
|
232
260
|
* The body of every story whose part holds revision markup, in docx4j's order (its CR-043
|
|
233
261
|
* `TrackedChanges.in`): the main document, each footnote, each endnote, each comment, then the
|
|
234
|
-
* headers and footers. A footnote, an endnote or a comment is a
|
|
262
|
+
* headers and footers in section order (`inSectionOrder`). A footnote, an endnote or a comment is a
|
|
263
|
+
* body of its own over its content.
|
|
235
264
|
*/
|
|
236
265
|
private revisedStories;
|
|
237
266
|
/** The tracker every content-API mutation asks for; undefined while the mode is `Off`. */
|
|
@@ -294,10 +323,18 @@ export declare class WordprocessingMLPackage extends OpcPackage implements Track
|
|
|
294
323
|
/** A clone carries the identity, the tracking date, the theme setting, the XPath engine and the styles still to ensure. */
|
|
295
324
|
protected copyPackageSettingsTo(target: OpcPackage): void;
|
|
296
325
|
saveTo<R>(sink: PartSink<R>): Promise<R>;
|
|
297
|
-
/**
|
|
326
|
+
/**
|
|
327
|
+
* The paragraph at an address anywhere in the document: 'body/3', 'header:rId5/0', 'footnote:2/0',
|
|
328
|
+
* 'endnote:1/0', 'comment:5/0', 'body/3/textbox:0/1' (a text box's paragraph, read-only: CR-012 D4 and
|
|
329
|
+
* D5), a paraId, or a text match. Undefined where the address names no paragraph.
|
|
330
|
+
*/
|
|
298
331
|
paragraphAt(address: Address): Promise<Paragraph | undefined>;
|
|
299
|
-
/**
|
|
300
|
-
|
|
332
|
+
/**
|
|
333
|
+
* Every paragraph and table with its address, style and text (CR-002 section 3.3), read by the text model
|
|
334
|
+
* under one context (CR-012 D3: `Body.outline`, whose options it takes): the main document, then each
|
|
335
|
+
* header and footer. Unmarshals the main part, headers and footers.
|
|
336
|
+
*/
|
|
337
|
+
outline(options?: TextOptionsInit | TextOptions, context?: TextContext): Promise<DocumentOutline>;
|
|
301
338
|
private bodies;
|
|
302
339
|
/**
|
|
303
340
|
* The XPath engine the custom XML views use (CR-002 section 3.6): `document.evaluate` in a
|
|
@@ -4,27 +4,33 @@ import { registerPackageClass } from './registry.mjs';
|
|
|
4
4
|
import { ContentTypes } from '../opc/ContentTypes.mjs';
|
|
5
5
|
import { Docx4JException } from '../opc/exceptions.mjs';
|
|
6
6
|
import { Namespaces } from '../parts/Namespaces.mjs';
|
|
7
|
-
import { MainDocumentPart, StyleDefinitionsPart, DocumentSettingsPart } from '../parts/wml/index.mjs';
|
|
7
|
+
import { MainDocumentPart, StyleDefinitionsPart, DocumentSettingsPart, GlossaryDocumentPart } from '../parts/wml/index.mjs';
|
|
8
8
|
import { DocPropsCorePart, DocPropsExtendedPart } from '../parts/docProps/index.mjs';
|
|
9
9
|
import { DEFAULT_STYLES_XML } from '../parts/wml/defaultStyles.mjs';
|
|
10
10
|
import { ThemePart } from '../parts/dml/index.mjs';
|
|
11
11
|
import { newFontSettings, themeOfSettings, } from '../model/fonts/defaultTheme.mjs';
|
|
12
12
|
import { HeaderPart, FooterPart } from '../parts/wml/index.mjs';
|
|
13
|
-
import { Body, resolveStory } from '../model/content/Body.mjs';
|
|
13
|
+
import { Body, resolveStory, trackedChangesOfStory } from '../model/content/Body.mjs';
|
|
14
|
+
import { pieceMatcher } from '../model/content/trackedChangeFilter.mjs';
|
|
14
15
|
import { CustomXmlPartCollection } from '../model/customxml/CustomXmlPartCollection.mjs';
|
|
15
16
|
import { DefaultXPathEngine } from '../model/customxml/xpath.mjs';
|
|
16
17
|
import { ChangeTracker, highestAnnotationId } from '../model/content/tracking.mjs';
|
|
17
18
|
import { NumberingFacade } from '../model/content/List.mjs';
|
|
18
19
|
import { StylesFacade } from '../model/content/stylesFacade.mjs';
|
|
19
20
|
import { flushPendingCommentRemovals } from '../model/content/Comment.mjs';
|
|
21
|
+
import { GlossaryEntries } from '../model/content/placeholders.mjs';
|
|
20
22
|
import { PropertyResolver } from '../model/properties/PropertyResolver.mjs';
|
|
21
23
|
import { PropertyResolverNotCreatedException } from '../opc/exceptions.mjs';
|
|
22
|
-
import { flushPendingNoteRemovals } from '../model/content/TrackedChange.mjs';
|
|
24
|
+
import { flushPendingNoteRemovals, notesGoing } from '../model/content/TrackedChange.mjs';
|
|
23
25
|
import { flushPendingRelationshipRemovals } from '../model/content/relationships.mjs';
|
|
24
26
|
import { XmlPart } from '../parts/XmlPart.mjs';
|
|
25
27
|
// Registers the comment parts with the content API (CR-002 phase G); no cycle: the model half
|
|
26
28
|
// never imports a part, as packages/registry.mts does for the package classes.
|
|
27
29
|
import '../parts/wml/comments.mjs';
|
|
30
|
+
// Registers the text model's outline reader with Body.outline (CR-012 D3), the same way: the content API
|
|
31
|
+
// can't import the text model, which imports it.
|
|
32
|
+
import '../model/text/outline.mjs';
|
|
33
|
+
import { Texts } from '../model/text/Texts.mjs';
|
|
28
34
|
const MAIN_CONTENT_TYPES = [
|
|
29
35
|
ContentTypes.WORDPROCESSINGML_DOCUMENT,
|
|
30
36
|
ContentTypes.WORDPROCESSINGML_DOCUMENT_MACROENABLED,
|
|
@@ -105,6 +111,12 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
105
111
|
* 47). Settled on save, not at once, so a picture cut and pasted back keeps its image. An extension.
|
|
106
112
|
*/
|
|
107
113
|
this.pendingRelationshipRemovals = new Map();
|
|
114
|
+
/**
|
|
115
|
+
* The glossary's placeholder entries: read privately when a body is first read (`getBody`, `Word.run`), and those a
|
|
116
|
+
* placeholder written since names, which go into the glossary when the package is saved, the glossary made where the
|
|
117
|
+
* file has none (CR-002 section 63, D8 and D9). An extension.
|
|
118
|
+
*/
|
|
119
|
+
this.glossaryEntries = new GlossaryEntries();
|
|
108
120
|
/**
|
|
109
121
|
* The parts `seedAnnotationIds()` has read, with what it read: `true` for a part still holding its
|
|
110
122
|
* source, whose bytes cannot change, and otherwise the bytes that were set, which stay the same
|
|
@@ -159,7 +171,8 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
159
171
|
if (landscape)
|
|
160
172
|
pgSz.orient = 'landscape';
|
|
161
173
|
const pgMar = { top: 1440, right: 1440, bottom: 1440, left: 1440, header: 708, footer: 708, gutter: 0 };
|
|
162
|
-
|
|
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 } } };
|
|
163
176
|
const main = new MainDocumentPart();
|
|
164
177
|
main.setContents(document);
|
|
165
178
|
pkg.addTargetPart(main);
|
|
@@ -414,12 +427,32 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
414
427
|
}
|
|
415
428
|
/**
|
|
416
429
|
* Office JS `document.getTrackedChanges()`: every tracked change in the main document part,
|
|
417
|
-
* in document order (headers and footers have their own `Body`
|
|
418
|
-
* unmarshalled, as `body` needs it to be.
|
|
430
|
+
* in document order (headers and footers have their own `Body`; `getAllTrackedChanges` lists
|
|
431
|
+
* every story). The part must be unmarshalled, as `body` needs it to be.
|
|
419
432
|
*/
|
|
420
433
|
getTrackedChanges() {
|
|
421
434
|
return this.body.getTrackedChanges();
|
|
422
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Every tracked change in every story, in docx4j's order (its CR-043 `TrackedChanges.in`, CR-011):
|
|
438
|
+
* the main document, each footnote, each endnote, each comment, then the headers and footers in the
|
|
439
|
+
* order the sections reference them; a text box's after the story it is in. Each story's are its
|
|
440
|
+
* `Body.getTrackedChanges()`, grouped as Office JS groups them, so changes never group across two
|
|
441
|
+
* stories. `TrackedChange.part` says which part each is in.
|
|
442
|
+
*
|
|
443
|
+
* With a filter, the changes with a piece it matches, each whole (docx4j's `in(pkg, filter)`).
|
|
444
|
+
*
|
|
445
|
+
* A story part whose source holds no revision markup is not read, so it keeps its bytes; one that
|
|
446
|
+
* does is unmarshalled, since the views returned must be resolvable, and so is re-marshalled on save.
|
|
447
|
+
* An extension: Office JS lists one body at a time.
|
|
448
|
+
*/
|
|
449
|
+
async getAllTrackedChanges(filter) {
|
|
450
|
+
const matches = filter === undefined ? undefined : pieceMatcher(filter);
|
|
451
|
+
const out = [];
|
|
452
|
+
for (const body of await this.revisedStories())
|
|
453
|
+
out.push(...trackedChangesOfStory(body));
|
|
454
|
+
return matches ? out.filter((change) => change.pieces.some(matches)) : out;
|
|
455
|
+
}
|
|
423
456
|
/**
|
|
424
457
|
* Accepts every tracked change in every story: the main document, the footnotes, the endnotes and
|
|
425
458
|
* the comments, the headers and footers, and the text boxes in each. Word's
|
|
@@ -427,24 +460,30 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
427
460
|
* revision in any story; `Body.acceptAll` resolves its own story only, as Office JS's `body` does
|
|
428
461
|
* (CR-002 section 49). A story part with no revision markup is not read, so it keeps its bytes.
|
|
429
462
|
* Returns how many changes were listed, story by story. An extension, named after Word's verb.
|
|
463
|
+
*
|
|
464
|
+
* With a filter (CR-011), only the single changes it matches are accepted, as `Body.acceptAll`
|
|
465
|
+
* takes one, and the count is of the listed changes with a matching piece.
|
|
430
466
|
*/
|
|
431
|
-
async acceptAllRevisions() {
|
|
432
|
-
return this.resolveEveryStory('accept');
|
|
467
|
+
async acceptAllRevisions(filter) {
|
|
468
|
+
return this.resolveEveryStory('accept', filter);
|
|
433
469
|
}
|
|
434
470
|
/** Rejects every tracked change in every story, as `acceptAllRevisions` accepts them (Word's `Document.RejectAllRevisions`). */
|
|
435
|
-
async rejectAllRevisions() {
|
|
436
|
-
return this.resolveEveryStory('reject');
|
|
471
|
+
async rejectAllRevisions(filter) {
|
|
472
|
+
return this.resolveEveryStory('reject', filter);
|
|
437
473
|
}
|
|
438
|
-
async resolveEveryStory(what) {
|
|
474
|
+
async resolveEveryStory(what, filter) {
|
|
475
|
+
if (filter !== undefined)
|
|
476
|
+
pieceMatcher(filter); // a filter misread throws before anything is read or resolved
|
|
439
477
|
let count = 0;
|
|
440
478
|
for (const body of await this.revisedStories())
|
|
441
|
-
count += resolveStory(body, what);
|
|
479
|
+
count += resolveStory(body, what, filter);
|
|
442
480
|
return count;
|
|
443
481
|
}
|
|
444
482
|
/**
|
|
445
483
|
* The body of every story whose part holds revision markup, in docx4j's order (its CR-043
|
|
446
484
|
* `TrackedChanges.in`): the main document, each footnote, each endnote, each comment, then the
|
|
447
|
-
* headers and footers. A footnote, an endnote or a comment is a
|
|
485
|
+
* headers and footers in section order (`inSectionOrder`). A footnote, an endnote or a comment is a
|
|
486
|
+
* body of its own over its content.
|
|
448
487
|
*/
|
|
449
488
|
async revisedStories() {
|
|
450
489
|
var _a, _b;
|
|
@@ -452,22 +491,33 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
452
491
|
const out = [];
|
|
453
492
|
if (await holdsRevisions(main))
|
|
454
493
|
out.push(await main.getBody());
|
|
494
|
+
// a note or comment a resolution has taken the reference or anchor of goes on save; it is no story now
|
|
495
|
+
const pending = this.pendingNoteRemovals;
|
|
496
|
+
const going = pending.footnote.size + pending.endnote.size > 0 ? notesGoing(await main.readContents(), pending) : pending;
|
|
455
497
|
for (const [part, kind] of [[main.footnotesPart, 'footnote'], [main.endnotesPart, 'endnote']]) {
|
|
456
498
|
if (!part || !(await holdsRevisions(part)))
|
|
457
499
|
continue;
|
|
458
500
|
const contents = await part.getContents();
|
|
459
501
|
for (const note of (_a = (kind === 'footnote' ? contents.footnote : contents.endnote)) !== null && _a !== void 0 ? _a : []) {
|
|
502
|
+
if ((note.type === undefined || note.type === 'normal') && going[kind].has(Number(note.id)))
|
|
503
|
+
continue;
|
|
460
504
|
out.push(new Body(part, note, `${kind}:${note.id}`, this));
|
|
461
505
|
}
|
|
462
506
|
}
|
|
463
507
|
const comments = main.commentsPart;
|
|
464
508
|
if (comments && (await holdsRevisions(comments))) {
|
|
465
|
-
for (const comment of (_b = (await comments.getContents()).comment) !== null && _b !== void 0 ? _b : [])
|
|
509
|
+
for (const comment of (_b = (await comments.getContents()).comment) !== null && _b !== void 0 ? _b : []) {
|
|
510
|
+
if (this.pendingCommentRemovals.has(comment.id))
|
|
511
|
+
continue;
|
|
466
512
|
out.push(new Body(comments, comment, `comment:${comment.id}`, this));
|
|
513
|
+
}
|
|
467
514
|
}
|
|
515
|
+
const revised = [];
|
|
468
516
|
for (const part of [...main.headerParts, ...main.footerParts])
|
|
469
517
|
if (await holdsRevisions(part))
|
|
470
|
-
|
|
518
|
+
revised.push(part);
|
|
519
|
+
for (const part of revised.length > 1 ? await inSectionOrder(main, revised) : revised)
|
|
520
|
+
out.push(await part.getBody());
|
|
471
521
|
return out;
|
|
472
522
|
}
|
|
473
523
|
/** The tracker every content-API mutation asks for; undefined while the mode is `Off`. */
|
|
@@ -583,6 +633,7 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
583
633
|
target.pendingNoteRemovals.endnote.add(id);
|
|
584
634
|
for (const [name, ids] of this.pendingRelationshipRemovals)
|
|
585
635
|
target.pendingRelationshipRemovals.set(name, new Set(ids));
|
|
636
|
+
this.glossaryEntries.copyTo(target.glossaryEntries);
|
|
586
637
|
target.trackedChangeDate = this.trackedChangeDate;
|
|
587
638
|
target.fonts.defaultTheme = this.fonts.defaultTheme;
|
|
588
639
|
target.xpathEngine = this.xpathEngine;
|
|
@@ -603,13 +654,23 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
603
654
|
}
|
|
604
655
|
if (this.pendingRelationshipRemovals.size > 0)
|
|
605
656
|
flushPendingRelationshipRemovals(this, this.pendingRelationshipRemovals);
|
|
657
|
+
if (this.glossaryEntries.waiting) {
|
|
658
|
+
await this.glossaryEntries.flush(this, {
|
|
659
|
+
glossary: () => new GlossaryDocumentPart(),
|
|
660
|
+
styles: () => new StyleDefinitionsPart('/word/glossary/styles.xml'),
|
|
661
|
+
});
|
|
662
|
+
}
|
|
606
663
|
if (this.requiredStyles.size > 0) {
|
|
607
664
|
await this.styles.ensure([...this.requiredStyles]);
|
|
608
665
|
this.requiredStyles.clear();
|
|
609
666
|
}
|
|
610
667
|
return super.saveTo(sink);
|
|
611
668
|
}
|
|
612
|
-
/**
|
|
669
|
+
/**
|
|
670
|
+
* The paragraph at an address anywhere in the document: 'body/3', 'header:rId5/0', 'footnote:2/0',
|
|
671
|
+
* 'endnote:1/0', 'comment:5/0', 'body/3/textbox:0/1' (a text box's paragraph, read-only: CR-012 D4 and
|
|
672
|
+
* D5), a paraId, or a text match. Undefined where the address names no paragraph.
|
|
673
|
+
*/
|
|
613
674
|
async paragraphAt(address) {
|
|
614
675
|
for (const body of await this.bodies(address)) {
|
|
615
676
|
const p = body.paragraphAt(address);
|
|
@@ -618,28 +679,44 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
618
679
|
}
|
|
619
680
|
return undefined;
|
|
620
681
|
}
|
|
621
|
-
/**
|
|
622
|
-
|
|
682
|
+
/**
|
|
683
|
+
* Every paragraph and table with its address, style and text (CR-002 section 3.3), read by the text model
|
|
684
|
+
* under one context (CR-012 D3: `Body.outline`, whose options it takes): the main document, then each
|
|
685
|
+
* header and footer. Unmarshals the main part, headers and footers.
|
|
686
|
+
*/
|
|
687
|
+
async outline(options, context) {
|
|
623
688
|
var _a, _b, _c, _d;
|
|
624
689
|
const main = await this.getBody();
|
|
625
|
-
const
|
|
690
|
+
const ctx = context !== null && context !== void 0 ? context : await Texts.contextOf(this);
|
|
691
|
+
const out = { ...await main.outline(options, ctx), headers: [], footers: [] };
|
|
626
692
|
for (const part of this.getMainDocumentPart().headerParts) {
|
|
627
693
|
const body = await part.getBody();
|
|
628
|
-
out.headers.push({ relId: (_b = (_a = part.sourceRelationship) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '', partName: part.partName.name, ...body.outline() });
|
|
694
|
+
out.headers.push({ relId: (_b = (_a = part.sourceRelationship) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '', partName: part.partName.name, ...await body.outline(options, ctx) });
|
|
629
695
|
}
|
|
630
696
|
for (const part of this.getMainDocumentPart().footerParts) {
|
|
631
697
|
const body = await part.getBody();
|
|
632
|
-
out.footers.push({ relId: (_d = (_c = part.sourceRelationship) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : '', partName: part.partName.name, ...body.outline() });
|
|
698
|
+
out.footers.push({ relId: (_d = (_c = part.sourceRelationship) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : '', partName: part.partName.name, ...await body.outline(options, ctx) });
|
|
633
699
|
}
|
|
634
700
|
return out;
|
|
635
701
|
}
|
|
636
702
|
async bodies(address) {
|
|
703
|
+
var _a;
|
|
637
704
|
const main = this.getMainDocumentPart();
|
|
638
705
|
if (typeof address === 'string' && !address.startsWith('w14:')) {
|
|
639
706
|
const prefix = address.split('/')[0];
|
|
640
707
|
if (prefix === 'body')
|
|
641
708
|
return [await main.getBody()];
|
|
642
709
|
const [kind, relId] = prefix.split(':');
|
|
710
|
+
if (kind === 'footnote' || kind === 'endnote' || kind === 'comment') {
|
|
711
|
+
// a note's or a comment's body, by its w:id, as the text model and Comment address them (CR-012 D4)
|
|
712
|
+
const part = kind === 'footnote' ? main.footnotesPart : kind === 'endnote' ? main.endnotesPart : main.commentsPart;
|
|
713
|
+
if (!part)
|
|
714
|
+
return [];
|
|
715
|
+
const contents = await part.getContents();
|
|
716
|
+
const entry = ((_a = contents[kind]) !== null && _a !== void 0 ? _a : []).find((e) => String(e.id) === relId);
|
|
717
|
+
await this.getPropertyResolver().catch(() => undefined);
|
|
718
|
+
return entry ? [new Body(part, entry, `${kind}:${relId}`, this)] : [];
|
|
719
|
+
}
|
|
643
720
|
const parts = kind === 'header' ? main.headerParts : kind === 'footer' ? main.footerParts : [];
|
|
644
721
|
const part = parts.find((p) => { var _a; return ((_a = p.sourceRelationship) === null || _a === void 0 ? void 0 : _a.id) === relId || p.partName.fileName === relId; });
|
|
645
722
|
return part instanceof HeaderPart || part instanceof FooterPart ? [await part.getBody()] : [];
|
|
@@ -709,12 +786,72 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
709
786
|
},
|
|
710
787
|
customXmlRelationshipSource: () => this.getMainDocumentPart(),
|
|
711
788
|
xhtmlHost: this,
|
|
789
|
+
getPropertyResolver: () => this.getPropertyResolver(),
|
|
712
790
|
})));
|
|
713
791
|
}
|
|
714
792
|
get progId() {
|
|
715
793
|
return 'Word.Document';
|
|
716
794
|
}
|
|
717
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Headers and footers in docx4j's order (its CR-043 `Lister.headersAndFooters`): as the sections
|
|
798
|
+
* reference them, in document order, a part once, then any other in the order of the main part's
|
|
799
|
+
* relationships. The main part's tree is read privately, so a main part nobody has otherwise read keeps
|
|
800
|
+
* its bytes.
|
|
801
|
+
*/
|
|
802
|
+
async function inSectionOrder(main, parts) {
|
|
803
|
+
var _a;
|
|
804
|
+
const rels = main.relationshipsPart;
|
|
805
|
+
if (!rels)
|
|
806
|
+
return parts;
|
|
807
|
+
const order = [];
|
|
808
|
+
const add = (part) => {
|
|
809
|
+
const known = parts.find((p) => p === part);
|
|
810
|
+
if (known && !order.includes(known))
|
|
811
|
+
order.push(known);
|
|
812
|
+
};
|
|
813
|
+
const body = (await main.readContents()).body;
|
|
814
|
+
for (const sectPr of sectionsOf(body))
|
|
815
|
+
for (const ref of (_a = sectPr.egHdrFtrReferences) !== null && _a !== void 0 ? _a : [])
|
|
816
|
+
add(rels.getPart(ref.id));
|
|
817
|
+
for (const rel of rels.list)
|
|
818
|
+
add(rels.getPart(rel));
|
|
819
|
+
for (const part of parts)
|
|
820
|
+
if (!order.includes(part))
|
|
821
|
+
order.push(part);
|
|
822
|
+
return order;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* The body's `w:sectPr`s in document order, the paragraphs' first and the body's own last, as docx4j's
|
|
826
|
+
* walk finds them: not inside a run (where a text box's paragraphs are), DOM the model does not type
|
|
827
|
+
* left alone.
|
|
828
|
+
*/
|
|
829
|
+
function sectionsOf(body) {
|
|
830
|
+
const out = [];
|
|
831
|
+
const visit = (o) => {
|
|
832
|
+
if (typeof o !== 'object' || o === null || typeof o.nodeType === 'number')
|
|
833
|
+
return;
|
|
834
|
+
if (Array.isArray(o)) {
|
|
835
|
+
for (const item of o)
|
|
836
|
+
visit(item);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const typeName = o.TYPE_NAME;
|
|
840
|
+
if (typeName === 'org_docx4j_wml.SectPr') {
|
|
841
|
+
out.push(o);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
if (typeName === 'org_docx4j_wml.R')
|
|
845
|
+
return;
|
|
846
|
+
for (const key in o)
|
|
847
|
+
if (key !== 'PARENT')
|
|
848
|
+
visit(o[key]);
|
|
849
|
+
};
|
|
850
|
+
visit(body === null || body === void 0 ? void 0 : body.content);
|
|
851
|
+
if (body === null || body === void 0 ? void 0 : body.sectPr)
|
|
852
|
+
out.push(body.sectPr);
|
|
853
|
+
return out;
|
|
854
|
+
}
|
|
718
855
|
/** Revision markup, by local name in any prefix: what a story part holds when it has a tracked change to resolve. */
|
|
719
856
|
const REVISION_MARKUP = /<(?:[\w.-]+:)?(?:ins|del|moveFrom|moveTo|rPrChange|pPrChange|sectPrChange|tblPrChange|trPrChange|tcPrChange|tblGridChange|tblPrExChange|cellIns|cellDel|cellMerge|numberingChange|customXmlInsRangeStart|customXmlDelRangeStart)[\s/>]/;
|
|
720
857
|
/**
|
|
@@ -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';
|
|
@@ -2,7 +2,7 @@ import { Part } from './Part.mjs';
|
|
|
2
2
|
import { ContentTypes } from '../opc/ContentTypes.mjs';
|
|
3
3
|
import { Namespaces } from './Namespaces.mjs';
|
|
4
4
|
import { Docx4JException } from '../opc/exceptions.mjs';
|
|
5
|
-
import { parseXml, serializeXmlPart, encodeText, decodeXmlText } from '../xml/dom.mjs';
|
|
5
|
+
import { parseXml, serializeXmlPart, encodeText, decodeXmlText, assertXmlCharacters } from '../xml/dom.mjs';
|
|
6
6
|
/**
|
|
7
7
|
* An XML part the object model does not type, held as a DOM (docx4j DefaultXmlPart / XmlPart).
|
|
8
8
|
* The document is parsed on first `getDocument()`; a part whose document was never requested is
|
|
@@ -71,7 +71,7 @@ export class DefaultXmlPart extends Part {
|
|
|
71
71
|
}
|
|
72
72
|
async getBytes() {
|
|
73
73
|
if (this.document !== undefined)
|
|
74
|
-
return encodeText(serializeXmlPart(this.document));
|
|
74
|
+
return encodeText(assertXmlCharacters(serializeXmlPart(this.document), `Part ${this.partName}`));
|
|
75
75
|
if (this.bytes !== undefined)
|
|
76
76
|
return this.bytes;
|
|
77
77
|
const loaded = await this.loadSourceBytes();
|