@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
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
import { deepCopy, marshalString } from '@docx4j/generated-objects-ts';
|
|
2
|
+
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
2
3
|
import { r as textRun, t as textItem, br as breakItem } from '@docx4j/generated-objects-ts/builders/wml';
|
|
3
|
-
import { segmentsOf, runsOf, runItemsOf, linkParents, textOf, W_NS, runOf, paragraphOf } from './tree.mjs';
|
|
4
|
+
import { segmentsOf, runsOf, runItemsOf, linkParents, textOf, textOfView, typeNameOf, W_NS, runOf, paragraphOf, revisionKindOf } from './tree.mjs';
|
|
4
5
|
function withRPr(run, rPr) {
|
|
5
6
|
if (rPr)
|
|
6
7
|
run.value.rPr = rPr;
|
|
7
8
|
return run;
|
|
8
9
|
}
|
|
9
10
|
import { Font } from './Font.mjs';
|
|
11
|
+
import { runFontSelectorOf } from '../fonts/lookup.mjs';
|
|
10
12
|
import { Range } from './Range.mjs';
|
|
11
13
|
import { searchPattern, findAll } from './search.mjs';
|
|
14
|
+
import { builtInOf, idOfBuiltIn, styleNameOf, styleIdOf } from './styles.mjs';
|
|
15
|
+
import { cellOf } from './Table.mjs';
|
|
16
|
+
import { ContentControl, collectRunControls } from './ContentControl.mjs';
|
|
17
|
+
import { sdt as sdtOf, nextSdtId } from '@docx4j/generated-objects-ts/builders/wml';
|
|
18
|
+
import { controlIdScope, sdtKindFor } from '../customxml/insert.mjs';
|
|
19
|
+
import { InlinePicture, addImage, writableWidthEmu } from './InlinePicture.mjs';
|
|
20
|
+
import { contentOf } from './ooxml.mjs';
|
|
21
|
+
import { commentApi } from './comments.mjs';
|
|
22
|
+
import { copyRPr, markDeleted, toDeletedText } from './tracking.mjs';
|
|
23
|
+
import { trackedChangesOfParagraph } from './TrackedChange.mjs';
|
|
24
|
+
import { isListItem, listOf, listOrNullObjectOf, listItemOf, listItemOrNullObjectOf, startNewList, attachToList, detachFromList, } from './List.mjs';
|
|
12
25
|
const TWIPS_PER_POINT = 20;
|
|
13
26
|
/**
|
|
14
27
|
* A subset of Office JS `Word.Paragraph` over a `w:p` in a body, cell, header, footer or
|
|
@@ -42,64 +55,111 @@ export class Paragraph {
|
|
|
42
55
|
/** Replaces the content with one run of the text, keeping the first run's formatting. */
|
|
43
56
|
set text(value) {
|
|
44
57
|
var _a;
|
|
58
|
+
if (this.changeTracker) {
|
|
59
|
+
this.splice(0, this.text.length, value);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
45
62
|
const rPr = (_a = runsOf(this.p)[0]) === null || _a === void 0 ? void 0 : _a.value.rPr;
|
|
46
63
|
this.p.content = [withRPr(textRun(value), rPr ? deepCopy(rPr) : undefined)];
|
|
47
64
|
linkParents(this.p.content, this.p);
|
|
48
65
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
66
|
+
/**
|
|
67
|
+
* The text in one of the two views (extension; `text` is the accepted one). `{ view: 'original' }`
|
|
68
|
+
* reads the document as it was before the tracked changes: `w:del` included, `w:ins` excluded.
|
|
69
|
+
*/
|
|
70
|
+
getText(options) {
|
|
71
|
+
return (options === null || options === void 0 ? void 0 : options.view) === 'original' ? textOfView(this.p, options) : this.text;
|
|
72
|
+
}
|
|
73
|
+
/** The style id (w:pStyle; docx4j's name for it); 'Normal' when none is set. Extension: Office JS has `style` and `styleBuiltIn` only. */
|
|
74
|
+
get styleId() {
|
|
51
75
|
var _a, _b, _c;
|
|
52
76
|
return (_c = (_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.pStyle) === null || _b === void 0 ? void 0 : _b.val) !== null && _c !== void 0 ? _c : 'Normal';
|
|
53
77
|
}
|
|
54
|
-
set
|
|
78
|
+
set styleId(id) {
|
|
79
|
+
// through pPr(), so that a tracked write records w:pPrChange first (CR-002 phase F)
|
|
80
|
+
const pPr = this.pPr();
|
|
55
81
|
if (id === '' || id === 'Normal') {
|
|
56
|
-
|
|
57
|
-
delete this.p.pPr.pStyle;
|
|
82
|
+
delete pPr.pStyle;
|
|
58
83
|
return;
|
|
59
84
|
}
|
|
60
|
-
|
|
85
|
+
pPr.pStyle = { val: id };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The style's display name ('Heading 1', 'My Style'), as Office JS: from the styles part's
|
|
89
|
+
* `w:name` when that part is unmarshalled, else derived from the id. Setting accepts a display
|
|
90
|
+
* name, a stored name, or an id.
|
|
91
|
+
*/
|
|
92
|
+
get style() {
|
|
93
|
+
return styleNameOf(this.parentBody.package_, this.styleId);
|
|
94
|
+
}
|
|
95
|
+
set style(name) {
|
|
96
|
+
this.styleId = styleIdOf(this.parentBody.package_, name);
|
|
61
97
|
}
|
|
62
|
-
/** Word'
|
|
98
|
+
/** The `Word.Style` value ('Heading1'), or 'Other' when the style is not a built-in one, as Office JS. */
|
|
63
99
|
get styleBuiltIn() {
|
|
64
|
-
return this.
|
|
100
|
+
return builtInOf(this.styleId);
|
|
101
|
+
}
|
|
102
|
+
set styleBuiltIn(value) {
|
|
103
|
+
this.styleId = idOfBuiltIn(value);
|
|
65
104
|
}
|
|
66
|
-
|
|
67
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The paragraph properties which actually apply: the document defaults, the style chain and
|
|
107
|
+
* the numbering level, then this paragraph's own `w:pPr` (docx4j
|
|
108
|
+
* `PropertyResolver.getEffectivePPr`). A live, possibly cached object: copy it before
|
|
109
|
+
* changing it. Needs the package's resolver; see `Body.propertyResolver`.
|
|
110
|
+
*/
|
|
111
|
+
get effectivePPr() {
|
|
112
|
+
return this.parentBody.propertyResolver.getEffectivePPr(this.p.pPr);
|
|
113
|
+
}
|
|
114
|
+
/** The paragraph mark's effective run properties (docx4j `getEffectiveParagraphMarkRPr`). */
|
|
115
|
+
get effectiveParagraphMarkRPr() {
|
|
116
|
+
return this.parentBody.propertyResolver.getEffectiveParagraphMarkRPr(this.p.pPr);
|
|
117
|
+
}
|
|
118
|
+
/** The `w:pPr` a formatting read works from: the resolved one, or this paragraph's own. */
|
|
119
|
+
readPPr(options) {
|
|
120
|
+
return (options === null || options === void 0 ? void 0 : options.direct) === true ? this.p.pPr : this.effectivePPr;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Office JS's paragraph formatting in one call, and the way to ask for direct formatting:
|
|
124
|
+
* `formatting({ direct: true })` is what the individual getters reported before CR-001
|
|
125
|
+
* Phase B step 2 (an absent property reads 0, 10 or `'Unknown'`).
|
|
126
|
+
*/
|
|
127
|
+
formatting(options) {
|
|
128
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
129
|
+
const pPr = this.readPPr(options);
|
|
130
|
+
const effective = (options === null || options === void 0 ? void 0 : options.direct) !== true;
|
|
131
|
+
return {
|
|
132
|
+
alignment: alignmentOf(pPr, effective),
|
|
133
|
+
leftIndent: ((_b = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.ind) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT,
|
|
134
|
+
rightIndent: ((_d = (_c = pPr === null || pPr === void 0 ? void 0 : pPr.ind) === null || _c === void 0 ? void 0 : _c.right) !== null && _d !== void 0 ? _d : 0) / TWIPS_PER_POINT,
|
|
135
|
+
firstLineIndent: firstLineIndentOf(pPr),
|
|
136
|
+
spaceBefore: ((_f = (_e = pPr === null || pPr === void 0 ? void 0 : pPr.spacing) === null || _e === void 0 ? void 0 : _e.before) !== null && _f !== void 0 ? _f : 0) / TWIPS_PER_POINT,
|
|
137
|
+
spaceAfter: ((_h = (_g = pPr === null || pPr === void 0 ? void 0 : pPr.spacing) === null || _g === void 0 ? void 0 : _g.after) !== null && _h !== void 0 ? _h : 0) / TWIPS_PER_POINT,
|
|
138
|
+
lineSpacing: lineSpacingOf(pPr),
|
|
139
|
+
outlineLevel: outlineLevelOf(pPr),
|
|
140
|
+
};
|
|
68
141
|
}
|
|
142
|
+
/** The effective alignment; an absent `w:jc` after resolution is `'Left'`, as Office JS. */
|
|
69
143
|
get alignment() {
|
|
70
|
-
|
|
71
|
-
switch ((_b = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.jc) === null || _b === void 0 ? void 0 : _b.val) {
|
|
72
|
-
case 'left':
|
|
73
|
-
case 'start': return 'Left';
|
|
74
|
-
case 'center': return 'Centered';
|
|
75
|
-
case 'right':
|
|
76
|
-
case 'end': return 'Right';
|
|
77
|
-
case 'both':
|
|
78
|
-
case 'distribute': return 'Justified';
|
|
79
|
-
default: return 'Unknown';
|
|
80
|
-
}
|
|
144
|
+
return alignmentOf(this.effectivePPr, true);
|
|
81
145
|
}
|
|
82
146
|
set alignment(v) {
|
|
147
|
+
const pPr = this.pPr();
|
|
83
148
|
const val = v === 'Left' ? 'left' : v === 'Centered' ? 'center' : v === 'Right' ? 'right' : v === 'Justified' ? 'both' : undefined;
|
|
84
149
|
if (val === undefined) {
|
|
85
|
-
|
|
86
|
-
delete this.p.pPr.jc;
|
|
150
|
+
delete pPr.jc;
|
|
87
151
|
return;
|
|
88
152
|
}
|
|
89
|
-
|
|
153
|
+
pPr.jc = { val };
|
|
90
154
|
}
|
|
91
|
-
/** Indents and spacing in points, as Office JS;
|
|
92
|
-
get leftIndent() { var _a, _b
|
|
155
|
+
/** Indents and spacing in points, as Office JS; the effective values (CR-001 Phase B step 2). */
|
|
156
|
+
get leftIndent() { var _a, _b; return ((_b = (_a = this.effectivePPr.ind) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
|
|
93
157
|
set leftIndent(pt) { this.ind().left = Math.round(pt * TWIPS_PER_POINT); }
|
|
94
|
-
get rightIndent() { var _a, _b
|
|
158
|
+
get rightIndent() { var _a, _b; return ((_b = (_a = this.effectivePPr.ind) === null || _a === void 0 ? void 0 : _a.right) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
|
|
95
159
|
set rightIndent(pt) { this.ind().right = Math.round(pt * TWIPS_PER_POINT); }
|
|
96
160
|
/** First-line indent; negative for a hanging indent, as Office JS. */
|
|
97
161
|
get firstLineIndent() {
|
|
98
|
-
|
|
99
|
-
const ind = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.ind;
|
|
100
|
-
if ((ind === null || ind === void 0 ? void 0 : ind.hanging) !== undefined)
|
|
101
|
-
return -ind.hanging / TWIPS_PER_POINT;
|
|
102
|
-
return ((_b = ind === null || ind === void 0 ? void 0 : ind.firstLine) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT;
|
|
162
|
+
return firstLineIndentOf(this.effectivePPr);
|
|
103
163
|
}
|
|
104
164
|
set firstLineIndent(pt) {
|
|
105
165
|
const ind = this.ind();
|
|
@@ -112,30 +172,34 @@ export class Paragraph {
|
|
|
112
172
|
delete ind.hanging;
|
|
113
173
|
}
|
|
114
174
|
}
|
|
115
|
-
get spaceBefore() { var _a, _b
|
|
175
|
+
get spaceBefore() { var _a, _b; return ((_b = (_a = this.effectivePPr.spacing) === null || _a === void 0 ? void 0 : _a.before) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
|
|
116
176
|
set spaceBefore(pt) { this.spacing().before = Math.round(pt * TWIPS_PER_POINT); }
|
|
117
|
-
get spaceAfter() { var _a, _b
|
|
177
|
+
get spaceAfter() { var _a, _b; return ((_b = (_a = this.effectivePPr.spacing) === null || _a === void 0 ? void 0 : _a.after) !== null && _b !== void 0 ? _b : 0) / TWIPS_PER_POINT; }
|
|
118
178
|
set spaceAfter(pt) { this.spacing().after = Math.round(pt * TWIPS_PER_POINT); }
|
|
119
179
|
/** Line spacing in points: w:line/240 lines of 12pt when the rule is auto, else w:line twips; 0 when not set. */
|
|
120
180
|
get lineSpacing() {
|
|
121
|
-
|
|
122
|
-
const s = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.spacing;
|
|
123
|
-
if ((s === null || s === void 0 ? void 0 : s.line) === undefined)
|
|
124
|
-
return 0;
|
|
125
|
-
return s.lineRule === undefined || s.lineRule === 'auto' ? (s.line / 240) * 12 : s.line / TWIPS_PER_POINT;
|
|
181
|
+
return lineSpacingOf(this.effectivePPr);
|
|
126
182
|
}
|
|
127
183
|
set lineSpacing(pt) { const s = this.spacing(); s.line = Math.round(pt * TWIPS_PER_POINT); s.lineRule = 'exact'; }
|
|
128
|
-
/** w:outlineLvl + 1 (1 to 9); 10 for body text, as Office JS. */
|
|
129
|
-
get outlineLevel() {
|
|
130
|
-
set outlineLevel(level) { if (level >= 10 || level < 1)
|
|
131
|
-
|
|
132
|
-
delete this.p.pPr.outlineLvl;
|
|
133
|
-
}
|
|
184
|
+
/** w:outlineLvl + 1 (1 to 9); 10 for body text, as Office JS. A heading style supplies it. */
|
|
185
|
+
get outlineLevel() { return outlineLevelOf(this.effectivePPr); }
|
|
186
|
+
set outlineLevel(level) { const pPr = this.pPr(); if (level >= 10 || level < 1)
|
|
187
|
+
delete pPr.outlineLvl;
|
|
134
188
|
else
|
|
135
|
-
|
|
136
|
-
/**
|
|
189
|
+
pPr.outlineLvl = { val: level - 1 }; }
|
|
190
|
+
/**
|
|
191
|
+
* The runs' formatting: reads the first run's *effective* properties, writes direct
|
|
192
|
+
* formatting to all (extension: `Font` is over runs, not the paragraph mark).
|
|
193
|
+
*/
|
|
137
194
|
get font() {
|
|
138
|
-
return
|
|
195
|
+
return this.getFont();
|
|
196
|
+
}
|
|
197
|
+
/** `font`, with `{ direct: true }` for the direct formatting of the first run (extension). */
|
|
198
|
+
getFont(options) {
|
|
199
|
+
const holders = () => runsOf(this.p).map((r) => r.value);
|
|
200
|
+
if ((options === null || options === void 0 ? void 0 : options.direct) === true)
|
|
201
|
+
return new Font(holders, () => this.fontTracking());
|
|
202
|
+
return new Font(holders, () => this.fontTracking(), (rPr) => this.parentBody.propertyResolver.getEffectiveRPr(rPr, this.p.pPr), (rPr) => { var _a; return (_a = runFontSelectorOf(this.parentBody.package_)) === null || _a === void 0 ? void 0 : _a.asciiFontName(rPr); });
|
|
139
203
|
}
|
|
140
204
|
/** w14:paraId, the stable address Word gives paragraphs. */
|
|
141
205
|
get paraId() {
|
|
@@ -151,6 +215,32 @@ export class Paragraph {
|
|
|
151
215
|
get runs() {
|
|
152
216
|
return runsOf(this.p);
|
|
153
217
|
}
|
|
218
|
+
/** The cell this paragraph is in, or undefined when it is not in a table (Office JS). */
|
|
219
|
+
get parentTableCell() {
|
|
220
|
+
return cellOf(this.p, this.parentBody);
|
|
221
|
+
}
|
|
222
|
+
/** The run-level content controls in this paragraph, in order, nested ones included. */
|
|
223
|
+
get contentControls() {
|
|
224
|
+
const out = [];
|
|
225
|
+
collectRunControls(this.p, this.parentBody, out);
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
/** The inline pictures in this paragraph, in order (Office JS Paragraph.inlinePictures). */
|
|
229
|
+
get inlinePictures() {
|
|
230
|
+
var _a, _b;
|
|
231
|
+
const out = [];
|
|
232
|
+
for (const run of runsOf(this.p)) {
|
|
233
|
+
for (const item of ((_a = run.value.content) !== null && _a !== void 0 ? _a : [])) {
|
|
234
|
+
if (item.name.localPart !== 'drawing')
|
|
235
|
+
continue;
|
|
236
|
+
const inline = (_b = item.value.anchorOrInline) === null || _b === void 0 ? void 0 : _b[0];
|
|
237
|
+
if (inline && inline.TYPE_NAME === 'org_docx4j_dml_wordprocessingDrawing.Inline') {
|
|
238
|
+
out.push(new InlinePicture(item, run, this));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return out;
|
|
243
|
+
}
|
|
154
244
|
/** Text inserted at the start, the end, or replacing the whole paragraph's text. */
|
|
155
245
|
insertText(text, location) {
|
|
156
246
|
const length = this.text.length;
|
|
@@ -166,6 +256,7 @@ export class Paragraph {
|
|
|
166
256
|
if (pPr) {
|
|
167
257
|
delete pPr.rPr;
|
|
168
258
|
delete pPr.sectPr;
|
|
259
|
+
delete pPr.pPrChange;
|
|
169
260
|
}
|
|
170
261
|
const el = paragraphOf(text === '' ? [] : [textRun(text)], pPr);
|
|
171
262
|
return this.parentBody.insertElement(el, location, this);
|
|
@@ -176,22 +267,92 @@ export class Paragraph {
|
|
|
176
267
|
const brk = breakItem(type === 'Page' ? 'page' : undefined);
|
|
177
268
|
if (location === 'Before' || location === 'After') {
|
|
178
269
|
const p = this.insertParagraph('', location);
|
|
179
|
-
|
|
180
|
-
|
|
270
|
+
const run = runOf([brk]);
|
|
271
|
+
const tracker = p.changeTracker;
|
|
272
|
+
const item = tracker ? tracker.ins([run]) : run;
|
|
273
|
+
p.p.content.push(item);
|
|
274
|
+
linkParents(item, p.p);
|
|
181
275
|
return;
|
|
182
276
|
}
|
|
183
277
|
const run = runOf([brk]);
|
|
278
|
+
const tracker = this.changeTracker;
|
|
279
|
+
const item = tracker ? tracker.ins([run]) : run;
|
|
184
280
|
const content = ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
|
|
281
|
+
if (location === 'Start')
|
|
282
|
+
content.unshift(item);
|
|
283
|
+
else
|
|
284
|
+
content.push(item);
|
|
285
|
+
linkParents(item, this.p);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Adds the image as a part of this paragraph's part, with a relationship, and shows it at the
|
|
289
|
+
* start or the end of this paragraph, or in place of its content (Office JS).
|
|
290
|
+
*/
|
|
291
|
+
insertInlinePictureFromBase64(base64, location, options) {
|
|
292
|
+
var _a;
|
|
293
|
+
var _b;
|
|
294
|
+
const part = this.parentBody.part;
|
|
295
|
+
if (!part)
|
|
296
|
+
throw new Docx4JException('This body has no part, so an image cannot be related to it');
|
|
297
|
+
const { run, drawing } = addImage(part, base64, this.parentBody.container, writableWidthEmu(this.parentBody.container), options);
|
|
298
|
+
const content = ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
|
|
299
|
+
if (location === 'Replace')
|
|
300
|
+
content.length = 0;
|
|
185
301
|
if (location === 'Start')
|
|
186
302
|
content.unshift(run);
|
|
187
303
|
else
|
|
188
304
|
content.push(run);
|
|
189
305
|
linkParents(run, this.p);
|
|
306
|
+
return new InlinePicture(drawing, run, this);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Word's `insertOoxml` at paragraph level: a flat OPC `pkg:package` (or a bare fragment). One
|
|
310
|
+
* incoming paragraph is merged into this one at 'Start' and 'End', as Word's paste does;
|
|
311
|
+
* anything else is inserted as blocks before or after. 'Replace' puts the content where this
|
|
312
|
+
* paragraph was and removes it.
|
|
313
|
+
*/
|
|
314
|
+
async insertOoxml(ooxml, location) {
|
|
315
|
+
var _a, _b;
|
|
316
|
+
const preprocess = (_a = this.parentBody.package_) === null || _a === void 0 ? void 0 : _a.loadOptions.preprocessor;
|
|
317
|
+
const elements = await contentOf(ooxml, { preprocess: preprocess ? (doc) => preprocess(doc) : undefined, target: this.parentBody.part });
|
|
318
|
+
if (elements.length === 0)
|
|
319
|
+
return [];
|
|
320
|
+
const only = elements.length === 1 && typeNameOf(elements[0]) === 'org_docx4j_wml.P' ? elements[0].value : undefined;
|
|
321
|
+
if (only && (location === 'Start' || location === 'End')) {
|
|
322
|
+
this.insertItemsAt(location === 'Start' ? 0 : this.text.length, ((_b = only.content) !== null && _b !== void 0 ? _b : []));
|
|
323
|
+
return [this];
|
|
324
|
+
}
|
|
325
|
+
if (location === 'Replace') {
|
|
326
|
+
const inserted = this.parentBody.insertElement(elements, 'Before', this);
|
|
327
|
+
void inserted;
|
|
328
|
+
this.delete();
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
this.parentBody.insertElement(elements, location === 'Start' ? 'Before' : location === 'End' ? 'After' : location, this);
|
|
332
|
+
}
|
|
333
|
+
return elements.map((el) => typeNameOf(el) === 'org_docx4j_wml.P'
|
|
334
|
+
? new Paragraph(el, this.container, this.parentBody)
|
|
335
|
+
: { element: el, container: this.container });
|
|
190
336
|
}
|
|
191
337
|
/** Matches within this paragraph. */
|
|
192
338
|
search(text, options) {
|
|
193
339
|
return findAll(this.text, searchPattern(text, options)).map(([s, e]) => new Range(this, s, e));
|
|
194
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Replaces every match of `find` with `replace`, last match first so that the offsets of the
|
|
343
|
+
* ones still to do stay valid (CR-002 section 3.7). Returns the number replaced; tracked when
|
|
344
|
+
* the package's `changeTrackingMode` is on.
|
|
345
|
+
*/
|
|
346
|
+
replaceText(find, replace, options) {
|
|
347
|
+
const matches = this.search(find, options);
|
|
348
|
+
for (let i = matches.length - 1; i >= 0; i--)
|
|
349
|
+
matches[i].insertText(replace, 'Replace');
|
|
350
|
+
return matches.length;
|
|
351
|
+
}
|
|
352
|
+
/** The tracked changes in this paragraph, in document order (CR-002 phase F). */
|
|
353
|
+
getTrackedChanges() {
|
|
354
|
+
return trackedChangesOfParagraph(this);
|
|
355
|
+
}
|
|
195
356
|
getRange(location = 'Whole') {
|
|
196
357
|
const length = this.text.length;
|
|
197
358
|
if (location === 'Start')
|
|
@@ -200,12 +361,53 @@ export class Paragraph {
|
|
|
200
361
|
return new Range(this, length, length);
|
|
201
362
|
return new Range(this, 0, length);
|
|
202
363
|
}
|
|
203
|
-
/**
|
|
364
|
+
/**
|
|
365
|
+
* Removes the paragraph from its container. While the package tracks changes, the content
|
|
366
|
+
* becomes a `w:del` and the mark is marked deleted (`w:pPr/w:rPr/w:del`) instead, unless the
|
|
367
|
+
* whole paragraph was this author's own insertion, which Word simply takes back.
|
|
368
|
+
*/
|
|
204
369
|
delete() {
|
|
370
|
+
const tracker = this.changeTracker;
|
|
371
|
+
if (tracker) {
|
|
372
|
+
this.trackedDelete(tracker);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
205
375
|
const i = this.index;
|
|
206
376
|
if (i >= 0)
|
|
207
377
|
this.container.splice(i, 1);
|
|
208
378
|
}
|
|
379
|
+
trackedDelete(tracker) {
|
|
380
|
+
var _a, _b;
|
|
381
|
+
if (markDeleted(this.p))
|
|
382
|
+
throw new Docx4JException('This paragraph is already marked deleted');
|
|
383
|
+
const length = this.text.length;
|
|
384
|
+
if (length > 0)
|
|
385
|
+
this.deleteText(tracker, 0, length);
|
|
386
|
+
const rPr = (_a = this.p.pPr) === null || _a === void 0 ? void 0 : _a.rPr;
|
|
387
|
+
const ownMark = (rPr === null || rPr === void 0 ? void 0 : rPr.ins) !== undefined && rPr.ins.author === tracker.author;
|
|
388
|
+
if (ownMark && ((_b = this.p.content) !== null && _b !== void 0 ? _b : []).length === 0) {
|
|
389
|
+
const i = this.index;
|
|
390
|
+
if (i >= 0)
|
|
391
|
+
this.container.splice(i, 1);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
tracker.markParagraphDeleted(this.p);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* The paragraph's content and its mark marked deleted, the paragraph element itself kept:
|
|
398
|
+
* what the cells of a deleted table row need (a `w:tc` must keep a block-level child, and Word
|
|
399
|
+
* writes `w:del` around every run and `w:pPr/w:rPr/w:del` on every mark inside a deleted row).
|
|
400
|
+
* The same primitives `delete()` uses, without its "take back my own insertion" step.
|
|
401
|
+
* Does nothing when the mark is already deleted.
|
|
402
|
+
*/
|
|
403
|
+
markDeletedInPlace(tracker) {
|
|
404
|
+
if (markDeleted(this.p))
|
|
405
|
+
return;
|
|
406
|
+
const length = this.text.length;
|
|
407
|
+
if (length > 0)
|
|
408
|
+
this.deleteText(tracker, 0, length);
|
|
409
|
+
tracker.markParagraphDeleted(this.p);
|
|
410
|
+
}
|
|
209
411
|
/** The paragraph as XML (extension; Office JS getOoxml wraps it in a package). */
|
|
210
412
|
getXml() {
|
|
211
413
|
return marshalString(this.element);
|
|
@@ -218,10 +420,33 @@ export class Paragraph {
|
|
|
218
420
|
return ((_a = (_b = this.p).content) !== null && _a !== void 0 ? _a : (_b.content = []));
|
|
219
421
|
}
|
|
220
422
|
// --- editing primitives, shared with Range ---
|
|
423
|
+
/**
|
|
424
|
+
* The paragraph's properties, created when absent. Every property setter goes through this
|
|
425
|
+
* one accessor, so this is where a tracked write records `w:pPrChange` with the properties as
|
|
426
|
+
* they stand before it.
|
|
427
|
+
*
|
|
428
|
+
* @internal public so that the list views (CR-002 phase H) write `w:numPr` the same way.
|
|
429
|
+
*/
|
|
221
430
|
pPr() {
|
|
431
|
+
var _a, _b;
|
|
432
|
+
var _c;
|
|
433
|
+
const pPr = ((_a = (_c = this.p).pPr) !== null && _a !== void 0 ? _a : (_c.pPr = { TYPE_NAME: 'org_docx4j_wml.PPr' }));
|
|
434
|
+
linkParents(pPr, this.p);
|
|
435
|
+
(_b = this.changeTracker) === null || _b === void 0 ? void 0 : _b.recordPPrChange(pPr);
|
|
436
|
+
return pPr;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* The paragraph's `w:numPr`, created when absent, through {@link pPr} so that a tracked
|
|
440
|
+
* write records `w:pPrChange` first.
|
|
441
|
+
*
|
|
442
|
+
* @internal what the list views write through (CR-002 phase H).
|
|
443
|
+
*/
|
|
444
|
+
numPr() {
|
|
222
445
|
var _a;
|
|
223
|
-
|
|
224
|
-
|
|
446
|
+
const pPr = this.pPr();
|
|
447
|
+
const numPr = ((_a = pPr.numPr) !== null && _a !== void 0 ? _a : (pPr.numPr = { TYPE_NAME: 'org_docx4j_wml.PPrBase.NumPr' }));
|
|
448
|
+
linkParents(numPr, pPr);
|
|
449
|
+
return numPr;
|
|
225
450
|
}
|
|
226
451
|
ind() {
|
|
227
452
|
var _a;
|
|
@@ -233,9 +458,24 @@ export class Paragraph {
|
|
|
233
458
|
var _b;
|
|
234
459
|
return ((_a = (_b = this.pPr()).spacing) !== null && _a !== void 0 ? _a : (_b.spacing = {}));
|
|
235
460
|
}
|
|
461
|
+
/** The package's change tracker while `changeTrackingMode` is on; undefined when it is off. */
|
|
462
|
+
get changeTracker() {
|
|
463
|
+
return this.parentBody.changeTracker;
|
|
464
|
+
}
|
|
465
|
+
/** What `Font` needs to write `w:rPrChange`: the tracker, and the runs that are our own insertion (`Range` shares it). */
|
|
466
|
+
fontTracking() {
|
|
467
|
+
const tracker = this.changeTracker;
|
|
468
|
+
if (!tracker)
|
|
469
|
+
return undefined;
|
|
470
|
+
const ownInsertions = new Set();
|
|
471
|
+
for (const seg of this.segments())
|
|
472
|
+
if (tracker.ownInsertion(seg.revision))
|
|
473
|
+
ownInsertions.add(seg.run);
|
|
474
|
+
return { tracker, ownInsertions };
|
|
475
|
+
}
|
|
236
476
|
/** The text segments (w:t, w:tab, ...) with their offsets. */
|
|
237
|
-
segments() {
|
|
238
|
-
return segmentsOf(this.p);
|
|
477
|
+
segments(options) {
|
|
478
|
+
return segmentsOf(this.p, options);
|
|
239
479
|
}
|
|
240
480
|
/**
|
|
241
481
|
* Replaces the text in [start, end) with `text` and returns the range of the inserted text.
|
|
@@ -249,6 +489,14 @@ export class Paragraph {
|
|
|
249
489
|
const length = this.text.length;
|
|
250
490
|
start = Math.max(0, Math.min(start, length));
|
|
251
491
|
end = Math.max(start, Math.min(end, length));
|
|
492
|
+
const tracker = this.changeTracker;
|
|
493
|
+
if (tracker) {
|
|
494
|
+
// a replacement is the w:del first and the w:ins after it, as Word writes one
|
|
495
|
+
const deletions = end > start ? this.deleteText(tracker, start, end) : [];
|
|
496
|
+
if (text.length > 0)
|
|
497
|
+
this.insertTracked(tracker, start, text, deletions[deletions.length - 1]);
|
|
498
|
+
return new Range(this, start, start + text.length);
|
|
499
|
+
}
|
|
252
500
|
let segs = this.segments();
|
|
253
501
|
let inserted = false;
|
|
254
502
|
if (end > start) {
|
|
@@ -323,6 +571,27 @@ export class Paragraph {
|
|
|
323
571
|
}
|
|
324
572
|
return new Range(this, start, start + text.length);
|
|
325
573
|
}
|
|
574
|
+
/**
|
|
575
|
+
* Inserts run-level items (runs, hyperlinks, content controls) at a text offset, splitting the
|
|
576
|
+
* run there when the offset falls inside one. PARENT is linked on what is inserted.
|
|
577
|
+
*/
|
|
578
|
+
insertItemsAt(offset, items) {
|
|
579
|
+
var _a, _b, _c;
|
|
580
|
+
var _d;
|
|
581
|
+
if (items.length === 0)
|
|
582
|
+
return;
|
|
583
|
+
this.splitAt(offset);
|
|
584
|
+
const segs = this.segments();
|
|
585
|
+
const after = segs.find((s) => s.start >= offset);
|
|
586
|
+
const before = [...segs].reverse().find((s) => s.end <= offset);
|
|
587
|
+
const neighbour = after !== null && after !== void 0 ? after : before;
|
|
588
|
+
const list = neighbour ? neighbour.runOwner : ((_a = (_d = this.p).content) !== null && _a !== void 0 ? _a : (_d.content = []));
|
|
589
|
+
const at = neighbour ? (after ? neighbour.runIndex : neighbour.runIndex + 1) : (offset === 0 ? 0 : list.length);
|
|
590
|
+
list.splice(at, 0, ...items);
|
|
591
|
+
const owner = (_c = (_b = neighbour === null || neighbour === void 0 ? void 0 : neighbour.run) === null || _b === void 0 ? void 0 : _b.PARENT) !== null && _c !== void 0 ? _c : this.p;
|
|
592
|
+
for (const item of items)
|
|
593
|
+
linkParents(item, owner);
|
|
594
|
+
}
|
|
326
595
|
/** Splits the run at a text offset so that [offset, ...) begins a run; returns nothing when the offset is already a boundary. */
|
|
327
596
|
splitAt(offset) {
|
|
328
597
|
var _a;
|
|
@@ -341,6 +610,87 @@ export class Paragraph {
|
|
|
341
610
|
seg.runOwner.splice(seg.runIndex + 1, 0, second);
|
|
342
611
|
linkParents(second, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
|
|
343
612
|
}
|
|
613
|
+
// --- lists (CR-002 phase H) ---
|
|
614
|
+
/**
|
|
615
|
+
* Office JS `paragraph.isListItem`: whether Word paints a label in front of this paragraph.
|
|
616
|
+
* The effective `w:numPr` decides it (docx4j `Emulator.numRefFor`), so a "List Number" style
|
|
617
|
+
* counts; a `w:numId` of 0, a `w:numId` naming no `w:num`, and a level linked to another
|
|
618
|
+
* paragraph style do not.
|
|
619
|
+
*/
|
|
620
|
+
get isListItem() {
|
|
621
|
+
return isListItem(this);
|
|
622
|
+
}
|
|
623
|
+
/** Office JS `paragraph.list`: the list this paragraph is in; throws when it is not in one. */
|
|
624
|
+
get list() {
|
|
625
|
+
return listOf(this);
|
|
626
|
+
}
|
|
627
|
+
/** Office JS `paragraph.listOrNullObject`: the list, or a null object (`isNullObject` true). */
|
|
628
|
+
get listOrNullObject() {
|
|
629
|
+
return listOrNullObjectOf(this);
|
|
630
|
+
}
|
|
631
|
+
/** Office JS `paragraph.listItem`: this paragraph's place in its list; throws when it has none. */
|
|
632
|
+
get listItem() {
|
|
633
|
+
return listItemOf(this);
|
|
634
|
+
}
|
|
635
|
+
/** Office JS `paragraph.listItemOrNullObject`. */
|
|
636
|
+
get listItemOrNullObject() {
|
|
637
|
+
return listItemOrNullObjectOf(this);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Office JS `paragraph.startNewList()`: a new list definition (docx4j's default decimal set,
|
|
641
|
+
* or its bullet set with `{ bullet: true }`) with this paragraph as its first item, adding
|
|
642
|
+
* the numbering part and its relationship when the document has none.
|
|
643
|
+
*
|
|
644
|
+
* Asynchronous where Office JS's is synchronous, since the default definitions are XML to be
|
|
645
|
+
* unmarshalled (CR-002 section 17).
|
|
646
|
+
*/
|
|
647
|
+
startNewList(options) {
|
|
648
|
+
return startNewList(this, options);
|
|
649
|
+
}
|
|
650
|
+
/** Office JS `paragraph.attachToList(listId, level)`: this paragraph joins that list. */
|
|
651
|
+
attachToList(listId, level = 0) {
|
|
652
|
+
return attachToList(this, listId, level);
|
|
653
|
+
}
|
|
654
|
+
/** Office JS `paragraph.detachFromList()`: this paragraph leaves its list. */
|
|
655
|
+
detachFromList() {
|
|
656
|
+
detachFromList(this);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* The same list, starting again at this paragraph: a new `w:num` over the same
|
|
660
|
+
* `w:abstractNum` with a `w:startOverride` (extension; `List.restart()` is the verb).
|
|
661
|
+
*/
|
|
662
|
+
restartList() {
|
|
663
|
+
const list = this.list;
|
|
664
|
+
const level = this.listItem.level;
|
|
665
|
+
const restarted = list.restart();
|
|
666
|
+
this.attachToList(restarted.id, level);
|
|
667
|
+
return restarted;
|
|
668
|
+
}
|
|
669
|
+
// --- comments (CR-002 phase G) ---
|
|
670
|
+
/** The comments anchored in this paragraph, replies nested under their parent. */
|
|
671
|
+
async getComments() {
|
|
672
|
+
return commentApi().commentsOf(this);
|
|
673
|
+
}
|
|
674
|
+
/** Comments the whole paragraph (sugar over `getRange().insertComment`). */
|
|
675
|
+
async insertComment(text) {
|
|
676
|
+
return commentApi().insertComment(this.getRange(), text);
|
|
677
|
+
}
|
|
678
|
+
// --- content controls (CR-002 phase E) ---
|
|
679
|
+
/**
|
|
680
|
+
* Wraps this paragraph in a new block-level content control (Office JS
|
|
681
|
+
* `Paragraph.insertContentControl`), typed for the kind when one is given. The `w:id` is free in
|
|
682
|
+
* the body. Returns the control.
|
|
683
|
+
*/
|
|
684
|
+
insertContentControl(kind) {
|
|
685
|
+
var _a;
|
|
686
|
+
const at = this.index;
|
|
687
|
+
if (at < 0)
|
|
688
|
+
throw new Docx4JException('This paragraph is not in its container any more');
|
|
689
|
+
const sdt = sdtOf([this.element], { kind: sdtKindFor(kind), id: nextSdtId(controlIdScope(this.parentBody)), form: 'block' });
|
|
690
|
+
this.container.splice(at, 1, sdt);
|
|
691
|
+
linkParents(sdt, (_a = this.p.PARENT) !== null && _a !== void 0 ? _a : this.parentBody.container);
|
|
692
|
+
return new ContentControl(sdt, this.container, this.parentBody);
|
|
693
|
+
}
|
|
344
694
|
removeEmptyRuns() {
|
|
345
695
|
var _a;
|
|
346
696
|
const prune = (items) => {
|
|
@@ -353,12 +703,216 @@ export class Paragraph {
|
|
|
353
703
|
}
|
|
354
704
|
else if (v.TYPE_NAME !== 'org_docx4j_wml.P') {
|
|
355
705
|
const nested = runItemsOf(v);
|
|
356
|
-
if (nested)
|
|
706
|
+
if (nested) {
|
|
357
707
|
prune(nested);
|
|
708
|
+
// a revision left with nothing in it goes too
|
|
709
|
+
if (nested.length === 0 && revisionKindOf(el) !== undefined)
|
|
710
|
+
items.splice(i, 1);
|
|
711
|
+
}
|
|
358
712
|
}
|
|
359
713
|
}
|
|
360
714
|
};
|
|
361
715
|
prune((_a = this.p.content) !== null && _a !== void 0 ? _a : []);
|
|
362
716
|
}
|
|
717
|
+
// --- tracked editing (CR-002 phase F) ---------------------------------------------------
|
|
718
|
+
/**
|
|
719
|
+
* The text in [start, end) becomes a deletion: the runs holding it are isolated, their `w:t`
|
|
720
|
+
* turned into `w:delText`, and each run of consecutive ones moved into one `w:del`. Text this
|
|
721
|
+
* author had inserted is simply removed, as Word does, rather than nested in a `w:del`.
|
|
722
|
+
* Returns the `w:del` elements it made, in document order.
|
|
723
|
+
*/
|
|
724
|
+
deleteText(tracker, start, end) {
|
|
725
|
+
var _a, _b, _c, _d, _e, _f;
|
|
726
|
+
const targets = this.isolate(start, end);
|
|
727
|
+
for (const seg of targets)
|
|
728
|
+
tracker.assertEditable(seg.revision);
|
|
729
|
+
const list = [];
|
|
730
|
+
for (const seg of targets) {
|
|
731
|
+
const run = seg.runOwner[seg.runIndex];
|
|
732
|
+
if (list.length > 0 && list[list.length - 1].run === run)
|
|
733
|
+
continue;
|
|
734
|
+
const target = { run, owner: seg.runOwner, own: tracker.ownInsertion(seg.revision) };
|
|
735
|
+
if (seg.revision)
|
|
736
|
+
target.revision = seg.revision;
|
|
737
|
+
list.push(target);
|
|
738
|
+
}
|
|
739
|
+
// groups of consecutive runs in the same array, so that one w:del holds them all
|
|
740
|
+
const groups = [];
|
|
741
|
+
for (const t of list) {
|
|
742
|
+
const last = groups[groups.length - 1];
|
|
743
|
+
const previous = last === null || last === void 0 ? void 0 : last[last.length - 1];
|
|
744
|
+
if (last && previous && previous.own === t.own && previous.owner === t.owner
|
|
745
|
+
&& t.owner.indexOf(t.run) === t.owner.indexOf(previous.run) + 1)
|
|
746
|
+
last.push(t);
|
|
747
|
+
else
|
|
748
|
+
groups.push([t]);
|
|
749
|
+
}
|
|
750
|
+
const made = [];
|
|
751
|
+
for (let g = groups.length - 1; g >= 0; g--) {
|
|
752
|
+
const group = groups[g];
|
|
753
|
+
const owner = group[0].owner;
|
|
754
|
+
const at = owner.indexOf(group[0].run);
|
|
755
|
+
const runs = owner.splice(at, group.length);
|
|
756
|
+
if (group[0].own) {
|
|
757
|
+
// taking back our own insertion: the runs go, and an emptied w:ins with them
|
|
758
|
+
const revision = group[0].revision;
|
|
759
|
+
if (revision && revision.items.length === 0) {
|
|
760
|
+
const i = revision.owner.indexOf(revision.element);
|
|
761
|
+
if (i >= 0)
|
|
762
|
+
revision.owner.splice(i, 1);
|
|
763
|
+
}
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
for (const run of runs)
|
|
767
|
+
toDeletedText(run.value);
|
|
768
|
+
const del = tracker.del(runs);
|
|
769
|
+
owner.splice(at, 0, del);
|
|
770
|
+
linkParents(del, ((_c = (_b = (_a = group[0].revision) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : group[0].run.value.PARENT) !== null && _c !== void 0 ? _c : this.p));
|
|
771
|
+
made.unshift({ owner, element: del, parent: ((_f = (_e = (_d = group[0].revision) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : del.value.PARENT) !== null && _f !== void 0 ? _f : this.p) });
|
|
772
|
+
}
|
|
773
|
+
return made;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Text inserted at `at` as a `w:ins`. A run of this author's own that is already inside a
|
|
777
|
+
* `w:ins` is extended rather than nested in another one, as Word does. `anchor` is the `w:del`
|
|
778
|
+
* of a replacement, which the insertion must follow.
|
|
779
|
+
*/
|
|
780
|
+
insertTracked(tracker, at, text, anchor) {
|
|
781
|
+
var _a, _b, _c, _d, _e;
|
|
782
|
+
var _f;
|
|
783
|
+
if (anchor) {
|
|
784
|
+
const rPr = copyRPr((_a = runsOf(anchor.element.value, { view: 'original' })[0]) === null || _a === void 0 ? void 0 : _a.value.rPr);
|
|
785
|
+
const ins = tracker.ins([runOf([textItem(text)], rPr)]);
|
|
786
|
+
anchor.owner.splice(anchor.owner.indexOf(anchor.element) + 1, 0, ins);
|
|
787
|
+
linkParents(ins, anchor.parent);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
this.splitAt(at);
|
|
791
|
+
const segs = this.segments();
|
|
792
|
+
const before = [...segs].reverse().find((s) => s.end <= at);
|
|
793
|
+
const after = segs.find((s) => s.start >= at);
|
|
794
|
+
for (const [seg, side] of [[before, 'after'], [after, 'before']]) {
|
|
795
|
+
if (!seg || !tracker.ownInsertion(seg.revision))
|
|
796
|
+
continue;
|
|
797
|
+
if (seg.editable) {
|
|
798
|
+
const t = seg.item.value;
|
|
799
|
+
t.value = side === 'after' ? seg.text + text : text + seg.text;
|
|
800
|
+
if (/^\s|\s$|\s\s/.test(t.value))
|
|
801
|
+
t.space = 'preserve';
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
const run = runOf([textItem(text)], copyRPr(seg.run.rPr));
|
|
805
|
+
seg.runOwner.splice(side === 'after' ? seg.runIndex + 1 : seg.runIndex, 0, run);
|
|
806
|
+
linkParents(run, seg.revision.value);
|
|
807
|
+
}
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
const neighbour = before !== null && before !== void 0 ? before : after;
|
|
811
|
+
tracker.assertEditable(neighbour === null || neighbour === void 0 ? void 0 : neighbour.revision);
|
|
812
|
+
const rPr = copyRPr((_b = neighbour === null || neighbour === void 0 ? void 0 : neighbour.run.rPr) !== null && _b !== void 0 ? _b : (_c = runsOf(this.p)[0]) === null || _c === void 0 ? void 0 : _c.value.rPr);
|
|
813
|
+
const ins = tracker.ins([runOf([textItem(text)], rPr)]);
|
|
814
|
+
if (neighbour) {
|
|
815
|
+
const owner = neighbour.revision ? neighbour.revision.owner : neighbour.runOwner;
|
|
816
|
+
const item = neighbour.revision ? neighbour.revision.element : neighbour.runOwner[neighbour.runIndex];
|
|
817
|
+
const parent = (neighbour.revision ? neighbour.revision.value : neighbour.run);
|
|
818
|
+
owner.splice(owner.indexOf(item) + (neighbour === before ? 1 : 0), 0, ins);
|
|
819
|
+
linkParents(ins, (_d = parent.PARENT) !== null && _d !== void 0 ? _d : this.p);
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
const content = ((_e = (_f = this.p).content) !== null && _e !== void 0 ? _e : (_f.content = []));
|
|
823
|
+
if (at === 0)
|
|
824
|
+
content.unshift(ins);
|
|
825
|
+
else
|
|
826
|
+
content.push(ins);
|
|
827
|
+
linkParents(ins, this.p);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Splits runs so that every run holding text in [start, end) holds nothing else, and returns
|
|
832
|
+
* the segments inside the span. `splitAt` does the `w:t` boundaries; this also moves the items
|
|
833
|
+
* of a run that straddles a boundary (a tab, a break, a drawing) out into runs of their own.
|
|
834
|
+
*/
|
|
835
|
+
isolate(start, end) {
|
|
836
|
+
this.splitAt(start);
|
|
837
|
+
this.splitAt(end);
|
|
838
|
+
for (let guard = 0; guard < 10000; guard++) {
|
|
839
|
+
const inside = this.segments().filter((s) => s.start >= start && s.end <= end && s.text.length > 0);
|
|
840
|
+
let split = false;
|
|
841
|
+
const seen = new Set();
|
|
842
|
+
for (const seg of inside) {
|
|
843
|
+
if (seen.has(seg.run))
|
|
844
|
+
continue;
|
|
845
|
+
seen.add(seg.run);
|
|
846
|
+
const ofRun = inside.filter((s) => s.run === seg.run);
|
|
847
|
+
const first = ofRun[0];
|
|
848
|
+
const last = ofRun[ofRun.length - 1];
|
|
849
|
+
if (first.index > 0) {
|
|
850
|
+
this.splitRunBefore(first);
|
|
851
|
+
split = true;
|
|
852
|
+
break;
|
|
853
|
+
}
|
|
854
|
+
if (last.index < last.owner.length - 1) {
|
|
855
|
+
this.splitRunAfter(last);
|
|
856
|
+
split = true;
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
if (!split)
|
|
861
|
+
return inside;
|
|
862
|
+
}
|
|
863
|
+
return this.segments().filter((s) => s.start >= start && s.end <= end && s.text.length > 0);
|
|
864
|
+
}
|
|
865
|
+
/** Moves the items before `seg` into a run of their own, in front of `seg`'s run. */
|
|
866
|
+
splitRunBefore(seg) {
|
|
867
|
+
var _a;
|
|
868
|
+
const head = seg.owner.splice(0, seg.index);
|
|
869
|
+
const first = runOf(head, copyRPr(seg.run.rPr));
|
|
870
|
+
seg.runOwner.splice(seg.runIndex, 0, first);
|
|
871
|
+
linkParents(first, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
|
|
872
|
+
}
|
|
873
|
+
/** Moves the items after `seg` into a run of their own, behind `seg`'s run. */
|
|
874
|
+
splitRunAfter(seg) {
|
|
875
|
+
var _a;
|
|
876
|
+
const tail = seg.owner.splice(seg.index + 1);
|
|
877
|
+
if (tail.length === 0)
|
|
878
|
+
return;
|
|
879
|
+
const rest = runOf(tail, copyRPr(seg.run.rPr));
|
|
880
|
+
seg.runOwner.splice(seg.runIndex + 1, 0, rest);
|
|
881
|
+
linkParents(rest, (_a = seg.run.PARENT) !== null && _a !== void 0 ? _a : this.p);
|
|
882
|
+
}
|
|
363
883
|
}
|
|
364
884
|
export { W_NS };
|
|
885
|
+
// --- reading one w:pPr, direct or resolved -----------------------------------------------
|
|
886
|
+
function alignmentOf(pPr, effective) {
|
|
887
|
+
var _a;
|
|
888
|
+
switch ((_a = pPr === null || pPr === void 0 ? void 0 : pPr.jc) === null || _a === void 0 ? void 0 : _a.val) {
|
|
889
|
+
case 'left':
|
|
890
|
+
case 'start': return 'Left';
|
|
891
|
+
case 'center': return 'Centered';
|
|
892
|
+
case 'right':
|
|
893
|
+
case 'end': return 'Right';
|
|
894
|
+
case 'both':
|
|
895
|
+
case 'distribute': return 'Justified';
|
|
896
|
+
// Word lays a paragraph with no w:jc out left-aligned, so that is the effective value
|
|
897
|
+
default: return effective ? 'Left' : 'Unknown';
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function firstLineIndentOf(pPr) {
|
|
901
|
+
var _a;
|
|
902
|
+
const ind = pPr === null || pPr === void 0 ? void 0 : pPr.ind;
|
|
903
|
+
if ((ind === null || ind === void 0 ? void 0 : ind.hanging) !== undefined)
|
|
904
|
+
return -ind.hanging / TWIPS_PER_POINT;
|
|
905
|
+
return ((_a = ind === null || ind === void 0 ? void 0 : ind.firstLine) !== null && _a !== void 0 ? _a : 0) / TWIPS_PER_POINT;
|
|
906
|
+
}
|
|
907
|
+
function lineSpacingOf(pPr) {
|
|
908
|
+
const spacing = pPr === null || pPr === void 0 ? void 0 : pPr.spacing;
|
|
909
|
+
if ((spacing === null || spacing === void 0 ? void 0 : spacing.line) === undefined)
|
|
910
|
+
return 0;
|
|
911
|
+
return spacing.lineRule === undefined || spacing.lineRule === 'auto'
|
|
912
|
+
? (spacing.line / 240) * 12 : spacing.line / TWIPS_PER_POINT;
|
|
913
|
+
}
|
|
914
|
+
function outlineLevelOf(pPr) {
|
|
915
|
+
var _a;
|
|
916
|
+
const level = (_a = pPr === null || pPr === void 0 ? void 0 : pPr.outlineLvl) === null || _a === void 0 ? void 0 : _a.val;
|
|
917
|
+
return level === undefined ? 10 : level + 1;
|
|
918
|
+
}
|