@docx4j/core-ts 0.1.5 → 0.2.1
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 +81 -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 +37 -21
- package/dist/model/content/Range.d.mts +36 -5
- package/dist/model/content/Range.mjs +97 -26
- package/dist/model/content/binder.d.mts +44 -0
- package/dist/model/content/binder.mjs +128 -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 +105 -3
- package/dist/packages/WordprocessingMLPackage.mjs +165 -2
- 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/dist/xml/dom.d.mts +10 -1
- package/dist/xml/dom.mjs +46 -2
- package/package.json +2 -2
|
@@ -12,8 +12,9 @@ import { newFontSettings, themeOfSettings, } from '../model/fonts/defaultTheme.m
|
|
|
12
12
|
import { HeaderPart, FooterPart } from '../parts/wml/index.mjs';
|
|
13
13
|
import { CustomXmlPartCollection } from '../model/customxml/CustomXmlPartCollection.mjs';
|
|
14
14
|
import { DefaultXPathEngine } from '../model/customxml/xpath.mjs';
|
|
15
|
-
import { ChangeTracker } from '../model/content/tracking.mjs';
|
|
15
|
+
import { ChangeTracker, highestAnnotationId } from '../model/content/tracking.mjs';
|
|
16
16
|
import { NumberingFacade } from '../model/content/List.mjs';
|
|
17
|
+
import { StylesFacade } from '../model/content/stylesFacade.mjs';
|
|
17
18
|
import { PropertyResolver } from '../model/properties/PropertyResolver.mjs';
|
|
18
19
|
import { PropertyResolverNotCreatedException } from '../opc/exceptions.mjs';
|
|
19
20
|
import { XmlPart } from '../parts/XmlPart.mjs';
|
|
@@ -68,6 +69,24 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
68
69
|
this.author = { name: 'docx4j' };
|
|
69
70
|
/** Set when `changeTrackingMode` was written but the settings part was not unmarshalled yet. */
|
|
70
71
|
this.trackingPending = false;
|
|
72
|
+
/**
|
|
73
|
+
* The `withTracking` calls still running, oldest first, and what the package said before the
|
|
74
|
+
* first of them. The latest call's markup applies; when it ends, the latest one still running
|
|
75
|
+
* applies again, and when none is left the package is as it was (CR-002 section 31).
|
|
76
|
+
*/
|
|
77
|
+
this.trackingScopes = [];
|
|
78
|
+
/**
|
|
79
|
+
* Style ids a synchronous setter has given runs, to be defined in the styles part by the time the
|
|
80
|
+
* package is saved: `Range.hyperlink` writes `w:rStyle w:val="Hyperlink"` and cannot await
|
|
81
|
+
* `styles.ensure` (CR-002 section 25). `saveTo` ensures them; nothing is read before then.
|
|
82
|
+
*/
|
|
83
|
+
this.requiredStyles = new Set();
|
|
84
|
+
/**
|
|
85
|
+
* The parts `seedAnnotationIds()` has read, with what it read: `true` for a part still holding its
|
|
86
|
+
* source, whose bytes cannot change, and otherwise the bytes that were set, which stay the same
|
|
87
|
+
* array until they are set again.
|
|
88
|
+
*/
|
|
89
|
+
this.seededParts = new WeakMap();
|
|
71
90
|
/**
|
|
72
91
|
* The package's font settings (CR-001 Phase B step 4), docx4j's `docx4j.fonts.*` properties
|
|
73
92
|
* scoped to one package: `defaultTheme` says which Office theme a font reference resolves
|
|
@@ -79,6 +98,11 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
79
98
|
* `mainDocumentPart.refreshFonts()`.
|
|
80
99
|
*/
|
|
81
100
|
this.fonts = newFontSettings();
|
|
101
|
+
/**
|
|
102
|
+
* TrackingHost: a floor for the annotation id, from the WordprocessingML parts that were **not**
|
|
103
|
+
* unmarshalled; `seedAnnotationIds()` fills it. 0 until then (CR-002 section 28.2).
|
|
104
|
+
*/
|
|
105
|
+
this.annotationIdFloor = 0;
|
|
82
106
|
// --- custom XML (CR-002 phase E) ---
|
|
83
107
|
/**
|
|
84
108
|
* The XPath engine the custom XML views use (CR-002 section 3.6): `document.evaluate` in a
|
|
@@ -258,6 +282,8 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
258
282
|
*/
|
|
259
283
|
get changeTrackingMode() {
|
|
260
284
|
var _a;
|
|
285
|
+
if (this.trackingOverride !== undefined)
|
|
286
|
+
return this.trackingOverride;
|
|
261
287
|
if (this.trackingMode !== undefined)
|
|
262
288
|
return this.trackingMode;
|
|
263
289
|
const settings = (_a = this.mainDocumentPart) === null || _a === void 0 ? void 0 : _a.documentSettingsPart;
|
|
@@ -268,6 +294,7 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
268
294
|
set changeTrackingMode(mode) {
|
|
269
295
|
this.trackingMode = mode;
|
|
270
296
|
this.tracker = undefined;
|
|
297
|
+
this.annotationIdCounter = undefined;
|
|
271
298
|
const settings = this.mainDocumentPart ? this.settingsPart() : undefined;
|
|
272
299
|
if (settings === null || settings === void 0 ? void 0 : settings.isUnmarshalled) {
|
|
273
300
|
writeTrackRevisions(settings.contents, mode);
|
|
@@ -276,6 +303,58 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
276
303
|
else
|
|
277
304
|
this.trackingPending = true;
|
|
278
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Runs `fn` with revisions recorded as `markup` says, and the document's own setting untouched:
|
|
308
|
+
* nothing is written to `w:trackRevisions`, no settings part is created, and the mode a later read
|
|
309
|
+
* reports is the one that was there before (CR-002 section 28.1, for an editor whose agent must
|
|
310
|
+
* record its edits as a named author in a room whose tracking setting belongs to the document).
|
|
311
|
+
*
|
|
312
|
+
* The author, the date and the mode are restored in a `finally`, so a throw from `fn` cannot leave
|
|
313
|
+
* the package tracking. It is asynchronous for one reason: it awaits `seedAnnotationIds()` before
|
|
314
|
+
* running `fn`, so a revision written inside it cannot reuse an id from a part nobody has read
|
|
315
|
+
* (section 28.2). `fn` itself may be synchronous.
|
|
316
|
+
*
|
|
317
|
+
* Calls nest, and calls that overlap in time end in whatever order they end without leaving the
|
|
318
|
+
* package tracking. But the markup is the package's for as long as a call runs, not the call's:
|
|
319
|
+
* while two are running, **the later one's author and mode apply to every edit**, the earlier
|
|
320
|
+
* one's included, because nothing here can tell which asynchronous call an edit came from. Await
|
|
321
|
+
* one before starting another when they must be recorded as different authors (section 31).
|
|
322
|
+
*/
|
|
323
|
+
async withTracking(markup, fn) {
|
|
324
|
+
await this.seedAnnotationIds();
|
|
325
|
+
const scope = { ...markup };
|
|
326
|
+
if (this.trackingScopes.length === 0) {
|
|
327
|
+
this.beforeScopes = { author: this.author, date: this.trackedChangeDate, override: this.trackingOverride };
|
|
328
|
+
}
|
|
329
|
+
this.trackingScopes.push(scope);
|
|
330
|
+
this.applyTrackingScope(scope);
|
|
331
|
+
try {
|
|
332
|
+
return await fn();
|
|
333
|
+
}
|
|
334
|
+
finally {
|
|
335
|
+
this.trackingScopes.splice(this.trackingScopes.indexOf(scope), 1);
|
|
336
|
+
const latest = this.trackingScopes[this.trackingScopes.length - 1];
|
|
337
|
+
if (latest !== undefined)
|
|
338
|
+
this.applyTrackingScope(latest);
|
|
339
|
+
else if (this.beforeScopes !== undefined) {
|
|
340
|
+
this.author = this.beforeScopes.author;
|
|
341
|
+
this.trackedChangeDate = this.beforeScopes.date;
|
|
342
|
+
this.trackingOverride = this.beforeScopes.override;
|
|
343
|
+
this.beforeScopes = undefined;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* One `withTracking` call's markup made the package's. The tracker is left alone: the getter makes
|
|
349
|
+
* another when the mode differs, and the id counter it reads is the package's, so a tracker kept
|
|
350
|
+
* across the call cannot reissue an id given out inside it (section 31).
|
|
351
|
+
*/
|
|
352
|
+
applyTrackingScope(scope) {
|
|
353
|
+
var _a;
|
|
354
|
+
this.author = scope.author;
|
|
355
|
+
this.trackedChangeDate = scope.date;
|
|
356
|
+
this.trackingOverride = (_a = scope.mode) !== null && _a !== void 0 ? _a : 'TrackAll';
|
|
357
|
+
}
|
|
279
358
|
/** The mode as the settings part has it, unmarshalling the part (docx4j's async counterpart of the getter). */
|
|
280
359
|
async getChangeTrackingMode() {
|
|
281
360
|
var _a, _b;
|
|
@@ -288,8 +367,11 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
288
367
|
async setChangeTrackingMode(mode) {
|
|
289
368
|
this.trackingMode = mode;
|
|
290
369
|
this.tracker = undefined;
|
|
370
|
+
this.annotationIdCounter = undefined;
|
|
291
371
|
this.trackingPending = false;
|
|
292
372
|
writeTrackRevisions(await this.settingsPart().getContents(), mode);
|
|
373
|
+
if (mode !== 'Off')
|
|
374
|
+
await this.seedAnnotationIds();
|
|
293
375
|
}
|
|
294
376
|
/** The settings part, created (with its relationship and content type) when the document has none. */
|
|
295
377
|
settingsPart() {
|
|
@@ -319,6 +401,53 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
319
401
|
this.tracker = new ChangeTracker(this, mode);
|
|
320
402
|
return this.tracker;
|
|
321
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* The objects an XPath selects in a part of this document, through the package's engine
|
|
406
|
+
* (CR-006; docx4j `MainDocumentPart.getJAXBNodesViaXPath`). The part defaults to the main
|
|
407
|
+
* document part, which is what a `//w:p[...]` expression means.
|
|
408
|
+
*/
|
|
409
|
+
async selectObjects(xpath, options = {}) {
|
|
410
|
+
var _a;
|
|
411
|
+
const part = (_a = options.part) !== null && _a !== void 0 ? _a : this.getMainDocumentPart();
|
|
412
|
+
return part.selectObjects(xpath, { engine: this.xpathEngine, namespaces: options.namespaces });
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Raises `annotationIdFloor` above every annotation id in the WordprocessingML parts that are not
|
|
416
|
+
* unmarshalled, reading each **privately** (`readContents`, CR-001 Phase D's device), so that a
|
|
417
|
+
* part nobody has touched keeps its byte-for-byte round trip and still cannot have its ids reused.
|
|
418
|
+
*
|
|
419
|
+
* Awaited by `setChangeTrackingMode()` and by `withTracking()`, which is where tracking is turned
|
|
420
|
+
* on; a caller that uses the synchronous `changeTrackingMode` setter on a document with unread
|
|
421
|
+
* parts should await this itself, since `nextId()` cannot (the content API's setters are
|
|
422
|
+
* synchronous, which is why the floor exists at all rather than the scan being made async).
|
|
423
|
+
*
|
|
424
|
+
* A part is read once for the bytes it holds: an agent that wraps every edit in `withTracking`
|
|
425
|
+
* would otherwise re-read every header, footer and note part each time (section 31). Its source
|
|
426
|
+
* bytes cannot change; bytes that were set are read again when they are set again.
|
|
427
|
+
*/
|
|
428
|
+
async seedAnnotationIds() {
|
|
429
|
+
for (const part of this.parts) {
|
|
430
|
+
if (!(part instanceof XmlPart) || part.isUnmarshalled)
|
|
431
|
+
continue;
|
|
432
|
+
if (!part.partName.name.startsWith('/word/'))
|
|
433
|
+
continue;
|
|
434
|
+
const read = part.isUntouched ? true : await part.getBytes();
|
|
435
|
+
if (this.seededParts.get(part) === read)
|
|
436
|
+
continue;
|
|
437
|
+
let tree;
|
|
438
|
+
try {
|
|
439
|
+
tree = await part.readContents();
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
tree = undefined;
|
|
443
|
+
} // an unreadable part cannot hold ids we must avoid
|
|
444
|
+
if (typeof tree === 'object' && tree !== null) {
|
|
445
|
+
this.annotationIdFloor = highestAnnotationId(tree, this.annotationIdFloor);
|
|
446
|
+
}
|
|
447
|
+
this.seededParts.set(part, read);
|
|
448
|
+
}
|
|
449
|
+
return this.annotationIdFloor;
|
|
450
|
+
}
|
|
322
451
|
/** TrackingHost: the trees a new revision id must be above, which is every part already unmarshalled. */
|
|
323
452
|
markupRoots() {
|
|
324
453
|
const out = [];
|
|
@@ -331,10 +460,20 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
331
460
|
}
|
|
332
461
|
return out;
|
|
333
462
|
}
|
|
334
|
-
/**
|
|
463
|
+
/**
|
|
464
|
+
* Asks for style definitions a synchronous setter has referenced; they are ensured on save, as
|
|
465
|
+
* `pkg.styles.ensure(ids)` would, and a document that already has them keeps its styles part
|
|
466
|
+
* byte for byte (CR-002 section 25). Await `styles.ensure` instead to have them at once.
|
|
467
|
+
*/
|
|
468
|
+
requireStyles(ids) {
|
|
469
|
+
for (const id of ids)
|
|
470
|
+
this.requiredStyles.add(id);
|
|
471
|
+
}
|
|
472
|
+
/** A clone carries the identity, the tracking date, the theme setting, the XPath engine and the styles still to ensure. */
|
|
335
473
|
copyPackageSettingsTo(target) {
|
|
336
474
|
if (!(target instanceof WordprocessingMLPackage))
|
|
337
475
|
return;
|
|
476
|
+
target.requireStyles(this.requiredStyles);
|
|
338
477
|
target.author = { ...this.author };
|
|
339
478
|
target.trackedChangeDate = this.trackedChangeDate;
|
|
340
479
|
target.fonts.defaultTheme = this.fonts.defaultTheme;
|
|
@@ -344,6 +483,10 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
344
483
|
var _a;
|
|
345
484
|
if (this.trackingPending)
|
|
346
485
|
await this.setChangeTrackingMode((_a = this.trackingMode) !== null && _a !== void 0 ? _a : 'Off');
|
|
486
|
+
if (this.requiredStyles.size > 0) {
|
|
487
|
+
await this.styles.ensure([...this.requiredStyles]);
|
|
488
|
+
this.requiredStyles.clear();
|
|
489
|
+
}
|
|
347
490
|
return super.saveTo(sink);
|
|
348
491
|
}
|
|
349
492
|
/** The paragraph at an address anywhere in the document: 'body/3', 'header:rId5/0', a paraId, or a text match. */
|
|
@@ -386,6 +529,26 @@ export class WordprocessingMLPackage extends OpcPackage {
|
|
|
386
529
|
all.push(await part.getBody());
|
|
387
530
|
return all;
|
|
388
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* The document's style definitions as a verb that needs no `Body`: `ensure(ids)` splices in a
|
|
534
|
+
* style the document lacks, out of the same defaults `createPackage()` writes, with what it is
|
|
535
|
+
* based on and linked to (CR-002 section 22.2).
|
|
536
|
+
*/
|
|
537
|
+
get styles() {
|
|
538
|
+
var _a;
|
|
539
|
+
return ((_a = this.stylesFacade) !== null && _a !== void 0 ? _a : (this.stylesFacade = new StylesFacade(this)));
|
|
540
|
+
}
|
|
541
|
+
/** The styles part, created with the defaults when the document has none (CR-002 section 22.2). */
|
|
542
|
+
ensureStyleDefinitionsPart() {
|
|
543
|
+
const main = this.getMainDocumentPart();
|
|
544
|
+
let part = main.styleDefinitionsPart;
|
|
545
|
+
if (!part) {
|
|
546
|
+
part = new StyleDefinitionsPart();
|
|
547
|
+
part.setXml(DEFAULT_STYLES_XML);
|
|
548
|
+
main.addTargetPart(part);
|
|
549
|
+
}
|
|
550
|
+
return part;
|
|
551
|
+
}
|
|
389
552
|
/**
|
|
390
553
|
* The document's list definitions as verbs that need no paragraph: `newList()` and
|
|
391
554
|
* `restart(numId)` (CR-002 section 19). `Paragraph.startNewList()` and `List.restart()` are
|
package/dist/parts/XmlPart.d.mts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { type Jsonix } from '@docx4j/generated-objects-ts';
|
|
2
2
|
import { Part } from './Part.mjs';
|
|
3
3
|
import { PartName } from '../opc/PartName.mjs';
|
|
4
|
+
import { type Bound } from '../model/content/binder.mjs';
|
|
5
|
+
/** What `selectObjects` needs: the engine to evaluate with, and any prefixes beyond the defaults. */
|
|
6
|
+
export interface SelectOptions {
|
|
7
|
+
/** The engine; `pkg.selectObjects` and `Body.select` pass the package's. It is readied on the snapshot. */
|
|
8
|
+
engine?: {
|
|
9
|
+
ready(context?: Node): Promise<void>;
|
|
10
|
+
select(expression: string, context: Node, namespaces?: Record<string, string>): Node[];
|
|
11
|
+
} | undefined;
|
|
12
|
+
/** Prefixes added to (or overriding) the objects package's own table. */
|
|
13
|
+
namespaces?: Record<string, string> | undefined;
|
|
14
|
+
}
|
|
4
15
|
/** A qualified name for a part's root element. */
|
|
5
16
|
export interface RootName {
|
|
6
17
|
namespaceURI: string;
|
|
@@ -31,6 +42,12 @@ export declare class XmlPart<T = unknown> extends Part {
|
|
|
31
42
|
/** True once contents were unmarshalled or set; the part is then re-marshalled on save. */
|
|
32
43
|
get isUnmarshalled(): boolean;
|
|
33
44
|
get isLoaded(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* True while the part holds nothing but its source: never unmarshalled, no contents or bytes set.
|
|
47
|
+
* Such a part is written back byte for byte, and what a private read finds in it cannot change,
|
|
48
|
+
* which is what lets a reader remember it (CR-002 section 31).
|
|
49
|
+
*/
|
|
50
|
+
get isUntouched(): boolean;
|
|
34
51
|
/** The unmarshalled contents (docx4j getJaxbElement()); throws when not yet unmarshalled. */
|
|
35
52
|
get contents(): T;
|
|
36
53
|
/** The root element as [name, value]; undefined until unmarshalled. */
|
|
@@ -57,8 +74,35 @@ export declare class XmlPart<T = unknown> extends Part {
|
|
|
57
74
|
getXml(): Promise<string>;
|
|
58
75
|
/** Marshalled bytes when unmarshalled or set, else the source bytes untouched. */
|
|
59
76
|
getBytes(): Promise<Uint8Array>;
|
|
77
|
+
/**
|
|
78
|
+
* The objects an XPath selects in this part, through a DOM marshalled for the purpose
|
|
79
|
+
* (CR-006; docx4j `JaxbXmlPart.getJAXBNodesViaXPath`, which does it with a JAXB `Binder`).
|
|
80
|
+
*
|
|
81
|
+
* Each result carries the node the expression selected, the tree object behind it, the attribute
|
|
82
|
+
* name when an attribute was selected, and the node's path from the root. The DOM is a **snapshot**:
|
|
83
|
+
* changing it changes nothing, and a select leaves the part's own bytes alone - the marshal is
|
|
84
|
+
* thrown away. Every call marshals afresh, since the tree has no change log a cached snapshot could
|
|
85
|
+
* be checked against (CR-006 section 2).
|
|
86
|
+
*
|
|
87
|
+
* The prefixes default to the ones the objects package writes, so `//w:p[w:pPr/w:pStyle/@w:val='Heading1']`
|
|
88
|
+
* needs no mapping; `options.namespaces` adds to or overrides them. The engine is the caller's
|
|
89
|
+
* (`pkg.xpathEngine`: XPath 1.0 by default, 3.1 with `FontoXPathEngine`), and is readied here on
|
|
90
|
+
* the snapshot itself: whether an engine can evaluate a tree is a property of the document that
|
|
91
|
+
* tree is in (CR-002 section 21), and readying it on a marshal of its own would cost a second one
|
|
92
|
+
* (CR-002 section 31).
|
|
93
|
+
*/
|
|
94
|
+
selectObjects(xpath: string, options?: SelectOptions): Promise<Bound[]>;
|
|
60
95
|
/** The root element as a DOM element (docx4j XmlUtils.marshaltoW3CDomDocument). */
|
|
61
96
|
marshalToNode(): Promise<Element>;
|
|
97
|
+
/**
|
|
98
|
+
* Unmarshals, and names the part when the runtime refuses. The runtime's own message says what is
|
|
99
|
+
* wrong and, since `@docx4j/jsonix` 3.4.0, where - `w:sz/@w:val (line 12): Argument [NaN] must be
|
|
100
|
+
* an integer` - but not which part it was reading, which is the first thing a person editing a
|
|
101
|
+
* part's XML needs (CR-002 section 27). The location it found is lifted onto the exception so a
|
|
102
|
+
* caller does not parse the message; `line` is undefined where the parser supplies no position,
|
|
103
|
+
* which is every browser (only xmldom carries a locator).
|
|
104
|
+
*/
|
|
105
|
+
private unmarshal;
|
|
62
106
|
/** The source root element's namespace declarations, prefix to URI (`xmlns=` is the empty prefix). */
|
|
63
107
|
private recordDeclarations;
|
|
64
108
|
/**
|
package/dist/parts/XmlPart.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { unmarshalNode, marshalNode, NAMESPACE_PREFIXES } from '@docx4j/generated-objects-ts';
|
|
2
2
|
import { Part } from './Part.mjs';
|
|
3
3
|
import { Namespaces } from './Namespaces.mjs';
|
|
4
|
-
import { Docx4JException } from '../opc/exceptions.mjs';
|
|
4
|
+
import { Docx4JException, PartUnmarshalException } from '../opc/exceptions.mjs';
|
|
5
5
|
import { parseXml, serializeXml, encodeText, decodeXmlText, XML_DECLARATION } from '../xml/dom.mjs';
|
|
6
6
|
import { log } from '../model/properties/log.mjs';
|
|
7
|
+
import { bindSnapshot, boundsOf } from '../model/content/binder.mjs';
|
|
7
8
|
const XMLNS_NS = 'http://www.w3.org/2000/xmlns/';
|
|
8
9
|
const MC_NS = Namespaces.MARKUP_COMPATIBILITY;
|
|
9
10
|
/** The objects package's prefix table the other way round, prefix to URI, built once. */
|
|
@@ -18,6 +19,26 @@ function knownUriOf(prefix) {
|
|
|
18
19
|
return prefixToUri.get(prefix);
|
|
19
20
|
}
|
|
20
21
|
const warnedPrefixes = new Set();
|
|
22
|
+
/**
|
|
23
|
+
* The element or attribute a located runtime error names, out of its message: jsonix writes
|
|
24
|
+
* `w:sz/@w:val (line 7): ...` when it could place the fault and `w:bogus (line 3): ...` for an
|
|
25
|
+
* element, so the location is everything before the position or the colon - and `w:sz` must not be
|
|
26
|
+
* cut at its own prefix separator, which a naive split on `:` does.
|
|
27
|
+
*/
|
|
28
|
+
function locationOf(message, located) {
|
|
29
|
+
var _a;
|
|
30
|
+
if (!located)
|
|
31
|
+
return undefined;
|
|
32
|
+
return (_a = /^(.+?)(?: \(line \d+(?:, column \d+)?\))?: /.exec(message)) === null || _a === void 0 ? void 0 : _a[1];
|
|
33
|
+
}
|
|
34
|
+
/** The objects package's prefix table as XPath wants it, prefix to URI; built once. */
|
|
35
|
+
const NAMESPACE_PREFIXES_BY_PREFIX = (() => {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const [uri, prefix] of Object.entries(NAMESPACE_PREFIXES))
|
|
38
|
+
if (prefix !== '' && !(prefix in out))
|
|
39
|
+
out[prefix] = uri;
|
|
40
|
+
return out;
|
|
41
|
+
})();
|
|
21
42
|
/**
|
|
22
43
|
* A part whose content is a typed element of the object model (docx4j JaxbXmlPart<E>). `T` is the
|
|
23
44
|
* root element's value type (`Document`, `Styles`, ...). Contents are unmarshalled on first
|
|
@@ -36,6 +57,14 @@ export class XmlPart extends Part {
|
|
|
36
57
|
get isLoaded() {
|
|
37
58
|
return this.element !== undefined || this.bytes !== undefined;
|
|
38
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* True while the part holds nothing but its source: never unmarshalled, no contents or bytes set.
|
|
62
|
+
* Such a part is written back byte for byte, and what a private read finds in it cannot change,
|
|
63
|
+
* which is what lets a reader remember it (CR-002 section 31).
|
|
64
|
+
*/
|
|
65
|
+
get isUntouched() {
|
|
66
|
+
return this.element === undefined && this.bytes === undefined;
|
|
67
|
+
}
|
|
39
68
|
/** The unmarshalled contents (docx4j getJaxbElement()); throws when not yet unmarshalled. */
|
|
40
69
|
get contents() {
|
|
41
70
|
if (this.element === undefined)
|
|
@@ -56,7 +85,7 @@ export class XmlPart extends Part {
|
|
|
56
85
|
const doc = parseXml(decodeXmlText(bytes));
|
|
57
86
|
this.recordDeclarations(doc);
|
|
58
87
|
(_b = this.preprocessor) === null || _b === void 0 ? void 0 : _b.call(this, doc, this);
|
|
59
|
-
this.element = await
|
|
88
|
+
this.element = await this.unmarshal(doc);
|
|
60
89
|
(_c = this.rootName) !== null && _c !== void 0 ? _c : (this.rootName = { namespaceURI: this.element.name.namespaceURI, localPart: this.element.name.localPart });
|
|
61
90
|
this.bytes = undefined;
|
|
62
91
|
}
|
|
@@ -81,7 +110,7 @@ export class XmlPart extends Part {
|
|
|
81
110
|
const doc = parseXml(decodeXmlText(bytes));
|
|
82
111
|
this.recordDeclarations(doc);
|
|
83
112
|
(_b = this.preprocessor) === null || _b === void 0 ? void 0 : _b.call(this, doc, this);
|
|
84
|
-
return (await
|
|
113
|
+
return (await this.unmarshal(doc)).value;
|
|
85
114
|
}
|
|
86
115
|
/** Replaces the contents (docx4j setJaxbElement / setContents). The root name defaults to the part's. */
|
|
87
116
|
setContents(value, rootName) {
|
|
@@ -116,6 +145,36 @@ export class XmlPart extends Part {
|
|
|
116
145
|
throw new Docx4JException(`Part ${this.partName} has no content and no source container`);
|
|
117
146
|
return loaded;
|
|
118
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* The objects an XPath selects in this part, through a DOM marshalled for the purpose
|
|
150
|
+
* (CR-006; docx4j `JaxbXmlPart.getJAXBNodesViaXPath`, which does it with a JAXB `Binder`).
|
|
151
|
+
*
|
|
152
|
+
* Each result carries the node the expression selected, the tree object behind it, the attribute
|
|
153
|
+
* name when an attribute was selected, and the node's path from the root. The DOM is a **snapshot**:
|
|
154
|
+
* changing it changes nothing, and a select leaves the part's own bytes alone - the marshal is
|
|
155
|
+
* thrown away. Every call marshals afresh, since the tree has no change log a cached snapshot could
|
|
156
|
+
* be checked against (CR-006 section 2).
|
|
157
|
+
*
|
|
158
|
+
* The prefixes default to the ones the objects package writes, so `//w:p[w:pPr/w:pStyle/@w:val='Heading1']`
|
|
159
|
+
* needs no mapping; `options.namespaces` adds to or overrides them. The engine is the caller's
|
|
160
|
+
* (`pkg.xpathEngine`: XPath 1.0 by default, 3.1 with `FontoXPathEngine`), and is readied here on
|
|
161
|
+
* the snapshot itself: whether an engine can evaluate a tree is a property of the document that
|
|
162
|
+
* tree is in (CR-002 section 21), and readying it on a marshal of its own would cost a second one
|
|
163
|
+
* (CR-002 section 31).
|
|
164
|
+
*/
|
|
165
|
+
async selectObjects(xpath, options = {}) {
|
|
166
|
+
var _a;
|
|
167
|
+
const element = (_a = this.element) !== null && _a !== void 0 ? _a : (await this.getContents(), this.element);
|
|
168
|
+
if (element === undefined)
|
|
169
|
+
throw new Docx4JException(`Part ${this.partName} has no contents to select over`);
|
|
170
|
+
const engine = options.engine;
|
|
171
|
+
if (engine === undefined)
|
|
172
|
+
throw new Docx4JException(`selectObjects on ${this.partName} needs an XPath engine; pkg.selectObjects passes the package's`);
|
|
173
|
+
const snapshot = await bindSnapshot(element);
|
|
174
|
+
await engine.ready(snapshot.root);
|
|
175
|
+
const namespaces = { ...NAMESPACE_PREFIXES_BY_PREFIX, ...options.namespaces };
|
|
176
|
+
return boundsOf(engine.select(xpath, snapshot.root, namespaces), snapshot);
|
|
177
|
+
}
|
|
119
178
|
/** The root element as a DOM element (docx4j XmlUtils.marshaltoW3CDomDocument). */
|
|
120
179
|
async marshalToNode() {
|
|
121
180
|
if (this.element === undefined)
|
|
@@ -124,6 +183,30 @@ export class XmlPart extends Part {
|
|
|
124
183
|
this.declareIgnorablePrefixes(root);
|
|
125
184
|
return root;
|
|
126
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Unmarshals, and names the part when the runtime refuses. The runtime's own message says what is
|
|
188
|
+
* wrong and, since `@docx4j/jsonix` 3.4.0, where - `w:sz/@w:val (line 12): Argument [NaN] must be
|
|
189
|
+
* an integer` - but not which part it was reading, which is the first thing a person editing a
|
|
190
|
+
* part's XML needs (CR-002 section 27). The location it found is lifted onto the exception so a
|
|
191
|
+
* caller does not parse the message; `line` is undefined where the parser supplies no position,
|
|
192
|
+
* which is every browser (only xmldom carries a locator).
|
|
193
|
+
*/
|
|
194
|
+
async unmarshal(doc) {
|
|
195
|
+
var _a, _b;
|
|
196
|
+
try {
|
|
197
|
+
return await unmarshalNode(doc);
|
|
198
|
+
}
|
|
199
|
+
catch (cause) {
|
|
200
|
+
const located = cause;
|
|
201
|
+
const message = typeof (located === null || located === void 0 ? void 0 : located.message) === 'string' ? located.message : String(cause);
|
|
202
|
+
throw new PartUnmarshalException(`${this.partName}: ${message}`, this.partName.name, {
|
|
203
|
+
cause,
|
|
204
|
+
location: locationOf(message, (located === null || located === void 0 ? void 0 : located.jsonixLocated) === true),
|
|
205
|
+
line: typeof ((_a = located === null || located === void 0 ? void 0 : located.node) === null || _a === void 0 ? void 0 : _a.lineNumber) === 'number' ? located.node.lineNumber : undefined,
|
|
206
|
+
column: typeof ((_b = located === null || located === void 0 ? void 0 : located.node) === null || _b === void 0 ? void 0 : _b.columnNumber) === 'number' ? located.node.columnNumber : undefined,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
127
210
|
/** The source root element's namespace declarations, prefix to URI (`xmlns=` is the empty prefix). */
|
|
128
211
|
recordDeclarations(doc) {
|
|
129
212
|
var _a;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type * as sml from '@docx4j/generated-objects-ts/modules/org_xlsx4j_sml';
|
|
2
|
+
import type * as x14 from '@docx4j/generated-objects-ts/modules/org_xlsx4j_com_microsoft_schemas_office_spreadsheetml_x2009_x9_main';
|
|
3
|
+
import type * as x15 from '@docx4j/generated-objects-ts/modules/org_xlsx4j_com_microsoft_schemas_office_spreadsheetml_x2010_x11_main';
|
|
2
4
|
import { XmlPart } from '../XmlPart.mjs';
|
|
3
|
-
import { DefaultXmlPart } from '../DefaultXmlPart.mjs';
|
|
4
5
|
import { BinaryPart } from '../BinaryPart.mjs';
|
|
5
6
|
import { Part } from '../Part.mjs';
|
|
6
7
|
import { PartName } from '../../opc/PartName.mjs';
|
|
@@ -99,31 +100,31 @@ export declare class PrinterSettingsPart extends BinaryPart {
|
|
|
99
100
|
constructor(partName: PartName | string);
|
|
100
101
|
}
|
|
101
102
|
/** A slicer cache (`x14:slicerCacheDefinition`), from the workbook. docx4j `SlicerCachePart`. */
|
|
102
|
-
export declare class SlicerCachePart extends
|
|
103
|
+
export declare class SlicerCachePart extends XmlPart<x14.CTSlicerCacheDefinition> {
|
|
103
104
|
constructor(partName?: PartName | string);
|
|
104
105
|
}
|
|
105
106
|
/** A sheet's slicers (`x14:slicers`). docx4j `SlicersPart`. */
|
|
106
|
-
export declare class SlicersPart extends
|
|
107
|
+
export declare class SlicersPart extends XmlPart<x14.CTSlicers> {
|
|
107
108
|
constructor(partName?: PartName | string);
|
|
108
109
|
}
|
|
109
110
|
/** A timeline cache (`x15:timelineCacheDefinition`), from the workbook. docx4j `TimelineCachePart`. */
|
|
110
|
-
export declare class TimelineCachePart extends
|
|
111
|
+
export declare class TimelineCachePart extends XmlPart<x15.CTTimelineCacheDefinition> {
|
|
111
112
|
constructor(partName?: PartName | string);
|
|
112
113
|
}
|
|
113
114
|
/** A sheet's timelines (`x15:timelines`). docx4j `TimelinesPart`. */
|
|
114
|
-
export declare class TimelinesPart extends
|
|
115
|
+
export declare class TimelinesPart extends XmlPart<x15.CTTimelines> {
|
|
115
116
|
constructor(partName?: PartName | string);
|
|
116
117
|
}
|
|
117
118
|
/** A form control's properties (`x14:formControlPr`), from a worksheet. docx4j `ControlPropertiesPart`. */
|
|
118
|
-
export declare class ControlPropertiesPart extends
|
|
119
|
+
export declare class ControlPropertiesPart extends XmlPart<x14.CTFormControlPr> {
|
|
119
120
|
constructor(partName?: PartName | string);
|
|
120
121
|
}
|
|
121
122
|
/** The properties of a custom data part (`x14:datastoreItem`). docx4j `CustomDataPropertiesPart`. */
|
|
122
|
-
export declare class CustomDataPropertiesPart extends
|
|
123
|
+
export declare class CustomDataPropertiesPart extends XmlPart<x14.CTDatastoreItem> {
|
|
123
124
|
constructor(partName?: PartName | string);
|
|
124
125
|
}
|
|
125
126
|
/** A survey (`x15:survey`), from the workbook. docx4j `SurveyPart`. */
|
|
126
|
-
export declare class SurveyPart extends
|
|
127
|
+
export declare class SurveyPart extends XmlPart<x15.CTSurvey> {
|
|
127
128
|
constructor(partName?: PartName | string);
|
|
128
129
|
}
|
|
129
130
|
/**
|
package/dist/parts/sml/index.mjs
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { XmlPart } from '../XmlPart.mjs';
|
|
2
|
-
import { DefaultXmlPart } from '../DefaultXmlPart.mjs';
|
|
3
2
|
import { BinaryPart } from '../BinaryPart.mjs';
|
|
4
3
|
import { ContentTypes } from '../../opc/ContentTypes.mjs';
|
|
5
4
|
import { Namespaces } from '../Namespaces.mjs';
|
|
6
5
|
import { Xlsx4jException } from '../../opc/exceptions.mjs';
|
|
7
6
|
const S = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
|
|
7
|
+
/** The Excel 2010 extension namespace (x14; docx4j's org.xlsx4j...x2009.x9.main). */
|
|
8
|
+
const X14 = 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main';
|
|
9
|
+
/** The Excel 2013 extension namespace (x15; docx4j's org.xlsx4j...x2010.x11.main). */
|
|
10
|
+
const X15 = 'http://schemas.microsoft.com/office/spreadsheetml/2010/11/main';
|
|
8
11
|
export class WorkbookPart extends XmlPart {
|
|
9
12
|
constructor(partName = '/xl/workbook.xml', contentType = ContentTypes.SPREADSHEETML_WORKBOOK) {
|
|
10
13
|
super(partName, contentType, Namespaces.SPREADSHEETML_WORKBOOK, { namespaceURI: S, localPart: 'workbook' });
|
|
@@ -196,50 +199,51 @@ export class PrinterSettingsPart extends BinaryPart {
|
|
|
196
199
|
super(partName, ContentTypes.SPREADSHEETML_PRINTER_SETTINGS, Namespaces.SPREADSHEETML_PRINTER_SETTINGS);
|
|
197
200
|
}
|
|
198
201
|
}
|
|
199
|
-
// The Excel 2010 and 2013 extension parts (CR-004
|
|
200
|
-
// org.docx4j.openpackaging.parts.SpreadsheetML).
|
|
201
|
-
//
|
|
202
|
-
//
|
|
202
|
+
// The Excel 2010 and 2013 extension parts (CR-004; docx4j
|
|
203
|
+
// org.docx4j.openpackaging.parts.SpreadsheetML). Phase A held the seven XML ones as DOM; phase B
|
|
204
|
+
// types them over the x14 and x15 roots the objects package's CR-022 regeneration bound, so their
|
|
205
|
+
// contents read like any other part's and a re-marshalled root is Excel's own shape (the
|
|
206
|
+
// mc:Ignorable Excel writes on them is a property of each root, re-declared by `XmlPart`).
|
|
203
207
|
/** A slicer cache (`x14:slicerCacheDefinition`), from the workbook. docx4j `SlicerCachePart`. */
|
|
204
|
-
export class SlicerCachePart extends
|
|
208
|
+
export class SlicerCachePart extends XmlPart {
|
|
205
209
|
constructor(partName = '/xl/slicerCaches/slicerCache1.xml') {
|
|
206
|
-
super(partName, ContentTypes.SPREADSHEETML_SLICER_CACHE, Namespaces.SPREADSHEETML_SLICER_CACHE);
|
|
210
|
+
super(partName, ContentTypes.SPREADSHEETML_SLICER_CACHE, Namespaces.SPREADSHEETML_SLICER_CACHE, { namespaceURI: X14, localPart: 'slicerCacheDefinition' });
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
/** A sheet's slicers (`x14:slicers`). docx4j `SlicersPart`. */
|
|
210
|
-
export class SlicersPart extends
|
|
214
|
+
export class SlicersPart extends XmlPart {
|
|
211
215
|
constructor(partName = '/xl/slicers/slicer1.xml') {
|
|
212
|
-
super(partName, ContentTypes.SPREADSHEETML_SLICERS, Namespaces.SPREADSHEETML_SLICERS);
|
|
216
|
+
super(partName, ContentTypes.SPREADSHEETML_SLICERS, Namespaces.SPREADSHEETML_SLICERS, { namespaceURI: X14, localPart: 'slicers' });
|
|
213
217
|
}
|
|
214
218
|
}
|
|
215
219
|
/** A timeline cache (`x15:timelineCacheDefinition`), from the workbook. docx4j `TimelineCachePart`. */
|
|
216
|
-
export class TimelineCachePart extends
|
|
220
|
+
export class TimelineCachePart extends XmlPart {
|
|
217
221
|
constructor(partName = '/xl/timelineCaches/timelineCache1.xml') {
|
|
218
|
-
super(partName, ContentTypes.SPREADSHEETML_TIMELINE_CACHE, Namespaces.SPREADSHEETML_TIMELINE_CACHE);
|
|
222
|
+
super(partName, ContentTypes.SPREADSHEETML_TIMELINE_CACHE, Namespaces.SPREADSHEETML_TIMELINE_CACHE, { namespaceURI: X15, localPart: 'timelineCacheDefinition' });
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
/** A sheet's timelines (`x15:timelines`). docx4j `TimelinesPart`. */
|
|
222
|
-
export class TimelinesPart extends
|
|
226
|
+
export class TimelinesPart extends XmlPart {
|
|
223
227
|
constructor(partName = '/xl/timelines/timeline1.xml') {
|
|
224
|
-
super(partName, ContentTypes.SPREADSHEETML_TIMELINES, Namespaces.SPREADSHEETML_TIMELINES);
|
|
228
|
+
super(partName, ContentTypes.SPREADSHEETML_TIMELINES, Namespaces.SPREADSHEETML_TIMELINES, { namespaceURI: X15, localPart: 'timelines' });
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
/** A form control's properties (`x14:formControlPr`), from a worksheet. docx4j `ControlPropertiesPart`. */
|
|
228
|
-
export class ControlPropertiesPart extends
|
|
232
|
+
export class ControlPropertiesPart extends XmlPart {
|
|
229
233
|
constructor(partName = '/xl/ctrlProps/ctrlProp1.xml') {
|
|
230
|
-
super(partName, ContentTypes.SPREADSHEETML_CONTROL_PROPERTIES, Namespaces.SPREADSHEETML_CONTROL_PROPERTIES);
|
|
234
|
+
super(partName, ContentTypes.SPREADSHEETML_CONTROL_PROPERTIES, Namespaces.SPREADSHEETML_CONTROL_PROPERTIES, { namespaceURI: X14, localPart: 'formControlPr' });
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
/** The properties of a custom data part (`x14:datastoreItem`). docx4j `CustomDataPropertiesPart`. */
|
|
234
|
-
export class CustomDataPropertiesPart extends
|
|
238
|
+
export class CustomDataPropertiesPart extends XmlPart {
|
|
235
239
|
constructor(partName = '/xl/customDataProps/customDataProps1.xml') {
|
|
236
|
-
super(partName, ContentTypes.SPREADSHEETML_CUSTOM_DATA_PROPERTIES, Namespaces.SPREADSHEETML_CUSTOM_DATA_PROPERTIES);
|
|
240
|
+
super(partName, ContentTypes.SPREADSHEETML_CUSTOM_DATA_PROPERTIES, Namespaces.SPREADSHEETML_CUSTOM_DATA_PROPERTIES, { namespaceURI: X14, localPart: 'datastoreItem' });
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
243
|
/** A survey (`x15:survey`), from the workbook. docx4j `SurveyPart`. */
|
|
240
|
-
export class SurveyPart extends
|
|
244
|
+
export class SurveyPart extends XmlPart {
|
|
241
245
|
constructor(partName = '/xl/surveys/survey1.xml') {
|
|
242
|
-
super(partName, ContentTypes.SPREADSHEETML_SURVEY, Namespaces.SPREADSHEETML_SURVEY);
|
|
246
|
+
super(partName, ContentTypes.SPREADSHEETML_SURVEY, Namespaces.SPREADSHEETML_SURVEY, { namespaceURI: X15, localPart: 'survey' });
|
|
243
247
|
}
|
|
244
248
|
}
|
|
245
249
|
/**
|
|
@@ -85,8 +85,16 @@ export declare class MainDocumentPart extends DocumentPart<wml.Document> {
|
|
|
85
85
|
/** The style ids used directly in the document (docx4j `getStylesInUse()`); not those that
|
|
86
86
|
* others are merely based on. */
|
|
87
87
|
getStylesInUse(): Promise<Set<string>>;
|
|
88
|
-
/**
|
|
89
|
-
*
|
|
88
|
+
/**
|
|
89
|
+
* The block-level content of each story, in docx4j's order: the body, then the headers and
|
|
90
|
+
* footers, the endnotes, the footnotes and the comments.
|
|
91
|
+
*
|
|
92
|
+
* Every story is read **privately** (`readContents`, which answers the unmarshalled tree when
|
|
93
|
+
* there is one and parses without keeping it when there is not), so asking a document which
|
|
94
|
+
* fonts it uses does not cost any part its byte-for-byte round trip. The body used to come from
|
|
95
|
+
* `getContents()`, which unmarshalled the main part and so re-marshalled it on the next save
|
|
96
|
+
* (CR-001 section 18).
|
|
97
|
+
*/
|
|
90
98
|
private stories;
|
|
91
99
|
/** The styles part and its `w:default="1"` style ids, read without costing it its round trip. */
|
|
92
100
|
private styleSource;
|
package/dist/parts/wml/index.mjs
CHANGED
|
@@ -207,11 +207,19 @@ export class MainDocumentPart extends DocumentPart {
|
|
|
207
207
|
async getStylesInUse() {
|
|
208
208
|
return walkStories(await this.stories(), await this.styleSource(), undefined, false).styles;
|
|
209
209
|
}
|
|
210
|
-
/**
|
|
211
|
-
*
|
|
210
|
+
/**
|
|
211
|
+
* The block-level content of each story, in docx4j's order: the body, then the headers and
|
|
212
|
+
* footers, the endnotes, the footnotes and the comments.
|
|
213
|
+
*
|
|
214
|
+
* Every story is read **privately** (`readContents`, which answers the unmarshalled tree when
|
|
215
|
+
* there is one and parses without keeping it when there is not), so asking a document which
|
|
216
|
+
* fonts it uses does not cost any part its byte-for-byte round trip. The body used to come from
|
|
217
|
+
* `getContents()`, which unmarshalled the main part and so re-marshalled it on the next save
|
|
218
|
+
* (CR-001 section 18).
|
|
219
|
+
*/
|
|
212
220
|
async stories() {
|
|
213
221
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
214
|
-
const out = [(_b = (_a = (await this.
|
|
222
|
+
const out = [(_b = (_a = (await this.readContents()).body) === null || _a === void 0 ? void 0 : _a.content) !== null && _b !== void 0 ? _b : []];
|
|
215
223
|
const rp = this.relationshipsPart;
|
|
216
224
|
for (const r of (_c = rp === null || rp === void 0 ? void 0 : rp.relationships.relationship) !== null && _c !== void 0 ? _c : []) {
|
|
217
225
|
const part = rp === null || rp === void 0 ? void 0 : rp.getPart(r);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SPLICEABLE_STYLES_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:styles xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n<w:style w:type=\"paragraph\" w:styleId=\"BlockText\">\n <w:name w:val=\"Block Text\" />\n <w:basedOn w:val=\"Normal\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00841CD9\" />\n <w:pPr>\n <w:pBdr>\n <w:top w:val=\"single\" w:sz=\"2\" w:space=\"10\" w:color=\"4F81BD\" w:themeColor=\"accent1\" w:shadow=\"1\" />\n <w:left w:val=\"single\" w:sz=\"2\" w:space=\"10\" w:color=\"4F81BD\" w:themeColor=\"accent1\" w:shadow=\"1\" />\n <w:bottom w:val=\"single\" w:sz=\"2\" w:space=\"10\" w:color=\"4F81BD\" w:themeColor=\"accent1\" w:shadow=\"1\" />\n <w:right w:val=\"single\" w:sz=\"2\" w:space=\"10\" w:color=\"4F81BD\" w:themeColor=\"accent1\" w:shadow=\"1\" />\n </w:pBdr>\n <w:ind w:left=\"1152\" w:right=\"1152\" />\n </w:pPr>\n <w:rPr>\n <w:rFonts w:eastAsiaTheme=\"minorEastAsia\" />\n <w:i />\n <w:iCs />\n <w:color w:val=\"4F81BD\" w:themeColor=\"accent1\" />\n </w:rPr>\n </w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"EndnoteText\">\n <w:name w:val=\"endnote text\" />\n <w:basedOn w:val=\"Normal\" />\n <w:link w:val=\"EndnoteTextChar\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00841CD9\" />\n <w:rPr>\n <w:sz w:val=\"20\" />\n <w:szCs w:val=\"20\" />\n </w:rPr>\n </w:style>\n <w:style w:type=\"character\" w:customStyle=\"1\" w:styleId=\"EndnoteTextChar\">\n <w:name w:val=\"Endnote Text Char\" />\n <w:basedOn w:val=\"DefaultParagraphFont\" />\n <w:link w:val=\"EndnoteText\" />\n <w:uiPriority w:val=\"99\" />\n <w:rsid w:val=\"00841CD9\" />\n <w:rPr>\n <w:sz w:val=\"20\" />\n <w:szCs w:val=\"20\" />\n </w:rPr>\n </w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Footer\">\n <w:name w:val=\"footer\" />\n <w:basedOn w:val=\"Normal\" />\n <w:link w:val=\"FooterChar\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00841CD9\" />\n <w:pPr>\n <w:tabs>\n <w:tab w:val=\"center\" w:pos=\"4680\" />\n <w:tab w:val=\"right\" w:pos=\"9360\" />\n </w:tabs>\n </w:pPr>\n </w:style>\n <w:style w:type=\"character\" w:customStyle=\"1\" w:styleId=\"FooterChar\">\n <w:name w:val=\"Footer Char\" />\n <w:basedOn w:val=\"DefaultParagraphFont\" />\n <w:link w:val=\"Footer\" />\n <w:uiPriority w:val=\"99\" />\n <w:rsid w:val=\"00841CD9\" />\n </w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"FootnoteText\">\n <w:name w:val=\"footnote text\" />\n <w:basedOn w:val=\"Normal\" />\n <w:link w:val=\"FootnoteTextChar\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00841CD9\" />\n <w:rPr>\n <w:sz w:val=\"20\" />\n <w:szCs w:val=\"20\" />\n </w:rPr>\n </w:style>\n <w:style w:type=\"character\" w:customStyle=\"1\" w:styleId=\"FootnoteTextChar\">\n <w:name w:val=\"Footnote Text Char\" />\n <w:basedOn w:val=\"DefaultParagraphFont\" />\n <w:link w:val=\"FootnoteText\" />\n <w:uiPriority w:val=\"99\" />\n <w:rsid w:val=\"00841CD9\" />\n <w:rPr>\n <w:sz w:val=\"20\" />\n <w:szCs w:val=\"20\" />\n </w:rPr>\n </w:style>\n<w:style w:type=\"character\" w:styleId=\"FootnoteReference\">\n <w:name w:val=\"footnote reference\" />\n <w:basedOn w:val=\"DefaultParagraphFont\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00D1197D\" />\n <w:rPr>\n <w:vertAlign w:val=\"superscript\" />\n </w:rPr>\n </w:style>\n <w:style w:type=\"character\" w:styleId=\"EndnoteReference\">\n <w:name w:val=\"endnote reference\" />\n <w:basedOn w:val=\"DefaultParagraphFont\" />\n <w:uiPriority w:val=\"99\" />\n <w:unhideWhenUsed />\n <w:rsid w:val=\"00D1197D\" />\n <w:rPr>\n <w:vertAlign w:val=\"superscript\" />\n </w:rPr>\n </w:style>\n</w:styles>";
|