@docx4j/core-ts 0.5.0 → 0.7.0
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/NOTICE +4 -0
- package/README.md +92 -4
- package/dist/html/convert.mjs +2 -1
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +145 -23
- package/dist/model/content/Body.mjs +507 -150
- package/dist/model/content/Comment.d.mts +23 -5
- package/dist/model/content/Comment.mjs +207 -26
- package/dist/model/content/ContentControl.d.mts +198 -19
- package/dist/model/content/ContentControl.mjs +672 -99
- package/dist/model/content/Font.d.mts +70 -17
- package/dist/model/content/Font.mjs +119 -36
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +18 -8
- package/dist/model/content/Paragraph.d.mts +200 -14
- package/dist/model/content/Paragraph.mjs +898 -82
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +135 -49
- package/dist/model/content/TrackedChange.d.mts +174 -15
- package/dist/model/content/TrackedChange.mjs +734 -170
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +10 -3
- package/dist/model/content/index.mjs +10 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/ooxml.mjs +12 -1
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +74 -0
- package/dist/model/content/search.mjs +255 -9
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +47 -0
- package/dist/model/content/story.mjs +95 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +102 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +63 -6
- package/dist/model/content/tracking.mjs +242 -22
- package/dist/model/content/tree.d.mts +172 -24
- package/dist/model/content/tree.mjs +328 -54
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
- package/dist/model/customxml/XmlMapping.d.mts +32 -8
- package/dist/model/customxml/XmlMapping.mjs +64 -10
- package/dist/model/customxml/bindings.d.mts +33 -4
- package/dist/model/customxml/bindings.mjs +171 -45
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +22 -8
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +23 -22
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +3 -0
- package/dist/model/index.mjs +5 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +74 -2
- package/dist/model/properties/PropertyResolver.mjs +133 -5
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +349 -0
- package/dist/model/text/Extractor.mjs +2406 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +542 -0
- package/dist/model/text/TextContext.d.mts +256 -0
- package/dist/model/text/TextContext.mjs +600 -0
- package/dist/model/text/TextOptions.d.mts +233 -0
- package/dist/model/text/TextOptions.mjs +419 -0
- package/dist/model/text/TextResult.d.mts +621 -0
- package/dist/model/text/TextResult.mjs +629 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +936 -0
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +8 -0
- package/dist/model/text/index.mjs +9 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +29 -12
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +32 -0
- package/dist/opc/Save.mjs +110 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +8 -5
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +141 -5
- package/dist/opc/mce/preprocessor.mjs +119 -18
- package/dist/opc/mce/understood.d.mts +3 -11
- package/dist/opc/mce/understood.mjs +27 -23
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +110 -4
- package/dist/packages/OpcPackage.mjs +123 -7
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +158 -21
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +14 -2
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +63 -32
- package/dist/parts/XmlPart.mjs +240 -96
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +37 -1
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Outline } from '../content/Body.mjs';
|
|
2
|
+
import type { TextBlock } from './TextResult.mjs';
|
|
3
|
+
/** The outline of blocks: each paragraph with its address, paraId, style and text, each table with its size; a cell's blocks after its table. */
|
|
4
|
+
export declare function outlineOfBlocks(blocks: readonly TextBlock[]): Outline;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// CR-012 D3: Body.outline() and pkg.outline() read the text model. The paragraph text is the model's (hidden
|
|
2
|
+
// text left out, a deleted mark joined, the view's), each text box's paragraphs follow their anchor at
|
|
3
|
+
// `textbox:` addresses, flagged, and the options are the model's; the shape is the outline's own.
|
|
4
|
+
import { setOutlineReader } from '../content/outline.mjs';
|
|
5
|
+
import { Extractor } from './Extractor.mjs';
|
|
6
|
+
import { PackageTrees, TextContext } from './TextContext.mjs';
|
|
7
|
+
import { contextFor, optionsOf, isPackage } from './Texts.mjs';
|
|
8
|
+
/** The story a body's blocks are in, from its address prefix. */
|
|
9
|
+
function storyOf(prefix) {
|
|
10
|
+
const kind = prefix.split(':')[0];
|
|
11
|
+
switch (kind) {
|
|
12
|
+
case 'header': return 'HEADER';
|
|
13
|
+
case 'footer': return 'FOOTER';
|
|
14
|
+
case 'footnote': return 'FOOTNOTE';
|
|
15
|
+
case 'endnote': return 'ENDNOTE';
|
|
16
|
+
case 'comment': return 'COMMENT';
|
|
17
|
+
default: return 'MAIN';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** The outline of blocks: each paragraph with its address, paraId, style and text, each table with its size; a cell's blocks after its table. */
|
|
21
|
+
export function outlineOfBlocks(blocks) {
|
|
22
|
+
const paragraphs = [];
|
|
23
|
+
const tables = [];
|
|
24
|
+
const visit = (list) => {
|
|
25
|
+
var _a, _b, _c;
|
|
26
|
+
for (const block of list) {
|
|
27
|
+
if (block.kind === 'PARAGRAPH') {
|
|
28
|
+
const entry = { address: block.address, style: (_a = block.style) !== null && _a !== void 0 ? _a : 'Normal', text: block.text };
|
|
29
|
+
if (block.paraId)
|
|
30
|
+
entry.paraId = block.paraId;
|
|
31
|
+
if (block.textbox)
|
|
32
|
+
entry.textbox = true;
|
|
33
|
+
if (block.joined.length > 0)
|
|
34
|
+
entry.joined = [...block.joined];
|
|
35
|
+
paragraphs.push(entry);
|
|
36
|
+
}
|
|
37
|
+
else if (block.kind === 'TABLE') {
|
|
38
|
+
tables.push({ address: block.address, rows: block.rows.length, cols: (_c = (_b = block.rows[0]) === null || _b === void 0 ? void 0 : _b.cells.length) !== null && _c !== void 0 ? _c : 0 });
|
|
39
|
+
for (const row of block.rows)
|
|
40
|
+
for (const cell of row.cells)
|
|
41
|
+
visit(cell.blocks);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
visit(blocks);
|
|
46
|
+
return { paragraphs, tables };
|
|
47
|
+
}
|
|
48
|
+
setOutlineReader(async (body, options, context, blocks) => {
|
|
49
|
+
const o = optionsOf(options);
|
|
50
|
+
const pkg = body.package_;
|
|
51
|
+
const kind = storyOf(body.prefix);
|
|
52
|
+
if (!isPackage(pkg)) {
|
|
53
|
+
// content with no package: read as it stands, as Texts.of(content) does
|
|
54
|
+
const none = PackageTrees.none();
|
|
55
|
+
const x = new Extractor(none, o, 'planless', new TextContext(none));
|
|
56
|
+
if (blocks === undefined)
|
|
57
|
+
return outlineOfBlocks(x.extractContent(body.container, kind, body.prefix, undefined).blocks);
|
|
58
|
+
const starts = Extractor.fieldsAtBlocks(none, o, 'planless', new TextContext(none), body.container, kind, body.prefix, undefined);
|
|
59
|
+
return outlineOfBlocks(x.extractBlocks(body.container, kind, body.prefix, undefined, blocks, starts).blocks);
|
|
60
|
+
}
|
|
61
|
+
const ctx = await contextFor(pkg, context, o);
|
|
62
|
+
const part = body.part;
|
|
63
|
+
if (blocks === undefined)
|
|
64
|
+
return outlineOfBlocks(new Extractor(ctx.trees, o, 'view', ctx).extractContent(body.container, kind, body.prefix, part).blocks);
|
|
65
|
+
// some blocks (section 17.13): the plan made in the context itself, so that the siblings share it, and the
|
|
66
|
+
// reading under a sibling, so that it numbers no note and counts no list in the caller's context
|
|
67
|
+
if (o.view !== 'markup')
|
|
68
|
+
ctx.plan(o.view === 'accepted');
|
|
69
|
+
const starts = ctx.blockStarts(body.container, JSON.stringify(o.toMap()), () => Extractor.fieldsAtBlocks(ctx.trees, o, 'view', ctx, body.container, kind, body.prefix, part));
|
|
70
|
+
return outlineOfBlocks(new Extractor(ctx.trees, o, 'view', ctx.sibling()).extractBlocks(body.container, kind, body.prefix, part, blocks, starts).blocks);
|
|
71
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type WordIntegerReading, type WordIntegerStorage } from '@docx4j/generated-objects-ts/helpers/wml';
|
|
2
|
+
/** `[min, max]` in the attribute's own unit: every value in it Word reads as written, and none outside. */
|
|
3
|
+
export type KeptRange = readonly [number, number];
|
|
4
|
+
/** The certain range of an attribute the table has but no round measured: outside it every measured attribute of its type changes. */
|
|
5
|
+
export declare const UNMEASURED_RANGE: KeptRange;
|
|
6
|
+
/** Whether a reading is of an attribute no round measured (`storage` says so), as against one Word reads to no number. */
|
|
7
|
+
export declare const isUnmeasured: (reading: WordIntegerReading) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The range Word 365 keeps as written in an attribute of the table (CR-017 E1's `range`; CR-002 section 65.3's bounds):
|
|
10
|
+
* - a signed field `-2^(bits-1)` to `2^(bits-1) - 1`, an unsigned one `0` to `2^bits - 1`;
|
|
11
|
+
* - `w:ind`'s `firstLine` and `hanging`, one signed field, `0` to `32767` and `0` to `32768`;
|
|
12
|
+
* - a line or a row height whose sign is the rule: under `exact` `1` to `32768`, under `atLeast` `0` to `32767`, a line
|
|
13
|
+
* under `auto` the plain signed field; a row height under `hRule="auto"` is ignored, so null;
|
|
14
|
+
* - a frame's height `0` to `32767` (15 bits);
|
|
15
|
+
* - then the clamps (a tab stop, the page size), and a column's width or space, whose negative Word replaces (a
|
|
16
|
+
* computed width; -1, which it also keeps as written, its own sentinel).
|
|
17
|
+
* The rule is the `lineRule` or `hRule` beside the attribute, where it has one. Undefined for an attribute not in the
|
|
18
|
+
* table. 65535 in an attribute Word's save writes as -1 (`w:spacing`'s `before` and `after`, the unsigned page margins)
|
|
19
|
+
* is in the range, and Word reads a -1 there as 65535 too, its own spelling.
|
|
20
|
+
*/
|
|
21
|
+
export declare function keptRange(typeName: string, property: string, rule?: string): KeptRange | null | undefined;
|
|
22
|
+
/** `keptRange` from the table's entry; `property` for the shared field, `rule` for a line or a height. */
|
|
23
|
+
export declare function rangeOf(entry: WordIntegerStorage, property: string, rule?: string): KeptRange | null;
|
|
24
|
+
/**
|
|
25
|
+
* Word's reading, for a message: the value, in the shared field's other attribute where the sign moved it (`25536 in
|
|
26
|
+
* w:hanging`), with the rule where the sign carries one (`atLeast 1`, `exact 32768`); `not known` for an unmeasured
|
|
27
|
+
* attribute.
|
|
28
|
+
*/
|
|
29
|
+
export declare function describeReading(reading: WordIntegerReading, attribute: string): string;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// CR-017: what Word 365 keeps of an integer attribute, from the objects package's table (its CR-016, docx4j CR-066's
|
|
2
|
+
// rounds 5 and 6, run by Jason 2026-10-26). Word stores each attribute in a field of its binary format's width, 16 bits
|
|
3
|
+
// for most, and reads a value past it wrapped, sometimes then clamped, with no error or repair. The table gives the
|
|
4
|
+
// width, the sign and the rules per attribute; this module turns an entry into the range of values Word keeps as
|
|
5
|
+
// written, which the setters' guards (CR-002 section 65.3, `wordRange.mts`) and the out-of-range warnings (CR-017 P2
|
|
6
|
+
// and P3, `XmlPart.valueOutOfRange`) both read, so there is one source for both. A report names its entry (`typeName`,
|
|
7
|
+
// `property`, `storage` and the `rule` beside the value, objects 0.7.0), so `rangeOf` takes it straight.
|
|
8
|
+
import { WORD_INTEGER_STORAGE } from '@docx4j/generated-objects-ts/helpers/wml';
|
|
9
|
+
/** The certain range of an attribute the table has but no round measured: outside it every measured attribute of its type changes. */
|
|
10
|
+
export const UNMEASURED_RANGE = [-32768, 65535];
|
|
11
|
+
/** Whether a reading is of an attribute no round measured (`storage` says so), as against one Word reads to no number. */
|
|
12
|
+
export const isUnmeasured = (reading) => reading.storage.startsWith('unmeasured');
|
|
13
|
+
/**
|
|
14
|
+
* The range Word 365 keeps as written in an attribute of the table (CR-017 E1's `range`; CR-002 section 65.3's bounds):
|
|
15
|
+
* - a signed field `-2^(bits-1)` to `2^(bits-1) - 1`, an unsigned one `0` to `2^bits - 1`;
|
|
16
|
+
* - `w:ind`'s `firstLine` and `hanging`, one signed field, `0` to `32767` and `0` to `32768`;
|
|
17
|
+
* - a line or a row height whose sign is the rule: under `exact` `1` to `32768`, under `atLeast` `0` to `32767`, a line
|
|
18
|
+
* under `auto` the plain signed field; a row height under `hRule="auto"` is ignored, so null;
|
|
19
|
+
* - a frame's height `0` to `32767` (15 bits);
|
|
20
|
+
* - then the clamps (a tab stop, the page size), and a column's width or space, whose negative Word replaces (a
|
|
21
|
+
* computed width; -1, which it also keeps as written, its own sentinel).
|
|
22
|
+
* The rule is the `lineRule` or `hRule` beside the attribute, where it has one. Undefined for an attribute not in the
|
|
23
|
+
* table. 65535 in an attribute Word's save writes as -1 (`w:spacing`'s `before` and `after`, the unsigned page margins)
|
|
24
|
+
* is in the range, and Word reads a -1 there as 65535 too, its own spelling.
|
|
25
|
+
*/
|
|
26
|
+
export function keptRange(typeName, property, rule) {
|
|
27
|
+
var _a;
|
|
28
|
+
const entry = (_a = WORD_INTEGER_STORAGE[typeName]) === null || _a === void 0 ? void 0 : _a[property];
|
|
29
|
+
return entry === undefined ? undefined : rangeOf(entry, property, rule);
|
|
30
|
+
}
|
|
31
|
+
/** `keptRange` from the table's entry; `property` for the shared field, `rule` for a line or a height. */
|
|
32
|
+
export function rangeOf(entry, property, rule) {
|
|
33
|
+
if (!entry.measured)
|
|
34
|
+
return UNMEASURED_RANGE;
|
|
35
|
+
const half = 2 ** (entry.bits - 1);
|
|
36
|
+
let min;
|
|
37
|
+
let max;
|
|
38
|
+
if (entry.heightFlag)
|
|
39
|
+
[min, max] = [0, half - 1];
|
|
40
|
+
else if (entry.pair)
|
|
41
|
+
[min, max] = property === entry.pair.negative ? [0, half] : [0, half - 1];
|
|
42
|
+
else if (entry.signRule) {
|
|
43
|
+
const read = rule !== null && rule !== void 0 ? rule : (entry.signRule === 'hRule' ? 'atLeast' : 'auto');
|
|
44
|
+
if (entry.signRule === 'hRule' && read === 'auto')
|
|
45
|
+
return null;
|
|
46
|
+
if (read === 'exact')
|
|
47
|
+
[min, max] = [1, half];
|
|
48
|
+
else if (read === 'atLeast')
|
|
49
|
+
[min, max] = [0, half - 1];
|
|
50
|
+
else
|
|
51
|
+
[min, max] = [-half, half - 1];
|
|
52
|
+
}
|
|
53
|
+
else if (entry.signed)
|
|
54
|
+
[min, max] = [-half, half - 1];
|
|
55
|
+
else
|
|
56
|
+
[min, max] = [0, 2 ** entry.bits - 1];
|
|
57
|
+
if (entry.negative !== undefined)
|
|
58
|
+
min = Math.max(min, 0);
|
|
59
|
+
if (entry.min !== undefined)
|
|
60
|
+
min = Math.max(min, entry.min);
|
|
61
|
+
if (entry.max !== undefined)
|
|
62
|
+
max = Math.min(max, entry.max);
|
|
63
|
+
return [min, max];
|
|
64
|
+
}
|
|
65
|
+
/** Whether a reading's storage string names a rule beside the value (a line's `lineRule`, a height's `hRule`). */
|
|
66
|
+
const dependsOnRule = (storage) => /\brule\b|clearing exact/.test(storage);
|
|
67
|
+
/**
|
|
68
|
+
* Word's reading, for a message: the value, in the shared field's other attribute where the sign moved it (`25536 in
|
|
69
|
+
* w:hanging`), with the rule where the sign carries one (`atLeast 1`, `exact 32768`); `not known` for an unmeasured
|
|
70
|
+
* attribute.
|
|
71
|
+
*/
|
|
72
|
+
export function describeReading(reading, attribute) {
|
|
73
|
+
if (reading.value === null)
|
|
74
|
+
return reading.storage.includes('computed') ? 'a width Word computes' : 'not known';
|
|
75
|
+
const where = reading.attribute !== undefined && reading.attribute !== attribute ? ` in w:${reading.attribute}` : '';
|
|
76
|
+
const rule = reading.rule !== undefined && dependsOnRule(reading.storage) ? `${reading.rule} ` : '';
|
|
77
|
+
return `${rule}${reading.value}${where}`;
|
|
78
|
+
}
|
|
@@ -15,10 +15,24 @@ function literal(text) {
|
|
|
15
15
|
function w3cdtf(date) {
|
|
16
16
|
return { TYPE_NAME: 'org_docx4j_docProps_core_dc_terms.W3CDTF', content: [date.toISOString().replace(/\.\d{3}Z$/, 'Z')] };
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A `dcterms:created` or `dcterms:modified` value as Word 365 reads it (docx4j CR-067 section 12.2, Jason's probe of
|
|
20
|
+
* 2026-10-28; CR-018 D6): a date alone (`2024-02-03`) and a time with no offset (`2025-06-07T08:09:10`) are UTC, as a `Z`
|
|
21
|
+
* value is (Word showed 11:00 and 18:09 at UTC+11 and UTC+10), so they are read here as UTC fields, where ECMAScript's
|
|
22
|
+
* `Date` would read the offset-free time as local. A `Z` or an offset is honoured as before. The seconds are kept: Word
|
|
23
|
+
* shows the value to the minute, but this reads the stored instant.
|
|
24
|
+
*/
|
|
18
25
|
function dateOf(value) {
|
|
19
|
-
const text = literalText(value);
|
|
26
|
+
const text = literalText(value).trim();
|
|
20
27
|
if (text === '')
|
|
21
28
|
return undefined;
|
|
29
|
+
const bare = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?)?$/.exec(text);
|
|
30
|
+
if (bare) {
|
|
31
|
+
const [year, month, day, hour, minute, second, fraction] = bare.slice(1);
|
|
32
|
+
const ms = fraction === undefined ? 0 : Math.round(Number(`0.${fraction}`) * 1000);
|
|
33
|
+
const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hour !== null && hour !== void 0 ? hour : 0), Number(minute !== null && minute !== void 0 ? minute : 0), Number(second !== null && second !== void 0 ? second : 0), ms));
|
|
34
|
+
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
35
|
+
}
|
|
22
36
|
const date = new Date(text);
|
|
23
37
|
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
24
38
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
1
|
import type { Range } from '../model/content/Range.mjs';
|
|
3
2
|
import type { Element } from '../model/content/tree.mjs';
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
6
|
-
* paragraph
|
|
4
|
+
* The blocks a range holds, as detached copies: within one paragraph, that paragraph trimmed to the range; across
|
|
5
|
+
* paragraphs, the first paragraph from the range's start, every block between whole (a table, a content control),
|
|
6
|
+
* and the last paragraph to the range's end, left out where the range ends at its start. The blocks are those
|
|
7
|
+
* `delete()` takes (`extentOf`), so a range starting or ending inside a table or a content control it doesn't hold
|
|
8
|
+
* whole is refused: a fragment of part of one isn't written.
|
|
7
9
|
*/
|
|
8
|
-
export declare function
|
|
9
|
-
/** The range as a
|
|
10
|
+
export declare function blocksOfRange(range: Range): Element[];
|
|
11
|
+
/** The range as a fragment: its blocks' XML, one after another (extension; Office JS wraps a range in a pkg:package). */
|
|
10
12
|
export declare function xmlOfRange(range: Range): Promise<string>;
|
|
@@ -1,23 +1,72 @@
|
|
|
1
1
|
// Marshalling a view back to a fragment: what `getOoxml()` and `toApiScript`'s fallback need.
|
|
2
|
-
//
|
|
3
|
-
// element of its own: it is a span of
|
|
2
|
+
// Copies of the blocks a range holds, its paragraphs trimmed to it, are the one piece the views do
|
|
3
|
+
// not offer (Range has no element of its own: it is a span of its paragraphs' text).
|
|
4
4
|
import { deepCopy, marshalString } from '@docx4j/generated-objects-ts';
|
|
5
|
+
import { Body } from '../model/content/Body.mjs';
|
|
5
6
|
import { Paragraph } from '../model/content/Paragraph.mjs';
|
|
7
|
+
import { extentOf } from '../model/content/spanEdits.mjs';
|
|
8
|
+
import { GeneralException } from '../model/content/generalException.mjs';
|
|
9
|
+
import { NotSupportedError } from './errors.mjs';
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
11
|
+
* The body a detached copy is trimmed through. It reads as the paragraph's own body does (its package's styles
|
|
12
|
+
* decide which runs are hidden, and so the offsets), and writes untracked: trimming a copy is no edit of the
|
|
13
|
+
* document, and under tracking the trim would otherwise mark the rest of the copy deleted. What the trim queues on
|
|
14
|
+
* the package (a picture's relationship, a comment whose reference the copy lost) is settled at save against the
|
|
15
|
+
* document as it stands, which still holds them.
|
|
9
16
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
class CopyBody extends Body {
|
|
18
|
+
get changeTracker() {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** A detached copy of `paragraph` holding only its text from `start` to `end`, with the runs and their formatting. */
|
|
23
|
+
function trimmed(paragraph, start, end) {
|
|
24
|
+
const copy = deepCopy(paragraph.element);
|
|
25
|
+
const own = paragraph.parentBody;
|
|
26
|
+
const view = new Paragraph(copy, [copy], new CopyBody(own.part, { content: [copy] }, own.prefix, own.package_));
|
|
13
27
|
const length = view.text.length;
|
|
14
|
-
if (
|
|
15
|
-
view.splice(
|
|
16
|
-
if (
|
|
17
|
-
view.splice(0,
|
|
28
|
+
if (end < length)
|
|
29
|
+
view.splice(end, length, '');
|
|
30
|
+
if (start > 0)
|
|
31
|
+
view.splice(0, start, '');
|
|
18
32
|
return copy;
|
|
19
33
|
}
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The blocks a range holds, as detached copies: within one paragraph, that paragraph trimmed to the range; across
|
|
36
|
+
* paragraphs, the first paragraph from the range's start, every block between whole (a table, a content control),
|
|
37
|
+
* and the last paragraph to the range's end, left out where the range ends at its start. The blocks are those
|
|
38
|
+
* `delete()` takes (`extentOf`), so a range starting or ending inside a table or a content control it doesn't hold
|
|
39
|
+
* whole is refused: a fragment of part of one isn't written.
|
|
40
|
+
*/
|
|
41
|
+
export function blocksOfRange(range) {
|
|
42
|
+
if (!range.spansParagraphs)
|
|
43
|
+
return [trimmed(range.paragraph, range.start, range.end)];
|
|
44
|
+
let extent;
|
|
45
|
+
try {
|
|
46
|
+
extent = extentOf(range, 'getOoxml');
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (!(error instanceof GeneralException) && !(error instanceof NotSupportedError))
|
|
50
|
+
throw error;
|
|
51
|
+
throw new NotSupportedError('Range', 'getOoxml', "this range starts or ends inside a table or a content control it doesn't hold whole, "
|
|
52
|
+
+ "and a fragment of part of one isn't written; take the whole table or control, or a range inside one cell");
|
|
53
|
+
}
|
|
54
|
+
const out = [];
|
|
55
|
+
for (let k = extent.first; k <= extent.last; k++) {
|
|
56
|
+
const block = extent.list[k];
|
|
57
|
+
if (k === extent.first && extent.head)
|
|
58
|
+
out.push(trimmed(extent.head, range.start, extent.head.text.length));
|
|
59
|
+
else if (k === extent.last && extent.tail) {
|
|
60
|
+
if (range.end > 0)
|
|
61
|
+
out.push(trimmed(extent.tail, 0, range.end));
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
out.push(deepCopy(block));
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/** The range as a fragment: its blocks' XML, one after another (extension; Office JS wraps a range in a pkg:package). */
|
|
69
|
+
export async function xmlOfRange(range) {
|
|
70
|
+
const xml = await Promise.all(blocksOfRange(range).map((block) => marshalString(block)));
|
|
71
|
+
return xml.join('');
|
|
23
72
|
}
|
|
@@ -23,6 +23,14 @@ export declare class ClientResult<T = unknown> {
|
|
|
23
23
|
resolveWith(value: T): void;
|
|
24
24
|
/** True once `context.sync()` has filled it. */
|
|
25
25
|
get isLoaded(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Office JS's `load` on what an asynchronous member returned: nothing to load here, so the result itself.
|
|
28
|
+
* With `items`, a collection a member returns asynchronously (`range.getComments()`, the comment parts
|
|
29
|
+
* being read first) reads as Office JS code expects: `load`, `context.sync()`, then `items` (CR-014 phase 1).
|
|
30
|
+
*/
|
|
31
|
+
load(): this;
|
|
32
|
+
/** The collection's items, once `context.sync()` has filled the result: an asynchronous collection's. */
|
|
33
|
+
get items(): T extends readonly (infer I)[] ? I[] : never;
|
|
26
34
|
toJSON(): {
|
|
27
35
|
value: T | undefined;
|
|
28
36
|
};
|
package/dist/office-js/proxy.mjs
CHANGED
|
@@ -47,6 +47,21 @@ export class ClientResult {
|
|
|
47
47
|
get isLoaded() {
|
|
48
48
|
return this.loaded;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Office JS's `load` on what an asynchronous member returned: nothing to load here, so the result itself.
|
|
52
|
+
* With `items`, a collection a member returns asynchronously (`range.getComments()`, the comment parts
|
|
53
|
+
* being read first) reads as Office JS code expects: `load`, `context.sync()`, then `items` (CR-014 phase 1).
|
|
54
|
+
*/
|
|
55
|
+
load() {
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/** The collection's items, once `context.sync()` has filled the result: an asynchronous collection's. */
|
|
59
|
+
get items() {
|
|
60
|
+
const value = this.value;
|
|
61
|
+
if (!Array.isArray(value))
|
|
62
|
+
throw new NotSupportedError('ClientResult', 'items', `the result of ${this.member}() is not a collection`);
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
50
65
|
toJSON() {
|
|
51
66
|
return { value: this.loaded ? this.result : undefined };
|
|
52
67
|
}
|
|
@@ -219,6 +234,9 @@ export class Wrapper {
|
|
|
219
234
|
return wrapped;
|
|
220
235
|
});
|
|
221
236
|
result.attach(settled);
|
|
237
|
+
// the next sync() reports a failure; code that throws before it (a member of the result called at once, as
|
|
238
|
+
// Office JS code chains `insertComment(...).getRange()`) leaves it unawaited, which must not end the process
|
|
239
|
+
settled.catch(() => { });
|
|
222
240
|
this.context.enqueue(settled);
|
|
223
241
|
return result;
|
|
224
242
|
}
|
|
@@ -253,6 +271,12 @@ export class Wrapper {
|
|
|
253
271
|
result.resolveWith(wrapped.length);
|
|
254
272
|
return result;
|
|
255
273
|
});
|
|
274
|
+
if (itemClass === 'ContentControl') {
|
|
275
|
+
// Office JS's ContentControlCollection lookups: the controls with the tag or title, as a collection
|
|
276
|
+
const matching = (key, value) => this.collection(items.filter((i) => unwrap(i)[key] === value), 'contentControls');
|
|
277
|
+
define('getByTag', (tag) => matching('tag', tag));
|
|
278
|
+
define('getByTitle', (title) => matching('title', title));
|
|
279
|
+
}
|
|
256
280
|
define('load', () => collectionProxy);
|
|
257
281
|
define('track', () => collectionProxy);
|
|
258
282
|
define('untrack', () => collectionProxy);
|
|
@@ -268,6 +292,11 @@ export class Wrapper {
|
|
|
268
292
|
if (!(prop in obj))
|
|
269
293
|
throw new NotSupportedError(className, prop);
|
|
270
294
|
const member2 = Reflect.get(obj, prop, obj);
|
|
295
|
+
// the array's own methods (map, filter, forEach) give what they give: an Office JS collection has
|
|
296
|
+
// none, and a map's empty result made into a collection wouldn't serialize (CR-014 phase 1)
|
|
297
|
+
if (typeof member2 === 'function' && Object.prototype.hasOwnProperty.call(Array.prototype, prop)) {
|
|
298
|
+
return member2.bind(obj);
|
|
299
|
+
}
|
|
271
300
|
if (typeof member2 === 'function' && !/^\d+$/.test(prop)) {
|
|
272
301
|
return (...args) => wrapperSelf.result(member2.apply(obj, args.map(unwrap)), prop);
|
|
273
302
|
}
|
package/dist/office-js/run.mjs
CHANGED
|
@@ -43,6 +43,8 @@ export class RequestContext {
|
|
|
43
43
|
async function prepare(pkg, options) {
|
|
44
44
|
const main = pkg.getMainDocumentPart();
|
|
45
45
|
await main.getContents();
|
|
46
|
+
// a control's placeholderText reads the glossary's entries, read privately (CR-002 section 63)
|
|
47
|
+
await pkg.glossaryEntries.load(main.glossaryDocumentPart);
|
|
46
48
|
if (options.unmarshalSideParts === false)
|
|
47
49
|
return;
|
|
48
50
|
const sideParts = [pkg.docPropsCorePart, pkg.docPropsExtendedPart, main.documentSettingsPart];
|
|
@@ -5,6 +5,8 @@ export const SUBSET_MEMBERS = [
|
|
|
5
5
|
'Body.clear',
|
|
6
6
|
'Body.contentControls',
|
|
7
7
|
'Body.getComments',
|
|
8
|
+
'Body.getContentControls',
|
|
9
|
+
'Body.getRange',
|
|
8
10
|
'Body.getTrackedChanges',
|
|
9
11
|
'Body.inlinePictures',
|
|
10
12
|
'Body.insertBreak',
|
|
@@ -23,6 +25,7 @@ export const SUBSET_MEMBERS = [
|
|
|
23
25
|
'Comment.content',
|
|
24
26
|
'Comment.creationDate',
|
|
25
27
|
'Comment.delete',
|
|
28
|
+
'Comment.getRange',
|
|
26
29
|
'Comment.replies',
|
|
27
30
|
'Comment.reply',
|
|
28
31
|
'Comment.resolved',
|
|
@@ -36,6 +39,7 @@ export const SUBSET_MEMBERS = [
|
|
|
36
39
|
'ContentControl.datePickerContentControl',
|
|
37
40
|
'ContentControl.delete',
|
|
38
41
|
'ContentControl.dropDownListContentControl',
|
|
42
|
+
'ContentControl.getContentControls',
|
|
39
43
|
'ContentControl.getRange',
|
|
40
44
|
'ContentControl.groupContentControl',
|
|
41
45
|
'ContentControl.id',
|
|
@@ -47,6 +51,7 @@ export const SUBSET_MEMBERS = [
|
|
|
47
51
|
'ContentControl.removeWhenEdited',
|
|
48
52
|
'ContentControl.repeatingSectionContentControl',
|
|
49
53
|
'ContentControl.search',
|
|
54
|
+
'ContentControl.showingPlaceholderText',
|
|
50
55
|
'ContentControl.tables',
|
|
51
56
|
'ContentControl.tag',
|
|
52
57
|
'ContentControl.text',
|
|
@@ -57,6 +62,7 @@ export const SUBSET_MEMBERS = [
|
|
|
57
62
|
'ContentControlListItem.displayText',
|
|
58
63
|
'ContentControlListItem.index',
|
|
59
64
|
'ContentControlListItem.value',
|
|
65
|
+
'ContentControlOptions.types',
|
|
60
66
|
'CustomXmlNode.attributes',
|
|
61
67
|
'CustomXmlNode.baseName',
|
|
62
68
|
'CustomXmlNode.childNodes',
|
|
@@ -151,6 +157,7 @@ export const SUBSET_MEMBERS = [
|
|
|
151
157
|
'Paragraph.firstLineIndent',
|
|
152
158
|
'Paragraph.font',
|
|
153
159
|
'Paragraph.getComments',
|
|
160
|
+
'Paragraph.getContentControls',
|
|
154
161
|
'Paragraph.getRange',
|
|
155
162
|
'Paragraph.getTrackedChanges',
|
|
156
163
|
'Paragraph.insertBreak',
|
|
@@ -172,19 +179,27 @@ export const SUBSET_MEMBERS = [
|
|
|
172
179
|
'Paragraph.startNewList',
|
|
173
180
|
'Paragraph.style',
|
|
174
181
|
'Paragraph.styleBuiltIn',
|
|
182
|
+
'Paragraph.tableNestingLevel',
|
|
175
183
|
'Paragraph.text',
|
|
176
184
|
'PictureContentControl.inlinePicture',
|
|
185
|
+
'Range.contentControls',
|
|
177
186
|
'Range.delete',
|
|
187
|
+
'Range.expandTo',
|
|
178
188
|
'Range.font',
|
|
179
189
|
'Range.getComments',
|
|
190
|
+
'Range.getContentControls',
|
|
180
191
|
'Range.getRange',
|
|
181
192
|
'Range.getTrackedChanges',
|
|
182
193
|
'Range.hyperlink',
|
|
183
194
|
'Range.insertComment',
|
|
184
195
|
'Range.insertParagraph',
|
|
185
196
|
'Range.insertText',
|
|
197
|
+
'Range.isEmpty',
|
|
198
|
+
'Range.paragraphs',
|
|
186
199
|
'Range.search',
|
|
187
200
|
'Range.style',
|
|
201
|
+
'Range.styleBuiltIn',
|
|
202
|
+
'Range.tables',
|
|
188
203
|
'Range.text',
|
|
189
204
|
'RepeatingSectionContentControl.allowInsertDeleteSection',
|
|
190
205
|
'RepeatingSectionContentControl.items',
|
|
@@ -196,6 +211,7 @@ export const SUBSET_MEMBERS = [
|
|
|
196
211
|
'Table.delete',
|
|
197
212
|
'Table.deleteRows',
|
|
198
213
|
'Table.getCell',
|
|
214
|
+
'Table.getRange',
|
|
199
215
|
'Table.headerRowCount',
|
|
200
216
|
'Table.rowCount',
|
|
201
217
|
'Table.rows',
|
|
@@ -9,8 +9,8 @@ import { Docx4JException } from '../opc/exceptions.mjs';
|
|
|
9
9
|
import { Body } from '../model/content/Body.mjs';
|
|
10
10
|
import { Paragraph } from '../model/content/Paragraph.mjs';
|
|
11
11
|
import { Range } from '../model/content/Range.mjs';
|
|
12
|
-
import { isElement, typeNameOf, textOf } from '../model/content/tree.mjs';
|
|
13
|
-
import {
|
|
12
|
+
import { isElement, typeNameOf, textOf, selectedBranchOf, ALTERNATE_CONTENT } from '../model/content/tree.mjs';
|
|
13
|
+
import { blocksOfRange } from './fragment.mjs';
|
|
14
14
|
import { builtInOf, displayNameOf } from '../model/content/styles.mjs';
|
|
15
15
|
const TWIPS_PER_POINT = 20;
|
|
16
16
|
/** Paragraph properties the verbs express; anything else sends the paragraph to `insertXml`. */
|
|
@@ -97,13 +97,23 @@ class Emitter {
|
|
|
97
97
|
line(text) {
|
|
98
98
|
this.lines.push(this.indent + text);
|
|
99
99
|
}
|
|
100
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* A block-level element: a paragraph, a table, or anything else through `insertXml`. A kept
|
|
102
|
+
* `mc:AlternateContent` is its selected branch's content, as Word reads it and as its save writes it:
|
|
103
|
+
* `insertXml` refuses the element itself (CR-013 phase 3).
|
|
104
|
+
*/
|
|
101
105
|
async element(element) {
|
|
106
|
+
var _a;
|
|
102
107
|
const typeName = typeNameOf(element);
|
|
103
108
|
if (typeName === 'org_docx4j_wml.P')
|
|
104
109
|
await this.paragraph(element);
|
|
105
110
|
else if (typeName === 'org_docx4j_wml.Tbl')
|
|
106
111
|
await this.table(element);
|
|
112
|
+
else if (typeName === ALTERNATE_CONTENT) {
|
|
113
|
+
this.line('// an mc:AlternateContent: its selected branch, as Word reads it');
|
|
114
|
+
for (const child of (_a = selectedBranchOf(element.value)) !== null && _a !== void 0 ? _a : [])
|
|
115
|
+
await this.element(child);
|
|
116
|
+
}
|
|
107
117
|
else
|
|
108
118
|
await this.fallback(element);
|
|
109
119
|
}
|
|
@@ -117,9 +127,10 @@ class Emitter {
|
|
|
117
127
|
await this.fallback(element, error.message);
|
|
118
128
|
}
|
|
119
129
|
}
|
|
120
|
-
/** A range: its text and run formatting, as one paragraph. */
|
|
130
|
+
/** A range: its text and run formatting, as one paragraph; across paragraphs, each block it holds. */
|
|
121
131
|
async range(range) {
|
|
122
|
-
|
|
132
|
+
for (const block of blocksOfRange(range))
|
|
133
|
+
await this.element(block);
|
|
123
134
|
}
|
|
124
135
|
emitParagraph(p) {
|
|
125
136
|
const properties = this.paragraphProperties(p);
|
|
@@ -173,7 +184,7 @@ class Emitter {
|
|
|
173
184
|
* the generated document (CR-001 Phase B step 2; the same holds for `runFormat` below).
|
|
174
185
|
*/
|
|
175
186
|
paragraphProperties(p) {
|
|
176
|
-
var _a, _b, _c, _d, _e, _f
|
|
187
|
+
var _a, _b, _c, _d, _e, _f;
|
|
177
188
|
const pPr = p.pPr;
|
|
178
189
|
if (!pPr)
|
|
179
190
|
return [];
|
|
@@ -212,13 +223,14 @@ class Emitter {
|
|
|
212
223
|
if (spacing.after !== undefined)
|
|
213
224
|
out.push(['spaceAfter', num(spacing.after / TWIPS_PER_POINT)]);
|
|
214
225
|
if (spacing.line !== undefined) {
|
|
215
|
-
// Paragraph.lineSpacing writes w:lineRule="
|
|
216
|
-
|
|
217
|
-
|
|
226
|
+
// Paragraph.lineSpacing writes w:lineRule="auto", as Word's setter does (CR-002 section 65.9), so only an auto rule,
|
|
227
|
+
// stated or the default, round-trips.
|
|
228
|
+
if (spacing.lineRule !== undefined && spacing.lineRule !== 'auto')
|
|
229
|
+
throw new Unexpressible(`w:spacing w:lineRule="${spacing.lineRule}"`);
|
|
218
230
|
out.push(['lineSpacing', num(spacing.line / TWIPS_PER_POINT)]);
|
|
219
231
|
}
|
|
220
232
|
}
|
|
221
|
-
const outlineLvl = (
|
|
233
|
+
const outlineLvl = (_c = pPr.outlineLvl) === null || _c === void 0 ? void 0 : _c.val;
|
|
222
234
|
if (outlineLvl !== undefined)
|
|
223
235
|
out.push(['outlineLevel', num(outlineLvl + 1)]);
|
|
224
236
|
const numPr = pPr.numPr;
|
|
@@ -229,10 +241,10 @@ class Emitter {
|
|
|
229
241
|
// to know whether the list is a bullet one (CR-002 section 17).
|
|
230
242
|
if (!within(numPr, NUMPR_KEYS))
|
|
231
243
|
throw new Unexpressible(`w:numPr (${keysOf(numPr).filter((k) => !NUMPR_KEYS.has(k)).join(', ')})`);
|
|
232
|
-
const numId = (
|
|
244
|
+
const numId = (_d = numPr.numId) === null || _d === void 0 ? void 0 : _d.val;
|
|
233
245
|
if (numId === undefined)
|
|
234
246
|
throw new Unexpressible('w:numPr with no w:numId');
|
|
235
|
-
out.push([CALL, numId === 0 ? 'detachFromList()' : `attachToList(${numId}, ${(
|
|
247
|
+
out.push([CALL, numId === 0 ? 'detachFromList()' : `attachToList(${numId}, ${(_f = (_e = numPr.ilvl) === null || _e === void 0 ? void 0 : _e.val) !== null && _f !== void 0 ? _f : 0})`]);
|
|
236
248
|
}
|
|
237
249
|
return out;
|
|
238
250
|
}
|
|
@@ -326,10 +338,15 @@ function tableGrid(tbl) {
|
|
|
326
338
|
const typeName = typeNameOf(item);
|
|
327
339
|
if (typeName === 'org_docx4j_wml.CTTblGridCol' || typeName === 'org_docx4j_wml.TblGrid')
|
|
328
340
|
continue;
|
|
341
|
+
// a row- or cell-level mc:AlternateContent is no plain grid: the table goes whole through insertXml (CR-013 phase 3)
|
|
342
|
+
if (typeName === ALTERNATE_CONTENT)
|
|
343
|
+
return undefined;
|
|
329
344
|
if (typeName !== 'org_docx4j_wml.Tr')
|
|
330
345
|
continue;
|
|
331
346
|
const row = [];
|
|
332
347
|
for (const cell of ((_b = item.value.content) !== null && _b !== void 0 ? _b : [])) {
|
|
348
|
+
if (typeNameOf(cell) === ALTERNATE_CONTENT)
|
|
349
|
+
return undefined;
|
|
333
350
|
if (typeNameOf(cell) !== 'org_docx4j_wml.Tc')
|
|
334
351
|
continue;
|
|
335
352
|
const tc = cell.value;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PartStore, type PartSink, type PutOptions } from './PartStore.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* A package spread over a directory: `word/document.xml` is the file `<dir>/word/document.xml`,
|
|
4
4
|
* `[Content_Types].xml` is read from the directory like any other entry, and a part's size comes
|
|
@@ -14,7 +14,10 @@ import type { PartStore, PartSink, PutOptions } from './PartStore.mjs';
|
|
|
14
14
|
*/
|
|
15
15
|
export declare class DirectoryPartStore implements PartStore {
|
|
16
16
|
readonly dir: string;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Store name (no leading '/') to [absolute file path, size], looked up without case; of two files whose names differ only
|
|
19
|
+
* in case (a case-sensitive file system), the first in the walk is read and the rest counted (CR-024).
|
|
20
|
+
*/
|
|
18
21
|
private readonly entries;
|
|
19
22
|
private constructor();
|
|
20
23
|
/** Scans a directory and returns a store over it. */
|
|
@@ -22,6 +25,7 @@ export declare class DirectoryPartStore implements PartStore {
|
|
|
22
25
|
private scan;
|
|
23
26
|
partNames(): Iterable<string>;
|
|
24
27
|
has(partName: string): boolean;
|
|
28
|
+
duplicates(): ReadonlyMap<string, number>;
|
|
25
29
|
load(partName: string): Promise<Uint8Array>;
|
|
26
30
|
size(partName: string): number | undefined;
|
|
27
31
|
}
|