@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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// only, never from `.` or `./opc`, so a browser or add-in bundle never sees them.
|
|
4
4
|
import { readFile, readdir, stat, mkdir, writeFile } from 'node:fs/promises';
|
|
5
5
|
import { join, dirname, sep } from 'node:path';
|
|
6
|
+
import { EntryIndex } from './PartStore.mjs';
|
|
6
7
|
import { CONTENT_TYPES_NAME } from './PartName.mjs';
|
|
7
8
|
import { Docx4JException } from './exceptions.mjs';
|
|
8
9
|
/**
|
|
@@ -21,8 +22,11 @@ import { Docx4JException } from './exceptions.mjs';
|
|
|
21
22
|
export class DirectoryPartStore {
|
|
22
23
|
constructor(dir) {
|
|
23
24
|
this.dir = dir;
|
|
24
|
-
/**
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Store name (no leading '/') to [absolute file path, size], looked up without case; of two files whose names differ only
|
|
27
|
+
* in case (a case-sensitive file system), the first in the walk is read and the rest counted (CR-024).
|
|
28
|
+
*/
|
|
29
|
+
this.entries = new EntryIndex();
|
|
26
30
|
}
|
|
27
31
|
/** Scans a directory and returns a store over it. */
|
|
28
32
|
static async open(dir) {
|
|
@@ -48,15 +52,18 @@ export class DirectoryPartStore {
|
|
|
48
52
|
if (info.isDirectory())
|
|
49
53
|
await this.scan(childRelative);
|
|
50
54
|
else if (info.isFile())
|
|
51
|
-
this.entries.
|
|
55
|
+
this.entries.add(childRelative, [childPath, info.size]);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
partNames() {
|
|
55
|
-
return this.entries.
|
|
59
|
+
return this.entries.names();
|
|
56
60
|
}
|
|
57
61
|
has(partName) {
|
|
58
62
|
return this.entries.has(normalize(partName));
|
|
59
63
|
}
|
|
64
|
+
duplicates() {
|
|
65
|
+
return this.entries.duplicates();
|
|
66
|
+
}
|
|
60
67
|
async load(partName) {
|
|
61
68
|
const entry = this.entries.get(normalize(partName));
|
|
62
69
|
if (!entry)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PackageElement } from '@docx4j/generated-objects-ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type PartStore, type PartSink, type PutOptions } from './PartStore.mjs';
|
|
3
3
|
export declare const PKG_NS = "http://schemas.microsoft.com/office/2006/xmlPackage";
|
|
4
4
|
/**
|
|
5
5
|
* A flat OPC package (`pkg:package`, what Office JS `getOoxml()` returns) as a container
|
|
@@ -7,10 +7,11 @@ export declare const PKG_NS = "http://schemas.microsoft.com/office/2006/xmlPacka
|
|
|
7
7
|
* same job is done by `FlatOpcXmlImporter`). The content types are carried per part, so
|
|
8
8
|
* `[Content_Types].xml` is synthesised. XML parts are serialised back to bytes on `load`; the
|
|
9
9
|
* document loaded from them is therefore not byte-identical to what Office would have zipped.
|
|
10
|
+
* Parts are looked up as OPC part names, without case, and of two `pkg:part`s of one name the first
|
|
11
|
+
* is the one read, the rest counted in `duplicates()` (CR-024).
|
|
10
12
|
*/
|
|
11
13
|
export declare class FlatOpcPartStore implements PartStore {
|
|
12
14
|
private readonly parts;
|
|
13
|
-
private readonly order;
|
|
14
15
|
private readonly cache;
|
|
15
16
|
private contentTypesXml?;
|
|
16
17
|
/** From the `pkg:package` string. */
|
|
@@ -22,6 +23,7 @@ export declare class FlatOpcPartStore implements PartStore {
|
|
|
22
23
|
contentTypeOf(partName: string): string | undefined;
|
|
23
24
|
partNames(): Iterable<string>;
|
|
24
25
|
has(partName: string): boolean;
|
|
26
|
+
duplicates(): ReadonlyMap<string, number>;
|
|
25
27
|
load(partName: string): Promise<Uint8Array>;
|
|
26
28
|
private buildContentTypes;
|
|
27
29
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { marshalNode } from '@docx4j/generated-objects-ts';
|
|
2
|
+
import { EntryIndex, entryKey } from './PartStore.mjs';
|
|
2
3
|
import { ContentTypeManager } from './ContentTypeManager.mjs';
|
|
3
4
|
import { ContentTypes, isXmlContentType } from './ContentTypes.mjs';
|
|
4
5
|
import { CONTENT_TYPES_NAME } from './PartName.mjs';
|
|
@@ -11,18 +12,18 @@ export const PKG_NS = 'http://schemas.microsoft.com/office/2006/xmlPackage';
|
|
|
11
12
|
* same job is done by `FlatOpcXmlImporter`). The content types are carried per part, so
|
|
12
13
|
* `[Content_Types].xml` is synthesised. XML parts are serialised back to bytes on `load`; the
|
|
13
14
|
* document loaded from them is therefore not byte-identical to what Office would have zipped.
|
|
15
|
+
* Parts are looked up as OPC part names, without case, and of two `pkg:part`s of one name the first
|
|
16
|
+
* is the one read, the rest counted in `duplicates()` (CR-024).
|
|
14
17
|
*/
|
|
15
18
|
export class FlatOpcPartStore {
|
|
16
19
|
/** From the `pkg:package` string. */
|
|
17
20
|
constructor(source) {
|
|
18
|
-
this.parts = new
|
|
19
|
-
this.order = [];
|
|
21
|
+
this.parts = new EntryIndex();
|
|
20
22
|
this.cache = new Map();
|
|
21
23
|
if (typeof source === 'string')
|
|
22
24
|
this.readString(source);
|
|
23
25
|
else
|
|
24
26
|
this.readPackageElement(source);
|
|
25
|
-
this.order.unshift(CONTENT_TYPES_NAME);
|
|
26
27
|
}
|
|
27
28
|
readString(text) {
|
|
28
29
|
var _a;
|
|
@@ -65,8 +66,7 @@ export class FlatOpcPartStore {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
add(entry) {
|
|
68
|
-
this.parts.
|
|
69
|
-
this.order.push(entry.name);
|
|
69
|
+
this.parts.add(entry.name, entry);
|
|
70
70
|
}
|
|
71
71
|
/** The content type of a part as carried by the flat package. */
|
|
72
72
|
contentTypeOf(partName) {
|
|
@@ -74,16 +74,19 @@ export class FlatOpcPartStore {
|
|
|
74
74
|
return (_a = this.parts.get(partName)) === null || _a === void 0 ? void 0 : _a.contentType;
|
|
75
75
|
}
|
|
76
76
|
partNames() {
|
|
77
|
-
return this.
|
|
77
|
+
return [CONTENT_TYPES_NAME, ...this.parts.names()];
|
|
78
78
|
}
|
|
79
79
|
has(partName) {
|
|
80
80
|
return partName === CONTENT_TYPES_NAME || this.parts.has(partName);
|
|
81
81
|
}
|
|
82
|
+
duplicates() {
|
|
83
|
+
return this.parts.duplicates();
|
|
84
|
+
}
|
|
82
85
|
async load(partName) {
|
|
83
86
|
var _a;
|
|
84
87
|
if (partName === CONTENT_TYPES_NAME)
|
|
85
88
|
return ((_a = this.contentTypesXml) !== null && _a !== void 0 ? _a : (this.contentTypesXml = encodeText(this.buildContentTypes().toXml())));
|
|
86
|
-
const cached = this.cache.get(partName);
|
|
89
|
+
const cached = this.cache.get(entryKey(partName));
|
|
87
90
|
if (cached)
|
|
88
91
|
return cached;
|
|
89
92
|
const part = this.parts.get(partName);
|
|
@@ -100,7 +103,7 @@ export class FlatOpcPartStore {
|
|
|
100
103
|
else {
|
|
101
104
|
bytes = new Uint8Array(0);
|
|
102
105
|
}
|
|
103
|
-
this.cache.set(partName, bytes);
|
|
106
|
+
this.cache.set(entryKey(partName), bytes);
|
|
104
107
|
return bytes;
|
|
105
108
|
}
|
|
106
109
|
buildContentTypes() {
|
package/dist/opc/Load.d.mts
CHANGED
|
@@ -2,6 +2,14 @@ import type { PartStore } from './PartStore.mjs';
|
|
|
2
2
|
import { type DomPreprocessor } from '../parts/XmlPart.mjs';
|
|
3
3
|
import { PartRegistry } from '../parts/PartRegistry.mjs';
|
|
4
4
|
import type { OpcPackage } from '../packages/OpcPackage.mjs';
|
|
5
|
+
/**
|
|
6
|
+
* WD REQ-207's option (CR-031): how a load treats a package Word reads only through a repair, or won't open. `'refuse'`, the
|
|
7
|
+
* default, keeps every refusal; `'word'` follows Word's repair where the WD states one, with that repair's warning; `'all'`
|
|
8
|
+
* does that and makes this package's own repairs, each documented and warned (README.md, "Repairs").
|
|
9
|
+
*/
|
|
10
|
+
export type RepairMode = 'refuse' | 'word' | 'all';
|
|
11
|
+
/** The values of `LoadOptions.repair`, in the WD's order. */
|
|
12
|
+
export declare const REPAIR_MODES: readonly RepairMode[];
|
|
5
13
|
export interface LoadOptions {
|
|
6
14
|
/** Part classes by content type; defaults to docx4j's table. */
|
|
7
15
|
registry?: PartRegistry;
|
|
@@ -16,6 +24,30 @@ export interface LoadOptions {
|
|
|
16
24
|
mcePreprocess?: boolean;
|
|
17
25
|
/** Runs over every XML part's DOM before it is unmarshalled; set by the package from `mcePreprocess` (`mceKeep` or `mcePreprocess`). */
|
|
18
26
|
preprocessor?: DomPreprocessor;
|
|
27
|
+
/**
|
|
28
|
+
* How a package Word reads only through a repair, or won't open, is loaded (WD REQ-207 and REQ-208; CR-031). It acts at the
|
|
29
|
+
* load, so it holds for every operation on the package. Any other value is refused.
|
|
30
|
+
*
|
|
31
|
+
* - `'refuse'`, the default: every refusal stands. A container holding two entries of one name, OPC part names compared
|
|
32
|
+
* without case, throws `DuplicateEntryException` (REQ-206, CR-024); more than one officeDocument relationship,
|
|
33
|
+
* `MultipleMainPartsException` (CR-024 section 9); a relationships part in another namespace or none,
|
|
34
|
+
* `RelationshipsNamespaceException` (CR-025 section 8); an `External` officeDocument relationship beside an internal
|
|
35
|
+
* one, `ExternalMainPartException` (REQ-206's NOTE).
|
|
36
|
+
* - `'word'`: Word's repair, each with its warning. The first entry of each duplicated name is read, in the container's
|
|
37
|
+
* order (a zip's central directory), the rest ignored, a `DuplicateEntryWarning` each; of several officeDocument
|
|
38
|
+
* relationships the **last** one's target, as a fresh Word reads it, the others dropped, one `MultipleMainPartsWarning`;
|
|
39
|
+
* a relationships part in a wrong namespace read by local name, a `RelationshipsNamespaceWarning`. A save writes the
|
|
40
|
+
* repaired package: one copy of each entry, one main part, the right namespace. `External` beside an internal
|
|
41
|
+
* relationship is still refused, since Word refuses it even through its repair.
|
|
42
|
+
* - `'all'`: `'word'`, and this package's own repairs. One today: `External` beside an internal relationship, the internal
|
|
43
|
+
* target read and every `External` officeDocument relationship dropped, its URL never fetched, an
|
|
44
|
+
* `ExternalMainPartWarning`.
|
|
45
|
+
*
|
|
46
|
+
* At every value an `External` officeDocument relationship with no internal one is refused, as a package with no main
|
|
47
|
+
* document part (REQ-321), and the save's own gate is left alone: `pkg.checkLossOnSave` decides whether a save may lose
|
|
48
|
+
* what a read skipped (CR-031 D6).
|
|
49
|
+
*/
|
|
50
|
+
repair?: RepairMode;
|
|
19
51
|
}
|
|
20
52
|
/**
|
|
21
53
|
* Loads a package from a container (docx4j io3.Load3): content types, then the package
|
package/dist/opc/Load.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PartName, CONTENT_TYPES_NAME } from './PartName.mjs';
|
|
2
2
|
import { ContentTypeManager } from './ContentTypeManager.mjs';
|
|
3
|
-
import { Docx4JException, InvalidFormatException } from './exceptions.mjs';
|
|
3
|
+
import { Docx4JException, DuplicateEntryException, ExternalMainPartException, InvalidFormatException, MultipleMainPartsException } from './exceptions.mjs';
|
|
4
4
|
import { Namespaces } from '../parts/Namespaces.mjs';
|
|
5
5
|
import { RelationshipsPart, isExternal } from '../parts/RelationshipsPart.mjs';
|
|
6
6
|
import { XmlPart } from '../parts/XmlPart.mjs';
|
|
@@ -8,6 +8,8 @@ import { CustomXmlDataStoragePart } from '../parts/DefaultXmlPart.mjs';
|
|
|
8
8
|
import { CustomXmlDataStoragePropertiesPart, DS_NS } from '../parts/customXml/index.mjs';
|
|
9
9
|
import { defaultPartRegistry } from '../parts/PartRegistry.mjs';
|
|
10
10
|
import { decodeXmlText, parseXml } from '../xml/dom.mjs';
|
|
11
|
+
/** The values of `LoadOptions.repair`, in the WD's order. */
|
|
12
|
+
export const REPAIR_MODES = Object.freeze(['refuse', 'word', 'all']);
|
|
11
13
|
/** Relationship types whose target is the main part (docx4j PackageRelsUtil.getNameOfMainPart). */
|
|
12
14
|
const MAIN_PART_RELATIONSHIPS = [
|
|
13
15
|
Namespaces.DOCUMENT,
|
|
@@ -15,23 +17,38 @@ const MAIN_PART_RELATIONSHIPS = [
|
|
|
15
17
|
Namespaces.DRAWINGML_DIAGRAM_LAYOUT,
|
|
16
18
|
Namespaces.DOCUMENT_STRICT,
|
|
17
19
|
];
|
|
20
|
+
/**
|
|
21
|
+
* What REQ-206's statement counts (docx4j PackageRelsUtil.isMainPart): a transitional and a strict relationship are two. An
|
|
22
|
+
* External one isn't counted (CR-024 section 9.2): it names no part, so it can't be what the package reads.
|
|
23
|
+
*/
|
|
24
|
+
const OFFICE_DOCUMENT_RELATIONSHIPS = [Namespaces.DOCUMENT, Namespaces.DOCUMENT_STRICT];
|
|
18
25
|
/**
|
|
19
26
|
* Loads a package from a container (docx4j io3.Load3): content types, then the package
|
|
20
27
|
* relationships, then every part reachable through relationships, recursively. Parts are not
|
|
21
28
|
* unmarshalled. `createPackage` picks the package class from the main part's content type.
|
|
22
29
|
*/
|
|
23
30
|
export async function loadPackage(store, createPackage, options = {}) {
|
|
24
|
-
var _a;
|
|
31
|
+
var _a, _b, _c;
|
|
25
32
|
const registry = (_a = options.registry) !== null && _a !== void 0 ? _a : defaultPartRegistry;
|
|
33
|
+
const repair = repairOf(options.repair);
|
|
34
|
+
const followsWord = repair !== 'refuse';
|
|
35
|
+
const duplicateEntries = duplicateEntriesOf(store, followsWord);
|
|
26
36
|
if (!store.has(CONTENT_TYPES_NAME))
|
|
27
37
|
throw new InvalidFormatException(`${CONTENT_TYPES_NAME} is missing from this package`);
|
|
28
38
|
const ctm = ContentTypeManager.parse(decodeXmlText(await store.load(CONTENT_TYPES_NAME)));
|
|
29
39
|
const packageRels = RelationshipsPart.createPackageRels();
|
|
30
40
|
if (!store.has('_rels/.rels'))
|
|
31
41
|
throw new InvalidFormatException('_rels/.rels appears to be missing from this package');
|
|
42
|
+
packageRels.readsByLocalName = followsWord;
|
|
32
43
|
packageRels.setBytes(await store.load('_rels/.rels'));
|
|
33
44
|
await packageRels.getContents();
|
|
34
|
-
|
|
45
|
+
// External first, as docx4j has it: refused at refuse and word whatever else the relationships hold, and dropped at all
|
|
46
|
+
// before Word's last-relationship repair
|
|
47
|
+
const external = externalMainPart(packageRels, repair);
|
|
48
|
+
const mainParts = oneMainPart(packageRels, followsWord);
|
|
49
|
+
// an External relationship names no part, so it gives way to one that does
|
|
50
|
+
const mainRels = packageRels.list.filter((r) => MAIN_PART_RELATIONSHIPS.includes(r.type));
|
|
51
|
+
const mainRel = (_b = mainRels.find((r) => !isExternal(r))) !== null && _b !== void 0 ? _b : mainRels[0];
|
|
35
52
|
if (!mainRel)
|
|
36
53
|
throw new InvalidFormatException('No relationship of type officeDocument');
|
|
37
54
|
const mainPartName = PartName.resolve(PartName.ROOT, mainRel.target);
|
|
@@ -39,19 +56,111 @@ export async function loadPackage(store, createPackage, options = {}) {
|
|
|
39
56
|
pkg.contentTypeManager = ctm;
|
|
40
57
|
pkg.sourcePartStore = store;
|
|
41
58
|
pkg.relationshipsPart = packageRels;
|
|
59
|
+
pkg.duplicateEntries = duplicateEntries;
|
|
60
|
+
pkg.multipleMainParts = mainParts === null || mainParts === void 0 ? void 0 : mainParts.warning;
|
|
61
|
+
pkg.externalMainPart = external;
|
|
42
62
|
packageRels.sourceP = pkg;
|
|
43
63
|
packageRels.package = pkg;
|
|
44
|
-
const loader = new Loader(pkg, store, registry, options.preprocessor);
|
|
64
|
+
const loader = new Loader(pkg, store, registry, options.preprocessor, followsWord);
|
|
45
65
|
await loader.addPartsFromRelationships(pkg, packageRels);
|
|
46
66
|
await loader.registerCustomXmlDataStorageParts();
|
|
67
|
+
// after the walk, so a target the kept part reaches by a relationship of its own, or a second relationship names, keeps its type
|
|
68
|
+
for (const name of (_c = mainParts === null || mainParts === void 0 ? void 0 : mainParts.dropped) !== null && _c !== void 0 ? _c : [])
|
|
69
|
+
if (!pkg.getPart(name))
|
|
70
|
+
ctm.removeOverrideContentType(name);
|
|
47
71
|
return pkg;
|
|
48
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* More than one officeDocument relationship (WD REQ-206's statement; CR-024 section 9): refused under `repair: 'refuse'`, naming
|
|
75
|
+
* the targets. Under `'word'` and `'all'` the last stands and the others go here, before anything is read, so that the package's class, the
|
|
76
|
+
* walk, `getMainPart()` and `getMainDocumentPart()` all find one main part, and a save writes one. `dropped` is the part
|
|
77
|
+
* names they gave, whose Overrides `loadPackage` settles after the walk.
|
|
78
|
+
*/
|
|
79
|
+
function oneMainPart(rels, followsWord) {
|
|
80
|
+
const mains = rels.list.filter((r) => OFFICE_DOCUMENT_RELATIONSHIPS.includes(r.type) && !isExternal(r));
|
|
81
|
+
if (mains.length < 2)
|
|
82
|
+
return undefined;
|
|
83
|
+
const names = mains.map((r) => PartName.resolve(PartName.ROOT, r.target));
|
|
84
|
+
if (!followsWord)
|
|
85
|
+
throw new MultipleMainPartsException(names.map((name) => name.name));
|
|
86
|
+
for (const r of mains.slice(0, -1))
|
|
87
|
+
rels.removeRelationship(r);
|
|
88
|
+
const partName = names[names.length - 1].name;
|
|
89
|
+
return {
|
|
90
|
+
warning: {
|
|
91
|
+
code: 'package.multiple_main_parts',
|
|
92
|
+
partName,
|
|
93
|
+
count: mains.length,
|
|
94
|
+
message: `${mains.length} officeDocument relationships in this package (REQ-206); the last's target read, ${partName}`,
|
|
95
|
+
},
|
|
96
|
+
dropped: names.slice(0, -1),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/** `LoadOptions.repair`, `'refuse'` when not given; any other value refused (WD REQ-207). */
|
|
100
|
+
function repairOf(repair) {
|
|
101
|
+
if (repair === undefined)
|
|
102
|
+
return 'refuse';
|
|
103
|
+
if (!REPAIR_MODES.includes(repair)) {
|
|
104
|
+
throw new Docx4JException(`repair: '${String(repair)}' is not ${REPAIR_MODES.map((m) => `'${m}'`).join(', ')} (WD REQ-207)`);
|
|
105
|
+
}
|
|
106
|
+
return repair;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* An `External` officeDocument relationship (WD REQ-206's NOTE; CR-031 section 2.2). With no internal one beside it the package
|
|
110
|
+
* has no main document part, refused at every value (REQ-321), where the URL used to be taken for a part name. Beside an
|
|
111
|
+
* internal one it's refused at `'refuse'` and `'word'`, first or last alike, since Word refuses it even through its repair;
|
|
112
|
+
* at `'all'` every such relationship goes here, before anything is read, so a save writes none and the URL is never
|
|
113
|
+
* fetched, and the warning names the part read: the last internal relationship's target, as Word's repair of several reads.
|
|
114
|
+
*/
|
|
115
|
+
function externalMainPart(rels, repair) {
|
|
116
|
+
const mains = rels.list.filter((r) => OFFICE_DOCUMENT_RELATIONSHIPS.includes(r.type));
|
|
117
|
+
const externals = mains.filter(isExternal);
|
|
118
|
+
if (externals.length === 0)
|
|
119
|
+
return undefined;
|
|
120
|
+
const urls = externals.map((r) => r.target);
|
|
121
|
+
const internals = mains.filter((r) => !isExternal(r)).map((r) => PartName.resolve(PartName.ROOT, r.target).name);
|
|
122
|
+
if (internals.length === 0) {
|
|
123
|
+
throw new InvalidFormatException(`This package's only officeDocument relationship is External, to ${urls.join(', ')}, so it has no `
|
|
124
|
+
+ 'main document part (REQ-321); refused at every value of repair. The URL is not fetched');
|
|
125
|
+
}
|
|
126
|
+
if (repair !== 'all')
|
|
127
|
+
throw new ExternalMainPartException(urls, internals);
|
|
128
|
+
for (const r of externals)
|
|
129
|
+
rels.removeRelationship(r);
|
|
130
|
+
const partName = internals[internals.length - 1];
|
|
131
|
+
return {
|
|
132
|
+
code: 'package.external_main_part',
|
|
133
|
+
partName,
|
|
134
|
+
urls,
|
|
135
|
+
message: `${urls.length === 1 ? 'An External officeDocument relationship' : `${urls.length} External officeDocument relationships`}, `
|
|
136
|
+
+ `to ${urls.join(', ')}, beside the internal one dropped, ${partName} read, the URL not fetched: a repair of this package's own (REQ-207)`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The store's duplicated names (CR-024, WD REQ-206), refused under `repair: 'refuse'` before anything is read, else one warning
|
|
141
|
+
* each. A store without `duplicates()` is not checked.
|
|
142
|
+
*/
|
|
143
|
+
function duplicateEntriesOf(store, followsWord) {
|
|
144
|
+
var _a;
|
|
145
|
+
const duplicates = (_a = store.duplicates) === null || _a === void 0 ? void 0 : _a.call(store);
|
|
146
|
+
if (!duplicates || duplicates.size === 0)
|
|
147
|
+
return [];
|
|
148
|
+
if (!followsWord)
|
|
149
|
+
throw new DuplicateEntryException(Object.fromEntries(duplicates));
|
|
150
|
+
return [...duplicates].map(([entry, count]) => ({
|
|
151
|
+
code: 'package.duplicate_entry',
|
|
152
|
+
entry,
|
|
153
|
+
count,
|
|
154
|
+
message: `${entry}: ${count} entries of one name in this package; the first read, the rest ignored (REQ-206)`,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
49
157
|
class Loader {
|
|
50
|
-
constructor(pkg, store, registry, preprocessor) {
|
|
158
|
+
constructor(pkg, store, registry, preprocessor, followsWord) {
|
|
51
159
|
this.pkg = pkg;
|
|
52
160
|
this.store = store;
|
|
53
161
|
this.registry = registry;
|
|
54
162
|
this.preprocessor = preprocessor;
|
|
163
|
+
this.followsWord = followsWord;
|
|
55
164
|
this.handled = new Set();
|
|
56
165
|
}
|
|
57
166
|
async addPartsFromRelationships(source, rp) {
|
|
@@ -88,6 +197,7 @@ class Loader {
|
|
|
88
197
|
const relsName = PartName.relsFor(partName).storeName;
|
|
89
198
|
if (this.store.has(relsName)) {
|
|
90
199
|
const rrp = new RelationshipsPart(part);
|
|
200
|
+
rrp.readsByLocalName = this.followsWord;
|
|
91
201
|
rrp.setBytes(await this.store.load(relsName));
|
|
92
202
|
await rrp.getContents();
|
|
93
203
|
part.relationshipsPart = rrp;
|
package/dist/opc/PartStore.d.mts
CHANGED
|
@@ -10,6 +10,35 @@ export interface PartStore {
|
|
|
10
10
|
load(partName: string): Promise<Uint8Array>;
|
|
11
11
|
/** Size if known without loading, else undefined. */
|
|
12
12
|
size?(partName: string): number | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* The names the container holds more than one entry of, OPC part names compared without case (WD REQ-206; CR-024): each
|
|
15
|
+
* first entry's spelling, with the number of entries, in container order. The load refuses a package with any, unless
|
|
16
|
+
* `LoadOptions.duplicateEntries` is `'first'`. Every store here has it; a store without it is not checked.
|
|
17
|
+
*/
|
|
18
|
+
duplicates?(): ReadonlyMap<string, number>;
|
|
19
|
+
}
|
|
20
|
+
/** An entry's key: its name without a leading '/', lower-cased, as `PartName`'s equality compares (CR-024 section 2.1). */
|
|
21
|
+
export declare function entryKey(name: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* A container's entries by key (`entryKey`), the first entry of each key kept with its spelling and its value and the
|
|
24
|
+
* rest counted: what each store reads its container into, so that `has`, `load` and `size` agree and look up without
|
|
25
|
+
* case, and `duplicates()` reports a name held twice (CR-024, WD REQ-206).
|
|
26
|
+
*/
|
|
27
|
+
export declare class EntryIndex<T> {
|
|
28
|
+
private readonly byKey;
|
|
29
|
+
/** Adds an entry; a second entry of a key is counted, its value not kept. */
|
|
30
|
+
add(name: string, value: T): void;
|
|
31
|
+
/** Sets an entry's value, replacing the one its key holds (a sink's write), its first spelling kept. */
|
|
32
|
+
set(name: string, value: T): void;
|
|
33
|
+
get(name: string): T | undefined;
|
|
34
|
+
has(name: string): boolean;
|
|
35
|
+
delete(name: string): boolean;
|
|
36
|
+
/** Each key's first spelling, in the order the entries were added. */
|
|
37
|
+
names(): string[];
|
|
38
|
+
/** Each key's value (its first entry's), in the same order. */
|
|
39
|
+
values(): T[];
|
|
40
|
+
/** The keys added more than once: the first spelling and the count. */
|
|
41
|
+
duplicates(): Map<string, number>;
|
|
13
42
|
}
|
|
14
43
|
export interface PutOptions {
|
|
15
44
|
/** Deflate in a zip (default true); ignored by containers that do not compress. */
|
|
@@ -23,7 +52,10 @@ export interface PartSink<R = unknown> {
|
|
|
23
52
|
/** Completes the container. */
|
|
24
53
|
finish(): Promise<R>;
|
|
25
54
|
}
|
|
26
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* An in-memory container: new packages, tests, and the result of `MemoryPartSink`. The constructor's entries are read as a
|
|
57
|
+
* container's (a second of one name counted, `duplicates()`); `put`, a sink's write, replaces.
|
|
58
|
+
*/
|
|
27
59
|
export declare class MemoryPartStore implements PartStore, PartSink<MemoryPartStore> {
|
|
28
60
|
private readonly parts;
|
|
29
61
|
/** Content types as put, for stores filled through the sink side. */
|
|
@@ -33,6 +65,7 @@ export declare class MemoryPartStore implements PartStore, PartSink<MemoryPartSt
|
|
|
33
65
|
has(partName: string): boolean;
|
|
34
66
|
load(partName: string): Promise<Uint8Array>;
|
|
35
67
|
size(partName: string): number | undefined;
|
|
68
|
+
duplicates(): ReadonlyMap<string, number>;
|
|
36
69
|
put(partName: string, bytes: Uint8Array, options?: PutOptions): void;
|
|
37
70
|
delete(partName: string): boolean;
|
|
38
71
|
finish(): Promise<MemoryPartStore>;
|
package/dist/opc/PartStore.mjs
CHANGED
|
@@ -1,28 +1,91 @@
|
|
|
1
|
-
/** An
|
|
1
|
+
/** An entry's key: its name without a leading '/', lower-cased, as `PartName`'s equality compares (CR-024 section 2.1). */
|
|
2
|
+
export function entryKey(name) {
|
|
3
|
+
return (name.startsWith('/') ? name.substring(1) : name).toLowerCase();
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A container's entries by key (`entryKey`), the first entry of each key kept with its spelling and its value and the
|
|
7
|
+
* rest counted: what each store reads its container into, so that `has`, `load` and `size` agree and look up without
|
|
8
|
+
* case, and `duplicates()` reports a name held twice (CR-024, WD REQ-206).
|
|
9
|
+
*/
|
|
10
|
+
export class EntryIndex {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.byKey = new Map();
|
|
13
|
+
}
|
|
14
|
+
/** Adds an entry; a second entry of a key is counted, its value not kept. */
|
|
15
|
+
add(name, value) {
|
|
16
|
+
const key = entryKey(name);
|
|
17
|
+
const entry = this.byKey.get(key);
|
|
18
|
+
if (entry)
|
|
19
|
+
entry.count++;
|
|
20
|
+
else
|
|
21
|
+
this.byKey.set(key, { name: name.startsWith('/') ? name.substring(1) : name, value, count: 1 });
|
|
22
|
+
}
|
|
23
|
+
/** Sets an entry's value, replacing the one its key holds (a sink's write), its first spelling kept. */
|
|
24
|
+
set(name, value) {
|
|
25
|
+
const entry = this.byKey.get(entryKey(name));
|
|
26
|
+
if (entry)
|
|
27
|
+
entry.value = value;
|
|
28
|
+
else
|
|
29
|
+
this.add(name, value);
|
|
30
|
+
}
|
|
31
|
+
get(name) {
|
|
32
|
+
var _a;
|
|
33
|
+
return (_a = this.byKey.get(entryKey(name))) === null || _a === void 0 ? void 0 : _a.value;
|
|
34
|
+
}
|
|
35
|
+
has(name) {
|
|
36
|
+
return this.byKey.has(entryKey(name));
|
|
37
|
+
}
|
|
38
|
+
delete(name) {
|
|
39
|
+
return this.byKey.delete(entryKey(name));
|
|
40
|
+
}
|
|
41
|
+
/** Each key's first spelling, in the order the entries were added. */
|
|
42
|
+
names() {
|
|
43
|
+
return [...this.byKey.values()].map((e) => e.name);
|
|
44
|
+
}
|
|
45
|
+
/** Each key's value (its first entry's), in the same order. */
|
|
46
|
+
values() {
|
|
47
|
+
return [...this.byKey.values()].map((e) => e.value);
|
|
48
|
+
}
|
|
49
|
+
/** The keys added more than once: the first spelling and the count. */
|
|
50
|
+
duplicates() {
|
|
51
|
+
const out = new Map();
|
|
52
|
+
for (const e of this.byKey.values())
|
|
53
|
+
if (e.count > 1)
|
|
54
|
+
out.set(e.name, e.count);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* An in-memory container: new packages, tests, and the result of `MemoryPartSink`. The constructor's entries are read as a
|
|
60
|
+
* container's (a second of one name counted, `duplicates()`); `put`, a sink's write, replaces.
|
|
61
|
+
*/
|
|
2
62
|
export class MemoryPartStore {
|
|
3
63
|
constructor(entries) {
|
|
4
|
-
this.parts = new
|
|
64
|
+
this.parts = new EntryIndex();
|
|
5
65
|
/** Content types as put, for stores filled through the sink side. */
|
|
6
66
|
this.contentTypes = new Map();
|
|
7
67
|
if (entries)
|
|
8
68
|
for (const [name, bytes] of entries)
|
|
9
|
-
this.parts.
|
|
69
|
+
this.parts.add(normalize(name), bytes);
|
|
10
70
|
}
|
|
11
71
|
partNames() {
|
|
12
|
-
return this.parts.
|
|
72
|
+
return this.parts.names();
|
|
13
73
|
}
|
|
14
74
|
has(partName) {
|
|
15
|
-
return this.parts.has(
|
|
75
|
+
return this.parts.has(partName);
|
|
16
76
|
}
|
|
17
77
|
async load(partName) {
|
|
18
|
-
const bytes = this.parts.get(
|
|
78
|
+
const bytes = this.parts.get(partName);
|
|
19
79
|
if (bytes === undefined)
|
|
20
80
|
throw new Error(`No part ${partName}`);
|
|
21
81
|
return bytes;
|
|
22
82
|
}
|
|
23
83
|
size(partName) {
|
|
24
84
|
var _a;
|
|
25
|
-
return (_a = this.parts.get(
|
|
85
|
+
return (_a = this.parts.get(partName)) === null || _a === void 0 ? void 0 : _a.length;
|
|
86
|
+
}
|
|
87
|
+
duplicates() {
|
|
88
|
+
return this.parts.duplicates();
|
|
26
89
|
}
|
|
27
90
|
put(partName, bytes, options) {
|
|
28
91
|
const name = normalize(partName);
|
|
@@ -31,7 +94,7 @@ export class MemoryPartStore {
|
|
|
31
94
|
this.contentTypes.set(name, options.contentType);
|
|
32
95
|
}
|
|
33
96
|
delete(partName) {
|
|
34
|
-
return this.parts.delete(
|
|
97
|
+
return this.parts.delete(partName);
|
|
35
98
|
}
|
|
36
99
|
async finish() {
|
|
37
100
|
return this;
|
package/dist/opc/Save.d.mts
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
import type { PartSink } from './PartStore.mjs';
|
|
2
|
+
import type { ValueOutOfRangeWarning, MisplacedContentWarning } from './mce/preprocessor.mjs';
|
|
3
|
+
import type { ContentSkippedWarning } from './skipped.mjs';
|
|
2
4
|
import type { OpcPackage } from '../packages/OpcPackage.mjs';
|
|
5
|
+
/**
|
|
6
|
+
* A value a save wrote in its normal form, or left out (CR-015 D2 and D8; the objects facade's normaliser, its
|
|
7
|
+
* CR-013 phase C, docx4j CR-061's rule): `path` from the part's root, `before` as read, `after` as written, null
|
|
8
|
+
* where the attribute or the element was left out. The code is this package's (CR-015 D8); docx4j-python CR-018 reports
|
|
9
|
+
* the same as `package.last_save.normalised`.
|
|
10
|
+
*/
|
|
11
|
+
export interface ValueNormalised {
|
|
12
|
+
code: 'value.normalised';
|
|
13
|
+
partName: string;
|
|
14
|
+
path: string;
|
|
15
|
+
before: string | undefined;
|
|
16
|
+
after: string | null;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What the last save of a package did beyond writing it: each value it normalised (CR-015 D8), each integer
|
|
21
|
+
* attribute value it wrote that Word 365 reads differently, written as held (CR-017 P3, E3), with
|
|
22
|
+
* `checkContentOnSave` off, each child it wrote where its container never admits one (CR-016 D2), each with its path,
|
|
23
|
+
* each item the read dropped that a changed part was written without as Word's own save writes it (CR-025 section 10), and,
|
|
24
|
+
* with `checkLossOnSave` off, each it was written without that Word's save keeps or nobody has measured (CR-025 D8).
|
|
25
|
+
*/
|
|
26
|
+
export interface SaveReport {
|
|
27
|
+
normalised: ValueNormalised[];
|
|
28
|
+
outOfRange: ValueOutOfRangeWarning[];
|
|
29
|
+
misplaced: MisplacedContentWarning[];
|
|
30
|
+
/** Items a changed part was written without, Word's own save dropping them too (`onSave: 'dropped'`, CR-025 D14): never refused. */
|
|
31
|
+
dropped: ContentSkippedWarning[];
|
|
32
|
+
/** Items a changed part was written without under `checkLossOnSave` off (`onSave: 'lost'`). */
|
|
33
|
+
lost: ContentSkippedWarning[];
|
|
34
|
+
}
|
|
3
35
|
/**
|
|
4
36
|
* Writes a package to a sink (docx4j io3.Save): `[Content_Types].xml` first, then the package
|
|
5
37
|
* relationships, then every part reachable through relationships, each once. Relationship parts
|