@docx4j/core-ts 0.1.0 → 0.1.2
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 +410 -10
- package/dist/model/content/Body.d.mts +109 -4
- package/dist/model/content/Body.mjs +300 -29
- package/dist/model/content/Comment.d.mts +78 -0
- package/dist/model/content/Comment.mjs +429 -0
- package/dist/model/content/ContentControl.d.mts +173 -0
- package/dist/model/content/ContentControl.mjs +638 -0
- package/dist/model/content/Font.d.mts +48 -8
- package/dist/model/content/Font.mjs +55 -13
- package/dist/model/content/InlinePicture.d.mts +103 -0
- package/dist/model/content/InlinePicture.mjs +361 -0
- package/dist/model/content/List.d.mts +253 -0
- package/dist/model/content/List.mjs +778 -0
- package/dist/model/content/Paragraph.d.mts +213 -16
- package/dist/model/content/Paragraph.mjs +611 -57
- package/dist/model/content/Range.d.mts +48 -4
- package/dist/model/content/Range.mjs +161 -4
- package/dist/model/content/Table.d.mts +130 -0
- package/dist/model/content/Table.mjs +429 -0
- package/dist/model/content/TrackedChange.d.mts +96 -0
- package/dist/model/content/TrackedChange.mjs +352 -0
- package/dist/model/content/comments.d.mts +122 -0
- package/dist/model/content/comments.mjs +248 -0
- package/dist/model/content/index.d.mts +13 -3
- package/dist/model/content/index.mjs +15 -3
- package/dist/model/content/ooxml.d.mts +17 -0
- package/dist/model/content/ooxml.mjs +214 -0
- package/dist/model/content/styles.d.mts +21 -0
- package/dist/model/content/styles.mjs +86 -0
- package/dist/model/content/tracking.d.mts +104 -0
- package/dist/model/content/tracking.mjs +313 -0
- package/dist/model/content/tree.d.mts +56 -9
- package/dist/model/content/tree.mjs +104 -31
- package/dist/model/customxml/CustomXmlPart.d.mts +158 -0
- package/dist/model/customxml/CustomXmlPart.mjs +415 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +68 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +183 -0
- package/dist/model/customxml/XmlMapping.d.mts +46 -0
- package/dist/model/customxml/XmlMapping.mjs +98 -0
- package/dist/model/customxml/bindings.d.mts +41 -0
- package/dist/model/customxml/bindings.mjs +230 -0
- package/dist/model/customxml/index.d.mts +7 -0
- package/dist/model/customxml/index.mjs +9 -0
- package/dist/model/customxml/insert.d.mts +20 -0
- package/dist/model/customxml/insert.mjs +22 -0
- package/dist/model/customxml/kinds.d.mts +103 -0
- package/dist/model/customxml/kinds.mjs +267 -0
- package/dist/model/customxml/xpath.d.mts +52 -0
- package/dist/model/customxml/xpath.mjs +205 -0
- package/dist/model/fonts/CJKToEnglish.d.mts +2 -0
- package/dist/model/fonts/CJKToEnglish.mjs +16 -0
- package/dist/model/fonts/FontFallback.d.mts +58 -0
- package/dist/model/fonts/FontFallback.mjs +219 -0
- package/dist/model/fonts/IdentityPlusMapper.d.mts +7 -0
- package/dist/model/fonts/IdentityPlusMapper.mjs +19 -0
- package/dist/model/fonts/LanguageTagToScriptMapping.d.mts +7 -0
- package/dist/model/fonts/LanguageTagToScriptMapping.mjs +67 -0
- package/dist/model/fonts/Mapper.d.mts +190 -0
- package/dist/model/fonts/Mapper.mjs +481 -0
- package/dist/model/fonts/PhysicalFont.d.mts +34 -0
- package/dist/model/fonts/PhysicalFont.mjs +62 -0
- package/dist/model/fonts/RunFontSelector.d.mts +194 -0
- package/dist/model/fonts/RunFontSelector.mjs +441 -0
- package/dist/model/fonts/ThemeFonts.d.mts +17 -0
- package/dist/model/fonts/ThemeFonts.mjs +76 -0
- package/dist/model/fonts/defaultTheme.d.mts +37 -0
- package/dist/model/fonts/defaultTheme.mjs +57 -0
- package/dist/model/fonts/families.generated.d.mts +11 -0
- package/dist/model/fonts/families.generated.mjs +17 -0
- package/dist/model/fonts/fontsInUse.d.mts +39 -0
- package/dist/model/fonts/fontsInUse.mjs +183 -0
- package/dist/model/fonts/index.d.mts +14 -0
- package/dist/model/fonts/index.mjs +29 -0
- package/dist/model/fonts/lookup.d.mts +5 -0
- package/dist/model/fonts/lookup.mjs +12 -0
- package/dist/model/fonts/registry.d.mts +31 -0
- package/dist/model/fonts/registry.mjs +103 -0
- package/dist/model/fonts/scripts.d.mts +2 -0
- package/dist/model/fonts/scripts.mjs +78 -0
- package/dist/model/fonts/substitutions.generated.d.mts +30 -0
- package/dist/model/fonts/substitutions.generated.mjs +12 -0
- package/dist/model/fonts/themes.generated.d.mts +6 -0
- package/dist/model/fonts/themes.generated.mjs +11 -0
- package/dist/model/index.d.mts +5 -0
- package/dist/model/index.mjs +13 -1
- package/dist/model/listnumbering/Emulator.d.mts +187 -0
- package/dist/model/listnumbering/Emulator.mjs +332 -0
- package/dist/model/listnumbering/definitions.d.mts +251 -0
- package/dist/model/listnumbering/definitions.mjs +571 -0
- package/dist/model/listnumbering/formats.d.mts +25 -0
- package/dist/model/listnumbering/formats.mjs +320 -0
- package/dist/model/listnumbering/index.d.mts +4 -0
- package/dist/model/listnumbering/index.mjs +15 -0
- package/dist/model/listnumbering/state.d.mts +97 -0
- package/dist/model/listnumbering/state.mjs +179 -0
- package/dist/model/properties/PropertyResolver.d.mts +216 -0
- package/dist/model/properties/PropertyResolver.mjs +524 -0
- package/dist/model/properties/catalogue.d.mts +179 -0
- package/dist/model/properties/catalogue.mjs +860 -0
- package/dist/model/properties/index.d.mts +4 -0
- package/dist/model/properties/index.mjs +9 -0
- package/dist/model/properties/log.d.mts +7 -0
- package/dist/model/properties/log.mjs +25 -0
- package/dist/model/properties/styleUtil.d.mts +112 -0
- package/dist/model/properties/styleUtil.mjs +359 -0
- package/dist/node/index.d.mts +1 -0
- package/dist/node/index.mjs +12 -0
- package/dist/office-js/document.d.mts +111 -0
- package/dist/office-js/document.mjs +267 -0
- package/dist/office-js/enums.d.mts +187 -0
- package/dist/office-js/enums.mjs +176 -0
- package/dist/office-js/errors.d.mts +29 -0
- package/dist/office-js/errors.mjs +39 -0
- package/dist/office-js/extras.d.mts +5 -0
- package/dist/office-js/extras.mjs +29 -0
- package/dist/office-js/fragment.d.mts +10 -0
- package/dist/office-js/fragment.mjs +23 -0
- package/dist/office-js/index.d.mts +183 -0
- package/dist/office-js/index.mjs +54 -0
- package/dist/office-js/proxy.d.mts +72 -0
- package/dist/office-js/proxy.mjs +279 -0
- package/dist/office-js/run.d.mts +32 -0
- package/dist/office-js/run.mjs +66 -0
- package/dist/office-js/supported.d.mts +7 -0
- package/dist/office-js/supported.generated.d.mts +1 -0
- package/dist/office-js/supported.generated.mjs +235 -0
- package/dist/office-js/supported.mjs +53 -0
- package/dist/office-js/toApiScript.d.mts +25 -0
- package/dist/office-js/toApiScript.mjs +394 -0
- package/dist/opc/ContentTypes.d.mts +11 -0
- package/dist/opc/ContentTypes.mjs +14 -0
- package/dist/opc/DirectoryPartStore.d.mts +47 -0
- package/dist/opc/DirectoryPartStore.mjs +123 -0
- package/dist/opc/exceptions.d.mts +30 -0
- package/dist/opc/exceptions.mjs +38 -0
- package/dist/opc/index.d.mts +1 -1
- package/dist/opc/index.mjs +1 -1
- package/dist/packages/OpcPackage.d.mts +19 -1
- package/dist/packages/OpcPackage.mjs +29 -0
- package/dist/packages/PresentationMLPackage.d.mts +71 -1
- package/dist/packages/PresentationMLPackage.mjs +179 -0
- package/dist/packages/SpreadsheetMLPackage.d.mts +30 -1
- package/dist/packages/SpreadsheetMLPackage.mjs +78 -0
- package/dist/packages/WordprocessingMLPackage.d.mts +124 -2
- package/dist/packages/WordprocessingMLPackage.mjs +309 -2
- package/dist/packages/index.d.mts +1 -1
- package/dist/packages/index.mjs +1 -1
- package/dist/parts/DefaultXmlPart.d.mts +18 -0
- package/dist/parts/DefaultXmlPart.mjs +34 -5
- package/dist/parts/Namespaces.d.mts +18 -0
- package/dist/parts/Namespaces.mjs +20 -0
- package/dist/parts/Part.d.mts +6 -0
- package/dist/parts/Part.mjs +13 -0
- package/dist/parts/PartRegistry.mjs +13 -1
- package/dist/parts/XmlPart.d.mts +33 -0
- package/dist/parts/XmlPart.mjs +105 -2
- package/dist/parts/pml/defaults.d.mts +6 -0
- package/dist/parts/pml/defaults.mjs +53 -0
- package/dist/parts/pml/index.d.mts +66 -3
- package/dist/parts/pml/index.mjs +206 -7
- package/dist/parts/pml/placeholders.d.mts +71 -0
- package/dist/parts/pml/placeholders.mjs +141 -0
- package/dist/parts/sml/index.d.mts +80 -1
- package/dist/parts/sml/index.mjs +154 -1
- package/dist/parts/wml/comments.d.mts +1 -0
- package/dist/parts/wml/comments.mjs +179 -0
- package/dist/parts/wml/defaultNumbering.d.mts +1 -0
- package/dist/parts/wml/defaultNumbering.mjs +216 -0
- package/dist/parts/wml/index.d.mts +121 -0
- package/dist/parts/wml/index.mjs +291 -0
- package/dist/xml/dom.mjs +1 -2
- package/package.json +25 -4
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
2
|
+
import { typeNameOf, childrenOf, runItemsOf, itemTextOf, revisionKindOf, RUN_HOLDERS } from './tree.mjs';
|
|
3
|
+
/** The style Word gives a comment's paragraphs. */
|
|
4
|
+
export const COMMENT_TEXT_STYLE = 'CommentText';
|
|
5
|
+
/** The character style of the annotation reference run, in the comment and in the body. */
|
|
6
|
+
export const COMMENT_REFERENCE_STYLE = 'CommentReference';
|
|
7
|
+
/** The initials Word would show: the first letter of each word of the name, at most three. */
|
|
8
|
+
export function initialsOf(author) {
|
|
9
|
+
if (author.initials)
|
|
10
|
+
return author.initials;
|
|
11
|
+
return author.name.split(/\s+/).filter((w) => w.length > 0).slice(0, 3).map((w) => w[0].toUpperCase()).join('');
|
|
12
|
+
}
|
|
13
|
+
let partsAccess;
|
|
14
|
+
/** Registered by `src/parts/wml/comments.mts` (imported for that by `WordprocessingMLPackage`). */
|
|
15
|
+
export function setCommentPartsAccess(access) {
|
|
16
|
+
partsAccess = access;
|
|
17
|
+
}
|
|
18
|
+
export function commentPartsAccess() {
|
|
19
|
+
if (!partsAccess)
|
|
20
|
+
throw new Docx4JException('Comments need the parts layer: import @docx4j/core-ts or @docx4j/core-ts/packages, which registers it');
|
|
21
|
+
return partsAccess;
|
|
22
|
+
}
|
|
23
|
+
let api;
|
|
24
|
+
export function setCommentApi(implementation) {
|
|
25
|
+
api = implementation;
|
|
26
|
+
}
|
|
27
|
+
export function commentApi() {
|
|
28
|
+
if (!api)
|
|
29
|
+
throw new Docx4JException('The Comment views are not loaded: import @docx4j/core-ts or @docx4j/core-ts/model');
|
|
30
|
+
return api;
|
|
31
|
+
}
|
|
32
|
+
const COMMENT_RANGE_START = 'org_docx4j_wml.CommentRangeStart';
|
|
33
|
+
const COMMENT_RANGE_END = 'org_docx4j_wml.CommentRangeEnd';
|
|
34
|
+
const COMMENT_REFERENCE = 'org_docx4j_wml.R.CommentReference';
|
|
35
|
+
/**
|
|
36
|
+
* Every comment marker under a container (a body, a cell, a paragraph), in document order.
|
|
37
|
+
* Deleted content (`w:del`) is not entered, as the text model does not enter it either.
|
|
38
|
+
*/
|
|
39
|
+
export function markersOf(container) {
|
|
40
|
+
const out = [];
|
|
41
|
+
collect(out, container);
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
/** The markers of one paragraph, with their offsets in its text. */
|
|
45
|
+
export function markersOfParagraph(element, container) {
|
|
46
|
+
const out = [];
|
|
47
|
+
collect(out, undefined, { element, container });
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
function collect(out, container, paragraph) {
|
|
51
|
+
var _a;
|
|
52
|
+
const visitParagraph = (element, blockContainer) => {
|
|
53
|
+
let pos = 0;
|
|
54
|
+
const visitRuns = (items) => {
|
|
55
|
+
var _a, _b, _c;
|
|
56
|
+
if (!items)
|
|
57
|
+
return;
|
|
58
|
+
for (const el of items) {
|
|
59
|
+
const tn = typeNameOf(el);
|
|
60
|
+
if (tn === 'org_docx4j_wml.R') {
|
|
61
|
+
const content = (_a = el.value.content) !== null && _a !== void 0 ? _a : [];
|
|
62
|
+
for (const item of content) {
|
|
63
|
+
if (typeNameOf(item) === COMMENT_REFERENCE) {
|
|
64
|
+
out.push({
|
|
65
|
+
id: item.value.id, kind: 'reference', item, owner: content,
|
|
66
|
+
run: el, runOwner: items, paragraph: element, paragraphContainer: blockContainer, offset: pos,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
pos += (_c = (_b = itemTextOf(item)) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (tn === COMMENT_RANGE_START || tn === COMMENT_RANGE_END) {
|
|
74
|
+
out.push({
|
|
75
|
+
id: el.value.id, kind: tn === COMMENT_RANGE_START ? 'start' : 'end',
|
|
76
|
+
item: el, owner: items, paragraph: element, paragraphContainer: blockContainer, offset: pos,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else if (tn !== undefined && RUN_HOLDERS.has(tn)) {
|
|
80
|
+
visitRuns(runItemsOf(el.value));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// the accepted view, which is what the offsets are in: a w:ins and a w:moveTo hold text
|
|
84
|
+
// and markers, a w:del and a w:moveFrom hold neither (CR-002 phase F)
|
|
85
|
+
const kind = revisionKindOf(el);
|
|
86
|
+
if (kind === 'ins' || kind === 'moveTo')
|
|
87
|
+
visitRuns(runItemsOf(el.value));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
visitRuns(runItemsOf(element.value));
|
|
92
|
+
};
|
|
93
|
+
const visitBlocks = (items) => {
|
|
94
|
+
var _a, _b, _c;
|
|
95
|
+
for (const el of items) {
|
|
96
|
+
const tn = typeNameOf(el);
|
|
97
|
+
if (tn === 'org_docx4j_wml.P')
|
|
98
|
+
visitParagraph(el, items);
|
|
99
|
+
else if (tn === COMMENT_RANGE_START || tn === COMMENT_RANGE_END) {
|
|
100
|
+
out.push({ id: el.value.id, kind: tn === COMMENT_RANGE_START ? 'start' : 'end', item: el, owner: items });
|
|
101
|
+
}
|
|
102
|
+
else if (typeof el.value === 'object' && el.value !== null) {
|
|
103
|
+
if (tn === 'org_docx4j_wml.Tbl') {
|
|
104
|
+
for (const row of (_a = childrenOf(el.value)) !== null && _a !== void 0 ? _a : []) {
|
|
105
|
+
for (const cell of (_b = childrenOf(row.value)) !== null && _b !== void 0 ? _b : [])
|
|
106
|
+
visitBlocks((_c = childrenOf(cell.value)) !== null && _c !== void 0 ? _c : []);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const children = childrenOf(el.value);
|
|
111
|
+
if (children)
|
|
112
|
+
visitBlocks(children);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
if (paragraph)
|
|
118
|
+
visitParagraph(paragraph.element, paragraph.container);
|
|
119
|
+
else if (container)
|
|
120
|
+
visitBlocks((_a = childrenOf(container)) !== null && _a !== void 0 ? _a : []);
|
|
121
|
+
}
|
|
122
|
+
/** The comment ids under a container, in document order, first occurrence first. */
|
|
123
|
+
export function commentIdsOf(container) {
|
|
124
|
+
const seen = new Set();
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const m of markersOf(container))
|
|
127
|
+
if (!seen.has(m.id)) {
|
|
128
|
+
seen.add(m.id);
|
|
129
|
+
out.push(m.id);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
/** Removes every marker of a comment from a body, and the reference run when nothing is left in it. */
|
|
134
|
+
export function removeMarkers(container, id) {
|
|
135
|
+
var _a;
|
|
136
|
+
for (const marker of markersOf(container)) {
|
|
137
|
+
if (marker.id !== id)
|
|
138
|
+
continue;
|
|
139
|
+
const i = marker.owner.indexOf(marker.item);
|
|
140
|
+
if (i >= 0)
|
|
141
|
+
marker.owner.splice(i, 1);
|
|
142
|
+
if (marker.kind === 'reference' && marker.run && marker.runOwner) {
|
|
143
|
+
const content = (_a = marker.run.value.content) !== null && _a !== void 0 ? _a : [];
|
|
144
|
+
if (content.length === 0) {
|
|
145
|
+
const j = marker.runOwner.indexOf(marker.run);
|
|
146
|
+
if (j >= 0)
|
|
147
|
+
marker.runOwner.splice(j, 1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// --- ids ---
|
|
153
|
+
/** The next free `w:id` for a comment: above every comment and every marker in the body. */
|
|
154
|
+
export function nextCommentId(comments, container) {
|
|
155
|
+
var _a;
|
|
156
|
+
let max = -1;
|
|
157
|
+
for (const c of (_a = comments.comment) !== null && _a !== void 0 ? _a : [])
|
|
158
|
+
if (typeof c.id === 'number' && c.id > max)
|
|
159
|
+
max = c.id;
|
|
160
|
+
for (const m of markersOf(container))
|
|
161
|
+
if (m.id > max)
|
|
162
|
+
max = m.id;
|
|
163
|
+
return max + 1;
|
|
164
|
+
}
|
|
165
|
+
/** An 8 hex digit id, as Word writes `w14:paraId` and `w16cid:durableId` (never 0, high bit clear). */
|
|
166
|
+
export function randomHexId(taken) {
|
|
167
|
+
for (let attempt = 0; attempt < 1000; attempt++) {
|
|
168
|
+
const id = (1 + Math.floor(Math.random() * 0x7ffffffe)).toString(16).toUpperCase().padStart(8, '0');
|
|
169
|
+
if (!taken(id))
|
|
170
|
+
return id;
|
|
171
|
+
}
|
|
172
|
+
throw new Docx4JException('Could not allocate a paragraph id');
|
|
173
|
+
}
|
|
174
|
+
/** The `w14:paraId` of a comment's first paragraph: the key of its w15 and w16cid entries. */
|
|
175
|
+
export function commentParaId(comment) {
|
|
176
|
+
var _a;
|
|
177
|
+
for (const el of (_a = comment.content) !== null && _a !== void 0 ? _a : [])
|
|
178
|
+
if (typeNameOf(el) === 'org_docx4j_wml.P')
|
|
179
|
+
return el.value.paraId;
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
/** True when a paragraph id is already used by a comment or by a paragraph of the document. */
|
|
183
|
+
export function paraIdTaken(parts, container, id) {
|
|
184
|
+
var _a, _b, _c;
|
|
185
|
+
for (const c of (_a = parts.comments.comment) !== null && _a !== void 0 ? _a : [])
|
|
186
|
+
for (const el of (_b = c.content) !== null && _b !== void 0 ? _b : []) {
|
|
187
|
+
if (typeNameOf(el) === 'org_docx4j_wml.P' && el.value.paraId === id)
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
let found = false;
|
|
191
|
+
const visit = (items) => {
|
|
192
|
+
var _a, _b, _c;
|
|
193
|
+
for (const el of items) {
|
|
194
|
+
const tn = typeNameOf(el);
|
|
195
|
+
if (tn === 'org_docx4j_wml.P') {
|
|
196
|
+
if (el.value.paraId === id)
|
|
197
|
+
found = true;
|
|
198
|
+
}
|
|
199
|
+
else if (typeof el.value === 'object' && el.value !== null) {
|
|
200
|
+
if (tn === 'org_docx4j_wml.Tbl') {
|
|
201
|
+
for (const row of (_a = childrenOf(el.value)) !== null && _a !== void 0 ? _a : [])
|
|
202
|
+
for (const cell of (_b = childrenOf(row.value)) !== null && _b !== void 0 ? _b : [])
|
|
203
|
+
visit((_c = childrenOf(cell.value)) !== null && _c !== void 0 ? _c : []);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const children = childrenOf(el.value);
|
|
207
|
+
if (children)
|
|
208
|
+
visit(children);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
visit((_c = childrenOf(container)) !== null && _c !== void 0 ? _c : []);
|
|
214
|
+
return found;
|
|
215
|
+
}
|
|
216
|
+
// --- w15 entries ---
|
|
217
|
+
/** The `w15:commentEx` entry keyed by a comment's first paragraph id. */
|
|
218
|
+
export function commentExOf(parts, paraId) {
|
|
219
|
+
var _a, _b;
|
|
220
|
+
if (!paraId)
|
|
221
|
+
return undefined;
|
|
222
|
+
return ((_b = (_a = parts.commentsEx) === null || _a === void 0 ? void 0 : _a.commentEx) !== null && _b !== void 0 ? _b : []).find((e) => e.paraId === paraId);
|
|
223
|
+
}
|
|
224
|
+
/** Word writes `w15:done="0"` and `"1"`; `w:ST_OnOff` also allows true/false/on/off. */
|
|
225
|
+
export function isDone(value) {
|
|
226
|
+
return value === '1' || value === 'true' || value === 'on';
|
|
227
|
+
}
|
|
228
|
+
// --- dates ---
|
|
229
|
+
/** A Jsonix calendar (what `w:date` unmarshals to) as a Date; undefined when there is none. */
|
|
230
|
+
export function calendarToDate(calendar) {
|
|
231
|
+
if (!calendar || calendar.year === undefined || Number.isNaN(calendar.year))
|
|
232
|
+
return undefined;
|
|
233
|
+
const num = (v, fallback = 0) => (v === undefined || Number.isNaN(v) ? fallback : v);
|
|
234
|
+
const ms = Date.UTC(calendar.year, num(calendar.month, 1) - 1, num(calendar.day, 1), num(calendar.hour), num(calendar.minute), num(calendar.second), Math.round(num(calendar.fractionalSecond) * 1000));
|
|
235
|
+
return new Date(ms - num(calendar.timezone) * 60000);
|
|
236
|
+
}
|
|
237
|
+
/** A Date as the UTC calendar Word writes (`2026-09-15T09:00:00Z`). */
|
|
238
|
+
export function dateToCalendar(date) {
|
|
239
|
+
return {
|
|
240
|
+
year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate(),
|
|
241
|
+
hour: date.getUTCHours(), minute: date.getUTCMinutes(), second: date.getUTCSeconds(),
|
|
242
|
+
fractionalSecond: 0, timezone: 0,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/** `2026-09-15T09:00:00Z`, the form Word writes in w16cex. */
|
|
246
|
+
export function toUtcString(date) {
|
|
247
|
+
return `${date.toISOString().substring(0, 19)}Z`;
|
|
248
|
+
}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
export { Body, type Address, type BlockElement, type Outline, type OutlineParagraph, type OutlineTable } from './Body.mjs';
|
|
2
2
|
export { Paragraph, type Alignment } from './Paragraph.mjs';
|
|
3
3
|
export { Range } from './Range.mjs';
|
|
4
|
-
export {
|
|
4
|
+
export { BUILT_IN_STYLES, builtInOf, idOfBuiltIn, displayNameOf, styleNameOf, styleIdOf, type BuiltInStyle } from './styles.mjs';
|
|
5
|
+
export { Comment } from './Comment.mjs';
|
|
6
|
+
export { List, ListItem, ListItemNotFoundError, listsOf, listLabelsOf, numberingEmulatorOf, levelOf, type ListLevelType, type ListNumbering, type ListBullet, type StartListOptions, type ListLabel, } from './List.mjs';
|
|
7
|
+
export { type Author, type CommentParts, type CommentPartsAccess, type CommentsExtensible, type CommentMarker, COMMENT_TEXT_STYLE, COMMENT_REFERENCE_STYLE, markersOf, markersOfParagraph, commentIdsOf } from './comments.mjs';
|
|
8
|
+
export { Font, type UnderlineType, type RPrHolder, type FontTracking } from './Font.mjs';
|
|
9
|
+
export { Table, TableRow, TableCell, cellOf } from './Table.mjs';
|
|
10
|
+
export { InlinePicture, imageInfoOf, naturalSizeEmu, addImage, writableWidthEmu, type ImageFormat, type ImageInfo, type InlinePictureOptions, type NewPicture } from './InlinePicture.mjs';
|
|
11
|
+
export { ContentControl, collectControls, collectRunControls, W14_NS, W15_NS, type ContentControlType, type ContentControlForm, type ContentControlAppearance } from './ContentControl.mjs';
|
|
12
|
+
export { contentOf, isFlatOpc, rewriteRelationshipIds, type OoxmlOptions } from './ooxml.mjs';
|
|
5
13
|
export { type SearchOptions, searchPattern } from './search.mjs';
|
|
6
|
-
export { segmentsOf, runsOf, runItemsOf, childrenOf, BLOCK_LEVEL_TYPES, runOf, paragraphOf, type TextSegment } from './tree.mjs';
|
|
7
|
-
export {
|
|
14
|
+
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf, type TextSegment, type Located, type TextView, type TextViewOptions, type RevisionKind, type RevisionHolder } from './tree.mjs';
|
|
15
|
+
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext, type TrackedChangeType, type TrackedChangeTarget } from './TrackedChange.mjs';
|
|
16
|
+
export { ChangeTracker, trackerOf, calendarOf, dateOf, copyRPr, markDeleted, markInserted, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, type ChangeTrackingMode, type TrackingHost, } from './tracking.mjs';
|
|
17
|
+
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS, type Element, type Wrapper, type WmlOptions, type Raw, type Interpolated, type RunOptions, type RunFormatting, type ParagraphOptions, type TableOptions, type CellOptions, type SdtKind, type SdtForm, type SdtOptions } from '@docx4j/generated-objects-ts/builders/wml';
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
// The content API (CR-002 phases B and
|
|
1
|
+
// The content API (CR-002 phases B, C, D, F and G): Office JS shapes over the docx4j tree.
|
|
2
2
|
export { Body } from './Body.mjs';
|
|
3
3
|
export { Paragraph } from './Paragraph.mjs';
|
|
4
4
|
export { Range } from './Range.mjs';
|
|
5
|
+
export { BUILT_IN_STYLES, builtInOf, idOfBuiltIn, displayNameOf, styleNameOf, styleIdOf } from './styles.mjs';
|
|
6
|
+
export { Comment } from './Comment.mjs';
|
|
7
|
+
// lists (CR-002 phase H)
|
|
8
|
+
export { List, ListItem, ListItemNotFoundError, listsOf, listLabelsOf, numberingEmulatorOf, levelOf, } from './List.mjs';
|
|
9
|
+
export { COMMENT_TEXT_STYLE, COMMENT_REFERENCE_STYLE, markersOf, markersOfParagraph, commentIdsOf } from './comments.mjs';
|
|
5
10
|
export { Font } from './Font.mjs';
|
|
11
|
+
export { Table, TableRow, TableCell, cellOf } from './Table.mjs';
|
|
12
|
+
export { InlinePicture, imageInfoOf, naturalSizeEmu, addImage, writableWidthEmu } from './InlinePicture.mjs';
|
|
13
|
+
export { ContentControl, collectControls, collectRunControls, W14_NS, W15_NS } from './ContentControl.mjs';
|
|
14
|
+
export { contentOf, isFlatOpc, rewriteRelationshipIds } from './ooxml.mjs';
|
|
6
15
|
export { searchPattern } from './search.mjs';
|
|
7
|
-
export { segmentsOf, runsOf, runItemsOf, childrenOf, BLOCK_LEVEL_TYPES, runOf, paragraphOf } from './tree.mjs';
|
|
16
|
+
export { segmentsOf, runsOf, runItemsOf, childrenOf, rowsOf, cellsOf, BLOCK_LEVEL_TYPES, SDT_TYPES, runOf, paragraphOf, textOfView, revisionKindOf } from './tree.mjs';
|
|
17
|
+
// change tracking (CR-002 phase F)
|
|
18
|
+
export { TrackedChange, trackedChangesOfParagraph, trackedChangesOfRow, joinWithNext } from './TrackedChange.mjs';
|
|
19
|
+
export { ChangeTracker, trackerOf, calendarOf, dateOf, copyRPr, markDeleted, markInserted, toDeletedText, toRestoredText, restoreRPr, restorePPr, trackInsertedParagraph, trackInsertedTable, wrapNewRuns, paraRPrOf, rowPrOf, pruneParagraphProperties, } from './tracking.mjs';
|
|
8
20
|
// The objects package's builders, re-exported so that one import serves the content API and the tree it works on.
|
|
9
|
-
export { wml, wmlOne, p, r, t, br, tab, tbl, textOf, walk, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
|
|
21
|
+
export { wml, wmlOne, p, r, t, br, tab, tbl, tr, tc, sdt, sdtPr, nextSdtId, sdtProperty, sdtKindOf, inlinePicture, rPrToElements, rPrFromElements, textOf, walk, walkAll, find, linkParents, applyRunOptions, readRunOptions, UNDERLINE_TO_WML, isElement, typeNameOf, W_NS } from '@docx4j/generated-objects-ts/builders/wml';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Part } from '../../parts/Part.mjs';
|
|
2
|
+
import type { Element } from './tree.mjs';
|
|
3
|
+
/** True for a flat OPC package (what Word's `insertOoxml` is given), as opposed to a bare fragment. */
|
|
4
|
+
export declare function isFlatOpc(ooxml: string): boolean;
|
|
5
|
+
export interface OoxmlOptions {
|
|
6
|
+
/** The DOM preprocessor (the package's MCE one), for both routes. */
|
|
7
|
+
preprocess?: (doc: Document) => void;
|
|
8
|
+
/** The part new relationships are added to: the main document part, or the header or footer. */
|
|
9
|
+
target?: Part;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The block-level content of `ooxml`, ready to insert: a flat OPC package's body content with
|
|
13
|
+
* its parts copied and its references rewritten, or a fragment's elements.
|
|
14
|
+
*/
|
|
15
|
+
export declare function contentOf(ooxml: string, options?: OoxmlOptions): Promise<Element[]>;
|
|
16
|
+
/** Rewrites the relationship ids the content refers to, in place. */
|
|
17
|
+
export declare function rewriteRelationshipIds(value: unknown, map: Map<string, string>): void;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// CR-002 phase C: insertOoxml. Word's `insertOoxml` takes a flat OPC `pkg:package` string; so
|
|
2
|
+
// does this one. The incoming package's body content is taken, the parts that content references
|
|
3
|
+
// through relationships (images, embedded objects, charts) are copied into the target package
|
|
4
|
+
// under fresh part names and relationship ids, the references in the content are rewritten, and
|
|
5
|
+
// the content is inserted. Styles and numbering are not merged (CR-002 open question 5: that is
|
|
6
|
+
// what docx4j's MergeDocx does). A bare `w:p` / `w:tbl` fragment is accepted too, which is what
|
|
7
|
+
// `insertXml` takes; the two share this module.
|
|
8
|
+
import { wml as parseFragment, walkAll } from '@docx4j/generated-objects-ts/builders/wml';
|
|
9
|
+
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
10
|
+
import { PartName } from '../../opc/PartName.mjs';
|
|
11
|
+
import { ContentTypes } from '../../opc/ContentTypes.mjs';
|
|
12
|
+
import { BinaryPart, ImagePart } from '../../parts/BinaryPart.mjs';
|
|
13
|
+
import { isExternal } from '../../parts/RelationshipsPart.mjs';
|
|
14
|
+
/** The flat OPC namespace; its presence is how a `pkg:package` is told from a fragment. */
|
|
15
|
+
const PKG_NS = 'http://schemas.microsoft.com/office/2006/xmlPackage';
|
|
16
|
+
/** True for a flat OPC package (what Word's `insertOoxml` is given), as opposed to a bare fragment. */
|
|
17
|
+
export function isFlatOpc(ooxml) {
|
|
18
|
+
return ooxml.includes(PKG_NS);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Attributes that carry a relationship id. A value is rewritten only when the source package
|
|
22
|
+
* really has a relationship of that id, so numeric ids (w:bookmarkStart/@w:id, wp:docPr/@id)
|
|
23
|
+
* are never touched.
|
|
24
|
+
*/
|
|
25
|
+
const REL_ATTRIBUTES = ['embed', 'link', 'id', 'href', 'pict', 'dm', 'lo', 'qs', 'cs', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'];
|
|
26
|
+
/** The relationships namespace, for the same attributes on DOM nodes kept as `any` content. */
|
|
27
|
+
const R_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
|
28
|
+
/**
|
|
29
|
+
* The block-level content of `ooxml`, ready to insert: a flat OPC package's body content with
|
|
30
|
+
* its parts copied and its references rewritten, or a fragment's elements.
|
|
31
|
+
*/
|
|
32
|
+
export async function contentOf(ooxml, options = {}) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
if (!isFlatOpc(ooxml)) {
|
|
35
|
+
return parseFragment(ooxml, { wrapper: 'body', preprocess: options.preprocess });
|
|
36
|
+
}
|
|
37
|
+
const target = options.target;
|
|
38
|
+
if (!target)
|
|
39
|
+
throw new Docx4JException('A pkg:package can only be inserted into a body that has a part');
|
|
40
|
+
// Imported here so that the content API does not import the packages statically: parts/wml
|
|
41
|
+
// builds Body views, and a static import back would be a cycle (CLAUDE.md).
|
|
42
|
+
const { WordprocessingMLPackage } = await import('../../packages/WordprocessingMLPackage.mjs');
|
|
43
|
+
const source = await WordprocessingMLPackage.load(ooxml, options.preprocess ? { preprocessor: options.preprocess } : {});
|
|
44
|
+
const main = source.getMainDocumentPart();
|
|
45
|
+
const document = await main.getContents();
|
|
46
|
+
const content = ((_b = (_a = document.body) === null || _a === void 0 ? void 0 : _a.content) !== null && _b !== void 0 ? _b : []);
|
|
47
|
+
if (content.length === 0)
|
|
48
|
+
return [];
|
|
49
|
+
const rewrites = await copyReferencedParts(content, main, target);
|
|
50
|
+
if (rewrites.size > 0)
|
|
51
|
+
rewriteRelationshipIds(content, rewrites);
|
|
52
|
+
return content;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Copies every part the content references into the target's package and returns the mapping
|
|
56
|
+
* from the incoming relationship ids to the new ones.
|
|
57
|
+
*/
|
|
58
|
+
async function copyReferencedParts(content, sourcePart, target) {
|
|
59
|
+
const sourceRels = sourcePart.relationshipsPart;
|
|
60
|
+
const map = new Map();
|
|
61
|
+
if (!sourceRels)
|
|
62
|
+
return map;
|
|
63
|
+
const referenced = new Set();
|
|
64
|
+
collectRelationshipIds(content, sourceRels, referenced);
|
|
65
|
+
const copied = new Map();
|
|
66
|
+
for (const id of referenced) {
|
|
67
|
+
const rel = sourceRels.getRelationshipById(id);
|
|
68
|
+
if (!rel)
|
|
69
|
+
continue;
|
|
70
|
+
if (isExternal(rel)) {
|
|
71
|
+
map.set(id, target.getRelationshipsPart(true).addExternalRelationship(rel.type, rel.target).id);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const part = sourceRels.getPart(rel);
|
|
75
|
+
if (!part)
|
|
76
|
+
continue;
|
|
77
|
+
const newId = await copyPart(part, target, copied);
|
|
78
|
+
if (newId)
|
|
79
|
+
map.set(id, newId);
|
|
80
|
+
}
|
|
81
|
+
return map;
|
|
82
|
+
}
|
|
83
|
+
/** Copies a part (and, recursively, everything its own relationships target) as a target of `owner`. */
|
|
84
|
+
async function copyPart(source, owner, copied) {
|
|
85
|
+
var _a;
|
|
86
|
+
const pkg = owner.package;
|
|
87
|
+
if (!pkg)
|
|
88
|
+
throw new Docx4JException('The target part is not in a package');
|
|
89
|
+
const already = copied.get(source.partName.key);
|
|
90
|
+
if (already) {
|
|
91
|
+
const rel = (_a = owner.getRelationshipsPart(true).getRel(already.partName)) !== null && _a !== void 0 ? _a : owner.addTargetPart(already, 'REUSE_EXISTING');
|
|
92
|
+
return rel.id;
|
|
93
|
+
}
|
|
94
|
+
const bytes = await source.getBytes();
|
|
95
|
+
const name = freeName(pkg, source);
|
|
96
|
+
const copy = source.contentType.startsWith('image/')
|
|
97
|
+
? new ImagePart(name, source.contentType)
|
|
98
|
+
: new BinaryPart(name, source.contentType, source.relationshipType);
|
|
99
|
+
copy.setBytes(bytes);
|
|
100
|
+
copied.set(source.partName.key, copy);
|
|
101
|
+
const rel = owner.addTargetPart(copy);
|
|
102
|
+
const childRels = source.relationshipsPart;
|
|
103
|
+
if (childRels && childRels.size > 0) {
|
|
104
|
+
const copyRels = copy.getRelationshipsPart(true);
|
|
105
|
+
for (const child of childRels.list) {
|
|
106
|
+
if (isExternal(child)) {
|
|
107
|
+
copyRels.addExternalRelationship(child.type, child.target, child.id);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const childPart = childRels.getPart(child);
|
|
111
|
+
if (!childPart)
|
|
112
|
+
continue;
|
|
113
|
+
// The child keeps its id, so nothing inside the copied part has to be rewritten.
|
|
114
|
+
await copyChild(childPart, copy, copyRels, child.id, copied);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return rel.id;
|
|
118
|
+
}
|
|
119
|
+
async function copyChild(source, owner, rels, relId, copied) {
|
|
120
|
+
const already = copied.get(source.partName.key);
|
|
121
|
+
if (already) {
|
|
122
|
+
rels.addPart(already, 'REUSE_EXISTING', relId);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const pkg = owner.package;
|
|
126
|
+
const bytes = await source.getBytes();
|
|
127
|
+
const copy = source.contentType.startsWith('image/')
|
|
128
|
+
? new ImagePart(freeName(pkg, source), source.contentType)
|
|
129
|
+
: new BinaryPart(freeName(pkg, source), source.contentType, source.relationshipType);
|
|
130
|
+
copy.setBytes(bytes);
|
|
131
|
+
copied.set(source.partName.key, copy);
|
|
132
|
+
rels.addPart(copy, 'OVERWRITE_IF_NAME_EXISTS', relId);
|
|
133
|
+
const childRels = source.relationshipsPart;
|
|
134
|
+
if (childRels && childRels.size > 0) {
|
|
135
|
+
const copyRels = copy.getRelationshipsPart(true);
|
|
136
|
+
for (const child of childRels.list) {
|
|
137
|
+
if (isExternal(child)) {
|
|
138
|
+
copyRels.addExternalRelationship(child.type, child.target, child.id);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const childPart = childRels.getPart(child);
|
|
142
|
+
if (childPart)
|
|
143
|
+
await copyChild(childPart, copy, copyRels, child.id, copied);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** A part name free in the package: `/word/media/imageN.ext` for images, else the source name with a suffix. */
|
|
148
|
+
function freeName(pkg, source) {
|
|
149
|
+
if (source.contentType.startsWith('image/')) {
|
|
150
|
+
const ext = source.partName.extension || extensionFor(source.contentType);
|
|
151
|
+
for (let i = 1;; i++) {
|
|
152
|
+
const candidate = PartName.of(`/word/media/image${i}.${ext}`);
|
|
153
|
+
if (!pkg.getPart(candidate))
|
|
154
|
+
return candidate;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (!pkg.getPart(source.partName))
|
|
158
|
+
return source.partName;
|
|
159
|
+
const name = source.partName.name;
|
|
160
|
+
const dot = name.lastIndexOf('.');
|
|
161
|
+
const stem = dot > name.lastIndexOf('/') ? name.substring(0, dot) : name;
|
|
162
|
+
const suffix = dot > name.lastIndexOf('/') ? name.substring(dot) : '';
|
|
163
|
+
for (let i = 2;; i++) {
|
|
164
|
+
const candidate = PartName.of(`${stem}${i}${suffix}`);
|
|
165
|
+
if (!pkg.getPart(candidate))
|
|
166
|
+
return candidate;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function extensionFor(contentType) {
|
|
170
|
+
const found = Object.entries({ png: ContentTypes.IMAGE_PNG, jpeg: ContentTypes.IMAGE_JPEG, gif: ContentTypes.IMAGE_GIF, bmp: ContentTypes.IMAGE_BMP, tiff: ContentTypes.IMAGE_TIFF, svg: ContentTypes.IMAGE_SVG, emf: ContentTypes.IMAGE_EMF, wmf: ContentTypes.IMAGE_WMF })
|
|
171
|
+
.find(([, ct]) => ct === contentType);
|
|
172
|
+
return found ? found[0] : 'bin';
|
|
173
|
+
}
|
|
174
|
+
/** Every relationship id the content refers to (typed objects and the DOM nodes kept as `any`). */
|
|
175
|
+
function collectRelationshipIds(value, rels, out) {
|
|
176
|
+
visitReferences(value, (id) => {
|
|
177
|
+
if (rels.getRelationshipById(id))
|
|
178
|
+
out.add(id);
|
|
179
|
+
return undefined;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/** Rewrites the relationship ids the content refers to, in place. */
|
|
183
|
+
export function rewriteRelationshipIds(value, map) {
|
|
184
|
+
visitReferences(value, (id) => map.get(id));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Offers every value that could be a relationship id to `rewrite`, in the typed tree and in the
|
|
188
|
+
* DOM an `xs:any` property holds (the builders' `walkAll`, objects CR-003 section 3.6); a string
|
|
189
|
+
* it returns replaces the value. Typed objects carry the id in one of `REL_ATTRIBUTES`, DOM
|
|
190
|
+
* elements in an attribute of the relationships namespace.
|
|
191
|
+
*/
|
|
192
|
+
function visitReferences(value, rewrite) {
|
|
193
|
+
walkAll(value, (object) => {
|
|
194
|
+
const record = object;
|
|
195
|
+
for (const key of REL_ATTRIBUTES) {
|
|
196
|
+
const item = record[key];
|
|
197
|
+
if (typeof item !== 'string')
|
|
198
|
+
continue;
|
|
199
|
+
const next = rewrite(item);
|
|
200
|
+
if (next !== undefined)
|
|
201
|
+
record[key] = next;
|
|
202
|
+
}
|
|
203
|
+
}, (node) => {
|
|
204
|
+
const attributes = node.attributes;
|
|
205
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
206
|
+
const attr = attributes[i];
|
|
207
|
+
if (attr.namespaceURI === R_NS && typeof attr.value === 'string') {
|
|
208
|
+
const next = rewrite(attr.value);
|
|
209
|
+
if (next !== undefined)
|
|
210
|
+
attr.value = next;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpcPackage } from '../../packages/OpcPackage.mjs';
|
|
2
|
+
/** Office JS `Word.Style` values other than 'Other', in Office JS's spelling. */
|
|
3
|
+
export declare const BUILT_IN_STYLES: readonly ["Normal", "Heading1", "Heading2", "Heading3", "Heading4", "Heading5", "Heading6", "Heading7", "Heading8", "Heading9", "Toc1", "Toc2", "Toc3", "Toc4", "Toc5", "Toc6", "Toc7", "Toc8", "Toc9", "FootnoteText", "Header", "Footer", "Caption", "FootnoteReference", "EndnoteReference", "EndnoteText", "Title", "Subtitle", "Hyperlink", "Strong", "Emphasis", "NoSpacing", "ListParagraph", "Quote", "IntenseQuote", "SubtleEmphasis", "IntenseEmphasis", "SubtleReference", "IntenseReference", "BookTitle", "Bibliography", "TocHeading", "TableGrid", "PlainTable1", "PlainTable2", "PlainTable3", "PlainTable4", "PlainTable5", "GridTable1Light", "ListTable1Light"];
|
|
4
|
+
export type BuiltInStyle = (typeof BUILT_IN_STYLES)[number] | 'Other';
|
|
5
|
+
/** Office JS's `styleBuiltIn` for a style id: the `Word.Style` value, or 'Other'. */
|
|
6
|
+
export declare function builtInOf(styleId: string): BuiltInStyle;
|
|
7
|
+
/**
|
|
8
|
+
* The style id for a `Word.Style` value ('Heading1'; leniently also the display name 'Heading 1'),
|
|
9
|
+
* in Word's spelling ('TOC1' for 'Toc1'). 'Other' cannot be set, as in Office JS.
|
|
10
|
+
*/
|
|
11
|
+
export declare function idOfBuiltIn(value: string): string;
|
|
12
|
+
/** The display name of a style id, from its stored `w:name` when given ('heading 1' to 'Heading 1'). */
|
|
13
|
+
export declare function displayNameOf(styleId: string, storedName?: string): string;
|
|
14
|
+
/** Office JS's `style`: the display name of a style id. */
|
|
15
|
+
export declare function styleNameOf(pkg: OpcPackage | undefined, styleId: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* The style id for what Office JS's `style` accepts: a display name ('Heading 1', 'My Style'), the
|
|
18
|
+
* stored name ('heading 1'), or, as an extension, the id itself ('Heading1'). Resolved against the
|
|
19
|
+
* styles part when it is unmarshalled, else by removing spaces.
|
|
20
|
+
*/
|
|
21
|
+
export declare function styleIdOf(pkg: OpcPackage | undefined, name: string): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Office JS `Word.Style` values other than 'Other', in Office JS's spelling. */
|
|
2
|
+
export const BUILT_IN_STYLES = Object.freeze([
|
|
3
|
+
'Normal', 'Heading1', 'Heading2', 'Heading3', 'Heading4', 'Heading5', 'Heading6', 'Heading7', 'Heading8', 'Heading9',
|
|
4
|
+
'Toc1', 'Toc2', 'Toc3', 'Toc4', 'Toc5', 'Toc6', 'Toc7', 'Toc8', 'Toc9',
|
|
5
|
+
'FootnoteText', 'Header', 'Footer', 'Caption', 'FootnoteReference', 'EndnoteReference', 'EndnoteText', 'Title', 'Subtitle',
|
|
6
|
+
'Hyperlink', 'Strong', 'Emphasis', 'NoSpacing', 'ListParagraph', 'Quote', 'IntenseQuote', 'SubtleEmphasis', 'IntenseEmphasis',
|
|
7
|
+
'SubtleReference', 'IntenseReference', 'BookTitle', 'Bibliography', 'TocHeading', 'TableGrid',
|
|
8
|
+
'PlainTable1', 'PlainTable2', 'PlainTable3', 'PlainTable4', 'PlainTable5', 'GridTable1Light', 'ListTable1Light',
|
|
9
|
+
]);
|
|
10
|
+
/**
|
|
11
|
+
* Word's ids and display names where the id is not the display name without spaces, or the name
|
|
12
|
+
* Word stores in `w:name` is not the display name (docx4j's KnownStyles.xml has the stored names).
|
|
13
|
+
*/
|
|
14
|
+
const DISPLAY_NAMES = Object.freeze({
|
|
15
|
+
TableNormal: 'Normal Table', NormalWeb: 'Normal (Web)', MacroText: 'Macro Text',
|
|
16
|
+
TableofAuthorities: 'Table of Authorities', TableofFigures: 'Table of Figures', TOAHeading: 'TOA Heading',
|
|
17
|
+
CommentText: 'Comment Text', CommentSubject: 'Comment Subject', CommentReference: 'Comment Reference',
|
|
18
|
+
'1ai': 'Outline List 1', '111111': 'Outline List 2', ArticleSection: 'Outline List 3',
|
|
19
|
+
});
|
|
20
|
+
/** Word's spelling of an id where it is not Office JS's spelling of the built-in value. */
|
|
21
|
+
const WORD_IDS = Object.freeze({
|
|
22
|
+
toc1: 'TOC1', toc2: 'TOC2', toc3: 'TOC3', toc4: 'TOC4', toc5: 'TOC5', toc6: 'TOC6', toc7: 'TOC7', toc8: 'TOC8', toc9: 'TOC9',
|
|
23
|
+
});
|
|
24
|
+
const BUILT_IN_BY_LOWER = new Map(BUILT_IN_STYLES.map((s) => [s.toLowerCase(), s]));
|
|
25
|
+
/** Office JS's `styleBuiltIn` for a style id: the `Word.Style` value, or 'Other'. */
|
|
26
|
+
export function builtInOf(styleId) {
|
|
27
|
+
var _a;
|
|
28
|
+
return (_a = BUILT_IN_BY_LOWER.get(styleId.replace(/\s+/g, '').toLowerCase())) !== null && _a !== void 0 ? _a : 'Other';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The style id for a `Word.Style` value ('Heading1'; leniently also the display name 'Heading 1'),
|
|
32
|
+
* in Word's spelling ('TOC1' for 'Toc1'). 'Other' cannot be set, as in Office JS.
|
|
33
|
+
*/
|
|
34
|
+
export function idOfBuiltIn(value) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
if (value === 'Other')
|
|
37
|
+
throw new RangeError("styleBuiltIn cannot be set to 'Other'");
|
|
38
|
+
const compact = value.replace(/\s+/g, '');
|
|
39
|
+
const lower = compact.toLowerCase();
|
|
40
|
+
return (_b = (_a = WORD_IDS[lower]) !== null && _a !== void 0 ? _a : BUILT_IN_BY_LOWER.get(lower)) !== null && _b !== void 0 ? _b : compact;
|
|
41
|
+
}
|
|
42
|
+
/** The display name of a style id, from its stored `w:name` when given ('heading 1' to 'Heading 1'). */
|
|
43
|
+
export function displayNameOf(styleId, storedName) {
|
|
44
|
+
const known = DISPLAY_NAMES[styleId];
|
|
45
|
+
if (known)
|
|
46
|
+
return known;
|
|
47
|
+
if (storedName !== undefined) {
|
|
48
|
+
// Word stores its built-in names in lower case ('heading 1', 'toc 1', 'footnote text'); a
|
|
49
|
+
// custom style keeps the case its author gave it. Built-ins are the ids Word derives from them.
|
|
50
|
+
if (storedName.replace(/\s+/g, '').toLowerCase() !== styleId.toLowerCase())
|
|
51
|
+
return storedName;
|
|
52
|
+
return storedName.replace(/(^|\s)([a-z])/g, (_, sp, c) => sp + c.toUpperCase()).replace(/^Toc\b/, 'TOC').replace(/^Toa\b/, 'TOA');
|
|
53
|
+
}
|
|
54
|
+
return styleId.replace(/(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Za-z])(?=[0-9])/g, ' ');
|
|
55
|
+
}
|
|
56
|
+
const stylesPartOf = (pkg) => { var _a; return (_a = pkg === null || pkg === void 0 ? void 0 : pkg.getMainPart()) === null || _a === void 0 ? void 0 : _a.styleDefinitionsPart; };
|
|
57
|
+
/** The styles of the package's styles part when it is unmarshalled; nothing is unmarshalled here. */
|
|
58
|
+
function stylesOf(pkg) {
|
|
59
|
+
var _a;
|
|
60
|
+
const part = stylesPartOf(pkg);
|
|
61
|
+
return (part === null || part === void 0 ? void 0 : part.isUnmarshalled) ? (_a = part.contents.style) !== null && _a !== void 0 ? _a : [] : [];
|
|
62
|
+
}
|
|
63
|
+
/** Office JS's `style`: the display name of a style id. */
|
|
64
|
+
export function styleNameOf(pkg, styleId) {
|
|
65
|
+
var _a;
|
|
66
|
+
const style = stylesOf(pkg).find((s) => s.styleId === styleId);
|
|
67
|
+
return displayNameOf(styleId, (_a = style === null || style === void 0 ? void 0 : style.name) === null || _a === void 0 ? void 0 : _a.val);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The style id for what Office JS's `style` accepts: a display name ('Heading 1', 'My Style'), the
|
|
71
|
+
* stored name ('heading 1'), or, as an extension, the id itself ('Heading1'). Resolved against the
|
|
72
|
+
* styles part when it is unmarshalled, else by removing spaces.
|
|
73
|
+
*/
|
|
74
|
+
export function styleIdOf(pkg, name) {
|
|
75
|
+
var _a, _b, _c, _d, _e, _f;
|
|
76
|
+
const lower = name.toLowerCase();
|
|
77
|
+
for (const s of stylesOf(pkg)) {
|
|
78
|
+
if (((_a = s.styleId) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === lower || ((_c = (_b = s.name) === null || _b === void 0 ? void 0 : _b.val) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === lower || (s.styleId && displayNameOf(s.styleId, (_d = s.name) === null || _d === void 0 ? void 0 : _d.val).toLowerCase() === lower))
|
|
79
|
+
return (_e = s.styleId) !== null && _e !== void 0 ? _e : name;
|
|
80
|
+
}
|
|
81
|
+
const compact = name.replace(/\s+/g, '');
|
|
82
|
+
for (const [id, display] of Object.entries(DISPLAY_NAMES))
|
|
83
|
+
if (display.toLowerCase() === lower)
|
|
84
|
+
return id;
|
|
85
|
+
return (_f = WORD_IDS[compact.toLowerCase()]) !== null && _f !== void 0 ? _f : compact;
|
|
86
|
+
}
|