odf.js 1.7.0 → 1.9.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 +5 -3
- package/dist/index.cjs +90 -11
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +89 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,9 +18,11 @@ This package is under active development. What's built and shipped:
|
|
|
18
18
|
- **Namespaces, media types, mimetype, manifest** (`src/ns.ts`, `src/media-type.ts`, `src/mimetype.ts`, `src/manifest.ts`) — full read *and* write, including `META-INF/manifest.xml`'s exhaustive per-part enumeration and the mimetype part's mandatory first-entry/stored/uncompressed byte layout, verified against real LibreOffice-produced output.
|
|
19
19
|
- **Style interning** (`src/styles/`) — `StyleRegistry`: adopts a part's existing automatic styles on construction, finds-or-mints on `intern()`, fingerprints on canonical serialized properties plus parent style name (never `JSON.stringify`), and is collision-checked across all four style containers a document can have.
|
|
20
20
|
- **Shared typed primitives** (`src/typed/shared/`) — ODF length-unit parsing (`cm`/`mm`/`in`/`pt`/`pc`/`px`), A1-style spreadsheet cell-reference computation with repeat-count cursor advancement, colour/geometry/master-page-size parsing into `document-content-model`'s own types, ODF's `text:s`/`text:tab`/`text:line-break` whitespace-run decoding, the read-side style cascade (`style:default-style` → parent chain → the referenced style — one layer shorter than OOXML's, since ODF has no separate direct-formatting layer on top), the `draw:transform`/`draw:g` group-flattening geometry resolver, an `svg:d`/`draw:points` vector-path grammar parser, and `meta.xml` reading.
|
|
21
|
-
- **Typed readers** — `readOdt` (wordprocessing), `readOdp` (presentation slides: `draw:frame`/`draw:g` text/image/table content),
|
|
21
|
+
- **Typed readers** — `readOdt` (wordprocessing), `readOdp` (presentation slides: `draw:frame`/`draw:g` text/image/table content), `readOdg` (drawing pages: every vector primitive — `draw:rect`/`draw:ellipse`/`draw:circle`/`draw:line`/`draw:path`/`draw:polygon`/`draw:polyline`, plus a recognised `draw:custom-shape` preset subset — in real `draw:z-index`-aware paint order), and `readOds` (spreadsheets: geometry- and print-settings-rich, every `office:value-type` variant with its own OpenFormula string) each resolve a `Package` into `document-content-model`'s own `ContentSection`/`ContentSlide`/`ContentDrawPage`/`ContentSheet` shapes.
|
|
22
|
+
- **`readOdfFormula`** resolves a standalone or embedded `.odf` formula's `content.xml` — bare MathML with no `office:document-content` wrapper, confirmed against real LibreOffice output — into its raw MathML nodes plus, when present, the formula's own native StarMath annotation string. There is no `document-content-model` pivot type for MathML, so this reader's own output type is its own.
|
|
23
|
+
- **`readOdm`** resolves a `.odm` master document's own `content.xml` into an ordered list of chapter references (`{ name, href, filterName? }`, one per top-level linked `text:section`) without opening the external `.odt` files those references point at. A master document's chapters are genuinely external files by ODF design, not embedded package sub-documents — confirmed against real LibreOffice output, which never caches a chapter's own content inside the master document itself (see `src/typed/odm/read.ts`'s own top-of-file note).
|
|
22
24
|
|
|
23
|
-
Not yet built: `
|
|
25
|
+
Not yet built: `readOdbInventory`, live-view editors, and the `.odb` database-table-export subsystem. This section will be replaced with real usage examples once those land — see the [Architecture](#architecture) section below for the intended shape, and this repository's own commit history/releases for current progress.
|
|
24
26
|
|
|
25
27
|
## Getting started
|
|
26
28
|
|
|
@@ -76,7 +78,7 @@ Layered from a lossless core outward, mirroring `ooxml.js`'s own structure:
|
|
|
76
78
|
- **`src/manifest.ts`** — unlike `ooxml.js` (which only ever *reads* OPC relationships, leaving writing to `documents.js`), `odf.js` owns manifest read **and** write, since the manifest is ODF's one mandatory part and its correctness is exhaustive.
|
|
77
79
|
- **`src/styles/`** — `properties.ts` (the property-bag shape + real ODF attribute parsing), `serialize.ts` (canonical, deterministic property-bag → XML attributes), `registry.ts` (`StyleRegistry`, ODF's mandatory style-interning layer, no OOXML equivalent), `span.ts` (character-range wrapping into a formattable `text:span`, correctly splitting `text:s`/`text:tab` elements that straddle a boundary).
|
|
78
80
|
- **`src/typed/shared/`** — the ODF-specific typed primitives every future format reader builds on: `units.ts`, `a1.ts`, `color.ts`/`geometry.ts` (parsing into `document-content-model`'s own types, never redefining them), `style.ts` (a thin re-export — ODF's style-properties concern is fully covered by `styles/properties.ts` and the cascade below), `text.ts` (whitespace-run decoding), `cascade.ts` (the read-side style-resolution walk), `metadata.ts` (`meta.xml` reading).
|
|
79
|
-
- **`src/typed/odt/`, `src/typed/odp/`, `src/typed/odg/`** — the built `readOdt`/`readOdp`/`readOdg` readers; **`src/typed/draw/`** — the `draw:frame`/`draw:g`/vector-primitive shape vocabulary `readOdp` and `readOdg` both share; **`src/typed/
|
|
81
|
+
- **`src/typed/odt/`, `src/typed/odp/`, `src/typed/odg/`, `src/typed/ods/`** — the built `readOdt`/`readOdp`/`readOdg`/`readOds` readers; **`src/typed/draw/`** — the `draw:frame`/`draw:g`/vector-primitive shape vocabulary `readOdp` and `readOdg` both share; **`src/typed/formula/`, `src/typed/odm/`** — `readOdfFormula` (raw MathML, no `document-content-model` pivot) and `readOdm` (a `.odm` master document's own external chapter references — name/href/filter-name per linked `text:section`, never the linked content itself).
|
|
80
82
|
|
|
81
83
|
## Why no `ooxml.js` dependency
|
|
82
84
|
|
package/dist/index.cjs
CHANGED
|
@@ -2484,7 +2484,7 @@ function readDrawPageContent(children, pkg) {
|
|
|
2484
2484
|
}
|
|
2485
2485
|
//#endregion
|
|
2486
2486
|
//#region src/typed/odp/read.ts
|
|
2487
|
-
const CONTENT_PART$
|
|
2487
|
+
const CONTENT_PART$5 = "content.xml";
|
|
2488
2488
|
function readSlideSize(page, pkg) {
|
|
2489
2489
|
return resolveDrawPageSize(page, pkg) ?? document_content_model.SLIDE_SIZE_WIDESCREEN;
|
|
2490
2490
|
}
|
|
@@ -2503,7 +2503,7 @@ function readSlide(page, pkg) {
|
|
|
2503
2503
|
};
|
|
2504
2504
|
}
|
|
2505
2505
|
function readOdp(pkg) {
|
|
2506
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2506
|
+
const contentPart = pkg.parts[CONTENT_PART$5];
|
|
2507
2507
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2508
2508
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2509
2509
|
const presentation = body === void 0 ? void 0 : findChildElement(body.children, "office:presentation");
|
|
@@ -2515,9 +2515,9 @@ function readOdp(pkg) {
|
|
|
2515
2515
|
}
|
|
2516
2516
|
//#endregion
|
|
2517
2517
|
//#region src/typed/odt/read.ts
|
|
2518
|
-
const CONTENT_PART$
|
|
2518
|
+
const CONTENT_PART$4 = "content.xml";
|
|
2519
2519
|
const STYLES_PART = "styles.xml";
|
|
2520
|
-
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART$
|
|
2520
|
+
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART$4, STYLES_PART];
|
|
2521
2521
|
function readOutlineLevel(headingElement) {
|
|
2522
2522
|
const raw = attrValue(headingElement, "text:outline-level");
|
|
2523
2523
|
if (raw === void 0) return 1;
|
|
@@ -2600,12 +2600,12 @@ function readFirstMasterPageGeometry(pkg) {
|
|
|
2600
2600
|
};
|
|
2601
2601
|
}
|
|
2602
2602
|
function readOdt(pkg) {
|
|
2603
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2604
|
-
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART$
|
|
2603
|
+
const contentPart = pkg.parts[CONTENT_PART$4];
|
|
2604
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART$4} part`);
|
|
2605
2605
|
const contentRoot = rootElement(contentPart.nodes);
|
|
2606
2606
|
const body = contentRoot === void 0 ? void 0 : findChildElement(contentRoot.children, "office:body");
|
|
2607
2607
|
const textElement = body === void 0 ? void 0 : findChildElement(body.children, "office:text");
|
|
2608
|
-
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART$
|
|
2608
|
+
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART$4} has no office:body/office:text element`);
|
|
2609
2609
|
const metadata = readOdfMetadata(pkg);
|
|
2610
2610
|
const { pageSize, margins } = readFirstMasterPageGeometry(pkg);
|
|
2611
2611
|
return {
|
|
@@ -2619,7 +2619,7 @@ function readOdt(pkg) {
|
|
|
2619
2619
|
}
|
|
2620
2620
|
//#endregion
|
|
2621
2621
|
//#region src/typed/odg/read.ts
|
|
2622
|
-
const CONTENT_PART$
|
|
2622
|
+
const CONTENT_PART$3 = "content.xml";
|
|
2623
2623
|
const DEFAULT_PAGE_SIZE$1 = document_content_model.PAGE_SIZE_A4;
|
|
2624
2624
|
function readPage(page, pkg) {
|
|
2625
2625
|
const size = resolveDrawPageSize(page, pkg) ?? DEFAULT_PAGE_SIZE$1;
|
|
@@ -2631,7 +2631,7 @@ function readPage(page, pkg) {
|
|
|
2631
2631
|
};
|
|
2632
2632
|
}
|
|
2633
2633
|
function readOdg(pkg) {
|
|
2634
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2634
|
+
const contentPart = pkg.parts[CONTENT_PART$3];
|
|
2635
2635
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2636
2636
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2637
2637
|
const drawing = body === void 0 ? void 0 : findChildElement(body.children, "office:drawing");
|
|
@@ -2643,7 +2643,7 @@ function readOdg(pkg) {
|
|
|
2643
2643
|
}
|
|
2644
2644
|
//#endregion
|
|
2645
2645
|
//#region src/typed/ods/read.ts
|
|
2646
|
-
const CONTENT_PART = "content.xml";
|
|
2646
|
+
const CONTENT_PART$2 = "content.xml";
|
|
2647
2647
|
function parseKnownOdfLength(value) {
|
|
2648
2648
|
const parsed = parseOdfLength(value);
|
|
2649
2649
|
if (parsed === void 0) throw new Error(`readOds: internal error -- "${value}" is not a valid ODF length literal`);
|
|
@@ -2933,7 +2933,7 @@ function readSheet(tableElement, pkg) {
|
|
|
2933
2933
|
};
|
|
2934
2934
|
}
|
|
2935
2935
|
function readOds(pkg) {
|
|
2936
|
-
const contentPart = pkg.parts[CONTENT_PART];
|
|
2936
|
+
const contentPart = pkg.parts[CONTENT_PART$2];
|
|
2937
2937
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2938
2938
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2939
2939
|
const spreadsheet = body === void 0 ? void 0 : findChildElement(body.children, "office:spreadsheet");
|
|
@@ -2949,6 +2949,83 @@ function readOds(pkg) {
|
|
|
2949
2949
|
};
|
|
2950
2950
|
}
|
|
2951
2951
|
//#endregion
|
|
2952
|
+
//#region src/typed/formula/read.ts
|
|
2953
|
+
const CONTENT_PART$1 = "content.xml";
|
|
2954
|
+
const MATH_ROOT_TAGS = ["math", "math:math"];
|
|
2955
|
+
const ANNOTATION_TAGS = ["annotation", "math:annotation"];
|
|
2956
|
+
const STARMATH_ENCODING_PREFIX = "StarMath";
|
|
2957
|
+
function findMathRoot(nodes) {
|
|
2958
|
+
const root = rootElement(nodes);
|
|
2959
|
+
if (root === void 0) return;
|
|
2960
|
+
if (MATH_ROOT_TAGS.includes(root.tag)) return root;
|
|
2961
|
+
for (const tag of MATH_ROOT_TAGS) {
|
|
2962
|
+
const [found] = elementsWithTag(root.children, tag);
|
|
2963
|
+
if (found !== void 0) return found;
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
function annotationText(element) {
|
|
2967
|
+
let text = "";
|
|
2968
|
+
for (const child of element.children) if (child.type === "text") text += decodeXmlText(child.value);
|
|
2969
|
+
return text;
|
|
2970
|
+
}
|
|
2971
|
+
function findStarMathAnnotation(mathRoot) {
|
|
2972
|
+
for (const tag of ANNOTATION_TAGS) for (const annotation of elementsWithTag(mathRoot.children, tag)) {
|
|
2973
|
+
if (!attrValue(annotation, "encoding")?.startsWith(STARMATH_ENCODING_PREFIX)) continue;
|
|
2974
|
+
const text = annotationText(annotation);
|
|
2975
|
+
if (text.length > 0) return text;
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
function readOdfFormula(pkg) {
|
|
2979
|
+
const contentPart = pkg.parts[CONTENT_PART$1];
|
|
2980
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdfFormula: package has no ${CONTENT_PART$1} part`);
|
|
2981
|
+
const mathRoot = findMathRoot(contentPart.nodes);
|
|
2982
|
+
if (mathRoot === void 0) throw new Error(`readOdfFormula: ${CONTENT_PART$1} has no MathML root element`);
|
|
2983
|
+
const metadata = readOdfMetadata(pkg);
|
|
2984
|
+
const starMath = findStarMathAnnotation(mathRoot);
|
|
2985
|
+
return starMath === void 0 ? {
|
|
2986
|
+
mathml: mathRoot.children,
|
|
2987
|
+
metadata
|
|
2988
|
+
} : {
|
|
2989
|
+
starMath,
|
|
2990
|
+
mathml: mathRoot.children,
|
|
2991
|
+
metadata
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
//#endregion
|
|
2995
|
+
//#region src/typed/odm/read.ts
|
|
2996
|
+
const CONTENT_PART = "content.xml";
|
|
2997
|
+
function readSection(element) {
|
|
2998
|
+
const sourceElement = findChildElement(element.children, "text:section-source");
|
|
2999
|
+
if (sourceElement === void 0) return;
|
|
3000
|
+
const name = attrValue(element, "text:name");
|
|
3001
|
+
const href = attrValue(sourceElement, "xlink:href");
|
|
3002
|
+
if (name === void 0 || href === void 0) return;
|
|
3003
|
+
const filterName = attrValue(sourceElement, "text:filter-name");
|
|
3004
|
+
return filterName === void 0 ? {
|
|
3005
|
+
name,
|
|
3006
|
+
href
|
|
3007
|
+
} : {
|
|
3008
|
+
name,
|
|
3009
|
+
href,
|
|
3010
|
+
filterName
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
function readOdm(pkg) {
|
|
3014
|
+
const contentPart = pkg.parts[CONTENT_PART];
|
|
3015
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdm: package has no ${CONTENT_PART} part`);
|
|
3016
|
+
const contentRoot = rootElement(contentPart.nodes);
|
|
3017
|
+
const body = contentRoot === void 0 ? void 0 : findChildElement(contentRoot.children, "office:body");
|
|
3018
|
+
const textElement = body === void 0 ? void 0 : findChildElement(body.children, "office:text");
|
|
3019
|
+
if (textElement === void 0) throw new Error(`readOdm: ${CONTENT_PART} has no office:body/office:text element`);
|
|
3020
|
+
const sections = [];
|
|
3021
|
+
for (const node of textElement.children) {
|
|
3022
|
+
if (node.type !== "element" || node.tag !== "text:section") continue;
|
|
3023
|
+
const section = readSection(node);
|
|
3024
|
+
if (section !== void 0) sections.push(section);
|
|
3025
|
+
}
|
|
3026
|
+
return { sections };
|
|
3027
|
+
}
|
|
3028
|
+
//#endregion
|
|
2952
3029
|
Object.defineProperty(exports, "AlignmentSchema", {
|
|
2953
3030
|
enumerable: true,
|
|
2954
3031
|
get: function() {
|
|
@@ -3037,10 +3114,12 @@ exports.readDrawFrame = readDrawFrame;
|
|
|
3037
3114
|
exports.readDrawPageContent = readDrawPageContent;
|
|
3038
3115
|
exports.readManifest = readManifest;
|
|
3039
3116
|
exports.readMimetype = readMimetype;
|
|
3117
|
+
exports.readOdfFormula = readOdfFormula;
|
|
3040
3118
|
exports.readOdfMetadata = readOdfMetadata;
|
|
3041
3119
|
exports.readOdfParagraph = readOdfParagraph;
|
|
3042
3120
|
exports.readOdfTable = readOdfTable;
|
|
3043
3121
|
exports.readOdg = readOdg;
|
|
3122
|
+
exports.readOdm = readOdm;
|
|
3044
3123
|
exports.readOdp = readOdp;
|
|
3045
3124
|
exports.readOds = readOds;
|
|
3046
3125
|
exports.readOdt = readOdt;
|
package/dist/index.d.cts
CHANGED
|
@@ -642,4 +642,24 @@ interface OdsDocument {
|
|
|
642
642
|
}
|
|
643
643
|
declare function readOds(pkg: Package): OdsDocument;
|
|
644
644
|
//#endregion
|
|
645
|
-
|
|
645
|
+
//#region src/typed/formula/read.d.ts
|
|
646
|
+
interface OdfFormulaDocument {
|
|
647
|
+
starMath?: string;
|
|
648
|
+
mathml: XmlNode[];
|
|
649
|
+
metadata: LayoutMetadata;
|
|
650
|
+
}
|
|
651
|
+
declare function readOdfFormula(pkg: Package): OdfFormulaDocument;
|
|
652
|
+
//#endregion
|
|
653
|
+
//#region src/typed/odm/read.d.ts
|
|
654
|
+
interface OdmSection {
|
|
655
|
+
name: string;
|
|
656
|
+
href: string;
|
|
657
|
+
filterName?: string;
|
|
658
|
+
inlineContent?: readonly XmlNode[];
|
|
659
|
+
}
|
|
660
|
+
interface OdmDocument {
|
|
661
|
+
sections: readonly OdmSection[];
|
|
662
|
+
}
|
|
663
|
+
declare function readOdm(pkg: Package): OdmDocument;
|
|
664
|
+
//#endregion
|
|
665
|
+
export { type Alignment, AlignmentSchema, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type BuildManifestOptions, type CascadeDiagnostic, type DrawPageContent, type ImageFormat, type InternRequest, type LengthUnit, MANIFEST_PART, META_PART, MIMETYPE_PART, type Manifest, type ManifestEntry, ManifestEntrySchema, type ManifestProblem, ManifestProblemSchema, ManifestSchema, ODF_MEDIA_TYPES, ODF_NAMESPACES, type OdfExtension, type OdfFormulaDocument, type OdfNamespacePrefix, type OdfPoint, type OdfRawPoint, type OdfRawSegment, type OdfRawSubpath, type OdfShapeGeometry, type OdfTransformFunction, type OdfViewBox, type OdgDocument, type OdmDocument, type OdmSection, type OdpDocument, type OdsDocument, type OdtDocument, type OtherPartRef, type Package, PackageSchema, type ParsedProperties, type Part, PartSchema, STYLE_FAMILIES, type StyleCascadeResult, type StyleElementChainResult, type StyleFamily, type StyleProperties, StylePropertiesSchema, StyleRegistry, type StyleRegistryOptions, TableCursor, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, type ZipEntry, applyOdfTransform, attrValue, base64ToBytes, buildManifest, buildOdfSubpaths, buildStylePropertyElements, buildXml, bytesToBase64, canonicalPropertiesString, cellReference, childrenWithTag, columnIndexToLetters, columnLettersToIndex, composeOdfGroupTransform, decodeOdfText, decodePackage, decodeXmlText, el, elementsWithTag, encodePackage, encodeXmlText, ensureSpan, findChildElement, findStyleElement, formatOdfColor, formatOdfLength, formatPercentageMultiplier, formatPt, getOdfSpaceCount, isStyleFamily, isXmlNode, measureOdfNodeLength, mediaTypeForExtension, netRotationDeg, packageCodec, paragraphPropertiesToAttributes, parseBox, parseCellReference, parseLength, parseLinePoints, parseMargins, parseOdfColor, parseOdfLength, parseOdfPathData, parseOdfPointsList, parseOdfTransform, parseOdfViewBox, parsePackage, parsePageSize, parseParagraphProperties, parseStyleElementProperties, parseTextProperties, parseXml, rawSubpathFromPoints, readDrawFrame, readDrawPageContent, readManifest, readMimetype, readOdfFormula, readOdfMetadata, readOdfParagraph, readOdfTable, readOdg, readOdm, readOdp, readOds, readOdt, resolveDrawPageSize, resolveOdfShapeGeometry, resolvePageLayoutProperties, resolveStyle, resolveStyleElementChain, rootElement, scaleOdfRawPoint, serializePackage, setDocumentMediaType, sniffImageFormat, sumOdfNodeLength, syncManifest, textPropertiesToAttributes, txt, unzipPackage, validateManifest, walkDrawShapes, writeManifest, writeMimetype, xmlCodec, xmlnsAttributes, zipPackage };
|
package/dist/index.d.ts
CHANGED
|
@@ -642,4 +642,24 @@ interface OdsDocument {
|
|
|
642
642
|
}
|
|
643
643
|
declare function readOds(pkg: Package): OdsDocument;
|
|
644
644
|
//#endregion
|
|
645
|
-
|
|
645
|
+
//#region src/typed/formula/read.d.ts
|
|
646
|
+
interface OdfFormulaDocument {
|
|
647
|
+
starMath?: string;
|
|
648
|
+
mathml: XmlNode[];
|
|
649
|
+
metadata: LayoutMetadata;
|
|
650
|
+
}
|
|
651
|
+
declare function readOdfFormula(pkg: Package): OdfFormulaDocument;
|
|
652
|
+
//#endregion
|
|
653
|
+
//#region src/typed/odm/read.d.ts
|
|
654
|
+
interface OdmSection {
|
|
655
|
+
name: string;
|
|
656
|
+
href: string;
|
|
657
|
+
filterName?: string;
|
|
658
|
+
inlineContent?: readonly XmlNode[];
|
|
659
|
+
}
|
|
660
|
+
interface OdmDocument {
|
|
661
|
+
sections: readonly OdmSection[];
|
|
662
|
+
}
|
|
663
|
+
declare function readOdm(pkg: Package): OdmDocument;
|
|
664
|
+
//#endregion
|
|
665
|
+
export { type Alignment, AlignmentSchema, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type BuildManifestOptions, type CascadeDiagnostic, type DrawPageContent, type ImageFormat, type InternRequest, type LengthUnit, MANIFEST_PART, META_PART, MIMETYPE_PART, type Manifest, type ManifestEntry, ManifestEntrySchema, type ManifestProblem, ManifestProblemSchema, ManifestSchema, ODF_MEDIA_TYPES, ODF_NAMESPACES, type OdfExtension, type OdfFormulaDocument, type OdfNamespacePrefix, type OdfPoint, type OdfRawPoint, type OdfRawSegment, type OdfRawSubpath, type OdfShapeGeometry, type OdfTransformFunction, type OdfViewBox, type OdgDocument, type OdmDocument, type OdmSection, type OdpDocument, type OdsDocument, type OdtDocument, type OtherPartRef, type Package, PackageSchema, type ParsedProperties, type Part, PartSchema, STYLE_FAMILIES, type StyleCascadeResult, type StyleElementChainResult, type StyleFamily, type StyleProperties, StylePropertiesSchema, StyleRegistry, type StyleRegistryOptions, TableCursor, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, type ZipEntry, applyOdfTransform, attrValue, base64ToBytes, buildManifest, buildOdfSubpaths, buildStylePropertyElements, buildXml, bytesToBase64, canonicalPropertiesString, cellReference, childrenWithTag, columnIndexToLetters, columnLettersToIndex, composeOdfGroupTransform, decodeOdfText, decodePackage, decodeXmlText, el, elementsWithTag, encodePackage, encodeXmlText, ensureSpan, findChildElement, findStyleElement, formatOdfColor, formatOdfLength, formatPercentageMultiplier, formatPt, getOdfSpaceCount, isStyleFamily, isXmlNode, measureOdfNodeLength, mediaTypeForExtension, netRotationDeg, packageCodec, paragraphPropertiesToAttributes, parseBox, parseCellReference, parseLength, parseLinePoints, parseMargins, parseOdfColor, parseOdfLength, parseOdfPathData, parseOdfPointsList, parseOdfTransform, parseOdfViewBox, parsePackage, parsePageSize, parseParagraphProperties, parseStyleElementProperties, parseTextProperties, parseXml, rawSubpathFromPoints, readDrawFrame, readDrawPageContent, readManifest, readMimetype, readOdfFormula, readOdfMetadata, readOdfParagraph, readOdfTable, readOdg, readOdm, readOdp, readOds, readOdt, resolveDrawPageSize, resolveOdfShapeGeometry, resolvePageLayoutProperties, resolveStyle, resolveStyleElementChain, rootElement, scaleOdfRawPoint, serializePackage, setDocumentMediaType, sniffImageFormat, sumOdfNodeLength, syncManifest, textPropertiesToAttributes, txt, unzipPackage, validateManifest, walkDrawShapes, writeManifest, writeMimetype, xmlCodec, xmlnsAttributes, zipPackage };
|
package/dist/index.js
CHANGED
|
@@ -2483,7 +2483,7 @@ function readDrawPageContent(children, pkg) {
|
|
|
2483
2483
|
}
|
|
2484
2484
|
//#endregion
|
|
2485
2485
|
//#region src/typed/odp/read.ts
|
|
2486
|
-
const CONTENT_PART$
|
|
2486
|
+
const CONTENT_PART$5 = "content.xml";
|
|
2487
2487
|
function readSlideSize(page, pkg) {
|
|
2488
2488
|
return resolveDrawPageSize(page, pkg) ?? SLIDE_SIZE_WIDESCREEN;
|
|
2489
2489
|
}
|
|
@@ -2502,7 +2502,7 @@ function readSlide(page, pkg) {
|
|
|
2502
2502
|
};
|
|
2503
2503
|
}
|
|
2504
2504
|
function readOdp(pkg) {
|
|
2505
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2505
|
+
const contentPart = pkg.parts[CONTENT_PART$5];
|
|
2506
2506
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2507
2507
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2508
2508
|
const presentation = body === void 0 ? void 0 : findChildElement(body.children, "office:presentation");
|
|
@@ -2514,9 +2514,9 @@ function readOdp(pkg) {
|
|
|
2514
2514
|
}
|
|
2515
2515
|
//#endregion
|
|
2516
2516
|
//#region src/typed/odt/read.ts
|
|
2517
|
-
const CONTENT_PART$
|
|
2517
|
+
const CONTENT_PART$4 = "content.xml";
|
|
2518
2518
|
const STYLES_PART = "styles.xml";
|
|
2519
|
-
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART$
|
|
2519
|
+
const AUTOMATIC_STYLE_PARTS = [CONTENT_PART$4, STYLES_PART];
|
|
2520
2520
|
function readOutlineLevel(headingElement) {
|
|
2521
2521
|
const raw = attrValue(headingElement, "text:outline-level");
|
|
2522
2522
|
if (raw === void 0) return 1;
|
|
@@ -2599,12 +2599,12 @@ function readFirstMasterPageGeometry(pkg) {
|
|
|
2599
2599
|
};
|
|
2600
2600
|
}
|
|
2601
2601
|
function readOdt(pkg) {
|
|
2602
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2603
|
-
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART$
|
|
2602
|
+
const contentPart = pkg.parts[CONTENT_PART$4];
|
|
2603
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdt: package has no ${CONTENT_PART$4} part`);
|
|
2604
2604
|
const contentRoot = rootElement(contentPart.nodes);
|
|
2605
2605
|
const body = contentRoot === void 0 ? void 0 : findChildElement(contentRoot.children, "office:body");
|
|
2606
2606
|
const textElement = body === void 0 ? void 0 : findChildElement(body.children, "office:text");
|
|
2607
|
-
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART$
|
|
2607
|
+
if (textElement === void 0) throw new Error(`readOdt: ${CONTENT_PART$4} has no office:body/office:text element`);
|
|
2608
2608
|
const metadata = readOdfMetadata(pkg);
|
|
2609
2609
|
const { pageSize, margins } = readFirstMasterPageGeometry(pkg);
|
|
2610
2610
|
return {
|
|
@@ -2618,7 +2618,7 @@ function readOdt(pkg) {
|
|
|
2618
2618
|
}
|
|
2619
2619
|
//#endregion
|
|
2620
2620
|
//#region src/typed/odg/read.ts
|
|
2621
|
-
const CONTENT_PART$
|
|
2621
|
+
const CONTENT_PART$3 = "content.xml";
|
|
2622
2622
|
const DEFAULT_PAGE_SIZE$1 = PAGE_SIZE_A4;
|
|
2623
2623
|
function readPage(page, pkg) {
|
|
2624
2624
|
const size = resolveDrawPageSize(page, pkg) ?? DEFAULT_PAGE_SIZE$1;
|
|
@@ -2630,7 +2630,7 @@ function readPage(page, pkg) {
|
|
|
2630
2630
|
};
|
|
2631
2631
|
}
|
|
2632
2632
|
function readOdg(pkg) {
|
|
2633
|
-
const contentPart = pkg.parts[CONTENT_PART$
|
|
2633
|
+
const contentPart = pkg.parts[CONTENT_PART$3];
|
|
2634
2634
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2635
2635
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2636
2636
|
const drawing = body === void 0 ? void 0 : findChildElement(body.children, "office:drawing");
|
|
@@ -2642,7 +2642,7 @@ function readOdg(pkg) {
|
|
|
2642
2642
|
}
|
|
2643
2643
|
//#endregion
|
|
2644
2644
|
//#region src/typed/ods/read.ts
|
|
2645
|
-
const CONTENT_PART = "content.xml";
|
|
2645
|
+
const CONTENT_PART$2 = "content.xml";
|
|
2646
2646
|
function parseKnownOdfLength(value) {
|
|
2647
2647
|
const parsed = parseOdfLength(value);
|
|
2648
2648
|
if (parsed === void 0) throw new Error(`readOds: internal error -- "${value}" is not a valid ODF length literal`);
|
|
@@ -2932,7 +2932,7 @@ function readSheet(tableElement, pkg) {
|
|
|
2932
2932
|
};
|
|
2933
2933
|
}
|
|
2934
2934
|
function readOds(pkg) {
|
|
2935
|
-
const contentPart = pkg.parts[CONTENT_PART];
|
|
2935
|
+
const contentPart = pkg.parts[CONTENT_PART$2];
|
|
2936
2936
|
const root = contentPart?.kind === "xml" ? rootElement(contentPart.nodes) : void 0;
|
|
2937
2937
|
const body = root === void 0 ? void 0 : findChildElement(root.children, "office:body");
|
|
2938
2938
|
const spreadsheet = body === void 0 ? void 0 : findChildElement(body.children, "office:spreadsheet");
|
|
@@ -2948,4 +2948,81 @@ function readOds(pkg) {
|
|
|
2948
2948
|
};
|
|
2949
2949
|
}
|
|
2950
2950
|
//#endregion
|
|
2951
|
-
|
|
2951
|
+
//#region src/typed/formula/read.ts
|
|
2952
|
+
const CONTENT_PART$1 = "content.xml";
|
|
2953
|
+
const MATH_ROOT_TAGS = ["math", "math:math"];
|
|
2954
|
+
const ANNOTATION_TAGS = ["annotation", "math:annotation"];
|
|
2955
|
+
const STARMATH_ENCODING_PREFIX = "StarMath";
|
|
2956
|
+
function findMathRoot(nodes) {
|
|
2957
|
+
const root = rootElement(nodes);
|
|
2958
|
+
if (root === void 0) return;
|
|
2959
|
+
if (MATH_ROOT_TAGS.includes(root.tag)) return root;
|
|
2960
|
+
for (const tag of MATH_ROOT_TAGS) {
|
|
2961
|
+
const [found] = elementsWithTag(root.children, tag);
|
|
2962
|
+
if (found !== void 0) return found;
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
function annotationText(element) {
|
|
2966
|
+
let text = "";
|
|
2967
|
+
for (const child of element.children) if (child.type === "text") text += decodeXmlText(child.value);
|
|
2968
|
+
return text;
|
|
2969
|
+
}
|
|
2970
|
+
function findStarMathAnnotation(mathRoot) {
|
|
2971
|
+
for (const tag of ANNOTATION_TAGS) for (const annotation of elementsWithTag(mathRoot.children, tag)) {
|
|
2972
|
+
if (!attrValue(annotation, "encoding")?.startsWith(STARMATH_ENCODING_PREFIX)) continue;
|
|
2973
|
+
const text = annotationText(annotation);
|
|
2974
|
+
if (text.length > 0) return text;
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
function readOdfFormula(pkg) {
|
|
2978
|
+
const contentPart = pkg.parts[CONTENT_PART$1];
|
|
2979
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdfFormula: package has no ${CONTENT_PART$1} part`);
|
|
2980
|
+
const mathRoot = findMathRoot(contentPart.nodes);
|
|
2981
|
+
if (mathRoot === void 0) throw new Error(`readOdfFormula: ${CONTENT_PART$1} has no MathML root element`);
|
|
2982
|
+
const metadata = readOdfMetadata(pkg);
|
|
2983
|
+
const starMath = findStarMathAnnotation(mathRoot);
|
|
2984
|
+
return starMath === void 0 ? {
|
|
2985
|
+
mathml: mathRoot.children,
|
|
2986
|
+
metadata
|
|
2987
|
+
} : {
|
|
2988
|
+
starMath,
|
|
2989
|
+
mathml: mathRoot.children,
|
|
2990
|
+
metadata
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
//#endregion
|
|
2994
|
+
//#region src/typed/odm/read.ts
|
|
2995
|
+
const CONTENT_PART = "content.xml";
|
|
2996
|
+
function readSection(element) {
|
|
2997
|
+
const sourceElement = findChildElement(element.children, "text:section-source");
|
|
2998
|
+
if (sourceElement === void 0) return;
|
|
2999
|
+
const name = attrValue(element, "text:name");
|
|
3000
|
+
const href = attrValue(sourceElement, "xlink:href");
|
|
3001
|
+
if (name === void 0 || href === void 0) return;
|
|
3002
|
+
const filterName = attrValue(sourceElement, "text:filter-name");
|
|
3003
|
+
return filterName === void 0 ? {
|
|
3004
|
+
name,
|
|
3005
|
+
href
|
|
3006
|
+
} : {
|
|
3007
|
+
name,
|
|
3008
|
+
href,
|
|
3009
|
+
filterName
|
|
3010
|
+
};
|
|
3011
|
+
}
|
|
3012
|
+
function readOdm(pkg) {
|
|
3013
|
+
const contentPart = pkg.parts[CONTENT_PART];
|
|
3014
|
+
if (contentPart?.kind !== "xml") throw new Error(`readOdm: package has no ${CONTENT_PART} part`);
|
|
3015
|
+
const contentRoot = rootElement(contentPart.nodes);
|
|
3016
|
+
const body = contentRoot === void 0 ? void 0 : findChildElement(contentRoot.children, "office:body");
|
|
3017
|
+
const textElement = body === void 0 ? void 0 : findChildElement(body.children, "office:text");
|
|
3018
|
+
if (textElement === void 0) throw new Error(`readOdm: ${CONTENT_PART} has no office:body/office:text element`);
|
|
3019
|
+
const sections = [];
|
|
3020
|
+
for (const node of textElement.children) {
|
|
3021
|
+
if (node.type !== "element" || node.tag !== "text:section") continue;
|
|
3022
|
+
const section = readSection(node);
|
|
3023
|
+
if (section !== void 0) sections.push(section);
|
|
3024
|
+
}
|
|
3025
|
+
return { sections };
|
|
3026
|
+
}
|
|
3027
|
+
//#endregion
|
|
3028
|
+
export { AlignmentSchema, AttributeSchema, BinaryPartSchema, MANIFEST_PART, META_PART, MIMETYPE_PART, ManifestEntrySchema, ManifestProblemSchema, ManifestSchema, ODF_MEDIA_TYPES, ODF_NAMESPACES, PackageSchema, PartSchema, STYLE_FAMILIES, StylePropertiesSchema, StyleRegistry, TableCursor, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, applyOdfTransform, attrValue, base64ToBytes, buildManifest, buildOdfSubpaths, buildStylePropertyElements, buildXml, bytesToBase64, canonicalPropertiesString, cellReference, childrenWithTag, columnIndexToLetters, columnLettersToIndex, composeOdfGroupTransform, decodeOdfText, decodePackage, decodeXmlText, el, elementsWithTag, encodePackage, encodeXmlText, ensureSpan, findChildElement, findStyleElement, formatOdfColor, formatOdfLength, formatPercentageMultiplier, formatPt, getOdfSpaceCount, isStyleFamily, isXmlNode, measureOdfNodeLength, mediaTypeForExtension, netRotationDeg, packageCodec, paragraphPropertiesToAttributes, parseBox, parseCellReference, parseLength, parseLinePoints, parseMargins, parseOdfColor, parseOdfLength, parseOdfPathData, parseOdfPointsList, parseOdfTransform, parseOdfViewBox, parsePackage, parsePageSize, parseParagraphProperties, parseStyleElementProperties, parseTextProperties, parseXml, rawSubpathFromPoints, readDrawFrame, readDrawPageContent, readManifest, readMimetype, readOdfFormula, readOdfMetadata, readOdfParagraph, readOdfTable, readOdg, readOdm, readOdp, readOds, readOdt, resolveDrawPageSize, resolveOdfShapeGeometry, resolvePageLayoutProperties, resolveStyle, resolveStyleElementChain, rootElement, scaleOdfRawPoint, serializePackage, setDocumentMediaType, sniffImageFormat, sumOdfNodeLength, syncManifest, textPropertiesToAttributes, txt, unzipPackage, validateManifest, walkDrawShapes, writeManifest, writeMimetype, xmlCodec, xmlnsAttributes, zipPackage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "odf.js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Type-safe, lossless round-trip conversion between OpenDocument Format packages (odt, ods, odp) and JSON, hand-written and dependency-minimal, built on Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|