@docx4j/core-ts 0.1.0 → 0.1.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 +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 +1 -0
- package/dist/opc/ContentTypes.mjs +1 -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/PartRegistry.mjs +1 -0
- 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 +19 -1
- package/dist/parts/sml/index.mjs +60 -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,104 @@
|
|
|
1
|
+
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
|
+
import { type Element, type RevisionHolder } from './tree.mjs';
|
|
3
|
+
import type { Author } from './comments.mjs';
|
|
4
|
+
/** Office JS `Word.ChangeTrackingMode`. */
|
|
5
|
+
export type ChangeTrackingMode = 'Off' | 'TrackAll' | 'TrackMineOnly';
|
|
6
|
+
/** What a package offers so that its edits can be tracked; `WordprocessingMLPackage` implements it. */
|
|
7
|
+
export interface TrackingHost {
|
|
8
|
+
/**
|
|
9
|
+
* The revision author (Office JS takes it from the signed-in user; here it is the package's).
|
|
10
|
+
* The same `author` phase G's comments use, so a revision and a comment made in one session
|
|
11
|
+
* carry one identity; only its `name` reaches `w:author`.
|
|
12
|
+
*/
|
|
13
|
+
readonly author: Author;
|
|
14
|
+
/** A fixed date for new revisions; `undefined` means now, read once per revision. */
|
|
15
|
+
readonly trackedChangeDate?: Date | undefined;
|
|
16
|
+
/** The trees to scan for the highest annotation id in use: the parts already unmarshalled. */
|
|
17
|
+
markupRoots(): object[];
|
|
18
|
+
}
|
|
19
|
+
/** The tracker of a package whose mode is not `Off`; `undefined` when it is (duck typed, no import cycle). */
|
|
20
|
+
export declare function trackerOf(pkg: unknown): ChangeTracker | undefined;
|
|
21
|
+
/** An `XmlCalendar` in UTC, as Word writes `w:date` (an xsd:dateTime ending in `Z`). */
|
|
22
|
+
export declare function calendarOf(date: Date): wml.XmlCalendar;
|
|
23
|
+
/** The `Date` of a `w:date`, or undefined when there is none. */
|
|
24
|
+
export declare function dateOf(cal: wml.XmlCalendar | undefined): Date | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The per-package writer of revision markup. Created by the package while
|
|
27
|
+
* `changeTrackingMode` is not `Off`; every content-API mutation asks its `Body` for one and,
|
|
28
|
+
* when it gets one, writes revisions instead of editing in place.
|
|
29
|
+
*
|
|
30
|
+
* Departure from docx4j, which has no such class: docx4j leaves revision markup to the caller.
|
|
31
|
+
* The name follows Office JS's vocabulary (`Word.ChangeTrackingMode`).
|
|
32
|
+
*/
|
|
33
|
+
export declare class ChangeTracker {
|
|
34
|
+
readonly host: TrackingHost;
|
|
35
|
+
readonly mode: ChangeTrackingMode;
|
|
36
|
+
private counter;
|
|
37
|
+
constructor(host: TrackingHost, mode: ChangeTrackingMode);
|
|
38
|
+
/** The `w:author` a new revision carries: the package author's name. */
|
|
39
|
+
get author(): string;
|
|
40
|
+
/** The next annotation id: one above the highest in use in the parts already unmarshalled. */
|
|
41
|
+
nextId(): number;
|
|
42
|
+
/** The `w:id`, `w:author` and `w:date` a new revision carries. */
|
|
43
|
+
markup(): {
|
|
44
|
+
id: number;
|
|
45
|
+
author: string;
|
|
46
|
+
date: wml.XmlCalendar;
|
|
47
|
+
};
|
|
48
|
+
/** A `w:ins` / `w:del` attribute set: the id, this package's author and the date. */
|
|
49
|
+
trackChange(): wml.CTTrackChange;
|
|
50
|
+
/** `w:ins` around run-level items (they go under `customXmlOrSmartTagOrSdt`, not `content`). */
|
|
51
|
+
ins(items: Element[]): Element<wml.RunIns>;
|
|
52
|
+
/** `w:del` around run-level items; the caller has already turned their `w:t` into `w:delText`. */
|
|
53
|
+
del(items: Element[]): Element<wml.RunDel>;
|
|
54
|
+
/** True when this revision is an insertion this package's author may extend rather than nest in. */
|
|
55
|
+
ownInsertion(revision: RevisionHolder | undefined): boolean;
|
|
56
|
+
/** Refuses an edit that would change deleted text; rejecting the deletion first is the way. */
|
|
57
|
+
assertEditable(revision: RevisionHolder | undefined): void;
|
|
58
|
+
/** Records the run's properties as they are now in `w:rPrChange`, once (a later write keeps the first original). */
|
|
59
|
+
recordRPrChange(rPr: wml.RPr): void;
|
|
60
|
+
/** Records the paragraph's properties as they are now in `w:pPrChange`, once. */
|
|
61
|
+
recordPPrChange(pPr: wml.PPr): void;
|
|
62
|
+
/** `w:pPr/w:rPr/w:ins`: the paragraph mark is an insertion. */
|
|
63
|
+
markParagraphInserted(p: wml.P): void;
|
|
64
|
+
/** `w:pPr/w:rPr/w:del`: the paragraph mark is deleted (accepting joins the paragraph with the next). */
|
|
65
|
+
markParagraphDeleted(p: wml.P): void;
|
|
66
|
+
/** `w:trPr/w:ins`: the table row is an insertion (CR-002 phase C's `Table` calls this). */
|
|
67
|
+
markRowInserted(tr: wml.Tr): void;
|
|
68
|
+
/** `w:trPr/w:del`: the table row is deleted. */
|
|
69
|
+
markRowDeleted(tr: wml.Tr): void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A whole paragraph inserted: the mark is marked inserted and every run of it goes into a
|
|
73
|
+
* `w:ins`. Word, splitting a paragraph, marks the *first* paragraph's mark instead and leaves
|
|
74
|
+
* the new one the original mark; marking the new paragraph's own mark is the same document once
|
|
75
|
+
* accepted or rejected and keeps the edit to the element that was added (CR-002 section 13).
|
|
76
|
+
*/
|
|
77
|
+
export declare function trackInsertedParagraph(tracker: ChangeTracker, p: wml.P): void;
|
|
78
|
+
/** Every top-level run of the paragraph that is not already in a revision, wrapped in one `w:ins` per group. */
|
|
79
|
+
export declare function wrapNewRuns(tracker: ChangeTracker, p: wml.P): void;
|
|
80
|
+
/** A whole table inserted: every row is marked inserted and every paragraph in it is an insertion. */
|
|
81
|
+
export declare function trackInsertedTable(tracker: ChangeTracker, tbl: wml.Tbl): void;
|
|
82
|
+
/** The paragraph mark's run properties (`w:pPr/w:rPr`), created when absent. */
|
|
83
|
+
export declare function paraRPrOf(p: wml.P): wml.ParaRPr;
|
|
84
|
+
/** The row's properties (`w:trPr`), created when absent. */
|
|
85
|
+
export declare function rowPrOf(tr: wml.Tr): wml.TrPr;
|
|
86
|
+
/** Drops `w:pPr/w:rPr` and `w:pPr` once nothing is left in them, so that accepting or rejecting leaves no husk. */
|
|
87
|
+
export declare function pruneParagraphProperties(p: wml.P): void;
|
|
88
|
+
/** True when a paragraph's mark is marked deleted. */
|
|
89
|
+
export declare function markDeleted(p: wml.P): boolean;
|
|
90
|
+
/** True when a paragraph's mark is marked inserted. */
|
|
91
|
+
export declare function markInserted(p: wml.P): boolean;
|
|
92
|
+
/** Turns a run's `w:t` into `w:delText` and `w:instrText` into `w:delInstrText`, in place. */
|
|
93
|
+
export declare function toDeletedText(run: wml.R): void;
|
|
94
|
+
/** The inverse, for `reject()` of a deletion. */
|
|
95
|
+
export declare function toRestoredText(run: wml.R): void;
|
|
96
|
+
/** Replaces a run's direct formatting with `original`, keeping nothing of what is there. */
|
|
97
|
+
export declare function restoreRPr(holder: {
|
|
98
|
+
rPr?: wml.RPr;
|
|
99
|
+
}, original: wml.RPr): void;
|
|
100
|
+
/** Replaces a paragraph's properties with `original` (a `w:pPrChange/w:pPr`), keeping the mark and the section. */
|
|
101
|
+
export declare function restorePPr(p: wml.P, original: wml.PPrBase | undefined): void;
|
|
102
|
+
/** A copy of a run's direct formatting for a new run: the recorded original (`w:rPrChange`) is not carried over. */
|
|
103
|
+
export declare function copyRPr(rPr: wml.RPr | undefined): wml.RPr | undefined;
|
|
104
|
+
export type { RevisionHolder, RevisionKind } from './tree.mjs';
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { deepCopy, deepCopyAsSync } from '@docx4j/generated-objects-ts';
|
|
2
|
+
import { createCTTrackChange, createCTRPrChange, createCTRPrChangeRPr, createCTPPrChange, createDelText, createPPr, createParaRPr, createTrPr, } from '@docx4j/generated-objects-ts/factory/org_docx4j_wml';
|
|
3
|
+
import { rPrToElements } from '@docx4j/generated-objects-ts/builders/wml';
|
|
4
|
+
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
5
|
+
import { W_NS, linkParents, walk, typeNameOf, revisionKindOf } from './tree.mjs';
|
|
6
|
+
/**
|
|
7
|
+
* `w:id` on these is the one annotation id space (ECMA-376 17.13.5.4): revisions, bookmarks,
|
|
8
|
+
* comment range marks and permissions share it. `w:comment/@w:id` (docx4j `Comments.Comment`,
|
|
9
|
+
* which also extends `CTMarkup`) is a different space and is excluded, so that phase G's
|
|
10
|
+
* comment ids and phase F's revision ids never have to agree.
|
|
11
|
+
*/
|
|
12
|
+
const MARKUP_TYPES = new Set([
|
|
13
|
+
'org_docx4j_wml.CTMarkup', 'org_docx4j_wml.CTBookmark', 'org_docx4j_wml.CTBookmarkRange',
|
|
14
|
+
'org_docx4j_wml.CTCellMergeTrackChange', 'org_docx4j_wml.CTMarkupRange', 'org_docx4j_wml.CTMathRunTrackChange',
|
|
15
|
+
'org_docx4j_wml.CTMoveBookmark', 'org_docx4j_wml.CTMoveFromRangeEnd', 'org_docx4j_wml.CTMoveToRangeEnd',
|
|
16
|
+
'org_docx4j_wml.CTPPrChange', 'org_docx4j_wml.CTRPrChange', 'org_docx4j_wml.CTSectPrChange',
|
|
17
|
+
'org_docx4j_wml.CTTblGridChange', 'org_docx4j_wml.CTTblPrChange', 'org_docx4j_wml.CTTblPrExChange',
|
|
18
|
+
'org_docx4j_wml.CTTcPrChange', 'org_docx4j_wml.CTTrPrChange', 'org_docx4j_wml.CTTrackChange',
|
|
19
|
+
'org_docx4j_wml.CTTrackChangeNumbering', 'org_docx4j_wml.CTTrackChangeRange',
|
|
20
|
+
'org_docx4j_wml.ParaRPrChange', 'org_docx4j_wml.RunDel', 'org_docx4j_wml.RunIns', 'org_docx4j_wml.RunTrackChange',
|
|
21
|
+
]);
|
|
22
|
+
/** The tracker of a package whose mode is not `Off`; `undefined` when it is (duck typed, no import cycle). */
|
|
23
|
+
export function trackerOf(pkg) {
|
|
24
|
+
return pkg === null || pkg === void 0 ? void 0 : pkg.changeTracker;
|
|
25
|
+
}
|
|
26
|
+
/** An `XmlCalendar` in UTC, as Word writes `w:date` (an xsd:dateTime ending in `Z`). */
|
|
27
|
+
export function calendarOf(date) {
|
|
28
|
+
return {
|
|
29
|
+
year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate(),
|
|
30
|
+
hour: date.getUTCHours(), minute: date.getUTCMinutes(), second: date.getUTCSeconds(), timezone: 0,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** The `Date` of a `w:date`, or undefined when there is none. */
|
|
34
|
+
export function dateOf(cal) {
|
|
35
|
+
var _a, _b, _c, _d, _e, _f;
|
|
36
|
+
if (!cal || cal.year === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
const ms = Date.UTC(cal.year, ((_a = cal.month) !== null && _a !== void 0 ? _a : 1) - 1, (_b = cal.day) !== null && _b !== void 0 ? _b : 1, (_c = cal.hour) !== null && _c !== void 0 ? _c : 0, (_d = cal.minute) !== null && _d !== void 0 ? _d : 0, (_e = cal.second) !== null && _e !== void 0 ? _e : 0);
|
|
39
|
+
return new Date(ms - ((_f = cal.timezone) !== null && _f !== void 0 ? _f : 0) * 60000);
|
|
40
|
+
}
|
|
41
|
+
function element(localPart, value) {
|
|
42
|
+
return { name: { namespaceURI: W_NS, localPart }, value };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The per-package writer of revision markup. Created by the package while
|
|
46
|
+
* `changeTrackingMode` is not `Off`; every content-API mutation asks its `Body` for one and,
|
|
47
|
+
* when it gets one, writes revisions instead of editing in place.
|
|
48
|
+
*
|
|
49
|
+
* Departure from docx4j, which has no such class: docx4j leaves revision markup to the caller.
|
|
50
|
+
* The name follows Office JS's vocabulary (`Word.ChangeTrackingMode`).
|
|
51
|
+
*/
|
|
52
|
+
export class ChangeTracker {
|
|
53
|
+
constructor(host, mode) {
|
|
54
|
+
this.host = host;
|
|
55
|
+
this.mode = mode;
|
|
56
|
+
}
|
|
57
|
+
/** The `w:author` a new revision carries: the package author's name. */
|
|
58
|
+
get author() {
|
|
59
|
+
return this.host.author.name;
|
|
60
|
+
}
|
|
61
|
+
/** The next annotation id: one above the highest in use in the parts already unmarshalled. */
|
|
62
|
+
nextId() {
|
|
63
|
+
if (this.counter === undefined) {
|
|
64
|
+
let highest = 0;
|
|
65
|
+
for (const root of this.host.markupRoots()) {
|
|
66
|
+
walk(root, (value) => {
|
|
67
|
+
const tn = value.TYPE_NAME;
|
|
68
|
+
const id = value.id;
|
|
69
|
+
if (tn !== undefined && MARKUP_TYPES.has(tn) && typeof id === 'number' && id > highest)
|
|
70
|
+
highest = id;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
this.counter = highest;
|
|
74
|
+
}
|
|
75
|
+
return ++this.counter;
|
|
76
|
+
}
|
|
77
|
+
/** The `w:id`, `w:author` and `w:date` a new revision carries. */
|
|
78
|
+
markup() {
|
|
79
|
+
var _a;
|
|
80
|
+
return { id: this.nextId(), author: this.author, date: calendarOf((_a = this.host.trackedChangeDate) !== null && _a !== void 0 ? _a : new Date()) };
|
|
81
|
+
}
|
|
82
|
+
/** A `w:ins` / `w:del` attribute set: the id, this package's author and the date. */
|
|
83
|
+
trackChange() {
|
|
84
|
+
return createCTTrackChange(this.markup());
|
|
85
|
+
}
|
|
86
|
+
/** `w:ins` around run-level items (they go under `customXmlOrSmartTagOrSdt`, not `content`). */
|
|
87
|
+
ins(items) {
|
|
88
|
+
const value = { TYPE_NAME: 'org_docx4j_wml.RunIns', ...this.markup(), customXmlOrSmartTagOrSdt: items };
|
|
89
|
+
const wrapper = element('ins', value);
|
|
90
|
+
linkParents(items, value);
|
|
91
|
+
return wrapper;
|
|
92
|
+
}
|
|
93
|
+
/** `w:del` around run-level items; the caller has already turned their `w:t` into `w:delText`. */
|
|
94
|
+
del(items) {
|
|
95
|
+
const value = { TYPE_NAME: 'org_docx4j_wml.RunDel', ...this.markup(), customXmlOrSmartTagOrSdt: items };
|
|
96
|
+
const wrapper = element('del', value);
|
|
97
|
+
linkParents(items, value);
|
|
98
|
+
return wrapper;
|
|
99
|
+
}
|
|
100
|
+
/** True when this revision is an insertion this package's author may extend rather than nest in. */
|
|
101
|
+
ownInsertion(revision) {
|
|
102
|
+
return (revision === null || revision === void 0 ? void 0 : revision.kind) === 'ins' && revision.value.author === this.author;
|
|
103
|
+
}
|
|
104
|
+
/** Refuses an edit that would change deleted text; rejecting the deletion first is the way. */
|
|
105
|
+
assertEditable(revision) {
|
|
106
|
+
if ((revision === null || revision === void 0 ? void 0 : revision.kind) === 'del' || (revision === null || revision === void 0 ? void 0 : revision.kind) === 'moveFrom') {
|
|
107
|
+
throw new Docx4JException(`Cannot edit text inside a w:${revision.kind} (deleted by ${revision.value.author}); reject the deletion first`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Records the run's properties as they are now in `w:rPrChange`, once (a later write keeps the first original). */
|
|
111
|
+
recordRPrChange(rPr) {
|
|
112
|
+
if (rPr.rPrChange)
|
|
113
|
+
return;
|
|
114
|
+
const original = createCTRPrChangeRPr({ egrPrBase: rPrToElements(rPr) });
|
|
115
|
+
rPr.rPrChange = createCTRPrChange({ ...this.markup(), rPr: original });
|
|
116
|
+
linkParents(rPr.rPrChange, rPr);
|
|
117
|
+
}
|
|
118
|
+
/** Records the paragraph's properties as they are now in `w:pPrChange`, once. */
|
|
119
|
+
recordPPrChange(pPr) {
|
|
120
|
+
if (pPr.pPrChange)
|
|
121
|
+
return;
|
|
122
|
+
// w:pPrChange's child is a CT_PPrBase: `deepCopyAsSync` types the copy as the base and drops
|
|
123
|
+
// what CT_PPrBase does not declare (w:rPr, w:sectPr, w:pPrChange), so no xsi:type is marshalled.
|
|
124
|
+
// Synchronous: the part this runs on is unmarshalled, so the Jsonix context is built.
|
|
125
|
+
const original = deepCopyAsSync(pPr, 'org_docx4j_wml.PPrBase');
|
|
126
|
+
pPr.pPrChange = createCTPPrChange({ ...this.markup(), pPr: original });
|
|
127
|
+
linkParents(pPr.pPrChange, pPr);
|
|
128
|
+
}
|
|
129
|
+
/** `w:pPr/w:rPr/w:ins`: the paragraph mark is an insertion. */
|
|
130
|
+
markParagraphInserted(p) {
|
|
131
|
+
const rPr = paraRPrOf(p);
|
|
132
|
+
rPr.ins = this.trackChange();
|
|
133
|
+
linkParents(rPr.ins, rPr);
|
|
134
|
+
}
|
|
135
|
+
/** `w:pPr/w:rPr/w:del`: the paragraph mark is deleted (accepting joins the paragraph with the next). */
|
|
136
|
+
markParagraphDeleted(p) {
|
|
137
|
+
const rPr = paraRPrOf(p);
|
|
138
|
+
if (rPr.del)
|
|
139
|
+
throw new Docx4JException('This paragraph mark is already marked deleted');
|
|
140
|
+
rPr.del = this.trackChange();
|
|
141
|
+
linkParents(rPr.del, rPr);
|
|
142
|
+
}
|
|
143
|
+
/** `w:trPr/w:ins`: the table row is an insertion (CR-002 phase C's `Table` calls this). */
|
|
144
|
+
markRowInserted(tr) {
|
|
145
|
+
const trPr = rowPrOf(tr);
|
|
146
|
+
trPr.ins = this.trackChange();
|
|
147
|
+
linkParents(trPr.ins, trPr);
|
|
148
|
+
}
|
|
149
|
+
/** `w:trPr/w:del`: the table row is deleted. */
|
|
150
|
+
markRowDeleted(tr) {
|
|
151
|
+
const trPr = rowPrOf(tr);
|
|
152
|
+
if (trPr.del)
|
|
153
|
+
throw new Docx4JException('This row is already marked deleted');
|
|
154
|
+
trPr.del = this.trackChange();
|
|
155
|
+
linkParents(trPr.del, trPr);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* A whole paragraph inserted: the mark is marked inserted and every run of it goes into a
|
|
160
|
+
* `w:ins`. Word, splitting a paragraph, marks the *first* paragraph's mark instead and leaves
|
|
161
|
+
* the new one the original mark; marking the new paragraph's own mark is the same document once
|
|
162
|
+
* accepted or rejected and keeps the edit to the element that was added (CR-002 section 13).
|
|
163
|
+
*/
|
|
164
|
+
export function trackInsertedParagraph(tracker, p) {
|
|
165
|
+
tracker.markParagraphInserted(p);
|
|
166
|
+
wrapNewRuns(tracker, p);
|
|
167
|
+
}
|
|
168
|
+
/** Every top-level run of the paragraph that is not already in a revision, wrapped in one `w:ins` per group. */
|
|
169
|
+
export function wrapNewRuns(tracker, p) {
|
|
170
|
+
const content = p.content;
|
|
171
|
+
if (!content)
|
|
172
|
+
return;
|
|
173
|
+
for (let i = 0; i < content.length; i++) {
|
|
174
|
+
if (typeNameOf(content[i]) !== 'org_docx4j_wml.R' || revisionKindOf(content[i]) !== undefined)
|
|
175
|
+
continue;
|
|
176
|
+
let j = i;
|
|
177
|
+
while (j < content.length && typeNameOf(content[j]) === 'org_docx4j_wml.R' && revisionKindOf(content[j]) === undefined)
|
|
178
|
+
j++;
|
|
179
|
+
const runs = content.splice(i, j - i);
|
|
180
|
+
const ins = tracker.ins(runs);
|
|
181
|
+
content.splice(i, 0, ins);
|
|
182
|
+
linkParents(ins, p);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/** A whole table inserted: every row is marked inserted and every paragraph in it is an insertion. */
|
|
186
|
+
export function trackInsertedTable(tracker, tbl) {
|
|
187
|
+
var _a, _b, _c;
|
|
188
|
+
for (const row of ((_a = tbl.content) !== null && _a !== void 0 ? _a : [])) {
|
|
189
|
+
if (typeNameOf(row) !== 'org_docx4j_wml.Tr')
|
|
190
|
+
continue;
|
|
191
|
+
const tr = row.value;
|
|
192
|
+
tracker.markRowInserted(tr);
|
|
193
|
+
for (const cell of ((_b = tr.content) !== null && _b !== void 0 ? _b : [])) {
|
|
194
|
+
if (typeNameOf(cell) !== 'org_docx4j_wml.Tc')
|
|
195
|
+
continue;
|
|
196
|
+
for (const block of ((_c = cell.value.content) !== null && _c !== void 0 ? _c : [])) {
|
|
197
|
+
if (typeNameOf(block) === 'org_docx4j_wml.P')
|
|
198
|
+
trackInsertedParagraph(tracker, block.value);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/** The paragraph mark's run properties (`w:pPr/w:rPr`), created when absent. */
|
|
204
|
+
export function paraRPrOf(p) {
|
|
205
|
+
var _a, _b;
|
|
206
|
+
const pPr = ((_a = p.pPr) !== null && _a !== void 0 ? _a : (p.pPr = createPPr()));
|
|
207
|
+
linkParents(pPr, p);
|
|
208
|
+
const rPr = ((_b = pPr.rPr) !== null && _b !== void 0 ? _b : (pPr.rPr = createParaRPr()));
|
|
209
|
+
linkParents(rPr, pPr);
|
|
210
|
+
return rPr;
|
|
211
|
+
}
|
|
212
|
+
/** The row's properties (`w:trPr`), created when absent. */
|
|
213
|
+
export function rowPrOf(tr) {
|
|
214
|
+
var _a;
|
|
215
|
+
const trPr = ((_a = tr.trPr) !== null && _a !== void 0 ? _a : (tr.trPr = createTrPr()));
|
|
216
|
+
linkParents(trPr, tr);
|
|
217
|
+
return trPr;
|
|
218
|
+
}
|
|
219
|
+
/** Drops `w:pPr/w:rPr` and `w:pPr` once nothing is left in them, so that accepting or rejecting leaves no husk. */
|
|
220
|
+
export function pruneParagraphProperties(p) {
|
|
221
|
+
const pPr = p.pPr;
|
|
222
|
+
if (!pPr)
|
|
223
|
+
return;
|
|
224
|
+
const rPr = pPr.rPr;
|
|
225
|
+
if (rPr && isEmpty(rPr))
|
|
226
|
+
delete pPr.rPr;
|
|
227
|
+
if (isEmpty(pPr))
|
|
228
|
+
delete p.pPr;
|
|
229
|
+
}
|
|
230
|
+
function isEmpty(value) {
|
|
231
|
+
return Object.keys(value).every((key) => key === 'TYPE_NAME' || value[key] === undefined);
|
|
232
|
+
}
|
|
233
|
+
/** True when a paragraph's mark is marked deleted. */
|
|
234
|
+
export function markDeleted(p) {
|
|
235
|
+
var _a, _b;
|
|
236
|
+
return ((_b = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.rPr) === null || _b === void 0 ? void 0 : _b.del) !== undefined;
|
|
237
|
+
}
|
|
238
|
+
/** True when a paragraph's mark is marked inserted. */
|
|
239
|
+
export function markInserted(p) {
|
|
240
|
+
var _a, _b;
|
|
241
|
+
return ((_b = (_a = p.pPr) === null || _a === void 0 ? void 0 : _a.rPr) === null || _b === void 0 ? void 0 : _b.ins) !== undefined;
|
|
242
|
+
}
|
|
243
|
+
// --- w:t <-> w:delText -------------------------------------------------------------------
|
|
244
|
+
const DELETED_NAME = { t: 'delText', instrText: 'delInstrText' };
|
|
245
|
+
const RESTORED_NAME = { delText: 't', delInstrText: 'instrText' };
|
|
246
|
+
/** Turns a run's `w:t` into `w:delText` and `w:instrText` into `w:delInstrText`, in place. */
|
|
247
|
+
export function toDeletedText(run) {
|
|
248
|
+
rename(run, DELETED_NAME, true);
|
|
249
|
+
}
|
|
250
|
+
/** The inverse, for `reject()` of a deletion. */
|
|
251
|
+
export function toRestoredText(run) {
|
|
252
|
+
rename(run, RESTORED_NAME, false);
|
|
253
|
+
}
|
|
254
|
+
function rename(run, table, deleting) {
|
|
255
|
+
const content = run.content;
|
|
256
|
+
if (!content)
|
|
257
|
+
return;
|
|
258
|
+
for (let i = 0; i < content.length; i++) {
|
|
259
|
+
const item = content[i];
|
|
260
|
+
const to = table[item.name.localPart];
|
|
261
|
+
if (to === undefined)
|
|
262
|
+
continue;
|
|
263
|
+
const v = item.value;
|
|
264
|
+
const value = deleting && to === 'delText'
|
|
265
|
+
? createDelText({ value: v.value, ...(v.space === undefined ? {} : { space: v.space }) })
|
|
266
|
+
: { TYPE_NAME: 'org_docx4j_wml.Text', value: v.value, ...(v.space === undefined ? {} : { space: v.space }) };
|
|
267
|
+
content[i] = element(to, value);
|
|
268
|
+
linkParents(content[i], run);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// --- w:rPr <-> w:rPrChange/w:rPr ---------------------------------------------------------
|
|
272
|
+
// The conversion itself is the builders' `rPrToElements` / `rPrFromElements` (objects CR-003
|
|
273
|
+
// section 3.5, in 0.1.4): every EG_RPrBase member in schema order, the w14 effects included.
|
|
274
|
+
/** Replaces a run's direct formatting with `original`, keeping nothing of what is there. */
|
|
275
|
+
export function restoreRPr(holder, original) {
|
|
276
|
+
if (Object.keys(original).filter((k) => k !== 'TYPE_NAME').length === 0)
|
|
277
|
+
delete holder.rPr;
|
|
278
|
+
else {
|
|
279
|
+
holder.rPr = original;
|
|
280
|
+
linkParents(original, holder);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/** Replaces a paragraph's properties with `original` (a `w:pPrChange/w:pPr`), keeping the mark and the section. */
|
|
284
|
+
export function restorePPr(p, original) {
|
|
285
|
+
const pPr = p.pPr;
|
|
286
|
+
if (!pPr)
|
|
287
|
+
return;
|
|
288
|
+
const keep = { rPr: pPr.rPr, sectPr: pPr.sectPr };
|
|
289
|
+
for (const key of Object.keys(pPr))
|
|
290
|
+
if (key !== 'TYPE_NAME' && key !== 'PARENT')
|
|
291
|
+
delete pPr[key];
|
|
292
|
+
if (original) {
|
|
293
|
+
for (const [key, value] of Object.entries(original)) {
|
|
294
|
+
if (key === 'TYPE_NAME' || key === 'PARENT')
|
|
295
|
+
continue;
|
|
296
|
+
pPr[key] = deepCopy(value);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (keep.rPr)
|
|
300
|
+
pPr.rPr = keep.rPr;
|
|
301
|
+
if (keep.sectPr)
|
|
302
|
+
pPr.sectPr = keep.sectPr;
|
|
303
|
+
linkParents(pPr, p);
|
|
304
|
+
pruneParagraphProperties(p);
|
|
305
|
+
}
|
|
306
|
+
/** A copy of a run's direct formatting for a new run: the recorded original (`w:rPrChange`) is not carried over. */
|
|
307
|
+
export function copyRPr(rPr) {
|
|
308
|
+
if (!rPr)
|
|
309
|
+
return undefined;
|
|
310
|
+
const copy = deepCopy(rPr);
|
|
311
|
+
delete copy.rPrChange;
|
|
312
|
+
return copy;
|
|
313
|
+
}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
|
-
import { isElement, type Element } from '@docx4j/generated-objects-ts/builders/wml';
|
|
2
|
+
import { isElement, runItemsOf, type Element } from '@docx4j/generated-objects-ts/builders/wml';
|
|
3
3
|
export { isElement, typeNameOf, walk, find, linkParents, textOf, W_NS, type Element } from '@docx4j/generated-objects-ts/builders/wml';
|
|
4
|
+
/** The two views of a tracked document: as it will read once accepted, or as it read before the changes. */
|
|
5
|
+
export type TextView = 'accepted' | 'original';
|
|
6
|
+
export interface TextViewOptions {
|
|
7
|
+
/** 'accepted' (the default: w:ins included, w:del excluded) or 'original' (the other way). */
|
|
8
|
+
view?: TextView;
|
|
9
|
+
}
|
|
10
|
+
/** The four run-level revision holders (CR-002 phase F); their runs live under `customXmlOrSmartTagOrSdt`. */
|
|
11
|
+
export type RevisionKind = 'ins' | 'del' | 'moveFrom' | 'moveTo';
|
|
12
|
+
/** The run-level revision a run sits in. */
|
|
13
|
+
export interface RevisionHolder {
|
|
14
|
+
kind: RevisionKind;
|
|
15
|
+
/** The `w:ins` / `w:del` / `w:moveFrom` / `w:moveTo` element pair. */
|
|
16
|
+
element: Element;
|
|
17
|
+
value: wml.CTTrackChange;
|
|
18
|
+
/** Its run items (the model's `customXmlOrSmartTagOrSdt`). */
|
|
19
|
+
items: Element[];
|
|
20
|
+
/** The array holding `element`. */
|
|
21
|
+
owner: Element[];
|
|
22
|
+
}
|
|
4
23
|
/** One text-bearing item of a run, with its position in the paragraph's text. */
|
|
5
24
|
export interface TextSegment {
|
|
6
25
|
/** The item: w:t, w:tab, w:br, ... */
|
|
@@ -18,19 +37,46 @@ export interface TextSegment {
|
|
|
18
37
|
end: number;
|
|
19
38
|
/** True for w:t: text that can be edited in place. */
|
|
20
39
|
editable: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The nearest enclosing w:ins / w:del / w:moveFrom / w:moveTo, when the run is in one.
|
|
42
|
+
* A deletion of this run goes inside it (`runOwner` is already its item list); an insertion
|
|
43
|
+
* next to it goes beside it (`revision.owner`) unless the same author may extend it.
|
|
44
|
+
*/
|
|
45
|
+
revision?: RevisionHolder;
|
|
21
46
|
}
|
|
47
|
+
/** Types whose value holds runs (directly or through sdtContent); the revision holders are separate. */
|
|
48
|
+
declare const RUN_HOLDERS: Set<string>;
|
|
49
|
+
/** The kind of a run-level revision element, by its name; undefined when it is not one. */
|
|
50
|
+
export declare function revisionKindOf(el: Element): RevisionKind | undefined;
|
|
51
|
+
export { runItemsOf };
|
|
52
|
+
declare function itemText(item: Element): string | undefined;
|
|
22
53
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
25
|
-
*
|
|
54
|
+
* The text segments of a paragraph (or any run holder) in order. The default view is the
|
|
55
|
+
* accepted one: the runs of a `w:ins` or `w:moveTo` count, those of a `w:del` or `w:moveFrom`
|
|
56
|
+
* do not. `{ view: 'original' }` is the other way round (CR-002 phase F).
|
|
26
57
|
*/
|
|
27
|
-
export declare function
|
|
28
|
-
/** The text
|
|
29
|
-
export declare function
|
|
58
|
+
export declare function segmentsOf(container: object, options?: TextViewOptions): TextSegment[];
|
|
59
|
+
/** The text of a paragraph or container in one of the two views (`textOf` is the accepted one). */
|
|
60
|
+
export declare function textOfView(container: object, options?: TextViewOptions): string;
|
|
30
61
|
/** The runs of a paragraph, direct and nested in hyperlinks, content controls and insertions, in order. */
|
|
31
|
-
export declare function runsOf(container: object): Element<wml.R>[];
|
|
32
|
-
/**
|
|
62
|
+
export declare function runsOf(container: object, options?: TextViewOptions): Element<wml.R>[];
|
|
63
|
+
/**
|
|
64
|
+
* The block-level children of a container: body, header, footer, cell, sdt content, table (rows),
|
|
65
|
+
* row (cells). A content control of any kind (block, row, cell, run) answers with its
|
|
66
|
+
* `sdtContent`'s content, so that a traversal does not have to know the four types.
|
|
67
|
+
*/
|
|
33
68
|
export declare function childrenOf(value: object): Element[] | undefined;
|
|
69
|
+
/** An element with the array that holds it: what a view needs to edit it in place. */
|
|
70
|
+
export interface Located<T = unknown> {
|
|
71
|
+
element: Element<T>;
|
|
72
|
+
container: Element[];
|
|
73
|
+
}
|
|
74
|
+
/** The rows of a table, in order, descending into row-level content controls (an OpenDoPE repeat). */
|
|
75
|
+
export declare function rowsOf(tbl: object): Located<wml.Tr>[];
|
|
76
|
+
/** The cells of a row, in order, descending into cell-level content controls. */
|
|
77
|
+
export declare function cellsOf(tr: object): Located<wml.Tc>[];
|
|
78
|
+
/** Content controls: `w:sdt` at block, row, cell and run level, by TYPE_NAME. */
|
|
79
|
+
export declare const SDT_TYPES: Set<string>;
|
|
34
80
|
/** True for what a body or cell may hold directly (the Body content union), by TYPE_NAME. */
|
|
35
81
|
export declare const BLOCK_LEVEL_TYPES: Set<string>;
|
|
36
82
|
/** A run element with the given items and, optionally, run properties (the builders' r() takes text; this takes items). */
|
|
@@ -38,3 +84,4 @@ export declare function runOf(items: Element[], rPr?: wml.RPr): Element<wml.R>;
|
|
|
38
84
|
/** A paragraph element with the given runs and, optionally, paragraph properties. */
|
|
39
85
|
export declare function paragraphOf(runs: Element[], pPr?: wml.PPr): Element<wml.P>;
|
|
40
86
|
export { isElement as isTypedElement };
|
|
87
|
+
export { RUN_HOLDERS, itemText as itemTextOf };
|