@docx4j/core-ts 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -0
- package/dist/model/content/Body.d.mts +36 -2
- package/dist/model/content/Body.mjs +79 -4
- package/dist/model/content/Comment.d.mts +15 -5
- package/dist/model/content/Comment.mjs +70 -22
- package/dist/model/content/List.d.mts +13 -2
- package/dist/model/content/List.mjs +48 -9
- package/dist/model/content/Paragraph.d.mts +11 -1
- package/dist/model/content/Paragraph.mjs +18 -7
- package/dist/model/content/Range.d.mts +7 -2
- package/dist/model/content/Range.mjs +21 -8
- package/dist/model/content/binder.d.mts +44 -0
- package/dist/model/content/binder.mjs +95 -0
- package/dist/model/content/comments.d.mts +19 -1
- package/dist/model/content/index.d.mts +5 -3
- package/dist/model/content/index.mjs +3 -1
- package/dist/model/content/search.d.mts +27 -2
- package/dist/model/content/search.mjs +59 -3
- package/dist/model/content/stylesFacade.d.mts +37 -0
- package/dist/model/content/stylesFacade.mjs +114 -0
- package/dist/model/content/tracking.d.mts +57 -2
- package/dist/model/content/tracking.mjs +47 -15
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +7 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +40 -6
- package/dist/model/customxml/xpath.d.mts +18 -3
- package/dist/model/customxml/xpath.mjs +18 -3
- package/dist/office-js/index.d.mts +3 -1
- package/dist/office-js/run.d.mts +12 -2
- package/dist/office-js/run.mjs +8 -1
- package/dist/office-js/shimmed.d.mts +46 -0
- package/dist/office-js/shimmed.mjs +1 -0
- package/dist/opc/exceptions.d.mts +25 -0
- package/dist/opc/exceptions.mjs +20 -0
- package/dist/opc/index.d.mts +1 -1
- package/dist/opc/index.mjs +1 -1
- package/dist/opc/mce/understood.mjs +37 -8
- package/dist/packages/WordprocessingMLPackage.d.mts +92 -2
- package/dist/packages/WordprocessingMLPackage.mjs +144 -1
- package/dist/parts/XmlPart.d.mts +44 -0
- package/dist/parts/XmlPart.mjs +86 -3
- package/dist/parts/sml/index.d.mts +9 -8
- package/dist/parts/sml/index.mjs +23 -19
- package/dist/parts/wml/index.d.mts +10 -2
- package/dist/parts/wml/index.mjs +11 -3
- package/dist/parts/wml/spliceableStyles.d.mts +1 -0
- package/dist/parts/wml/spliceableStyles.mjs +122 -0
- package/package.json +2 -2
|
@@ -3,6 +3,19 @@ import { type Element, type RevisionHolder } from './tree.mjs';
|
|
|
3
3
|
import type { Author } from './comments.mjs';
|
|
4
4
|
/** Office JS `Word.ChangeTrackingMode`. */
|
|
5
5
|
export type ChangeTrackingMode = 'Off' | 'TrackAll' | 'TrackMineOnly';
|
|
6
|
+
/**
|
|
7
|
+
* `w:id` on these is the one annotation id space (ECMA-376 17.13.5.4): revisions, bookmarks,
|
|
8
|
+
* comment range marks and permissions share it. `w:comment/@w:id` (docx4j `Comments.Comment`,
|
|
9
|
+
* which also extends `CTMarkup`) is a different space and is excluded, so that phase G's
|
|
10
|
+
* comment ids and phase F's revision ids never have to agree.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MARKUP_TYPES: ReadonlySet<string>;
|
|
13
|
+
/**
|
|
14
|
+
* The highest annotation id in a tree (`MARKUP_TYPES` only, the one `w:id` space of ECMA-376
|
|
15
|
+
* 17.13.5.4). Shared so that the tracker's scan of the unmarshalled parts and the package's
|
|
16
|
+
* private read of the rest cannot drift apart (CR-002 section 28.2).
|
|
17
|
+
*/
|
|
18
|
+
export declare function highestAnnotationId(root: object, from?: number): number;
|
|
6
19
|
/** What a package offers so that its edits can be tracked; `WordprocessingMLPackage` implements it. */
|
|
7
20
|
export interface TrackingHost {
|
|
8
21
|
/**
|
|
@@ -15,9 +28,43 @@ export interface TrackingHost {
|
|
|
15
28
|
readonly trackedChangeDate?: Date | undefined;
|
|
16
29
|
/** The trees to scan for the highest annotation id in use: the parts already unmarshalled. */
|
|
17
30
|
markupRoots(): object[];
|
|
31
|
+
/**
|
|
32
|
+
* A floor for the annotation id, above every id in the parts that were **not** unmarshalled
|
|
33
|
+
* (`seedAnnotationIds()` reads them privately). 0 until it is seeded; `markupRoots()` covers the
|
|
34
|
+
* rest, so the next id is one above the greater of the two (CR-002 section 28.2).
|
|
35
|
+
*/
|
|
36
|
+
readonly annotationIdFloor: number;
|
|
37
|
+
/**
|
|
38
|
+
* The last annotation id issued in the document, or `undefined` until the first, when the tracker
|
|
39
|
+
* scans for the highest in use. The host holds it rather than the tracker because a document has
|
|
40
|
+
* one id space and may have several trackers over its life - `withTracking` can make one with
|
|
41
|
+
* another mode - and a tracker with a counter of its own reissues the ids another one gave out
|
|
42
|
+
* (CR-002 section 31).
|
|
43
|
+
*/
|
|
44
|
+
annotationIdCounter: number | undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* What `WordprocessingMLPackage.withTracking` records for the duration of one call: who, when, and
|
|
48
|
+
* which mode (`TrackAll` unless said otherwise). The document's own `w:trackRevisions` is not
|
|
49
|
+
* touched - an editor's agent records its edits as itself in a room whose setting belongs to the
|
|
50
|
+
* document, not to the caller (CR-002 section 28.1).
|
|
51
|
+
*/
|
|
52
|
+
export interface TrackingScope {
|
|
53
|
+
author: Author;
|
|
54
|
+
/** The `w:date` for every revision in the call; `undefined` means now, to the minute. */
|
|
55
|
+
date?: Date | undefined;
|
|
56
|
+
/** `TrackAll` unless given; `Off` runs `fn` with tracking suppressed for the call. */
|
|
57
|
+
mode?: ChangeTrackingMode | undefined;
|
|
18
58
|
}
|
|
19
59
|
/** The tracker of a package whose mode is not `Off`; `undefined` when it is (duck typed, no import cycle). */
|
|
20
60
|
export declare function trackerOf(pkg: unknown): ChangeTracker | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Now, with the seconds and milliseconds dropped, which is what Word stamps a revision with.
|
|
63
|
+
* Not cosmetic: Word groups adjacent revisions by author **and** timestamp, so a per-second stamp
|
|
64
|
+
* makes one change of every keystroke run and an editor's typing unreviewable (CR-002 section 28.2).
|
|
65
|
+
* A caller that sets `trackedChangeDate` gets exactly the date it asked for, truncated or not.
|
|
66
|
+
*/
|
|
67
|
+
export declare function nowToTheMinute(): Date;
|
|
21
68
|
/** An `XmlCalendar` in UTC, as Word writes `w:date` (an xsd:dateTime ending in `Z`). */
|
|
22
69
|
export declare function calendarOf(date: Date): wml.XmlCalendar;
|
|
23
70
|
/** The `Date` of a `w:date`, or undefined when there is none. */
|
|
@@ -33,11 +80,19 @@ export declare function dateOf(cal: wml.XmlCalendar | undefined): Date | undefin
|
|
|
33
80
|
export declare class ChangeTracker {
|
|
34
81
|
readonly host: TrackingHost;
|
|
35
82
|
readonly mode: ChangeTrackingMode;
|
|
36
|
-
private counter;
|
|
37
83
|
constructor(host: TrackingHost, mode: ChangeTrackingMode);
|
|
38
84
|
/** The `w:author` a new revision carries: the package author's name. */
|
|
39
85
|
get author(): string;
|
|
40
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* The next annotation id: one above the highest in use anywhere in the document - the parts
|
|
88
|
+
* already unmarshalled, scanned here, and the rest through the host's `annotationIdFloor`,
|
|
89
|
+
* which `seedAnnotationIds()` fills from their bytes without unmarshalling them (CR-002
|
|
90
|
+
* section 28.2; before that this saw only the unmarshalled parts, so a revision in an unread
|
|
91
|
+
* footnote or comment part did not raise the counter).
|
|
92
|
+
*
|
|
93
|
+
* The scan runs once per document, not per tracker: the counter is the host's. The floor is
|
|
94
|
+
* consulted on every call, so a `seedAnnotationIds()` awaited after the first id still counts.
|
|
95
|
+
*/
|
|
41
96
|
nextId(): number;
|
|
42
97
|
/** The `w:id`, `w:author` and `w:date` a new revision carries. */
|
|
43
98
|
markup(): {
|
|
@@ -9,7 +9,7 @@ import { W_NS, linkParents, walk, typeNameOf, revisionKindOf } from './tree.mjs'
|
|
|
9
9
|
* which also extends `CTMarkup`) is a different space and is excluded, so that phase G's
|
|
10
10
|
* comment ids and phase F's revision ids never have to agree.
|
|
11
11
|
*/
|
|
12
|
-
const MARKUP_TYPES = new Set([
|
|
12
|
+
export const MARKUP_TYPES = new Set([
|
|
13
13
|
'org_docx4j_wml.CTMarkup', 'org_docx4j_wml.CTBookmark', 'org_docx4j_wml.CTBookmarkRange',
|
|
14
14
|
'org_docx4j_wml.CTCellMergeTrackChange', 'org_docx4j_wml.CTMarkupRange', 'org_docx4j_wml.CTMathRunTrackChange',
|
|
15
15
|
'org_docx4j_wml.CTMoveBookmark', 'org_docx4j_wml.CTMoveFromRangeEnd', 'org_docx4j_wml.CTMoveToRangeEnd',
|
|
@@ -19,10 +19,36 @@ const MARKUP_TYPES = new Set([
|
|
|
19
19
|
'org_docx4j_wml.CTTrackChangeNumbering', 'org_docx4j_wml.CTTrackChangeRange',
|
|
20
20
|
'org_docx4j_wml.ParaRPrChange', 'org_docx4j_wml.RunDel', 'org_docx4j_wml.RunIns', 'org_docx4j_wml.RunTrackChange',
|
|
21
21
|
]);
|
|
22
|
+
/**
|
|
23
|
+
* The highest annotation id in a tree (`MARKUP_TYPES` only, the one `w:id` space of ECMA-376
|
|
24
|
+
* 17.13.5.4). Shared so that the tracker's scan of the unmarshalled parts and the package's
|
|
25
|
+
* private read of the rest cannot drift apart (CR-002 section 28.2).
|
|
26
|
+
*/
|
|
27
|
+
export function highestAnnotationId(root, from = 0) {
|
|
28
|
+
let highest = from;
|
|
29
|
+
walk(root, (value) => {
|
|
30
|
+
const tn = value.TYPE_NAME;
|
|
31
|
+
const id = value.id;
|
|
32
|
+
if (tn !== undefined && MARKUP_TYPES.has(tn) && typeof id === 'number' && id > highest)
|
|
33
|
+
highest = id;
|
|
34
|
+
});
|
|
35
|
+
return highest;
|
|
36
|
+
}
|
|
22
37
|
/** The tracker of a package whose mode is not `Off`; `undefined` when it is (duck typed, no import cycle). */
|
|
23
38
|
export function trackerOf(pkg) {
|
|
24
39
|
return pkg === null || pkg === void 0 ? void 0 : pkg.changeTracker;
|
|
25
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Now, with the seconds and milliseconds dropped, which is what Word stamps a revision with.
|
|
43
|
+
* Not cosmetic: Word groups adjacent revisions by author **and** timestamp, so a per-second stamp
|
|
44
|
+
* makes one change of every keystroke run and an editor's typing unreviewable (CR-002 section 28.2).
|
|
45
|
+
* A caller that sets `trackedChangeDate` gets exactly the date it asked for, truncated or not.
|
|
46
|
+
*/
|
|
47
|
+
export function nowToTheMinute() {
|
|
48
|
+
const now = new Date();
|
|
49
|
+
now.setUTCSeconds(0, 0);
|
|
50
|
+
return now;
|
|
51
|
+
}
|
|
26
52
|
/** An `XmlCalendar` in UTC, as Word writes `w:date` (an xsd:dateTime ending in `Z`). */
|
|
27
53
|
export function calendarOf(date) {
|
|
28
54
|
return {
|
|
@@ -58,26 +84,32 @@ export class ChangeTracker {
|
|
|
58
84
|
get author() {
|
|
59
85
|
return this.host.author.name;
|
|
60
86
|
}
|
|
61
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* The next annotation id: one above the highest in use anywhere in the document - the parts
|
|
89
|
+
* already unmarshalled, scanned here, and the rest through the host's `annotationIdFloor`,
|
|
90
|
+
* which `seedAnnotationIds()` fills from their bytes without unmarshalling them (CR-002
|
|
91
|
+
* section 28.2; before that this saw only the unmarshalled parts, so a revision in an unread
|
|
92
|
+
* footnote or comment part did not raise the counter).
|
|
93
|
+
*
|
|
94
|
+
* The scan runs once per document, not per tracker: the counter is the host's. The floor is
|
|
95
|
+
* consulted on every call, so a `seedAnnotationIds()` awaited after the first id still counts.
|
|
96
|
+
*/
|
|
62
97
|
nextId() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (tn !== undefined && MARKUP_TYPES.has(tn) && typeof id === 'number' && id > highest)
|
|
70
|
-
highest = id;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
this.counter = highest;
|
|
98
|
+
const host = this.host;
|
|
99
|
+
let counter = host.annotationIdCounter;
|
|
100
|
+
if (counter === undefined) {
|
|
101
|
+
counter = 0;
|
|
102
|
+
for (const root of host.markupRoots())
|
|
103
|
+
counter = highestAnnotationId(root, counter);
|
|
74
104
|
}
|
|
75
|
-
|
|
105
|
+
counter = Math.max(counter, host.annotationIdFloor) + 1;
|
|
106
|
+
host.annotationIdCounter = counter;
|
|
107
|
+
return counter;
|
|
76
108
|
}
|
|
77
109
|
/** The `w:id`, `w:author` and `w:date` a new revision carries. */
|
|
78
110
|
markup() {
|
|
79
111
|
var _a;
|
|
80
|
-
return { id: this.nextId(), author: this.author, date: calendarOf((_a = this.host.trackedChangeDate) !== null && _a !== void 0 ? _a :
|
|
112
|
+
return { id: this.nextId(), author: this.author, date: calendarOf((_a = this.host.trackedChangeDate) !== null && _a !== void 0 ? _a : nowToTheMinute()) };
|
|
81
113
|
}
|
|
82
114
|
/** A `w:ins` / `w:del` attribute set: the id, this package's author and the date. */
|
|
83
115
|
trackChange() {
|
|
@@ -40,9 +40,16 @@ export declare class CustomXmlPartCollection implements CustomXmlPartOwner, Cust
|
|
|
40
40
|
* A new custom XML part holding this XML, with its properties part and a fresh itemID, related
|
|
41
41
|
* from the main document part (docx4j's `AbstractMigrator.addPropertiesPart` recipe: Word
|
|
42
42
|
* silently drops a custom XML part that only the package relates to).
|
|
43
|
+
*
|
|
44
|
+
* `itemID` and `partName` may be given, both checked unused, for a co-editing room where two
|
|
45
|
+
* sessions allocate at once and the next free name is not the right answer (CR-002 section 24).
|
|
46
|
+
* A clash throws rather than renaming, as a chosen list `numId` does: the caller is asserting
|
|
47
|
+
* something about the room's state, and renaming would break the peer that chose it.
|
|
43
48
|
*/
|
|
44
49
|
add(xml: string, options?: {
|
|
45
50
|
schemaRefs?: string[];
|
|
51
|
+
itemID?: string;
|
|
52
|
+
partName?: string;
|
|
46
53
|
}): CustomXmlPart;
|
|
47
54
|
/**
|
|
48
55
|
* Removes a part, its properties part and the relationships (Office JS CustomXmlPart.delete).
|
|
@@ -33,7 +33,10 @@ export class CustomXmlPartCollection {
|
|
|
33
33
|
if (!this.views.has(part))
|
|
34
34
|
this.views.set(part, await this.viewFor(part));
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
// A parsed document, not the global one: whether a native `document.evaluate` can read these
|
|
37
|
+
// trees is a property of the parser that built them (CR-002 section 21).
|
|
38
|
+
const parsed = this.views.size > 0 ? [...this.views.values()][0].document : undefined;
|
|
39
|
+
await this.host.xpathEngine.ready(parsed);
|
|
37
40
|
return this.items;
|
|
38
41
|
}
|
|
39
42
|
/** The parts, in the order they were registered. Call `load()` once first: a DOM has to be parsed. */
|
|
@@ -61,20 +64,40 @@ export class CustomXmlPartCollection {
|
|
|
61
64
|
* A new custom XML part holding this XML, with its properties part and a fresh itemID, related
|
|
62
65
|
* from the main document part (docx4j's `AbstractMigrator.addPropertiesPart` recipe: Word
|
|
63
66
|
* silently drops a custom XML part that only the package relates to).
|
|
67
|
+
*
|
|
68
|
+
* `itemID` and `partName` may be given, both checked unused, for a co-editing room where two
|
|
69
|
+
* sessions allocate at once and the next free name is not the right answer (CR-002 section 24).
|
|
70
|
+
* A clash throws rather than renaming, as a chosen list `numId` does: the caller is asserting
|
|
71
|
+
* something about the room's state, and renaming would break the peer that chose it.
|
|
64
72
|
*/
|
|
65
73
|
add(xml, options = {}) {
|
|
66
|
-
var _a;
|
|
74
|
+
var _a, _b;
|
|
67
75
|
const document = parseXml(xml);
|
|
68
76
|
const root = document.documentElement;
|
|
69
77
|
if (!root)
|
|
70
78
|
throw new Docx4JException('A custom XML part needs a document element');
|
|
71
|
-
|
|
79
|
+
// Everything that can refuse the call runs before a part is made, so a refusal leaves the package
|
|
80
|
+
// as it was (CR-002 section 31: a malformed itemID used to be refused after the data part was
|
|
81
|
+
// related, which left it in the package without a properties part). The itemID is checked
|
|
82
|
+
// against the keys the package indexes its custom XML parts by, which needs no parse; the views
|
|
83
|
+
// do, and `load()` is not a precondition of `add()`.
|
|
84
|
+
const chosenName = options.partName === undefined ? undefined : PartName.of(options.partName);
|
|
85
|
+
if (chosenName && ((_a = this.host.customXmlRelationshipSource().package) === null || _a === void 0 ? void 0 : _a.parts.get(chosenName.name))) {
|
|
86
|
+
throw new Docx4JException(`The part name ${chosenName.name} is already in this package`);
|
|
87
|
+
}
|
|
88
|
+
const itemID = options.itemID === undefined ? `{${uuid().toUpperCase()}}` : normaliseChosenItemID(options.itemID);
|
|
89
|
+
if (options.itemID !== undefined) {
|
|
90
|
+
const key = normaliseId(itemID);
|
|
91
|
+
if ([...this.host.customXmlDataStorageParts.keys()].some((existing) => normaliseId(existing) === key)) {
|
|
92
|
+
throw new Docx4JException(`The itemID ${options.itemID} is already in use by a custom XML part`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const dataPart = new CustomXmlDataStoragePart(chosenName !== null && chosenName !== void 0 ? chosenName : '/customXml/item1.xml');
|
|
72
96
|
dataPart.setDocument(document);
|
|
73
|
-
this.host.customXmlRelationshipSource().addTargetPart(dataPart, 'RENAME_IF_NAME_EXISTS');
|
|
74
|
-
const itemID = `{${uuid().toUpperCase()}}`;
|
|
97
|
+
this.host.customXmlRelationshipSource().addTargetPart(dataPart, chosenName ? 'OVERWRITE_IF_NAME_EXISTS' : 'RENAME_IF_NAME_EXISTS');
|
|
75
98
|
const propsName = PartName.of(`/customXml/itemProps${suffixOf(dataPart.partName)}.xml`);
|
|
76
99
|
const props = new CustomXmlDataStoragePropertiesPart(propsName);
|
|
77
|
-
const refs = (
|
|
100
|
+
const refs = (_b = options.schemaRefs) !== null && _b !== void 0 ? _b : (root.namespaceURI ? [root.namespaceURI] : []);
|
|
78
101
|
props.setContents(createDatastoreItem({
|
|
79
102
|
itemID,
|
|
80
103
|
...(refs.length > 0 ? { schemaRefs: { schemaRef: refs.map((uri) => ({ uri })) } } : {}),
|
|
@@ -152,6 +175,17 @@ export class CustomXmlPartCollection {
|
|
|
152
175
|
}
|
|
153
176
|
}
|
|
154
177
|
/** An itemID without braces, lower-cased: how docx4j keys the map and how Office JS compares ids. */
|
|
178
|
+
/**
|
|
179
|
+
* A chosen itemID in the form the properties part carries: braced and upper case, as Word and
|
|
180
|
+
* `uuid()` write it. A caller may pass it either way round (CR-002 section 24).
|
|
181
|
+
*/
|
|
182
|
+
function normaliseChosenItemID(id) {
|
|
183
|
+
const bare = id.trim().replace(/^\{|\}$/g, '');
|
|
184
|
+
if (!/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(bare)) {
|
|
185
|
+
throw new Docx4JException(`An itemID must be a GUID, with or without braces, not ${id}`);
|
|
186
|
+
}
|
|
187
|
+
return `{${bare.toUpperCase()}}`;
|
|
188
|
+
}
|
|
155
189
|
function normaliseId(id) {
|
|
156
190
|
return id.replace(/[{}]/g, '').toLowerCase();
|
|
157
191
|
}
|
|
@@ -19,8 +19,15 @@ export type BooleanConversionMode = 'java' | 'xpath1' | 'xpath2';
|
|
|
19
19
|
* string, number or boolean result. `namespaces` maps prefixes used in the expression to URIs.
|
|
20
20
|
*/
|
|
21
21
|
export interface XPathEngine {
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Prepares the engine (loads the `xpath` package in Node); idempotent, and cheap once done.
|
|
24
|
+
*
|
|
25
|
+
* `context` is a node from a document the engine will be asked about, when the caller has one:
|
|
26
|
+
* whether a native `document.evaluate` can be used is a property of **that document**, not of
|
|
27
|
+
* the global one, and the two differ in a mixed environment - a jsdom test whose XML is parsed
|
|
28
|
+
* by xmldom has a global `document.evaluate` that cannot evaluate over the parsed tree.
|
|
29
|
+
*/
|
|
30
|
+
ready(context?: Node): Promise<void>;
|
|
24
31
|
/** True when `select` and `selectValue` can be called synchronously. */
|
|
25
32
|
readonly isReady: boolean;
|
|
26
33
|
select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
|
|
@@ -55,7 +62,15 @@ export declare class DefaultXPathEngine implements XPathEngine {
|
|
|
55
62
|
/** True when the runtime has a native `document.evaluate` (a browser, a Word add-in). */
|
|
56
63
|
private native;
|
|
57
64
|
get isReady(): boolean;
|
|
58
|
-
|
|
65
|
+
/**
|
|
66
|
+
* @param context a node from a document this engine will be asked about. Given one, readiness is
|
|
67
|
+
* decided from **that document** rather than from the global: a global `document.evaluate` says
|
|
68
|
+
* nothing about a tree some other parser built, and in a mixed environment - jsdom's global
|
|
69
|
+
* with xmldom's parser, which is what a Node test runner gives when the runtime resolves its
|
|
70
|
+
* `node` export condition - the global would claim readiness the parsed tree cannot honour.
|
|
71
|
+
* `pkg.customXmlParts.load()` passes a parsed document for exactly this reason.
|
|
72
|
+
*/
|
|
73
|
+
ready(context?: Node): Promise<void>;
|
|
59
74
|
select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
|
|
60
75
|
selectValue(expression: string, context: Node, namespaces?: Record<string, string>): XPathValue;
|
|
61
76
|
private call;
|
|
@@ -67,9 +67,19 @@ export class DefaultXPathEngine {
|
|
|
67
67
|
get isReady() {
|
|
68
68
|
return this.native || this.module !== undefined;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @param context a node from a document this engine will be asked about. Given one, readiness is
|
|
72
|
+
* decided from **that document** rather than from the global: a global `document.evaluate` says
|
|
73
|
+
* nothing about a tree some other parser built, and in a mixed environment - jsdom's global
|
|
74
|
+
* with xmldom's parser, which is what a Node test runner gives when the runtime resolves its
|
|
75
|
+
* `node` export condition - the global would claim readiness the parsed tree cannot honour.
|
|
76
|
+
* `pkg.customXmlParts.load()` passes a parsed document for exactly this reason.
|
|
77
|
+
*/
|
|
78
|
+
async ready(context) {
|
|
71
79
|
var _a;
|
|
72
|
-
if (this.
|
|
80
|
+
if (this.module !== undefined)
|
|
81
|
+
return;
|
|
82
|
+
if (context === undefined ? this.native : nativeEvaluatorFor(context) !== undefined)
|
|
73
83
|
return;
|
|
74
84
|
(_a = this.loading) !== null && _a !== void 0 ? _a : (this.loading = (async () => {
|
|
75
85
|
const specifier = 'xpath';
|
|
@@ -124,7 +134,12 @@ export class DefaultXPathEngine {
|
|
|
124
134
|
}
|
|
125
135
|
call(expression, context, namespaces) {
|
|
126
136
|
if (!this.module) {
|
|
127
|
-
throw new Docx4JException(
|
|
137
|
+
throw new Docx4JException(this.native
|
|
138
|
+
? 'This document cannot be evaluated by the host DOM: it was parsed by another one (jsdom\'s '
|
|
139
|
+
+ 'document.evaluate over an xmldom tree, say). Install the optional peer dependency '
|
|
140
|
+
+ "'xpath' and await pkg.xpathEngine.ready(node) with a node of this document, or set "
|
|
141
|
+
+ 'pkg.xpathEngine to an engine that can read it'
|
|
142
|
+
: 'The XPath engine is not ready yet: await pkg.customXmlParts.load() (or pkg.xpathEngine.ready()) once before selecting nodes');
|
|
128
143
|
}
|
|
129
144
|
const select = Object.keys(namespaces).length > 0 ? this.module.useNamespaces(namespaces) : this.module.select;
|
|
130
145
|
return select(expression, context);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { run, RequestContext, type RunOptions, type TrackedObjects } from './run.mjs';
|
|
1
|
+
import { run, RequestContext, type RunOptions, type TrackedObjects, type ShimmedDocument } from './run.mjs';
|
|
2
2
|
import { Document, DocumentProperties } from './document.mjs';
|
|
3
3
|
import { supported, SUBSET_MEMBERS } from './supported.mjs';
|
|
4
4
|
import { ClientResult, unwrap, nullObject, Wrapper, type Collection, type PendingSink } from './proxy.mjs';
|
|
@@ -6,6 +6,8 @@ import { NotSupportedError, ItemNotFoundError, ValueNotLoadedError } from './err
|
|
|
6
6
|
import { toApiScript, type ApiScriptOptions, type ApiScriptTarget } from './toApiScript.mjs';
|
|
7
7
|
import { InsertLocation, Alignment, UnderlineType, ChangeTrackingMode, BreakType, ContentControlType, Style, ErrorCodes, SearchOptions, ListLevelType, ListNumbering, ListBullet, type InsertLocationValue, type ChangeTrackingModeValue, type BreakTypeValue, type ContentControlTypeValue, type StyleValue, type AlignmentValue, type UnderlineTypeValue, type ListLevelTypeValue, type ListNumberingValue, type ListBulletValue } from './enums.mjs';
|
|
8
8
|
export { run, RequestContext, Document, DocumentProperties, ClientResult, unwrap, nullObject, Wrapper, toApiScript, supported, SUBSET_MEMBERS };
|
|
9
|
+
export type { Shimmed, ShimmedObject, ShimmedCollection, Loadable } from './shimmed.mjs';
|
|
10
|
+
export type { ShimmedDocument };
|
|
9
11
|
export { NotSupportedError, ItemNotFoundError, ValueNotLoadedError };
|
|
10
12
|
export { InsertLocation, Alignment, UnderlineType, ChangeTrackingMode, BreakType, ContentControlType, Style, ErrorCodes, SearchOptions };
|
|
11
13
|
export { ListLevelType, ListNumbering, ListBullet };
|
package/dist/office-js/run.d.mts
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import type { WordprocessingMLPackage } from '../packages/WordprocessingMLPackage.mjs';
|
|
2
2
|
import { Document, type RunOptions } from './document.mjs';
|
|
3
3
|
import { type PendingSink } from './proxy.mjs';
|
|
4
|
+
import type { Shimmed } from './shimmed.mjs';
|
|
4
5
|
export type { RunOptions };
|
|
6
|
+
/** The `Document` as the shim presents it (CR-002 section 22.1): `context.document`'s type. */
|
|
7
|
+
export type ShimmedDocument = Shimmed<Document>;
|
|
5
8
|
/** Office JS's `context.trackedObjects`: object lifetime is the garbage collector's business here. */
|
|
6
9
|
export interface TrackedObjects {
|
|
7
10
|
add<T>(object: T): T;
|
|
8
11
|
remove<T>(object: T): T;
|
|
9
12
|
}
|
|
10
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* A subset of Office JS `Word.RequestContext` over a package.
|
|
15
|
+
*
|
|
16
|
+
* `document` is typed `ShimmedDocument`, which is what the proxies actually present: every array a
|
|
17
|
+
* `Collection` with `items` and `getFirst`, every object `load`able (CR-002 section 22.1). The
|
|
18
|
+
* runtime object is the same either way; the type is what lets an add-in script type-check against
|
|
19
|
+
* this package exactly as it does against Office JS.
|
|
20
|
+
*/
|
|
11
21
|
export declare class RequestContext implements PendingSink {
|
|
12
22
|
/** The package this context is over (extension: Office JS has a host document). */
|
|
13
23
|
readonly package_: WordprocessingMLPackage;
|
|
14
|
-
readonly document:
|
|
24
|
+
readonly document: ShimmedDocument;
|
|
15
25
|
/** Tracking is a no-op: nothing here is a remote proxy. */
|
|
16
26
|
readonly trackedObjects: TrackedObjects;
|
|
17
27
|
private pending;
|
package/dist/office-js/run.mjs
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
import { Document } from './document.mjs';
|
|
8
8
|
import { EXTRA_MEMBERS } from './extras.mjs';
|
|
9
9
|
import { Wrapper, unwrap } from './proxy.mjs';
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* A subset of Office JS `Word.RequestContext` over a package.
|
|
12
|
+
*
|
|
13
|
+
* `document` is typed `ShimmedDocument`, which is what the proxies actually present: every array a
|
|
14
|
+
* `Collection` with `items` and `getFirst`, every object `load`able (CR-002 section 22.1). The
|
|
15
|
+
* runtime object is the same either way; the type is what lets an add-in script type-check against
|
|
16
|
+
* this package exactly as it does against Office JS.
|
|
17
|
+
*/
|
|
11
18
|
export class RequestContext {
|
|
12
19
|
constructor(
|
|
13
20
|
/** The package this context is over (extension: Office JS has a host document). */
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ClientResult, Collection } from './proxy.mjs';
|
|
2
|
+
/** Office JS's `load` / `track` / `untrack`, which every proxy answers and which return the object. */
|
|
3
|
+
export interface Loadable<T> {
|
|
4
|
+
/**
|
|
5
|
+
* Office JS's `load`: a no-op here, since the tree is in memory and nothing is a remote proxy
|
|
6
|
+
* (CR-002 section 3.10). Returns the object, so `body.load('text')` chains as it does in Word.
|
|
7
|
+
*/
|
|
8
|
+
load(option?: string | string[] | Record<string, unknown>): T;
|
|
9
|
+
track(): T;
|
|
10
|
+
untrack(): T;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* What the shim presents for a value of type `T`:
|
|
14
|
+
*
|
|
15
|
+
* - a function becomes a function whose result is shimmed in turn (a method call on a proxy hands
|
|
16
|
+
* back another proxy), except that a promise stays a promise and a `ClientResult` stays one;
|
|
17
|
+
* - an array becomes a `Collection` of shimmed items - Office JS's `items`, `getFirst`,
|
|
18
|
+
* `getFirstOrNullObject`, `getLast`, `getLastOrNullObject` and `getCount`;
|
|
19
|
+
* - any other object becomes itself with its members shimmed, plus `load`, `track` and `untrack`;
|
|
20
|
+
* - a primitive is itself.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately **not** distributive over unions of objects beyond the array case: a `Range | undefined`
|
|
23
|
+
* shims to `Shimmed<Range> | undefined`, which is what a caller wants, and the conditional's natural
|
|
24
|
+
* distribution gives that.
|
|
25
|
+
*/
|
|
26
|
+
export type Shimmed<T> = T extends ClientResult<unknown> ? T : T extends Promise<unknown> ? T : T extends (...args: infer A) => infer R ? ((...args: A) => Shimmed<R>) & Loadable<T> : T extends readonly (infer I)[] ? ShimmedCollection<I> : T extends object ? ShimmedObject<T> : T;
|
|
27
|
+
/** A collection of shimmed items, as the proxies wrap an array. */
|
|
28
|
+
export type ShimmedCollection<I> = Collection<Shimmed<I>> & Loadable<Collection<Shimmed<I>>>;
|
|
29
|
+
/**
|
|
30
|
+
* An object with every member shimmed, and Office JS's `load` / `track` / `untrack` beside them.
|
|
31
|
+
*
|
|
32
|
+
* `T &` matters and is not redundant: a mapped type keeps only the public members, so without it a
|
|
33
|
+
* shimmed `Body` is not assignable to `Body` and a consumer cannot pass `context.document.body` to
|
|
34
|
+
* its own function typed on the plain view - which is exactly what an add-in that shares one `edit`
|
|
35
|
+
* between Word and the shim does (`examples/office-addin/taskpane.ts`). Intersecting keeps that
|
|
36
|
+
* assignable while the mapped half still narrows an array member to a `Collection`.
|
|
37
|
+
*
|
|
38
|
+
* The **order** matters too, and is the subtler half: an intersection of two call signatures is an
|
|
39
|
+
* overload set, and TypeScript picks the first that matches. With `T` first, `getRange()` resolves
|
|
40
|
+
* to `T`'s own signature and hands back a plain `Range`, so `paragraph.getRange().font.load(...)`
|
|
41
|
+
* is rejected although the shim allows it. The mapped half therefore comes first, so the shimmed
|
|
42
|
+
* return type wins, and `T` follows to keep assignability.
|
|
43
|
+
*/
|
|
44
|
+
export type ShimmedObject<T> = {
|
|
45
|
+
[K in keyof T]: Shimmed<T[K]>;
|
|
46
|
+
} & T & Loadable<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -45,3 +45,28 @@ export declare class Xlsx4jException extends Docx4JException {
|
|
|
45
45
|
export declare class PartUnrecognisedException extends Docx4JException {
|
|
46
46
|
constructor(message: string);
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* An XML part that could not be unmarshalled, naming the part (CR-002 section 27, item 9 of the
|
|
50
|
+
* E4 release). The runtime's own message is specific about *what* is wrong and, since
|
|
51
|
+
* `@docx4j/jsonix` 3.4.0, *where* - `w:sz/@w:val (line 12): Argument [NaN] must be an integer` -
|
|
52
|
+
* but it cannot know which part it was reading, and a person editing a part's XML in an editor needs
|
|
53
|
+
* that first. The location fields are lifted off the runtime's error so a caller does not have to
|
|
54
|
+
* parse the message.
|
|
55
|
+
*/
|
|
56
|
+
export declare class PartUnmarshalException extends Docx4JException {
|
|
57
|
+
/** The part being unmarshalled: `/word/styles.xml`. */
|
|
58
|
+
readonly partName: string;
|
|
59
|
+
constructor(message: string,
|
|
60
|
+
/** The part being unmarshalled: `/word/styles.xml`. */
|
|
61
|
+
partName: string, options?: {
|
|
62
|
+
cause?: unknown;
|
|
63
|
+
/** The element or attribute the runtime was on, when it said. */
|
|
64
|
+
location?: string | undefined;
|
|
65
|
+
/** Its line in the source, when the parser supplied one (Node only: xmldom's locator). */
|
|
66
|
+
line?: number | undefined;
|
|
67
|
+
column?: number | undefined;
|
|
68
|
+
});
|
|
69
|
+
readonly location: string | undefined;
|
|
70
|
+
readonly line: number | undefined;
|
|
71
|
+
readonly column: number | undefined;
|
|
72
|
+
}
|
package/dist/opc/exceptions.mjs
CHANGED
|
@@ -58,3 +58,23 @@ export class PartUnrecognisedException extends Docx4JException {
|
|
|
58
58
|
this.name = 'PartUnrecognisedException';
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* An XML part that could not be unmarshalled, naming the part (CR-002 section 27, item 9 of the
|
|
63
|
+
* E4 release). The runtime's own message is specific about *what* is wrong and, since
|
|
64
|
+
* `@docx4j/jsonix` 3.4.0, *where* - `w:sz/@w:val (line 12): Argument [NaN] must be an integer` -
|
|
65
|
+
* but it cannot know which part it was reading, and a person editing a part's XML in an editor needs
|
|
66
|
+
* that first. The location fields are lifted off the runtime's error so a caller does not have to
|
|
67
|
+
* parse the message.
|
|
68
|
+
*/
|
|
69
|
+
export class PartUnmarshalException extends Docx4JException {
|
|
70
|
+
constructor(message,
|
|
71
|
+
/** The part being unmarshalled: `/word/styles.xml`. */
|
|
72
|
+
partName, options) {
|
|
73
|
+
super(message, { cause: options === null || options === void 0 ? void 0 : options.cause });
|
|
74
|
+
this.partName = partName;
|
|
75
|
+
this.name = 'PartUnmarshalException';
|
|
76
|
+
this.location = options === null || options === void 0 ? void 0 : options.location;
|
|
77
|
+
this.line = options === null || options === void 0 ? void 0 : options.line;
|
|
78
|
+
this.column = options === null || options === void 0 ? void 0 : options.column;
|
|
79
|
+
}
|
|
80
|
+
}
|
package/dist/opc/index.d.mts
CHANGED
|
@@ -8,5 +8,5 @@ export { loadPackage, type LoadOptions } from './Load.mjs';
|
|
|
8
8
|
export { savePackage } from './Save.mjs';
|
|
9
9
|
export { mcePreprocess, createMcePreprocessor, resolveAlternateContent, MCE_NS, type McePreprocessOptions } from './mce/preprocessor.mjs';
|
|
10
10
|
export { UNDERSTOOD_NAMESPACES } from './mce/understood.mjs';
|
|
11
|
-
export { Docx4JException, InvalidFormatException, PartUnrecognisedException, CyclicStylesException, PropertyResolverNotCreatedException } from './exceptions.mjs';
|
|
11
|
+
export { Docx4JException, InvalidFormatException, PartUnrecognisedException, PartUnmarshalException, CyclicStylesException, PropertyResolverNotCreatedException } from './exceptions.mjs';
|
|
12
12
|
export { parseXml, serializeXml, serializeXmlPart, createDocument, encodeText, decodeXmlText, stripXmlDeclaration, base64Encode, base64Decode, childElements, XML_DECLARATION } from '../xml/dom.mjs';
|
package/dist/opc/index.mjs
CHANGED
|
@@ -9,5 +9,5 @@ export { loadPackage } from './Load.mjs';
|
|
|
9
9
|
export { savePackage } from './Save.mjs';
|
|
10
10
|
export { mcePreprocess, createMcePreprocessor, resolveAlternateContent, MCE_NS } from './mce/preprocessor.mjs';
|
|
11
11
|
export { UNDERSTOOD_NAMESPACES } from './mce/understood.mjs';
|
|
12
|
-
export { Docx4JException, InvalidFormatException, PartUnrecognisedException, CyclicStylesException, PropertyResolverNotCreatedException } from './exceptions.mjs';
|
|
12
|
+
export { Docx4JException, InvalidFormatException, PartUnrecognisedException, PartUnmarshalException, CyclicStylesException, PropertyResolverNotCreatedException } from './exceptions.mjs';
|
|
13
13
|
export { parseXml, serializeXml, serializeXmlPart, createDocument, encodeText, decodeXmlText, stripXmlDeclaration, base64Encode, base64Decode, childElements, XML_DECLARATION } from '../xml/dom.mjs';
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// What "understanding" an mc:Choice means here: the namespaces whose content survives a load and
|
|
2
|
+
// a save. Word takes the first mc:Choice whose Requires prefixes it all understands (ECMA-376
|
|
3
|
+
// Part 3, 10.2.1), and so does this preprocessor.
|
|
4
|
+
//
|
|
5
|
+
// It is the defaultElementNamespaceURI of every generated module of @docx4j/generated-objects-ts
|
|
6
|
+
// (0.3.0), which `mce.test.mjs` asserts so that the next regeneration announces an addition, plus
|
|
7
|
+
// two groups of hand-kept entries, each marked below: namespaces no module *defaults* to but which
|
|
8
|
+
// the model binds anyway (attributes, or elements a module of another namespace declares), and the
|
|
9
|
+
// slicer namespaces of CR-004 phase B, whose content the model does not bind at all but carries
|
|
10
|
+
// through as DOM.
|
|
5
11
|
export const UNDERSTOOD_NAMESPACES = new Set([
|
|
6
12
|
'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
|
|
7
|
-
'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
|
8
13
|
'http://schemas.openxmlformats.org/package/2006/relationships',
|
|
9
14
|
'http://schemas.openxmlformats.org/markup-compatibility/2006',
|
|
10
15
|
'http://schemas.openxmlformats.org/officeDocument/2006/math',
|
|
11
16
|
'http://schemas.openxmlformats.org/officeDocument/2006/bibliography',
|
|
12
17
|
'http://schemas.openxmlformats.org/officeDocument/2006/customXml',
|
|
13
18
|
'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
|
|
14
|
-
'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties',
|
|
15
19
|
'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties',
|
|
16
20
|
'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
|
|
17
21
|
'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
|
|
@@ -36,7 +40,6 @@ export const UNDERSTOOD_NAMESPACES = new Set([
|
|
|
36
40
|
'http://schemas.microsoft.com/office/drawing/2010/diagram',
|
|
37
41
|
'http://schemas.microsoft.com/office/drawing/2012/main',
|
|
38
42
|
'http://schemas.microsoft.com/office/drawing/2012/chart',
|
|
39
|
-
'http://schemas.microsoft.com/office/drawing/2012/chartStyle',
|
|
40
43
|
'http://schemas.microsoft.com/office/drawing/2013/main/command',
|
|
41
44
|
'http://schemas.microsoft.com/office/drawing/2014/main',
|
|
42
45
|
'http://schemas.microsoft.com/office/drawing/2014/chart',
|
|
@@ -44,7 +47,6 @@ export const UNDERSTOOD_NAMESPACES = new Set([
|
|
|
44
47
|
'http://schemas.microsoft.com/office/drawing/2014/chartex',
|
|
45
48
|
'http://schemas.microsoft.com/office/drawing/2016/11/main',
|
|
46
49
|
'http://schemas.microsoft.com/office/drawing/2016/12/diagram',
|
|
47
|
-
'http://schemas.microsoft.com/office/drawing/2016/ink',
|
|
48
50
|
'http://schemas.microsoft.com/office/drawing/2016/SVG/main',
|
|
49
51
|
'http://schemas.microsoft.com/office/drawing/2017/03/chart',
|
|
50
52
|
'http://schemas.microsoft.com/office/drawing/2017/decorative',
|
|
@@ -68,6 +70,9 @@ export const UNDERSTOOD_NAMESPACES = new Set([
|
|
|
68
70
|
'http://schemas.microsoft.com/office/word/2012/wordprocessingDrawing',
|
|
69
71
|
'http://schemas.microsoft.com/office/word/2015/wordml/symex',
|
|
70
72
|
'http://schemas.microsoft.com/office/word/2016/wordml/cid',
|
|
73
|
+
'http://schemas.microsoft.com/office/word/2018/wordml',
|
|
74
|
+
'http://schemas.microsoft.com/office/word/2018/wordml/cex',
|
|
75
|
+
'http://schemas.microsoft.com/office/word/2026/wordml/cei',
|
|
71
76
|
'http://schemas.microsoft.com/office/webextensions/taskpanes/2010/11',
|
|
72
77
|
'http://schemas.microsoft.com/office/webextensions/webextension/2010/11',
|
|
73
78
|
'http://schemas.microsoft.com/office/powerpoint/2010/main',
|
|
@@ -89,10 +94,34 @@ export const UNDERSTOOD_NAMESPACES = new Set([
|
|
|
89
94
|
'http://schemas.microsoft.com/office/excel/2006/main',
|
|
90
95
|
'http://schemas.microsoft.com/office/excel/2008/2/main',
|
|
91
96
|
'http://schemas.microsoft.com/office/excel/2010/spreadsheetDrawing',
|
|
97
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main',
|
|
98
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2010/11/main',
|
|
99
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac',
|
|
100
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac',
|
|
101
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2014/11/main',
|
|
102
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2014/revision',
|
|
103
|
+
'http://schemas.microsoft.com/office/spreadsheetml/2018/calcfeatures',
|
|
92
104
|
'http://schemas.microsoft.com/ink/2010/main',
|
|
93
105
|
'http://www.w3.org/1998/Math/MathML',
|
|
94
106
|
'http://www.w3.org/2003/InkML',
|
|
95
107
|
'http://schemas.microsoft.com/office/2006/encryption',
|
|
96
108
|
'http://schemas.microsoft.com/office/2006/keyEncryptor/certificate',
|
|
97
109
|
'http://schemas.microsoft.com/office/2006/keyEncryptor/password',
|
|
110
|
+
// Bound by the model without being any module's default element namespace (so the check in
|
|
111
|
+
// mce.test.mjs does not reach them): relationship ids and the custom document properties are
|
|
112
|
+
// attributes and elements other modules' types carry, chartStyle has a module that defaults to
|
|
113
|
+
// the DrawingML main namespace, and the 2016 ink one a module with no default at all.
|
|
114
|
+
'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
|
115
|
+
'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties',
|
|
116
|
+
'http://schemas.microsoft.com/office/drawing/2012/chartStyle',
|
|
117
|
+
'http://schemas.microsoft.com/office/drawing/2016/ink',
|
|
118
|
+
// Excel's slicer and timeline drawings (CR-004 phase B). Nothing binds these - docx4j has not
|
|
119
|
+
// bound the schemas either - but the Choice they gate is an xdr:graphicFrame whose a:graphicData
|
|
120
|
+
// holds the one unbound element, and that wildcard is lax (docx4j 8e8f6ea83), so it loads as DOM
|
|
121
|
+
// and re-marshals unchanged. Taking the Choice therefore keeps the slicer or timeline; leaving
|
|
122
|
+
// it would take the Fallback, an "Excel 2010 or higher" placeholder box, and lose the slicer for
|
|
123
|
+
// good. A Choice is only worth taking when everything in it round-trips (docx4j CR-021 8.9).
|
|
124
|
+
'http://schemas.microsoft.com/office/drawing/2010/slicer',
|
|
125
|
+
'http://schemas.microsoft.com/office/drawing/2012/slicer',
|
|
126
|
+
'http://schemas.microsoft.com/office/drawing/2012/timeslicer',
|
|
98
127
|
]);
|