@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
package/README.md
CHANGED
|
@@ -6,12 +6,18 @@ and font resolution, over the Office Open XML object model of
|
|
|
6
6
|
[`@docx4j/generated-objects-ts`](https://github.com/plutext/docx4j-generated-objects-ts). Node,
|
|
7
7
|
browsers and Word add-ins.
|
|
8
8
|
|
|
9
|
-
Status:
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
Status: [CR-001](docs/change-requests/CR-001-engine.md), the engine, is **complete**. The Open
|
|
10
|
+
Packaging layer, the typed parts and the packages (Phase A); `PropertyResolver`, list numbering,
|
|
11
|
+
so a paragraph can be asked for the label Word would paint, and font selection, so a run's font
|
|
12
|
+
resolves through the theme, with paragraph and run reads reporting the formatting that actually
|
|
13
|
+
applies (Phase B); the pptx and xlsx packages with `createPackage()`, the unzipped-directory
|
|
14
|
+
container, `clone()`, and the guides and examples below (Phase C). Every resolution answer is
|
|
15
|
+
held to docx4j's own on 45 documents (`test/golden/`, made by the Java harness in `test/java/`):
|
|
16
|
+
the resolver, the emulator and the selector agree with docx4j `VERSION_17_1_1` exactly.
|
|
12
17
|
|
|
13
18
|
```
|
|
14
19
|
npm install @docx4j/core-ts
|
|
20
|
+
npm install xpath # optional, Node only: XPath over custom XML parts (browsers use document.evaluate)
|
|
15
21
|
```
|
|
16
22
|
|
|
17
23
|
```ts
|
|
@@ -39,11 +45,28 @@ const ooxml = await pkg.saveFlatOpc(); // pkg:package, for insertOo
|
|
|
39
45
|
A part that is never touched is written back byte for byte; `getContents()` (or a view over
|
|
40
46
|
it) marks a part for re-marshalling. `mc:AlternateContent` is resolved when a part is
|
|
41
47
|
unmarshalled, as Word does on open (`{ mcePreprocess: false }` to keep it). Subpaths
|
|
42
|
-
`@docx4j/core-ts/opc`, `/parts`, `/packages` and `/model` give the layers separately
|
|
48
|
+
`@docx4j/core-ts/opc`, `/parts`, `/packages` and `/model` give the layers separately,
|
|
49
|
+
`/office-js` the `Word` shim (below), and `/node` the one Node-only piece (the unzipped-directory
|
|
50
|
+
container; nothing else in the package imports a `node:` builtin, so a browser or add-in bundle
|
|
51
|
+
never sees one).
|
|
52
|
+
|
|
53
|
+
### Guides
|
|
54
|
+
|
|
55
|
+
| | |
|
|
56
|
+
|---|---|
|
|
57
|
+
| [Getting started in Node](docs/guides/getting-started-node.md) | install, load, the content API, save |
|
|
58
|
+
| [In a Word add-in](docs/guides/office-addin.md) | flat OPC in and out, testing add-in code in Node, bundling |
|
|
59
|
+
| [pptx and xlsx](docs/guides/presentationml-spreadsheetml.md) | what the PresentationML and SpreadsheetML packages give |
|
|
60
|
+
| [Parity with docx4j](docs/guides/parity.md) | what the goldens are, and running the harness against a newer docx4j |
|
|
61
|
+
|
|
62
|
+
Runnable code: [`examples/node/`](examples/node) (create, report, pptx, xlsx, an unzipped
|
|
63
|
+
directory) and [`examples/office-addin/`](examples/office-addin) (a sideloadable Word task pane
|
|
64
|
+
whose edit also runs in Node). `test/examples.test.mjs` runs them all, so they cannot rot.
|
|
43
65
|
|
|
44
66
|
### The content API
|
|
45
67
|
|
|
46
|
-
`Body`, `Paragraph`, `Range`
|
|
68
|
+
`Body`, `Paragraph`, `Range`, `Font`, `Table`, `InlinePicture` and `ContentControl` follow
|
|
69
|
+
Office JS's `Word.*` shapes (a compile-time
|
|
47
70
|
check keeps them assignable to a subset of those types), so add-in code runs against a
|
|
48
71
|
package with its `load` and `sync` lines removed. Hello World, from nothing to a `.docx`:
|
|
49
72
|
|
|
@@ -61,7 +84,7 @@ Editing what is there:
|
|
|
61
84
|
```ts
|
|
62
85
|
const body = await pkg.getBody();
|
|
63
86
|
const title = body.insertParagraph('Report', 'Start');
|
|
64
|
-
title.styleBuiltIn = 'Heading 1'
|
|
87
|
+
title.styleBuiltIn = 'Heading1'; // Word.Style value; title.style reads 'Heading 1'
|
|
65
88
|
title.alignment = 'Centered';
|
|
66
89
|
const [hit] = body.search('quick brown fox'); // across runs
|
|
67
90
|
hit.font.italic = true; // runs split at the boundaries
|
|
@@ -84,6 +107,129 @@ Docx4j's names are there as aliases (`addParagraphOfText`, `addStyledParagraphOf
|
|
|
84
107
|
`addObject`, `getContent`), and the tree stays reachable: `paragraph.p` is the `P`,
|
|
85
108
|
`body.content` the live array.
|
|
86
109
|
|
|
110
|
+
### List numbering
|
|
111
|
+
|
|
112
|
+
`Emulator` is docx4j's list-numbering emulator: the label Word would paint in front of a
|
|
113
|
+
paragraph, given its `w:pPr`. Counters live in a `NumberingState`, one per **story** — Word
|
|
114
|
+
numbers the body, the headers and footers together, each notes part and each text box from their
|
|
115
|
+
own counters — so a caller walks a story in document order with the state for it.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { WordprocessingMLPackage, Emulator, NumberingStates } from '@docx4j/core-ts';
|
|
119
|
+
|
|
120
|
+
const pkg = await WordprocessingMLPackage.load(bytes);
|
|
121
|
+
const emulator = await pkg.getNumberingEmulator(); // undefined when the document has no lists
|
|
122
|
+
const states = new NumberingStates();
|
|
123
|
+
const main = pkg.getMainDocumentPart();
|
|
124
|
+
const state = states.forPart(main); // states.forPart(headerPart), states.newStory(), ...
|
|
125
|
+
|
|
126
|
+
for (const paragraph of (await main.getBody()).paragraphs) {
|
|
127
|
+
const label = emulator?.getNumber(paragraph.p.pPr, state);
|
|
128
|
+
if (label) console.log(label.numString, label.isBullet, label.indResolved?.left);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Emulator.peek(pkg, pPr, state); // the same answer, without taking the number
|
|
132
|
+
Emulator.numRefFor(pkg, pPr); // which list and level, or why Word numbers nothing
|
|
133
|
+
pkg.numberingDefinitionsPart.getIndOf('3', '0'); // the indent that level contributes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Reading labels does not unmarshal `word/numbering.xml`, so a document you only read still saves
|
|
137
|
+
byte for byte. After editing the numbering or styles parts, `await pkg.refresh()`.
|
|
138
|
+
|
|
139
|
+
### Lists
|
|
140
|
+
|
|
141
|
+
`Word.List` and `Word.ListItem` over the same numbering, so an add-in's list code runs here
|
|
142
|
+
unchanged. A paragraph knows whether Word numbers it — through its own `w:numPr` or through a
|
|
143
|
+
numbered style — which list it is in and what label it shows.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const body = await pkg.getBody();
|
|
147
|
+
|
|
148
|
+
for (const p of body.paragraphs) {
|
|
149
|
+
if (p.isListItem) console.log(p.listItem.listString, p.listItem.level, p.text);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
body.lists; // every list a paragraph of this body names, in order of first use
|
|
153
|
+
body.listLabels(); // Map<P, { listString, level, numId, siblingIndex, isBullet }>, in one walk
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`listItem.listString` is the label Word paints, counted by walking the paragraph's story from
|
|
157
|
+
its start — Word's numbering is a running count, so that walk is the answer. Use
|
|
158
|
+
`body.listLabels()` when you want every label at once.
|
|
159
|
+
|
|
160
|
+
Making and changing lists:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
const list = await p.startNewList(); // { bullet: true } for the bullet set
|
|
164
|
+
p2.attachToList(list.id, 1); // join it, at level 1
|
|
165
|
+
p2.listItem.level = 2; // or move it
|
|
166
|
+
p3.detachFromList();
|
|
167
|
+
|
|
168
|
+
list.setLevelNumbering(0, 'UpperRoman', ['(', 0, ')']); // w:numFmt and w:lvlText "(%1)"
|
|
169
|
+
list.setLevelBullet(1, 'Square');
|
|
170
|
+
list.setLevelIndents(0, 36, 18); // points, as Office JS
|
|
171
|
+
list.setLevelStartingNumber(0, 5);
|
|
172
|
+
|
|
173
|
+
const again = p4.restartList(); // the same list, numbering again from its start
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
A level writer changes the `w:abstractNum`, so it copies that definition first when another
|
|
177
|
+
`w:num` shares it — the change stays local to this list. `startNewList()` is asynchronous here
|
|
178
|
+
(Office JS's is not): it copies its definition from docx4j's default `numbering.xml` and adds
|
|
179
|
+
the numbering part when the document has none.
|
|
180
|
+
|
|
181
|
+
### Change tracking
|
|
182
|
+
|
|
183
|
+
`pkg.changeTrackingMode` is Office JS's `document.changeTrackingMode`, backed by
|
|
184
|
+
`w:trackRevisions` in the settings part. While it is on, every edit made through the content
|
|
185
|
+
API writes Word's revision markup instead of changing the tree in place: an insertion becomes
|
|
186
|
+
`w:ins`, a deletion `w:del` with `w:delText`, a replacement a `w:del` followed by a `w:ins`, a
|
|
187
|
+
new paragraph's mark `w:pPr/w:rPr/w:ins`, a deleted one `w:pPr/w:rPr/w:del`, and a formatting
|
|
188
|
+
change keeps what was there in `w:rPrChange` or `w:pPrChange`. The author is `pkg.author` and
|
|
189
|
+
the date `pkg.trackedChangeDate` (now, unless you fix one).
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
pkg.author = { name: 'Ada Lovelace' }; // the same author phase G's comments use
|
|
193
|
+
pkg.changeTrackingMode = 'TrackAll'; // await pkg.setChangeTrackingMode(...) on a loaded package
|
|
194
|
+
body.search('quick brown fox')[0].insertText('slow red fox', 'Replace');
|
|
195
|
+
body.replaceText('colour', 'color'); // returns the number replaced, tracked like any other edit
|
|
196
|
+
|
|
197
|
+
body.text; // the accepted view: w:ins in, w:del out
|
|
198
|
+
body.getText({ view: 'original' }); // the other way round
|
|
199
|
+
|
|
200
|
+
for (const change of body.getTrackedChanges()) {
|
|
201
|
+
change.type; // 'Added' | 'Deleted' | 'Formatted'
|
|
202
|
+
change.author; change.date; change.text;
|
|
203
|
+
change.getRange(); // where it is
|
|
204
|
+
}
|
|
205
|
+
body.acceptAll(); // or rejectAll(), or accept()/reject() one at a time
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`getTrackedChanges()` is also on `Paragraph` and `Range`. Text and searches read the accepted
|
|
209
|
+
view throughout, so an agent sees the document as it will read once the changes are taken.
|
|
210
|
+
|
|
211
|
+
### Comments
|
|
212
|
+
|
|
213
|
+
`getComments()` on the body, a paragraph or a range, and `insertComment` on a range or a
|
|
214
|
+
paragraph, over the four parts Word writes (`w:comments`, `w15:commentsEx`, `w16cid` and
|
|
215
|
+
`w:people`, plus `w16cex` when the document has one); threads, `resolved` (`w15:done`) and
|
|
216
|
+
`delete()` keep them all in step, and any of the parts the document lacks is created with its
|
|
217
|
+
relationship, content type and the `CommentText` and `CommentReference` styles.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
pkg.author = { name: 'Ada Lovelace', initials: 'AL', email: 'ada@example.com' }; // whose comments these are
|
|
221
|
+
|
|
222
|
+
const [hit] = body.search('quick brown fox');
|
|
223
|
+
const comment = await hit.insertComment('Is this the right idiom?');
|
|
224
|
+
await comment.reply('Yes, Word writes it this way');
|
|
225
|
+
comment.resolved = true; // w15:done
|
|
226
|
+
|
|
227
|
+
for (const c of await body.getComments()) { // document order, replies nested
|
|
228
|
+
console.log(c.authorName, c.creationDate, c.content, c.replies.length, c.getRange().map((r) => r.text));
|
|
229
|
+
if (c.resolved) await c.delete(); // the comment, its replies, the markers and every side entry
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
87
233
|
### XML in
|
|
88
234
|
|
|
89
235
|
A whole `word/document.xml` becomes the main document part's contents with `setXml`, and a
|
|
@@ -107,18 +253,272 @@ import * as el from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
|
|
|
107
253
|
body.addObject(el.p({ content: [el.r({ content: [el.t({ value: 'Hello World' })] })] }));
|
|
108
254
|
```
|
|
109
255
|
|
|
110
|
-
Tables, pictures
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
256
|
+
### Tables, pictures and content controls
|
|
257
|
+
|
|
258
|
+
`Table`, `TableRow` and `TableCell` are Office JS shapes too; a cell is a `Body` of its own, so
|
|
259
|
+
everything above works inside one:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
const table = body.insertTable(3, 2, 'End', [['Item', 'Price'], ['apples', '$20']]);
|
|
263
|
+
table.styleBuiltIn = 'TableGrid'; // Word.Style value; table.style is then 'Table Grid', table.styleId 'TableGrid'
|
|
264
|
+
table.headerRowCount = 1; // w:tblHeader: the row repeats on every page
|
|
265
|
+
table.getCell(1, 1).value = '$25';
|
|
266
|
+
table.addRows('End', 1, [['pears', '$30']]);
|
|
267
|
+
table.values; // [['Item', 'Price'], ['apples', '$25'], ['pears', '$30']]
|
|
268
|
+
body.paragraphs[4].parentTableCell?.cellIndex;
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
A picture adds its own `ImagePart`, the relationship and a `w:drawing` sized from the image's
|
|
272
|
+
pixels and resolution (96 dpi when the file declares none, as docx4j does), scaled down if it
|
|
273
|
+
is wider than the text area:
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
const picture = body.insertInlinePictureFromBase64(pngBase64, 'End', { altTextDescription: 'The logo' });
|
|
277
|
+
picture.width = 144; // points; the height follows the aspect ratio
|
|
278
|
+
picture.imageFormat; // 'Png'
|
|
279
|
+
await body.inlinePictures[0].getBase64();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`insertOoxml` takes what Word's does, a flat OPC `pkg:package` string: the body content comes
|
|
283
|
+
over with the parts it references (images, embedded objects) copied in under fresh names and
|
|
284
|
+
relationship ids. A bare fragment works too, as `insertXml`.
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
await body.insertOoxml(await other.saveFlatOpc(), 'End'); // or an add-in's getOoxml() string
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Content controls (`w:sdt`) are read at block, row, cell and run level:
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
for (const control of body.contentControls) {
|
|
294
|
+
console.log(control.form, control.type, control.title, control.tag, control.text);
|
|
295
|
+
}
|
|
296
|
+
body.contentControls[0].insertText('Jane Doe', 'Replace');
|
|
297
|
+
body.contentControls[1].delete(true); // unwrap, keeping what it held
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`Font` and `Paragraph` reads report **effective** formatting - the document defaults, the style
|
|
301
|
+
chain and the numbering level resolved, as Office JS reports it - through docx4j's
|
|
302
|
+
`PropertyResolver` (CR-001 Phase B step 2). Writes are always direct formatting, and
|
|
303
|
+
`paragraph.getFont({ direct: true })`, `range.getFont({ direct: true })` and
|
|
304
|
+
`paragraph.formatting({ direct: true })` read the direct values.
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
const p = (await pkg.getBody()).paragraphs[0];
|
|
308
|
+
p.font.size; // 14: the style's w:sz, not the run's
|
|
309
|
+
p.getFont({ direct: true }).size; // 0: the run states none
|
|
310
|
+
p.alignment; // 'Left' when nothing states a w:jc, as Word lays it out
|
|
311
|
+
p.formatting({ direct: true }).alignment; // 'Unknown'
|
|
312
|
+
p.effectivePPr; // docx4j's resolved w:pPr, for anything the view does not cover
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Custom XML and content controls
|
|
316
|
+
|
|
317
|
+
`pkg.customXmlParts` is Office JS's `CustomXmlPartCollection` over the custom XML data storage
|
|
318
|
+
parts, with XPath 1.0 over their DOM: `document.evaluate` in a browser or a Word add-in, the
|
|
319
|
+
optional peer dependency [`xpath`](https://www.npmjs.com/package/xpath) in Node (`npm install
|
|
320
|
+
xpath`; `pkg.xpathEngine` takes any other engine). One `await` warms it, and the node model is
|
|
321
|
+
synchronous from then on:
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const parts = await pkg.customXmlParts.load(); // parses the DOMs, warms the XPath engine
|
|
325
|
+
const data = pkg.customXmlParts.getItem('{8B049945-9DFE-4726-9DE9-CF5691E53858}');
|
|
326
|
+
data.selectSingleNode('/invoice/customer/name').text; // 'Joe Bloggs'
|
|
327
|
+
data.selectNodes('/invoice/items/item').map((n) => n.text);
|
|
328
|
+
data.documentElement.appendChildNode('<note>paid</note>');
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
A content control's `xmlMapping` is its `w:dataBinding`, and the two directions are docx4j's,
|
|
332
|
+
under docx4j's names:
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
const control = (await pkg.getBody()).contentControls[0];
|
|
336
|
+
control.xmlMapping.isMapped; // true
|
|
337
|
+
control.xmlMapping.xpath; // '/invoice[1]/customer[1]/name[1]'
|
|
338
|
+
control.xmlMapping.customXmlNode.text; // 'Joe Bloggs'
|
|
339
|
+
|
|
340
|
+
await pkg.customXmlParts.applyBindings(); // docx4j BindingHandler: XML -> controls
|
|
341
|
+
control.insertText('Jane Doe', 'Replace'); // writes through to the bound node as well
|
|
342
|
+
await pkg.customXmlParts.updateFromContentControls(); // docx4j: controls -> XML
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
That last pair matters: Word refreshes a bound control from the custom XML part when it opens a
|
|
346
|
+
document, so an edit that only touched `w:sdtContent` would not show.
|
|
347
|
+
|
|
348
|
+
A new part comes with its properties part, a fresh `ds:itemID` and the relationship from the main
|
|
349
|
+
document part (Word drops a custom XML part the main part does not relate to):
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
const part = pkg.customXmlParts.add('<greeting xmlns="http://example.com/g"><to>World</to></greeting>');
|
|
353
|
+
control.xmlMapping.setMapping('/ns0:greeting[1]/ns0:to[1]', "xmlns:ns0='http://example.com/g'", part);
|
|
354
|
+
control.xmlMapping.setMappingByNode(part.selectSingleNode('/ns0:greeting/ns0:to', "xmlns:ns0='http://example.com/g'"));
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Controls are created by wrapping what is there, and the kind-specific views are Office JS's:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
const control = paragraph.insertContentControl('CheckBox'); // also on body and range
|
|
361
|
+
control.checkboxContentControl.isChecked = true; // shows ☒, as Word does
|
|
362
|
+
control.title = 'Applies'; control.appearance = 'Tags'; control.cannotDelete = true;
|
|
363
|
+
|
|
364
|
+
const list = body.paragraphs[1].insertContentControl('DropDownList').dropDownListContentControl;
|
|
365
|
+
list.addListItem('Apples', 'apples');
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Fonts
|
|
369
|
+
|
|
370
|
+
Two questions, kept apart as they are in docx4j: which **document** font formats each character
|
|
371
|
+
of a run, and which physical face draws that name.
|
|
372
|
+
|
|
373
|
+
`RunFontSelector` answers the first. It resolves the run's effective properties, resolves every
|
|
374
|
+
theme reference (`w:asciiTheme` and friends) through the theme part for the document's
|
|
375
|
+
`w:themeFontLang`, and then walks the text through the [MS-OI29500] 17.3.2.26 character-range
|
|
376
|
+
table, folding the answer into spans:
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
const main = pkg.getMainDocumentPart();
|
|
380
|
+
const selector = await main.getRunFontSelector();
|
|
381
|
+
|
|
382
|
+
selector.spans(paragraph.pPr, run.rPr, 'Hello 日本 שלום');
|
|
383
|
+
// [ { text: 'Hello ', documentFont: 'Calibri', bold: false, italic: false,
|
|
384
|
+
// cs: false, rtl: false, script: 'LATIN' },
|
|
385
|
+
// { text: '日本', documentFont: 'MS Gothic', ..., script: 'CJK' },
|
|
386
|
+
// { text: ' ', documentFont: 'Calibri', ..., script: null },
|
|
387
|
+
// { text: 'שלום', documentFont: 'Calibri', ..., script: 'HEBREW' } ]
|
|
388
|
+
|
|
389
|
+
selector.documentFontFor(paragraph.pPr, run.rPr, 0x1F600); // one code point
|
|
390
|
+
selector.asciiFontName(effectiveRPr); // what `font.name` reports
|
|
391
|
+
selector.defaultFont; // the document's default face
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
`w:cs` and `w:rtl` are read **by value** (`<w:cs w:val="0"/>` turns an inherited complex-script
|
|
395
|
+
flag off), the symbol fonts are matched case-insensitively, and the space between two East Asian
|
|
396
|
+
words takes the ascii font — each of those verified against Word, in docx4j's CR-016.
|
|
397
|
+
|
|
398
|
+
A package with **no theme part** is read as coming from a particular version of Word:
|
|
399
|
+
`pkg.fonts.defaultTheme` is `'2023'` (Word 365: Aptos Display / Aptos), `'2013'` (Calibri Light /
|
|
400
|
+
Calibri) or `'2007'` (Cambria / Calibri). `createPackage()` gives a new package that theme's
|
|
401
|
+
theme part, as Word does, so a document created here and one created by docx4j resolve alike.
|
|
402
|
+
|
|
403
|
+
`Mapper` answers the second question, over a `FontRegistry` the caller supplies — the names the
|
|
404
|
+
consumer can actually draw with. `IdentityPlusMapper` takes the font itself where the registry
|
|
405
|
+
has it, then the document's embedded form, a variant of the name, docx4j's measured substitute
|
|
406
|
+
table (`font-substitutes.xml`: Arial to Arimo, Calibri to Carlito, Cambria to Caladea, Aptos to
|
|
407
|
+
Akasia), the document's own `w:altName` chain, a face of the same class, and finally what Word
|
|
408
|
+
itself draws a font it cannot find:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
const mapper = await main.getFontMapper(); // IdentityPlusMapper over DEFAULT_FONT_REGISTRY
|
|
412
|
+
mapper.get('Calibri'); // PhysicalFont { name: 'Carlito Regular', familyName: 'Carlito' }
|
|
413
|
+
mapper.getDecision('Calibri'); // { source: 'METRIC_CLONE', via: null, widthError: '0.07% ...' }
|
|
414
|
+
|
|
415
|
+
await main.fontsInUse(); // every name the document could ask for
|
|
416
|
+
await main.getStylesInUse(); // the style ids used directly
|
|
417
|
+
|
|
418
|
+
// your own font environment
|
|
419
|
+
const mine = new IdentityPlusMapper(new SimpleFontRegistry(faces.map((f) => new PhysicalFont(f.fullName, f.family))));
|
|
420
|
+
await main.getFontMapper(mine);
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The default registry is the faces docx4j's four font jars carry, which is the environment the
|
|
424
|
+
parity goldens were made in. Reading font files (`PhysicalFonts.discover`, glyph coverage, font
|
|
425
|
+
metrics) is a later CR; the `Mapper` interface is what a consumer with `fontkit` plugs into.
|
|
426
|
+
|
|
427
|
+
### pptx and xlsx
|
|
428
|
+
|
|
429
|
+
The Open Packaging layer is one layer for all three formats: a `.pptx` and an `.xlsx` load, round
|
|
430
|
+
-trip byte for byte and save exactly as a `.docx` does, with their parts typed by the same object
|
|
431
|
+
model. What they do not have is the content API, which is WordprocessingML.
|
|
432
|
+
|
|
433
|
+
```ts
|
|
434
|
+
import { PresentationMLPackage, SpreadsheetMLPackage } from '@docx4j/core-ts';
|
|
435
|
+
|
|
436
|
+
const deck = await PresentationMLPackage.createPackage({ slideSize: 'SCREEN16x9' });
|
|
437
|
+
await deck.addSlide();
|
|
438
|
+
deck.slideParts; // in p:sldIdLst order; .slideMasterParts, .slideLayoutParts
|
|
439
|
+
|
|
440
|
+
const book = await SpreadsheetMLPackage.createPackage();
|
|
441
|
+
const sheet = book.createWorksheetPart('Sales'); // the tab, its r:id and the worksheet part
|
|
442
|
+
book.worksheetParts; // in `sheets` order; .sharedStringsPart, .stylesPart
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Both follow docx4j's part set, so the files open in PowerPoint and Excel; the detail is in
|
|
446
|
+
[docs/guides/presentationml-spreadsheetml.md](docs/guides/presentationml-spreadsheetml.md).
|
|
447
|
+
|
|
448
|
+
### Use in Node: running add-in code against a package
|
|
449
|
+
|
|
450
|
+
`@docx4j/core-ts/office-js` is a `Word` shim: `Word.run(pkg, fn)` gives the callback a
|
|
451
|
+
`context` whose `document.body` is the package's body, `load()` is a no-op and `context.sync()`
|
|
452
|
+
resolves what was asynchronous. An add-in's batch therefore runs unchanged in a test, in CI,
|
|
453
|
+
or on a server, with the saved `.docx` as the assertion — and a member this package does not
|
|
454
|
+
implement throws `NotSupportedError` naming it, rather than doing nothing.
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
import { WordprocessingMLPackage } from '@docx4j/core-ts';
|
|
458
|
+
import { Word } from '@docx4j/core-ts/office-js';
|
|
459
|
+
|
|
460
|
+
const pkg = await WordprocessingMLPackage.load(bytes);
|
|
461
|
+
await Word.run(pkg, async (context) => {
|
|
462
|
+
const paragraphs = context.document.body.paragraphs;
|
|
463
|
+
paragraphs.load('text');
|
|
464
|
+
await context.sync();
|
|
465
|
+
|
|
466
|
+
paragraphs.items[0].styleBuiltIn = Word.Style.heading1;
|
|
467
|
+
for (const range of context.document.body.search('draft')) range.font.highlightColor = '#FFFF00';
|
|
468
|
+
context.document.properties.lastAuthor = 'an add-in';
|
|
469
|
+
context.document.changeTrackingMode = Word.ChangeTrackingMode.trackAll;
|
|
470
|
+
|
|
471
|
+
const ooxml = context.document.body.getOoxml(); // a ClientResult, as in Office JS
|
|
472
|
+
await context.sync();
|
|
473
|
+
ooxml.value; // the flat OPC package
|
|
474
|
+
});
|
|
475
|
+
await writeFile('edited.docx', await pkg.save());
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
`Word.supported` is the set of `Class.member` strings this package implements
|
|
479
|
+
(`Word.supported.has('Body.insertParagraph')`), generated from the compile-time subset, so a
|
|
480
|
+
tool can check a script before running it. The selection an add-in edits is passed in:
|
|
481
|
+
`Word.run(pkg, fn, { selection })`.
|
|
482
|
+
|
|
483
|
+
`toApiScript` goes the other way: given a paragraph, a range or an element, it emits the
|
|
484
|
+
content-API calls that reproduce it, falling back to `insertXml` for what the verbs cannot say.
|
|
485
|
+
|
|
486
|
+
```ts
|
|
487
|
+
import { toApiScript } from '@docx4j/core-ts/model';
|
|
488
|
+
|
|
489
|
+
await toApiScript(body.paragraphs[1]);
|
|
490
|
+
// const p1 = body.insertParagraph('Chapter 1', 'End');
|
|
491
|
+
// p1.styleBuiltIn = 'Heading1';
|
|
492
|
+
// p1.alignment = 'Centered';
|
|
493
|
+
// const r1 = p1.insertText(' (draft)', 'End');
|
|
494
|
+
// r1.font.italic = true;
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
The bundling rules for an add-in, and a complete sideloadable example, are in
|
|
498
|
+
[docs/guides/office-addin.md](docs/guides/office-addin.md). A generated script reproduces the
|
|
499
|
+
document's *markup*, so it emits direct formatting only, not the effective values the reads
|
|
500
|
+
report (CR-001 Phase B step 2).
|
|
114
501
|
|
|
115
502
|
## Development
|
|
116
503
|
|
|
117
504
|
```
|
|
118
505
|
npm ci # the locked dependencies from npm
|
|
119
506
|
npm run typecheck && npm test # test = build, then node --test test/*.test.mjs
|
|
507
|
+
npm run typecheck:examples # examples/office-addin (also run by npm run typecheck)
|
|
508
|
+
npm run generate # src/office-js/supported.generated.mts from test/office-js-subset.ts
|
|
509
|
+
npm run generate:fonts # src/model/fonts/*.generated.mts from a docx4j checkout
|
|
120
510
|
```
|
|
121
511
|
|
|
512
|
+
`npm run generate` is committed output: the build does not depend on the script, but `npm test`
|
|
513
|
+
regenerates it so that `Word.supported` stays in step with the Office JS subset.
|
|
514
|
+
`npm run generate:fonts` is committed output too, re-run when docx4j's font tables change; it
|
|
515
|
+
reads a sibling `../docx4j` checkout and records the commit it ran against in each header.
|
|
516
|
+
|
|
517
|
+
The parity goldens under `test/golden/` are docx4j's own answers for 45 documents, produced by
|
|
518
|
+
the Java harness in [`test/java/`](test/java/README.md) and compared by `test/parity.test.mjs`.
|
|
519
|
+
They are regenerated by hand when docx4j or the fixtures change, and weekly by
|
|
520
|
+
`.github/workflows/parity.yml`, which opens a pull request when docx4j's answer moves.
|
|
521
|
+
|
|
122
522
|
Releases are published to npm from GitHub Actions; see `RELEASING.md`.
|
|
123
523
|
|
|
124
524
|
## Licence
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
|
+
import type { PropertyResolver } from '../properties/PropertyResolver.mjs';
|
|
2
3
|
import type { XmlPart } from '../../parts/XmlPart.mjs';
|
|
3
4
|
import type { OpcPackage } from '../../packages/OpcPackage.mjs';
|
|
4
|
-
import { type Element } from './tree.mjs';
|
|
5
|
+
import { type Element, type TextViewOptions } from './tree.mjs';
|
|
5
6
|
import { Paragraph } from './Paragraph.mjs';
|
|
6
7
|
import { Range } from './Range.mjs';
|
|
8
|
+
import { Table } from './Table.mjs';
|
|
9
|
+
import { ContentControl, type ContentControlType } from './ContentControl.mjs';
|
|
10
|
+
import { InlinePicture, type InlinePictureOptions } from './InlinePicture.mjs';
|
|
7
11
|
import type { SearchOptions } from './search.mjs';
|
|
12
|
+
import type { Comment } from './Comment.mjs';
|
|
13
|
+
import { type ChangeTracker } from './tracking.mjs';
|
|
14
|
+
import { type TrackedChange } from './TrackedChange.mjs';
|
|
15
|
+
import { type List, type ListLabel } from './List.mjs';
|
|
8
16
|
/** Where a paragraph or table is, for agents and across tool calls (CR-002 section 3.3). */
|
|
9
17
|
export type Address = string | {
|
|
10
18
|
contains: string;
|
|
@@ -55,17 +63,71 @@ export declare class Body {
|
|
|
55
63
|
},
|
|
56
64
|
/** The address prefix: 'body', 'header:rId3', 'footer:rId4', 'footnote:2'. */
|
|
57
65
|
prefix?: string, package_?: OpcPackage | undefined);
|
|
66
|
+
/**
|
|
67
|
+
* The package's `PropertyResolver`, which every effective-formatting read goes through
|
|
68
|
+
* (CR-001 Phase B step 2). Throws `PropertyResolverNotCreatedException` when this body has
|
|
69
|
+
* no package, or the package has not built one yet: building it unmarshals the styles part,
|
|
70
|
+
* which cannot be done synchronously, so `await pkg.getPropertyResolver()` (or `getBody()`,
|
|
71
|
+
* which does it) first - or read direct formatting with `{ direct: true }`.
|
|
72
|
+
*/
|
|
73
|
+
get propertyResolver(): PropertyResolver;
|
|
58
74
|
/** The live content array (docx4j getContent()); block-level elements only, sectPr excluded. */
|
|
59
75
|
get content(): Element[];
|
|
60
76
|
/** Every paragraph in document order, descending into tables and content controls. */
|
|
61
77
|
get paragraphs(): Paragraph[];
|
|
62
|
-
/** The tables directly in this body
|
|
63
|
-
get tables():
|
|
78
|
+
/** The tables directly in this body, as Office JS reports them (nested tables are a cell's). */
|
|
79
|
+
get tables(): Table[];
|
|
80
|
+
/** Every content control in this body, in document order, nested ones included. */
|
|
81
|
+
get contentControls(): ContentControl[];
|
|
82
|
+
/** Every inline picture in this body, in document order (Office JS Body.inlinePictures). */
|
|
83
|
+
get inlinePictures(): InlinePicture[];
|
|
84
|
+
/**
|
|
85
|
+
* Office JS `body.lists`: every `w:num` a paragraph of this body names, in the order they are
|
|
86
|
+
* first used (CR-002 phase H). Empty where the document has no numbering part, or where
|
|
87
|
+
* nothing has read it yet (`await pkg.getBody()` builds the resolver, which does).
|
|
88
|
+
*/
|
|
89
|
+
get lists(): List[];
|
|
90
|
+
/**
|
|
91
|
+
* Every numbered paragraph of this body's **story** with its label, level, list and sibling
|
|
92
|
+
* index, in one walk (extension). `listItem.listString` walks the story per read, which is
|
|
93
|
+
* what Word's counting needs; this is the way to ask for all of them at once.
|
|
94
|
+
*
|
|
95
|
+
* Keyed by the `w:p` itself: `labels.get(paragraph.p)?.listString`.
|
|
96
|
+
*/
|
|
97
|
+
listLabels(): Map<wml.P, ListLabel>;
|
|
98
|
+
/**
|
|
99
|
+
* A view over a container nested in this body (a cell, a content control), sharing this body's
|
|
100
|
+
* part and package. The address prefix is the container's own address, so that the addresses a
|
|
101
|
+
* nested body reports carry on from this one.
|
|
102
|
+
*/
|
|
103
|
+
sub(container: {
|
|
104
|
+
content?: Element[];
|
|
105
|
+
}, prefix?: string): Body;
|
|
106
|
+
/** The view of a `w:p` somewhere in this body's tree; its container comes from PARENT. */
|
|
107
|
+
paragraphFor(p: wml.P): Paragraph | undefined;
|
|
64
108
|
/** The text, a paragraph per line. */
|
|
65
109
|
get text(): string;
|
|
110
|
+
/**
|
|
111
|
+
* The text in one of the two views (extension; `text` is the accepted one).
|
|
112
|
+
* `{ view: 'original' }` reads the document as it was before the tracked changes.
|
|
113
|
+
*/
|
|
114
|
+
getText(options?: TextViewOptions): string;
|
|
115
|
+
/** The package's change tracker while `changeTrackingMode` is on; undefined when it is off (CR-002 phase F). */
|
|
116
|
+
get changeTracker(): ChangeTracker | undefined;
|
|
66
117
|
insertParagraph(text: string, location: 'Start' | 'End'): Paragraph;
|
|
67
118
|
/** Text at the start of the first paragraph, the end of the last, or replacing everything with one paragraph. */
|
|
68
119
|
insertText(text: string, location: 'Start' | 'End' | 'Replace'): Range;
|
|
120
|
+
/**
|
|
121
|
+
* A table of `rowCount` by `columnCount` cells at the start or end (Office JS insertTable);
|
|
122
|
+
* `values` fills it row by row. The columns are equal over the section's text width.
|
|
123
|
+
*/
|
|
124
|
+
insertTable(rowCount: number, columnCount: number, location: 'Start' | 'End', values?: string[][]): Table;
|
|
125
|
+
/**
|
|
126
|
+
* Adds the image as a part of this body's part, with a relationship, and shows it in a new
|
|
127
|
+
* paragraph at the start or the end (Office JS insertInlinePictureFromBase64). An image wider
|
|
128
|
+
* than the text area is scaled down, as docx4j's CxCy.scale does.
|
|
129
|
+
*/
|
|
130
|
+
insertInlinePictureFromBase64(base64: string, location: 'Start' | 'End', options?: InlinePictureOptions): InlinePicture;
|
|
69
131
|
insertBreak(type: 'Page' | 'Line', location: 'Start' | 'End'): void;
|
|
70
132
|
/**
|
|
71
133
|
* Inserts block-level elements (docx4j addObject): at the start or end of this body, or
|
|
@@ -75,10 +137,41 @@ export declare class Body {
|
|
|
75
137
|
insertElement(element: Element | Element[], location: 'Start' | 'End' | 'Before' | 'After', target?: Paragraph | BlockElement | Address): Paragraph | BlockElement;
|
|
76
138
|
/** Inserts a WML fragment (one or more w:p / w:tbl / ... as inside document.xml); the standard prefixes are declared for it. */
|
|
77
139
|
insertXml(xml: string, location: 'Start' | 'End' | 'Before' | 'After', target?: Paragraph | BlockElement | Address): Promise<(Paragraph | BlockElement)[]>;
|
|
140
|
+
/**
|
|
141
|
+
* Word's `insertOoxml`: a flat OPC `pkg:package` string, whose body content is inserted with
|
|
142
|
+
* the parts it references (images, embedded objects) copied into this package under fresh
|
|
143
|
+
* names and relationship ids; styles and numbering are not merged (CR-002 open question 5).
|
|
144
|
+
* A bare `w:p` / `w:tbl` fragment is accepted too, as `insertXml` takes. Returns the views of
|
|
145
|
+
* what was inserted, as `insertXml` does, since a package may bring several blocks.
|
|
146
|
+
*/
|
|
147
|
+
insertOoxml(ooxml: string, location: 'Start' | 'End' | 'Replace' | 'Before' | 'After', target?: Paragraph | BlockElement | Address): Promise<(Paragraph | BlockElement)[]>;
|
|
148
|
+
/** The package's DOM preprocessor (the MCE one), for fragments and incoming packages. */
|
|
149
|
+
private preprocessor;
|
|
150
|
+
private insertContent;
|
|
78
151
|
/** Matches over every paragraph, in document order. */
|
|
79
152
|
search(text: string, options?: SearchOptions): Range[];
|
|
80
|
-
/**
|
|
153
|
+
/**
|
|
154
|
+
* Replaces every match of `find` with `replace`, last match first so that the offsets of the
|
|
155
|
+
* ones still to do stay valid (CR-002 section 3.7). Returns the number replaced; tracked when
|
|
156
|
+
* the package's `changeTrackingMode` is on.
|
|
157
|
+
*/
|
|
158
|
+
replaceText(find: string, replace: string, options?: SearchOptions): number;
|
|
159
|
+
/**
|
|
160
|
+
* Removes everything (section properties stay). While the package tracks changes, every
|
|
161
|
+
* paragraph is marked deleted and every row's `w:trPr` takes a `w:del` instead.
|
|
162
|
+
*/
|
|
81
163
|
clear(): void;
|
|
164
|
+
/** Every tracked change in this body, in document order. */
|
|
165
|
+
getTrackedChanges(): TrackedChange[];
|
|
166
|
+
/**
|
|
167
|
+
* Accepts every tracked change, last first so that a paragraph join never disturbs one still
|
|
168
|
+
* to do (docx4j `AcceptTrackedChanges` is the reference). Returns how many were accepted.
|
|
169
|
+
*/
|
|
170
|
+
acceptAll(): number;
|
|
171
|
+
/** Rejects every tracked change, last first. Returns how many were rejected. */
|
|
172
|
+
rejectAll(): number;
|
|
173
|
+
/** Every `w:tr` in this body's tables, in document order (rows of nested tables included). */
|
|
174
|
+
private rowElements;
|
|
82
175
|
/** The part's XML (extension; Office JS getOoxml wraps it in a package). */
|
|
83
176
|
getXml(): Promise<string>;
|
|
84
177
|
/** The element at an address: 'body/3' (fourth block), 'body/3/1/0/2' (table row 1, cell 0, block 2), a paraId, or a text match. */
|
|
@@ -104,4 +197,16 @@ export declare class Body {
|
|
|
104
197
|
/** Gives a new paragraph a w14:paraId when the document already uses them. */
|
|
105
198
|
private assignParaId;
|
|
106
199
|
private usesParaIds;
|
|
200
|
+
/**
|
|
201
|
+
* The comments anchored in this body, in document order, with replies nested under their
|
|
202
|
+
* parent (only top-level comments are in the array). Asynchronous because it unmarshals the
|
|
203
|
+
* comment parts.
|
|
204
|
+
*/
|
|
205
|
+
getComments(): Promise<Comment[]>;
|
|
206
|
+
/**
|
|
207
|
+
* Wraps everything this body holds in a new content control (Office JS
|
|
208
|
+
* `Body.insertContentControl`), typed for the kind when one is given; the `w:id` is free in this
|
|
209
|
+
* body. Returns the control.
|
|
210
|
+
*/
|
|
211
|
+
insertContentControl(kind?: ContentControlType): ContentControl;
|
|
107
212
|
}
|