ooxml.js 4.2.0 → 4.3.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/README.md +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{read-fuJpC4BH.js → read-BQoFiqsb.js} +19 -3
- package/dist/{read-C3AaxcT9.cjs → read-Di5UfiSh.cjs} +18 -2
- package/dist/typed/document-package.cjs +1 -1
- package/dist/typed/document-package.js +1 -1
- package/dist/typed/docx/constructs.cjs +32 -0
- package/dist/typed/docx/constructs.d.cts +10 -2
- package/dist/typed/docx/constructs.d.ts +10 -2
- package/dist/typed/docx/constructs.js +32 -1
- package/dist/typed/docx/read.cjs +1 -1
- package/dist/typed/docx/read.js +1 -1
- package/dist/typed/docx/write.cjs +40 -1
- package/dist/typed/docx/write.js +41 -2
- package/dist/typed/embedded.cjs +1 -1
- package/dist/typed/embedded.js +1 -1
- package/dist/typed/pptx/read.cjs +1 -1
- package/dist/typed/pptx/read.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -144,7 +144,7 @@ const pkg = buildXlsxPackageFromContent(content); // a fresh Package built from
|
|
|
144
144
|
|
|
145
145
|
Both docx readers read the block-scoped fidelity constructs — structured document tags, fields, bookmarks, and tracked changes. In the flat form they are `document-schema.js` construct-boundary markers bracketing the blocks each one spans, one matched `constructStart`/`constructEnd` pair per construct, nesting as brackets do; in the tree they are promoted to a group over exactly that region, carrying the same descriptor. Both docx writers write them back.
|
|
146
146
|
|
|
147
|
-
A
|
|
147
|
+
A bookmark whose extent is a sub-sequence of one paragraph's runs — the bookmark over three words inside a sentence — is read onto that paragraph's own `constructs` field (`document-schema.js`'s run-level construct extents: a descriptor plus a half-open run range, so the paragraph is never split to host a wrapper), and the docx writer puts its `w:bookmarkStart`/`w:bookmarkEnd` halves back between the runs the range names. Two such bookmarks whose extents cross both survive — run ranges are data, not brackets. The other run-level constructs — a field inside a sentence, a run-level content control, a few inserted words in an otherwise untouched paragraph, and a bookmark whose halves sit in two different paragraphs — still have no encoding here: the text comes through, the construct does not. See the gotchas below.
|
|
148
148
|
|
|
149
149
|
A construct with format-specific specifics the harmonised vocabulary does not name carries them in the descriptor's quarantined `source` residue (`document-schema.js`'s residue channel): an SDT whose `w:docPartObj` gallery is not the Table of Contents degrades to a `richText` control with the whole `w:docPartObj` element carried verbatim, and the docx writer re-emits that element from the residue in place of the default `w:richText` type element — the restorable tier in action, the gallery name no longer lost to the round trip.
|
|
150
150
|
|
|
@@ -296,7 +296,7 @@ The package layers a lossless core outward to lossy convenience views:
|
|
|
296
296
|
## Gotchas and quirks
|
|
297
297
|
|
|
298
298
|
- **A `Content` suffix means the flat form, not a lesser one.** `readDocx` and `readDocxContent` are the same read; the suffix says which shape comes back (`DocumentPackage` versus the flat `DocxDocument`/`ContentDocument`), never which is more faithful. The pair that genuinely differs in what it reads is `readXlsxWorkbook`, whose name says so by naming its own return type rather than taking a suffix.
|
|
299
|
-
- **A construct marker brackets whole blocks, never a sub-sequence of runs.**
|
|
299
|
+
- **A construct marker brackets whole blocks, never a sub-sequence of runs.** A mid-paragraph bookmark is the one run-level construct with an encoding here — it lands on the paragraph's `constructs` field as a run range (see the fidelity-constructs section above). An inline field, a run-level content control, or a few inserted words inside an otherwise untouched paragraph are still read exactly as before — the text survives, the construct does not — as is a bookmark whose two halves sit in different paragraphs. So does a block extent that crosses another, or that straddles a section break or table-cell boundary: neither is expressible as balanced brackets (nor as a tree group, which is what the marker pair promotes to), and both are dropped — a drop `document-schema.js`'s extent-scope note ratifies — rather than emitted at a position that would decode to a different nesting.
|
|
300
300
|
- **The docx pair round-trips `sections`, not a whole `DocxDocument`.** Numbering definitions, cell border styling/shading, and `w:themeColor` (without `themeShade`/`themeTint`) are read; images read into `ContentImageBlock` (floating `wp:anchor` position not recorded); `PAGE`/`NUMPAGES` fields resolve to Word's cached text. An inline `w:object`/`o:OLEObject` whose payload part is itself a ZIP archive — a modern producer's embedded xlsx/docx/pptx, detected by magic bytes through `archive-codec` — or a classic OLE compound-file `.bin` whose root storage carries the embedded file as an OLE-packaged `Package` stream, read through `archive-codec`'s bounded CFB reader, is decoded into a nested content document and emitted as a `ContentEmbeddedObjectBlock` beside its containing paragraph's own block, sized from `w:dxaOrig`/`w:dyaOrig`; the object's VML preview picture (`v:imagedata`) and a `w:object` inside a header/footer/footnote (recovery walks the document body's block flow only) are not read, a compound file holding native legacy streams (BIFF and friends — no `Package` stream, or a packaged file that is not a ZIP) stays opaque, and a payload that does not decode as one of the three OOXML flavours (a plain archive, corrupt zip or compound-file data, a bodyless docx) degrades to no embedded block rather than failing the host read. The writer emits such a block back out as the inverse `w:object`/`o:OLEObject`: the nested document is re-serialised through its own format's builder into a fresh `word/embeddings/oleObject<N>.<docx|xlsx>` ZIP part carrying its relationship and content-type override, and `w:dxaOrig`/`w:dyaOrig` are derived from the block's frame (twips). An embedded presentation document has no serialiser here — pptx is read-only in this package — so a `ContentDocument` carrying one is refused with a thrown error rather than a silent drop, and no VML preview picture is regenerated (the reader never read one into the model, and real previews are WMF/EMF this ecosystem has no writer for; Word shows a blank until activated). The writer emits no `styles.xml`, `numbering.xml`, comments, footnotes, or headers/footers, so the `DocxDocument` fields outside `sections` do not come back — a paragraph's `styleId` is still written as a `w:pStyle` reference, resolving to nothing, since every property the style would have contributed is already spelled as direct formatting by then.
|
|
301
301
|
- **pptx is read-only.** Connector shapes (`p:cxnSp`) are skipped; shape rotation composes through groups; a chart graphic frame reads its chart part's cached series/category model into a table block (header row = series names, one row per category index); a SmartArt graphic frame reads its diagram data model's node text as paragraphs in diagram order (depth-first over `parOf` connections, siblings by `srcOrd`); an OLE graphic frame reads the fallback picture its `mc:Fallback` carries (or, with none reachable, a paragraph naming the `p:oleObj`'s `progId`), and when the payload part is itself a ZIP archive — a modern producer's embedded xlsx/docx/pptx, detected by magic bytes through `archive-codec` — or a classic OLE compound-file `.bin` whose root storage carries the embedded file as an OLE-packaged `Package` stream, read through `archive-codec`'s bounded CFB reader, also decodes it into a nested content document and emits it as an `embeddedObject` block beside the picture, sized to the frame's own geometry; a compound file holding native legacy streams (no `Package` stream, or a packaged file that is not a ZIP) stays opaque external-application data, and a payload that does not decode as one of the three OOXML flavours degrades to no embedded block rather than failing the slide read.
|
|
302
302
|
- **xlsx has no native percentage/currency/date/time cell type.** Both directions are closed via the number-format engine: reading classifies style → format code → kind; writing emits interned `numFmt` codes, fed back through the classifier in tests. `displayText` is the typed-value spelling, not the producer's rendered string.
|
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,7 @@ const require_typed_util = require("./typed/util.cjs");
|
|
|
15
15
|
const require_typed_shared_color = require("./typed/shared/color.cjs");
|
|
16
16
|
const require_typed_shared_metadata = require("./typed/shared/metadata.cjs");
|
|
17
17
|
const require_image_sniff = require("./image/sniff.cjs");
|
|
18
|
-
const require_read = require("./read-
|
|
18
|
+
const require_read = require("./read-Di5UfiSh.cjs");
|
|
19
19
|
const require_typed_xlsx_content = require("./typed/xlsx/content.cjs");
|
|
20
20
|
const require_typed_docx_numbering = require("./typed/docx/numbering.cjs");
|
|
21
21
|
const require_typed_xlsx_build = require("./typed/xlsx/build.cjs");
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { attr, childrenWithTag, decodeEntities, elementsWithTag, resolveRelation
|
|
|
14
14
|
import { applyColorTransforms } from "./typed/shared/color.js";
|
|
15
15
|
import { DocumentMetadataSchema } from "./typed/shared/metadata.js";
|
|
16
16
|
import { sniffImageFormat } from "./image/sniff.js";
|
|
17
|
-
import { c as readPptxContent, i as readDocxContent, n as DocxDocumentSchema, r as FootnoteSchema, s as PptxDocumentSchema, t as CommentSchema } from "./read-
|
|
17
|
+
import { c as readPptxContent, i as readDocxContent, n as DocxDocumentSchema, r as FootnoteSchema, s as PptxDocumentSchema, t as CommentSchema } from "./read-BQoFiqsb.js";
|
|
18
18
|
import { readXlsxContent } from "./typed/xlsx/content.js";
|
|
19
19
|
import { NumberingDefinitionSchema, NumberingLevelSchema, readNumberingDefinitions } from "./typed/docx/numbering.js";
|
|
20
20
|
import { buildXlsxPackageFromContent } from "./typed/xlsx/build.js";
|
|
@@ -12,7 +12,7 @@ import { readDiagramText } from "./typed/pptx/diagram.js";
|
|
|
12
12
|
import { readXlsxContent } from "./typed/xlsx/content.js";
|
|
13
13
|
import { resolveParagraphProperties, resolveRunProperties } from "./typed/docx/styles.js";
|
|
14
14
|
import { NumberingDefinitionSchema, readNumberingDefinitions } from "./typed/docx/numbering.js";
|
|
15
|
-
import { PROVENANCE_CHANGE_BY_TAG, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runInstructionText } from "./typed/docx/constructs.js";
|
|
15
|
+
import { PROVENANCE_CHANGE_BY_TAG, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runBookmarkExtents, runInstructionText } from "./typed/docx/constructs.js";
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
import { COLOR_BLACK, ContentSectionSchema, ContentSlideSchema, PAGE_SIZE_LETTER, SLIDE_SIZE_WIDESCREEN, clampHeadingLevel, rgbHexToColor } from "document-schema.js";
|
|
18
18
|
import { isCompoundFile, isZipArchive, readCompoundFile, readOlePackage, walkArchive } from "archive-codec";
|
|
@@ -662,7 +662,7 @@ function readRun(run, paragraph, context) {
|
|
|
662
662
|
color: props.color
|
|
663
663
|
};
|
|
664
664
|
}
|
|
665
|
-
function readParagraphRuns(paragraph, ctx, carryDeletions) {
|
|
665
|
+
function readParagraphRuns(paragraph, ctx, carryDeletions, halves) {
|
|
666
666
|
const runs = [];
|
|
667
667
|
let fieldState = "none";
|
|
668
668
|
function walk(nodes, hyperlinkTarget) {
|
|
@@ -693,6 +693,18 @@ function readParagraphRuns(paragraph, ctx, carryDeletions) {
|
|
|
693
693
|
} else if (node.tag === "w:sdt") {
|
|
694
694
|
const sdtContent = childrenWithTag(node, "w:sdtContent")[0];
|
|
695
695
|
if (sdtContent !== void 0) walk(sdtContent.children, hyperlinkTarget);
|
|
696
|
+
} else if (node.tag === "w:bookmarkStart" || node.tag === "w:bookmarkEnd") {
|
|
697
|
+
const id = attr(node, "w:id");
|
|
698
|
+
if (id !== void 0) {
|
|
699
|
+
const name = attr(node, "w:name");
|
|
700
|
+
halves.push({
|
|
701
|
+
element: node,
|
|
702
|
+
id,
|
|
703
|
+
name: node.tag === "w:bookmarkStart" && name !== void 0 ? decodeEntities(name) : void 0,
|
|
704
|
+
kind: node.tag === "w:bookmarkStart" ? "start" : "end",
|
|
705
|
+
runPosition: runs.length
|
|
706
|
+
});
|
|
707
|
+
}
|
|
696
708
|
}
|
|
697
709
|
}
|
|
698
710
|
}
|
|
@@ -703,9 +715,13 @@ function readParagraph(paragraph, ctx, carryDeletions) {
|
|
|
703
715
|
const pPr = childrenWithTag(paragraph, "w:pPr")[0];
|
|
704
716
|
const pStyleEl = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:pStyle")[0];
|
|
705
717
|
const props = resolveParagraphProperties(paragraph, ctx.styles);
|
|
718
|
+
const halves = [];
|
|
719
|
+
const runs = readParagraphRuns(paragraph, ctx, carryDeletions, halves);
|
|
720
|
+
const constructs = runBookmarkExtents(halves, indexParagraphContent(paragraph));
|
|
706
721
|
return {
|
|
707
722
|
kind: "paragraph",
|
|
708
|
-
runs
|
|
723
|
+
runs,
|
|
724
|
+
...constructs.length > 0 ? { constructs } : {},
|
|
709
725
|
styleId: pStyleEl === void 0 ? void 0 : attr(pStyleEl, "w:val"),
|
|
710
726
|
headingLevel: props.outlineLvl === void 0 ? void 0 : clampHeadingLevel(props.outlineLvl + 1),
|
|
711
727
|
alignment: props.alignment,
|
|
@@ -662,7 +662,7 @@ function readRun(run, paragraph, context) {
|
|
|
662
662
|
color: props.color
|
|
663
663
|
};
|
|
664
664
|
}
|
|
665
|
-
function readParagraphRuns(paragraph, ctx, carryDeletions) {
|
|
665
|
+
function readParagraphRuns(paragraph, ctx, carryDeletions, halves) {
|
|
666
666
|
const runs = [];
|
|
667
667
|
let fieldState = "none";
|
|
668
668
|
function walk(nodes, hyperlinkTarget) {
|
|
@@ -693,6 +693,18 @@ function readParagraphRuns(paragraph, ctx, carryDeletions) {
|
|
|
693
693
|
} else if (node.tag === "w:sdt") {
|
|
694
694
|
const sdtContent = require_typed_util.childrenWithTag(node, "w:sdtContent")[0];
|
|
695
695
|
if (sdtContent !== void 0) walk(sdtContent.children, hyperlinkTarget);
|
|
696
|
+
} else if (node.tag === "w:bookmarkStart" || node.tag === "w:bookmarkEnd") {
|
|
697
|
+
const id = require_typed_util.attr(node, "w:id");
|
|
698
|
+
if (id !== void 0) {
|
|
699
|
+
const name = require_typed_util.attr(node, "w:name");
|
|
700
|
+
halves.push({
|
|
701
|
+
element: node,
|
|
702
|
+
id,
|
|
703
|
+
name: node.tag === "w:bookmarkStart" && name !== void 0 ? require_typed_util.decodeEntities(name) : void 0,
|
|
704
|
+
kind: node.tag === "w:bookmarkStart" ? "start" : "end",
|
|
705
|
+
runPosition: runs.length
|
|
706
|
+
});
|
|
707
|
+
}
|
|
696
708
|
}
|
|
697
709
|
}
|
|
698
710
|
}
|
|
@@ -703,9 +715,13 @@ function readParagraph(paragraph, ctx, carryDeletions) {
|
|
|
703
715
|
const pPr = require_typed_util.childrenWithTag(paragraph, "w:pPr")[0];
|
|
704
716
|
const pStyleEl = pPr === void 0 ? void 0 : require_typed_util.childrenWithTag(pPr, "w:pStyle")[0];
|
|
705
717
|
const props = require_typed_docx_styles.resolveParagraphProperties(paragraph, ctx.styles);
|
|
718
|
+
const halves = [];
|
|
719
|
+
const runs = readParagraphRuns(paragraph, ctx, carryDeletions, halves);
|
|
720
|
+
const constructs = require_typed_docx_constructs.runBookmarkExtents(halves, require_typed_docx_constructs.indexParagraphContent(paragraph));
|
|
706
721
|
return {
|
|
707
722
|
kind: "paragraph",
|
|
708
|
-
runs
|
|
723
|
+
runs,
|
|
724
|
+
...constructs.length > 0 ? { constructs } : {},
|
|
709
725
|
styleId: pStyleEl === void 0 ? void 0 : require_typed_util.attr(pStyleEl, "w:val"),
|
|
710
726
|
headingLevel: props.outlineLvl === void 0 ? void 0 : (0, document_schema_js.clampHeadingLevel)(props.outlineLvl + 1),
|
|
711
727
|
alignment: props.alignment,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_read = require("../read-
|
|
2
|
+
const require_read = require("../read-Di5UfiSh.cjs");
|
|
3
3
|
const require_typed_xlsx_content = require("./xlsx/content.cjs");
|
|
4
4
|
const require_typed_xlsx_build = require("./xlsx/build.cjs");
|
|
5
5
|
const require_typed_docx_write = require("./docx/write.cjs");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as readPptxContent, i as readDocxContent } from "../read-
|
|
1
|
+
import { c as readPptxContent, i as readDocxContent } from "../read-BQoFiqsb.js";
|
|
2
2
|
import { readXlsxContent } from "./xlsx/content.js";
|
|
3
3
|
import { buildXlsxPackageFromContent } from "./xlsx/build.js";
|
|
4
4
|
import { buildDocxPackageFromContent } from "./docx/write.js";
|
|
@@ -86,6 +86,37 @@ function insertConstructMarkers(blocks, extents) {
|
|
|
86
86
|
}
|
|
87
87
|
return out;
|
|
88
88
|
}
|
|
89
|
+
function isBlockScopedHalf(half, index) {
|
|
90
|
+
const position = index.elements.indexOf(half.element);
|
|
91
|
+
if (position === -1) return false;
|
|
92
|
+
const leading = index.firstContentIndex === -1 || position < index.firstContentIndex;
|
|
93
|
+
const trailing = index.lastContentIndex === -1 || position > index.lastContentIndex;
|
|
94
|
+
return leading || trailing;
|
|
95
|
+
}
|
|
96
|
+
function runBookmarkExtents(halves, index) {
|
|
97
|
+
const byId = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const half of halves) {
|
|
99
|
+
const existing = byId.get(half.id);
|
|
100
|
+
if (existing === void 0) byId.set(half.id, [half]);
|
|
101
|
+
else existing.push(half);
|
|
102
|
+
}
|
|
103
|
+
const extents = [];
|
|
104
|
+
for (const pair of byId.values()) {
|
|
105
|
+
const starts = pair.filter((half) => half.kind === "start");
|
|
106
|
+
const ends = pair.filter((half) => half.kind === "end");
|
|
107
|
+
const open = starts[0];
|
|
108
|
+
const close = ends[0];
|
|
109
|
+
if (starts.length !== 1 || ends.length !== 1 || open === void 0 || close === void 0) continue;
|
|
110
|
+
if (open.name === void 0 || close.runPosition < open.runPosition) continue;
|
|
111
|
+
if (isBlockScopedHalf(open, index) && isBlockScopedHalf(close, index)) continue;
|
|
112
|
+
extents.push({
|
|
113
|
+
descriptor: bookmarkAnchorDescriptor(open.name),
|
|
114
|
+
startRun: open.runPosition,
|
|
115
|
+
endRun: close.runPosition
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return extents;
|
|
119
|
+
}
|
|
89
120
|
const CONTROL_TYPE_BY_TAG = /* @__PURE__ */ new Map([
|
|
90
121
|
["w:richText", "richText"],
|
|
91
122
|
["w:text", "plainText"],
|
|
@@ -230,4 +261,5 @@ exports.insertConstructMarkers = insertConstructMarkers;
|
|
|
230
261
|
exports.isDeletedChange = isDeletedChange;
|
|
231
262
|
exports.readContentControlDescriptor = readContentControlDescriptor;
|
|
232
263
|
exports.readProvenanceDescriptor = readProvenanceDescriptor;
|
|
264
|
+
exports.runBookmarkExtents = runBookmarkExtents;
|
|
233
265
|
exports.runInstructionText = runInstructionText;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { l as XmlElement } from "../../node-CkBWRjNR.cjs";
|
|
2
|
-
import { AnchorDescriptor, ConstructDescriptor, ContentBlock, ContentControlDescriptor, ProvenanceChange, ProvenanceDescriptor } from "document-schema.js";
|
|
2
|
+
import { AnchorDescriptor, ConstructDescriptor, ContentBlock, ContentControlDescriptor, ProvenanceChange, ProvenanceDescriptor, RunConstructExtent } from "document-schema.js";
|
|
3
3
|
//#region src/typed/docx/constructs.d.ts
|
|
4
4
|
interface ParagraphContentIndex {
|
|
5
5
|
readonly elements: readonly XmlElement[];
|
|
@@ -15,6 +15,14 @@ interface ConstructExtent {
|
|
|
15
15
|
readonly descriptor: ConstructDescriptor;
|
|
16
16
|
}
|
|
17
17
|
declare function insertConstructMarkers(blocks: readonly ContentBlock[], extents: readonly ConstructExtent[]): ContentBlock[];
|
|
18
|
+
interface ParagraphBookmarkHalf {
|
|
19
|
+
readonly element: XmlElement;
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly name: string | undefined;
|
|
22
|
+
readonly kind: 'start' | 'end';
|
|
23
|
+
readonly runPosition: number;
|
|
24
|
+
}
|
|
25
|
+
declare function runBookmarkExtents(halves: readonly ParagraphBookmarkHalf[], index: ParagraphContentIndex): RunConstructExtent[];
|
|
18
26
|
declare const TABLE_OF_CONTENTS_GALLERY = "Table of Contents";
|
|
19
27
|
declare function readContentControlDescriptor(sdt: XmlElement): ContentControlDescriptor;
|
|
20
28
|
declare const PROVENANCE_CHANGE_BY_TAG: ReadonlyMap<string, ProvenanceChange>;
|
|
@@ -24,4 +32,4 @@ declare function bookmarkAnchorDescriptor(name: string): AnchorDescriptor;
|
|
|
24
32
|
declare function runInstructionText(run: XmlElement): string;
|
|
25
33
|
declare function fieldCharType(run: XmlElement): string | undefined;
|
|
26
34
|
//#endregion
|
|
27
|
-
export { ConstructExtent, PROVENANCE_CHANGE_BY_TAG, ParagraphContentIndex, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runInstructionText };
|
|
35
|
+
export { ConstructExtent, PROVENANCE_CHANGE_BY_TAG, ParagraphBookmarkHalf, ParagraphContentIndex, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runBookmarkExtents, runInstructionText };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { l as XmlElement } from "../../node-CkBWRjNR.js";
|
|
2
|
-
import { AnchorDescriptor, ConstructDescriptor, ContentBlock, ContentControlDescriptor, ProvenanceChange, ProvenanceDescriptor } from "document-schema.js";
|
|
2
|
+
import { AnchorDescriptor, ConstructDescriptor, ContentBlock, ContentControlDescriptor, ProvenanceChange, ProvenanceDescriptor, RunConstructExtent } from "document-schema.js";
|
|
3
3
|
//#region src/typed/docx/constructs.d.ts
|
|
4
4
|
interface ParagraphContentIndex {
|
|
5
5
|
readonly elements: readonly XmlElement[];
|
|
@@ -15,6 +15,14 @@ interface ConstructExtent {
|
|
|
15
15
|
readonly descriptor: ConstructDescriptor;
|
|
16
16
|
}
|
|
17
17
|
declare function insertConstructMarkers(blocks: readonly ContentBlock[], extents: readonly ConstructExtent[]): ContentBlock[];
|
|
18
|
+
interface ParagraphBookmarkHalf {
|
|
19
|
+
readonly element: XmlElement;
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly name: string | undefined;
|
|
22
|
+
readonly kind: 'start' | 'end';
|
|
23
|
+
readonly runPosition: number;
|
|
24
|
+
}
|
|
25
|
+
declare function runBookmarkExtents(halves: readonly ParagraphBookmarkHalf[], index: ParagraphContentIndex): RunConstructExtent[];
|
|
18
26
|
declare const TABLE_OF_CONTENTS_GALLERY = "Table of Contents";
|
|
19
27
|
declare function readContentControlDescriptor(sdt: XmlElement): ContentControlDescriptor;
|
|
20
28
|
declare const PROVENANCE_CHANGE_BY_TAG: ReadonlyMap<string, ProvenanceChange>;
|
|
@@ -24,4 +32,4 @@ declare function bookmarkAnchorDescriptor(name: string): AnchorDescriptor;
|
|
|
24
32
|
declare function runInstructionText(run: XmlElement): string;
|
|
25
33
|
declare function fieldCharType(run: XmlElement): string | undefined;
|
|
26
34
|
//#endregion
|
|
27
|
-
export { ConstructExtent, PROVENANCE_CHANGE_BY_TAG, ParagraphContentIndex, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runInstructionText };
|
|
35
|
+
export { ConstructExtent, PROVENANCE_CHANGE_BY_TAG, ParagraphBookmarkHalf, ParagraphContentIndex, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runBookmarkExtents, runInstructionText };
|
|
@@ -85,6 +85,37 @@ function insertConstructMarkers(blocks, extents) {
|
|
|
85
85
|
}
|
|
86
86
|
return out;
|
|
87
87
|
}
|
|
88
|
+
function isBlockScopedHalf(half, index) {
|
|
89
|
+
const position = index.elements.indexOf(half.element);
|
|
90
|
+
if (position === -1) return false;
|
|
91
|
+
const leading = index.firstContentIndex === -1 || position < index.firstContentIndex;
|
|
92
|
+
const trailing = index.lastContentIndex === -1 || position > index.lastContentIndex;
|
|
93
|
+
return leading || trailing;
|
|
94
|
+
}
|
|
95
|
+
function runBookmarkExtents(halves, index) {
|
|
96
|
+
const byId = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const half of halves) {
|
|
98
|
+
const existing = byId.get(half.id);
|
|
99
|
+
if (existing === void 0) byId.set(half.id, [half]);
|
|
100
|
+
else existing.push(half);
|
|
101
|
+
}
|
|
102
|
+
const extents = [];
|
|
103
|
+
for (const pair of byId.values()) {
|
|
104
|
+
const starts = pair.filter((half) => half.kind === "start");
|
|
105
|
+
const ends = pair.filter((half) => half.kind === "end");
|
|
106
|
+
const open = starts[0];
|
|
107
|
+
const close = ends[0];
|
|
108
|
+
if (starts.length !== 1 || ends.length !== 1 || open === void 0 || close === void 0) continue;
|
|
109
|
+
if (open.name === void 0 || close.runPosition < open.runPosition) continue;
|
|
110
|
+
if (isBlockScopedHalf(open, index) && isBlockScopedHalf(close, index)) continue;
|
|
111
|
+
extents.push({
|
|
112
|
+
descriptor: bookmarkAnchorDescriptor(open.name),
|
|
113
|
+
startRun: open.runPosition,
|
|
114
|
+
endRun: close.runPosition
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return extents;
|
|
118
|
+
}
|
|
88
119
|
const CONTROL_TYPE_BY_TAG = /* @__PURE__ */ new Map([
|
|
89
120
|
["w:richText", "richText"],
|
|
90
121
|
["w:text", "plainText"],
|
|
@@ -219,4 +250,4 @@ function fieldCharType(run) {
|
|
|
219
250
|
return fldChar === void 0 ? void 0 : attr(fldChar, "w:fldCharType");
|
|
220
251
|
}
|
|
221
252
|
//#endregion
|
|
222
|
-
export { PROVENANCE_CHANGE_BY_TAG, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runInstructionText };
|
|
253
|
+
export { PROVENANCE_CHANGE_BY_TAG, TABLE_OF_CONTENTS_GALLERY, bookmarkAnchorDescriptor, contentBearingChildren, fieldCharType, indexParagraphContent, insertConstructMarkers, isDeletedChange, readContentControlDescriptor, readProvenanceDescriptor, runBookmarkExtents, runInstructionText };
|
package/dist/typed/docx/read.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_read = require("../../read-
|
|
2
|
+
const require_read = require("../../read-Di5UfiSh.cjs");
|
|
3
3
|
exports.CommentSchema = require_read.CommentSchema;
|
|
4
4
|
exports.DocxDocumentSchema = require_read.DocxDocumentSchema;
|
|
5
5
|
exports.FootnoteSchema = require_read.FootnoteSchema;
|
package/dist/typed/docx/read.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as readDocxContent, n as DocxDocumentSchema, r as FootnoteSchema, t as CommentSchema } from "../../read-
|
|
1
|
+
import { i as readDocxContent, n as DocxDocumentSchema, r as FootnoteSchema, t as CommentSchema } from "../../read-BQoFiqsb.js";
|
|
2
2
|
export { CommentSchema, DocxDocumentSchema, FootnoteSchema, readDocxContent };
|
|
@@ -179,10 +179,49 @@ function buildParagraph(paragraph, state, pageBreakBefore, deleted, provenance)
|
|
|
179
179
|
const changeTag = provenance === void 0 ? void 0 : TRACKED_CHANGE_TAG_BY_CHANGE[provenance.change];
|
|
180
180
|
const pPr = properties === void 0 && changeTag !== void 0 ? require_xml_fragment.el("w:pPr", {}, []) : properties;
|
|
181
181
|
if (pPr !== void 0 && changeTag !== void 0 && provenance !== void 0) pPr.children.push(require_xml_fragment.el("w:rPr", {}, [require_xml_fragment.el(changeTag, trackChangeAttrs(state, provenance))]));
|
|
182
|
-
const runs = paragraph.runs.map((run) => buildRun(run, state, deleted));
|
|
182
|
+
const runs = interleaveRunConstructExtents(paragraph.runs.map((run) => buildRun(run, state, deleted)), paragraph, state);
|
|
183
183
|
const content = changeTag === void 0 || provenance === void 0 ? runs : [require_xml_fragment.el(changeTag, trackChangeAttrs(state, provenance), runs)];
|
|
184
184
|
return require_xml_fragment.el("w:p", {}, [...pPr === void 0 ? [] : [pPr], ...content]);
|
|
185
185
|
}
|
|
186
|
+
function interleaveRunConstructExtents(runElements, paragraph, state) {
|
|
187
|
+
if (paragraph.constructs === void 0) return [...runElements];
|
|
188
|
+
const fault = (0, document_schema_js.findRunConstructFault)(paragraph);
|
|
189
|
+
if (fault !== void 0) throw new Error(`buildDocxPackageFromContent: run-level construct extent at index ${String(fault.index)} of a paragraph does not name real runs (${fault.kind})`);
|
|
190
|
+
const bookmarks = paragraph.constructs.filter((extent) => extent.descriptor.kind === "anchor" && extent.descriptor.anchorType === "bookmark");
|
|
191
|
+
if (bookmarks.length === 0) return [...runElements];
|
|
192
|
+
const closingAt = /* @__PURE__ */ new Map();
|
|
193
|
+
const openingAt = /* @__PURE__ */ new Map();
|
|
194
|
+
const pointAt = /* @__PURE__ */ new Map();
|
|
195
|
+
const push = (map, position, element) => {
|
|
196
|
+
const existing = map.get(position);
|
|
197
|
+
if (existing === void 0) map.set(position, [element]);
|
|
198
|
+
else existing.push(element);
|
|
199
|
+
};
|
|
200
|
+
for (const bookmark of bookmarks) {
|
|
201
|
+
const id = String(state.nextMarkerId++);
|
|
202
|
+
const open = require_xml_fragment.el("w:bookmarkStart", {
|
|
203
|
+
"w:id": id,
|
|
204
|
+
"w:name": require_xml_entities.encodeXmlText(bookmark.descriptor.name)
|
|
205
|
+
});
|
|
206
|
+
const close = require_xml_fragment.el("w:bookmarkEnd", { "w:id": id });
|
|
207
|
+
if (bookmark.startRun === bookmark.endRun) {
|
|
208
|
+
push(pointAt, bookmark.startRun, open);
|
|
209
|
+
push(pointAt, bookmark.startRun, close);
|
|
210
|
+
} else {
|
|
211
|
+
push(openingAt, bookmark.startRun, open);
|
|
212
|
+
push(closingAt, bookmark.endRun, close);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const out = [];
|
|
216
|
+
for (let position = 0; position <= runElements.length; position++) {
|
|
217
|
+
for (const close of closingAt.get(position) ?? []) out.push(close);
|
|
218
|
+
for (const open of openingAt.get(position) ?? []) out.push(open);
|
|
219
|
+
for (const half of pointAt.get(position) ?? []) out.push(half);
|
|
220
|
+
const run = runElements[position];
|
|
221
|
+
if (run !== void 0) out.push(run);
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
186
225
|
function trailingEmptyRunElements(paragraph, element) {
|
|
187
226
|
const runElements = [];
|
|
188
227
|
for (const child of element.children) if (child.type === "element" && (child.tag === "w:r" || child.tag === "w:hyperlink")) runElements.push(child);
|
package/dist/typed/docx/write.js
CHANGED
|
@@ -6,7 +6,7 @@ import { encodeXmlText } from "../../xml/entities.js";
|
|
|
6
6
|
import { ptToEighthPoints, ptToEmu, ptToHalfPoints, ptToTwips } from "../shared/units.js";
|
|
7
7
|
import { TABLE_OF_CONTENTS_GALLERY, isDeletedChange } from "./constructs.js";
|
|
8
8
|
import { buildXlsxPackageFromContent } from "../xlsx/build.js";
|
|
9
|
-
import { colorToRgbHex, findConstructMarkerImbalance } from "document-schema.js";
|
|
9
|
+
import { colorToRgbHex, findConstructMarkerImbalance, findRunConstructFault } from "document-schema.js";
|
|
10
10
|
//#region src/typed/docx/write.ts
|
|
11
11
|
const WML_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
12
12
|
const REL_NS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
@@ -178,10 +178,49 @@ function buildParagraph(paragraph, state, pageBreakBefore, deleted, provenance)
|
|
|
178
178
|
const changeTag = provenance === void 0 ? void 0 : TRACKED_CHANGE_TAG_BY_CHANGE[provenance.change];
|
|
179
179
|
const pPr = properties === void 0 && changeTag !== void 0 ? el("w:pPr", {}, []) : properties;
|
|
180
180
|
if (pPr !== void 0 && changeTag !== void 0 && provenance !== void 0) pPr.children.push(el("w:rPr", {}, [el(changeTag, trackChangeAttrs(state, provenance))]));
|
|
181
|
-
const runs = paragraph.runs.map((run) => buildRun(run, state, deleted));
|
|
181
|
+
const runs = interleaveRunConstructExtents(paragraph.runs.map((run) => buildRun(run, state, deleted)), paragraph, state);
|
|
182
182
|
const content = changeTag === void 0 || provenance === void 0 ? runs : [el(changeTag, trackChangeAttrs(state, provenance), runs)];
|
|
183
183
|
return el("w:p", {}, [...pPr === void 0 ? [] : [pPr], ...content]);
|
|
184
184
|
}
|
|
185
|
+
function interleaveRunConstructExtents(runElements, paragraph, state) {
|
|
186
|
+
if (paragraph.constructs === void 0) return [...runElements];
|
|
187
|
+
const fault = findRunConstructFault(paragraph);
|
|
188
|
+
if (fault !== void 0) throw new Error(`buildDocxPackageFromContent: run-level construct extent at index ${String(fault.index)} of a paragraph does not name real runs (${fault.kind})`);
|
|
189
|
+
const bookmarks = paragraph.constructs.filter((extent) => extent.descriptor.kind === "anchor" && extent.descriptor.anchorType === "bookmark");
|
|
190
|
+
if (bookmarks.length === 0) return [...runElements];
|
|
191
|
+
const closingAt = /* @__PURE__ */ new Map();
|
|
192
|
+
const openingAt = /* @__PURE__ */ new Map();
|
|
193
|
+
const pointAt = /* @__PURE__ */ new Map();
|
|
194
|
+
const push = (map, position, element) => {
|
|
195
|
+
const existing = map.get(position);
|
|
196
|
+
if (existing === void 0) map.set(position, [element]);
|
|
197
|
+
else existing.push(element);
|
|
198
|
+
};
|
|
199
|
+
for (const bookmark of bookmarks) {
|
|
200
|
+
const id = String(state.nextMarkerId++);
|
|
201
|
+
const open = el("w:bookmarkStart", {
|
|
202
|
+
"w:id": id,
|
|
203
|
+
"w:name": encodeXmlText(bookmark.descriptor.name)
|
|
204
|
+
});
|
|
205
|
+
const close = el("w:bookmarkEnd", { "w:id": id });
|
|
206
|
+
if (bookmark.startRun === bookmark.endRun) {
|
|
207
|
+
push(pointAt, bookmark.startRun, open);
|
|
208
|
+
push(pointAt, bookmark.startRun, close);
|
|
209
|
+
} else {
|
|
210
|
+
push(openingAt, bookmark.startRun, open);
|
|
211
|
+
push(closingAt, bookmark.endRun, close);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const out = [];
|
|
215
|
+
for (let position = 0; position <= runElements.length; position++) {
|
|
216
|
+
for (const close of closingAt.get(position) ?? []) out.push(close);
|
|
217
|
+
for (const open of openingAt.get(position) ?? []) out.push(open);
|
|
218
|
+
for (const half of pointAt.get(position) ?? []) out.push(half);
|
|
219
|
+
const run = runElements[position];
|
|
220
|
+
if (run !== void 0) out.push(run);
|
|
221
|
+
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
185
224
|
function trailingEmptyRunElements(paragraph, element) {
|
|
186
225
|
const runElements = [];
|
|
187
226
|
for (const child of element.children) if (child.type === "element" && (child.tag === "w:r" || child.tag === "w:hyperlink")) runElements.push(child);
|
package/dist/typed/embedded.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_read = require("../read-
|
|
2
|
+
const require_read = require("../read-Di5UfiSh.cjs");
|
|
3
3
|
exports.readEmbeddedOoxmlPayload = require_read.readEmbeddedOoxmlPayload;
|
|
4
4
|
exports.readEmbeddedPayloadPart = require_read.readEmbeddedPayloadPart;
|
package/dist/typed/embedded.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as readEmbeddedOoxmlPayload, o as readEmbeddedPayloadPart } from "../read-
|
|
1
|
+
import { a as readEmbeddedOoxmlPayload, o as readEmbeddedPayloadPart } from "../read-BQoFiqsb.js";
|
|
2
2
|
export { readEmbeddedOoxmlPayload, readEmbeddedPayloadPart };
|
package/dist/typed/pptx/read.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_read = require("../../read-
|
|
2
|
+
const require_read = require("../../read-Di5UfiSh.cjs");
|
|
3
3
|
exports.PptxDocumentSchema = require_read.PptxDocumentSchema;
|
|
4
4
|
exports.readPptxContent = require_read.readPptxContent;
|
package/dist/typed/pptx/read.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as readPptxContent, s as PptxDocumentSchema } from "../../read-
|
|
1
|
+
import { c as readPptxContent, s as PptxDocumentSchema } from "../../read-BQoFiqsb.js";
|
|
2
2
|
export { PptxDocumentSchema, readPptxContent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ooxml.js",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Type-safe, lossless round-trip conversion between OOXML packages (docx, pptx, xlsx) and JSON, built on Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"packageManager": "pnpm@11.6.0",
|
|
82
82
|
"dependencies": {
|
|
83
83
|
"archive-codec": "^1.1.0",
|
|
84
|
-
"document-schema.js": "^4.
|
|
84
|
+
"document-schema.js": "^4.5.0",
|
|
85
85
|
"fast-xml-parser": "^5.10.1",
|
|
86
86
|
"fflate": "^0.8.3",
|
|
87
87
|
"zod": "^4.4.3"
|