odf.js 0.0.0 → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joseph Mearman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs ADDED
@@ -0,0 +1,356 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let zod = require("zod");
3
+ let fast_xml_parser = require("fast-xml-parser");
4
+ let fflate = require("fflate");
5
+ //#region src/model/node.ts
6
+ const AttributeSchema = zod.z.object({
7
+ name: zod.z.string(),
8
+ value: zod.z.string()
9
+ });
10
+ const XmlTextSchema = zod.z.object({
11
+ type: zod.z.literal("text"),
12
+ value: zod.z.string()
13
+ });
14
+ const XmlCdataSchema = zod.z.object({
15
+ type: zod.z.literal("cdata"),
16
+ value: zod.z.string()
17
+ });
18
+ const XmlCommentSchema = zod.z.object({
19
+ type: zod.z.literal("comment"),
20
+ value: zod.z.string()
21
+ });
22
+ const XmlDeclarationSchema = zod.z.object({
23
+ type: zod.z.literal("declaration"),
24
+ attributes: zod.z.array(AttributeSchema)
25
+ });
26
+ const XmlPiSchema = zod.z.object({
27
+ type: zod.z.literal("pi"),
28
+ target: zod.z.string(),
29
+ content: zod.z.string()
30
+ });
31
+ function isRecord$1(value) {
32
+ return typeof value === "object" && value !== null && !Array.isArray(value);
33
+ }
34
+ function isAttribute(value) {
35
+ return isRecord$1(value) && typeof value.name === "string" && typeof value.value === "string";
36
+ }
37
+ function isXmlNode(value) {
38
+ if (!isRecord$1(value)) return false;
39
+ const t = value.type;
40
+ if (t === "text" || t === "cdata" || t === "comment") return typeof value.value === "string";
41
+ if (t === "declaration") return Array.isArray(value.attributes) && value.attributes.every(isAttribute);
42
+ if (t === "pi") return typeof value.target === "string" && typeof value.content === "string";
43
+ if (t === "element") return typeof value.tag === "string" && Array.isArray(value.attributes) && value.attributes.every(isAttribute) && Array.isArray(value.children) && value.children.every(isXmlNode);
44
+ return false;
45
+ }
46
+ const XmlElementSchema = zod.z.object({
47
+ type: zod.z.literal("element"),
48
+ tag: zod.z.string(),
49
+ attributes: zod.z.array(AttributeSchema),
50
+ children: zod.z.array(zod.z.custom(isXmlNode))
51
+ });
52
+ const XmlNodeSchema = zod.z.discriminatedUnion("type", [
53
+ XmlTextSchema,
54
+ XmlCdataSchema,
55
+ XmlCommentSchema,
56
+ XmlDeclarationSchema,
57
+ XmlPiSchema,
58
+ XmlElementSchema
59
+ ]);
60
+ //#endregion
61
+ //#region src/model/package.ts
62
+ const XmlPartSchema = zod.z.object({
63
+ kind: zod.z.literal("xml"),
64
+ nodes: zod.z.array(XmlNodeSchema)
65
+ });
66
+ const BinaryPartSchema = zod.z.object({
67
+ kind: zod.z.literal("binary"),
68
+ base64: zod.z.string()
69
+ });
70
+ const PartSchema = zod.z.discriminatedUnion("kind", [XmlPartSchema, BinaryPartSchema]);
71
+ const PackageSchema = zod.z.object({ parts: zod.z.record(zod.z.string(), PartSchema) });
72
+ //#endregion
73
+ //#region src/util/base64.ts
74
+ const TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
75
+ const DECODE = (() => {
76
+ const map = (/* @__PURE__ */ new Uint8Array(256)).fill(255);
77
+ for (let i = 0; i < 64; i = i + 1) map[TABLE.charCodeAt(i)] = i;
78
+ return map;
79
+ })();
80
+ function bytesToBase64(bytes) {
81
+ let out = "";
82
+ const len = bytes.length;
83
+ for (let i = 0; i < len; i = i + 3) {
84
+ const b0 = bytes[i];
85
+ const b1 = i + 1 < len ? bytes[i + 1] : 0;
86
+ const b2 = i + 2 < len ? bytes[i + 2] : 0;
87
+ out += TABLE[b0 >> 2];
88
+ out += TABLE[(b0 & 3) << 4 | b1 >> 4];
89
+ out += i + 1 < len ? TABLE[(b1 & 15) << 2 | b2 >> 6] : "=";
90
+ out += i + 2 < len ? TABLE[b2 & 63] : "=";
91
+ }
92
+ return out;
93
+ }
94
+ function base64ToBytes(b64) {
95
+ const clean = b64.replace(/[^A-Za-z0-9+/=]/g, "");
96
+ const len = clean.length;
97
+ const out = new Uint8Array(len * 3 / 4 | 0);
98
+ let p = 0;
99
+ for (let i = 0; i < len; i = i + 4) {
100
+ const c0 = DECODE[clean.charCodeAt(i)];
101
+ const c1 = DECODE[clean.charCodeAt(i + 1)];
102
+ const c2 = clean.charCodeAt(i + 2);
103
+ const c3 = clean.charCodeAt(i + 3);
104
+ if (c0 === 255 || c1 === 255) throw new Error("invalid base64 input");
105
+ out[p++] = c0 << 2 | c1 >> 4;
106
+ if (c2 !== 61) {
107
+ const d2 = DECODE[c2];
108
+ out[p++] = (c1 & 15) << 4 | d2 >> 2;
109
+ if (c3 !== 61) {
110
+ const d3 = DECODE[c3];
111
+ out[p++] = (d2 & 3) << 6 | d3;
112
+ }
113
+ }
114
+ }
115
+ return out.subarray(0, p);
116
+ }
117
+ //#endregion
118
+ //#region src/xml/parse.ts
119
+ const PARSER = new fast_xml_parser.XMLParser({
120
+ preserveOrder: true,
121
+ attributeNamePrefix: "@_",
122
+ ignoreAttributes: false,
123
+ textNodeName: "#text",
124
+ cdataPropName: "__cdata",
125
+ commentPropName: "__comment",
126
+ processEntities: false,
127
+ parseTagValue: false,
128
+ trimValues: false
129
+ });
130
+ function parseXml(xml) {
131
+ return parseNodes(PARSER.parse(xml));
132
+ }
133
+ function isRecord(value) {
134
+ return typeof value === "object" && value !== null && !Array.isArray(value);
135
+ }
136
+ function isUnknownArray(value) {
137
+ return Array.isArray(value);
138
+ }
139
+ function asString(value) {
140
+ if (typeof value !== "string") throw new Error(`expected string while parsing XML, got ${typeof value}`);
141
+ return value;
142
+ }
143
+ function parseNodes(raw) {
144
+ if (!isUnknownArray(raw)) throw new Error("fast-xml-parser output was not an ordered array");
145
+ return raw.map(parseNode);
146
+ }
147
+ function parseNode(raw) {
148
+ if (!isRecord(raw)) throw new Error("fast-xml-parser node was not an object");
149
+ let tagKey;
150
+ for (const key of Object.keys(raw)) if (key !== ":@") {
151
+ if (tagKey !== void 0) throw new Error("XML node had multiple tag keys");
152
+ tagKey = key;
153
+ }
154
+ if (tagKey === void 0) throw new Error("XML node had no tag key");
155
+ const attributes = parseAttributes(raw[":@"]);
156
+ if (tagKey === "#text") return {
157
+ type: "text",
158
+ value: asString(raw["#text"])
159
+ };
160
+ if (tagKey === "__comment") return {
161
+ type: "comment",
162
+ value: scalarText(raw.__comment)
163
+ };
164
+ if (tagKey === "__cdata") return {
165
+ type: "cdata",
166
+ value: scalarText(raw.__cdata)
167
+ };
168
+ if (tagKey === "?xml") return {
169
+ type: "declaration",
170
+ attributes
171
+ };
172
+ if (tagKey.startsWith("?")) return {
173
+ type: "pi",
174
+ target: tagKey.slice(1),
175
+ content: scalarText(raw[tagKey])
176
+ };
177
+ return {
178
+ type: "element",
179
+ tag: tagKey,
180
+ attributes,
181
+ children: parseNodes(raw[tagKey])
182
+ };
183
+ }
184
+ function parseAttributes(raw) {
185
+ if (raw === void 0) return [];
186
+ if (!isRecord(raw)) throw new Error("XML attributes were not an object");
187
+ const attrs = [];
188
+ for (const key of Object.keys(raw)) {
189
+ if (!key.startsWith("@_")) throw new Error(`unexpected attribute key without @_ prefix: ${key}`);
190
+ attrs.push({
191
+ name: key.slice(2),
192
+ value: asString(raw[key])
193
+ });
194
+ }
195
+ return attrs;
196
+ }
197
+ function scalarText(raw) {
198
+ if (!isUnknownArray(raw) || raw.length === 0) throw new Error("expected a scalar-text wrapper array");
199
+ const first = raw[0];
200
+ if (!isRecord(first)) throw new Error("scalar-text wrapper was not an object");
201
+ return asString(first["#text"]);
202
+ }
203
+ //#endregion
204
+ //#region src/zip.ts
205
+ function unzipPackage(bytes) {
206
+ return (0, fflate.unzipSync)(bytes);
207
+ }
208
+ function zipPackage(entries) {
209
+ const data = {};
210
+ for (const [path, entry] of entries) if (entry.stored === true) data[path] = [entry.bytes, { level: 0 }];
211
+ else data[path] = entry.bytes;
212
+ return (0, fflate.zipSync)(data);
213
+ }
214
+ //#endregion
215
+ //#region src/package-io/read.ts
216
+ function parsePackage(bytes) {
217
+ const entries = unzipPackage(bytes);
218
+ const parts = {};
219
+ for (const [path, partBytes] of Object.entries(entries)) if (looksLikeXml(partBytes)) parts[path] = {
220
+ kind: "xml",
221
+ nodes: parseXml(new TextDecoder("utf-8").decode(partBytes))
222
+ };
223
+ else parts[path] = {
224
+ kind: "binary",
225
+ base64: bytesToBase64(partBytes)
226
+ };
227
+ return { parts };
228
+ }
229
+ function looksLikeXml(bytes) {
230
+ let i = 0;
231
+ if (bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) i = 3;
232
+ while (i < bytes.length) {
233
+ const b = bytes[i];
234
+ if (b === 32 || b === 9 || b === 10 || b === 13) {
235
+ i = i + 1;
236
+ continue;
237
+ }
238
+ return b === 60;
239
+ }
240
+ return false;
241
+ }
242
+ //#endregion
243
+ //#region src/xml/build.ts
244
+ const BUILDER = new fast_xml_parser.XMLBuilder({
245
+ preserveOrder: true,
246
+ attributeNamePrefix: "@_",
247
+ ignoreAttributes: false,
248
+ textNodeName: "#text",
249
+ cdataPropName: "__cdata",
250
+ commentPropName: "__comment",
251
+ processEntities: false,
252
+ format: false,
253
+ suppressEmptyNode: false
254
+ });
255
+ function buildXml(nodes) {
256
+ const out = BUILDER.build(toOrdered(nodes));
257
+ if (typeof out !== "string") throw new Error("XMLBuilder did not return a string");
258
+ return out;
259
+ }
260
+ function toOrdered(nodes) {
261
+ return nodes.map(toOrderedNode);
262
+ }
263
+ function attrsObject(attributes) {
264
+ const obj = {};
265
+ for (const a of attributes) obj[`@_${a.name}`] = a.value;
266
+ return obj;
267
+ }
268
+ function toOrderedNode(node) {
269
+ switch (node.type) {
270
+ case "text": return { "#text": node.value };
271
+ case "comment": return { __comment: [{ "#text": node.value }] };
272
+ case "cdata": return { __cdata: [{ "#text": node.value }] };
273
+ case "pi": return { [`?${node.target}`]: [{ "#text": node.content }] };
274
+ case "declaration": return {
275
+ "?xml": [{ "#text": "" }],
276
+ ":@": attrsObject(node.attributes)
277
+ };
278
+ case "element": {
279
+ const obj = { [node.tag]: toOrdered(node.children) };
280
+ const attrs = attrsObject(node.attributes);
281
+ if (Object.keys(attrs).length > 0) obj[":@"] = attrs;
282
+ return obj;
283
+ }
284
+ }
285
+ }
286
+ //#endregion
287
+ //#region src/package-io/write.ts
288
+ const MIMETYPE_PART = "mimetype";
289
+ const MANIFEST_PART = "META-INF/manifest.xml";
290
+ function serializePackage(pkg) {
291
+ const remaining = new Map(Object.entries(pkg.parts));
292
+ const entries = [];
293
+ const mimetype = remaining.get(MIMETYPE_PART);
294
+ if (mimetype !== void 0) {
295
+ entries.push([MIMETYPE_PART, {
296
+ bytes: partToBytes(mimetype),
297
+ stored: true
298
+ }]);
299
+ remaining.delete(MIMETYPE_PART);
300
+ }
301
+ const manifest = remaining.get(MANIFEST_PART);
302
+ if (manifest !== void 0) {
303
+ entries.push([MANIFEST_PART, { bytes: partToBytes(manifest) }]);
304
+ remaining.delete(MANIFEST_PART);
305
+ }
306
+ for (const [path, part] of remaining) entries.push([path, { bytes: partToBytes(part) }]);
307
+ return zipPackage(entries);
308
+ }
309
+ function partToBytes(part) {
310
+ switch (part.kind) {
311
+ case "xml": return new TextEncoder().encode(buildXml(part.nodes));
312
+ case "binary": return base64ToBytes(part.base64);
313
+ }
314
+ }
315
+ //#endregion
316
+ //#region src/codec.ts
317
+ const xmlCodec = zod.z.codec(zod.z.string(), zod.z.array(XmlNodeSchema), {
318
+ decode: (xml) => parseXml(xml),
319
+ encode: (nodes) => buildXml(nodes)
320
+ });
321
+ const packageCodec = zod.z.codec(zod.z.instanceof(Uint8Array), PackageSchema, {
322
+ decode: (bytes) => parsePackage(bytes),
323
+ encode: (pkg) => serializePackage(pkg)
324
+ });
325
+ function decodePackage(bytes) {
326
+ return zod.z.decode(packageCodec, bytes);
327
+ }
328
+ function encodePackage(pkg) {
329
+ return zod.z.encode(packageCodec, pkg);
330
+ }
331
+ //#endregion
332
+ exports.AttributeSchema = AttributeSchema;
333
+ exports.BinaryPartSchema = BinaryPartSchema;
334
+ exports.PackageSchema = PackageSchema;
335
+ exports.PartSchema = PartSchema;
336
+ exports.XmlCdataSchema = XmlCdataSchema;
337
+ exports.XmlCommentSchema = XmlCommentSchema;
338
+ exports.XmlDeclarationSchema = XmlDeclarationSchema;
339
+ exports.XmlElementSchema = XmlElementSchema;
340
+ exports.XmlNodeSchema = XmlNodeSchema;
341
+ exports.XmlPartSchema = XmlPartSchema;
342
+ exports.XmlPiSchema = XmlPiSchema;
343
+ exports.XmlTextSchema = XmlTextSchema;
344
+ exports.base64ToBytes = base64ToBytes;
345
+ exports.buildXml = buildXml;
346
+ exports.bytesToBase64 = bytesToBase64;
347
+ exports.decodePackage = decodePackage;
348
+ exports.encodePackage = encodePackage;
349
+ exports.isXmlNode = isXmlNode;
350
+ exports.packageCodec = packageCodec;
351
+ exports.parsePackage = parsePackage;
352
+ exports.parseXml = parseXml;
353
+ exports.serializePackage = serializePackage;
354
+ exports.unzipPackage = unzipPackage;
355
+ exports.xmlCodec = xmlCodec;
356
+ exports.zipPackage = zipPackage;
@@ -0,0 +1,286 @@
1
+ import { z } from "zod";
2
+ //#region src/model/node.d.ts
3
+ declare const AttributeSchema: z.ZodObject<{
4
+ name: z.ZodString;
5
+ value: z.ZodString;
6
+ }, z.core.$strip>;
7
+ type Attribute = z.infer<typeof AttributeSchema>;
8
+ declare const XmlTextSchema: z.ZodObject<{
9
+ type: z.ZodLiteral<"text">;
10
+ value: z.ZodString;
11
+ }, z.core.$strip>;
12
+ type XmlText = z.infer<typeof XmlTextSchema>;
13
+ declare const XmlCdataSchema: z.ZodObject<{
14
+ type: z.ZodLiteral<"cdata">;
15
+ value: z.ZodString;
16
+ }, z.core.$strip>;
17
+ type XmlCdata = z.infer<typeof XmlCdataSchema>;
18
+ declare const XmlCommentSchema: z.ZodObject<{
19
+ type: z.ZodLiteral<"comment">;
20
+ value: z.ZodString;
21
+ }, z.core.$strip>;
22
+ type XmlComment = z.infer<typeof XmlCommentSchema>;
23
+ declare const XmlDeclarationSchema: z.ZodObject<{
24
+ type: z.ZodLiteral<"declaration">;
25
+ attributes: z.ZodArray<z.ZodObject<{
26
+ name: z.ZodString;
27
+ value: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ }, z.core.$strip>;
30
+ type XmlDeclaration = z.infer<typeof XmlDeclarationSchema>;
31
+ declare const XmlPiSchema: z.ZodObject<{
32
+ type: z.ZodLiteral<"pi">;
33
+ target: z.ZodString;
34
+ content: z.ZodString;
35
+ }, z.core.$strip>;
36
+ type XmlPi = z.infer<typeof XmlPiSchema>;
37
+ interface XmlElement {
38
+ type: 'element';
39
+ tag: string;
40
+ attributes: Attribute[];
41
+ children: XmlNode[];
42
+ }
43
+ type XmlNode = XmlText | XmlCdata | XmlComment | XmlDeclaration | XmlPi | XmlElement;
44
+ declare function isXmlNode(value: unknown): value is XmlNode;
45
+ declare const XmlElementSchema: z.ZodObject<{
46
+ type: z.ZodLiteral<"element">;
47
+ tag: z.ZodString;
48
+ attributes: z.ZodArray<z.ZodObject<{
49
+ name: z.ZodString;
50
+ value: z.ZodString;
51
+ }, z.core.$strip>>;
52
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
53
+ }, z.core.$strip>;
54
+ declare const XmlNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
55
+ type: z.ZodLiteral<"text">;
56
+ value: z.ZodString;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ type: z.ZodLiteral<"cdata">;
59
+ value: z.ZodString;
60
+ }, z.core.$strip>, z.ZodObject<{
61
+ type: z.ZodLiteral<"comment">;
62
+ value: z.ZodString;
63
+ }, z.core.$strip>, z.ZodObject<{
64
+ type: z.ZodLiteral<"declaration">;
65
+ attributes: z.ZodArray<z.ZodObject<{
66
+ name: z.ZodString;
67
+ value: z.ZodString;
68
+ }, z.core.$strip>>;
69
+ }, z.core.$strip>, z.ZodObject<{
70
+ type: z.ZodLiteral<"pi">;
71
+ target: z.ZodString;
72
+ content: z.ZodString;
73
+ }, z.core.$strip>, z.ZodObject<{
74
+ type: z.ZodLiteral<"element">;
75
+ tag: z.ZodString;
76
+ attributes: z.ZodArray<z.ZodObject<{
77
+ name: z.ZodString;
78
+ value: z.ZodString;
79
+ }, z.core.$strip>>;
80
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
81
+ }, z.core.$strip>], "type">;
82
+ //#endregion
83
+ //#region src/model/package.d.ts
84
+ declare const XmlPartSchema: z.ZodObject<{
85
+ kind: z.ZodLiteral<"xml">;
86
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
87
+ type: z.ZodLiteral<"text">;
88
+ value: z.ZodString;
89
+ }, z.core.$strip>, z.ZodObject<{
90
+ type: z.ZodLiteral<"cdata">;
91
+ value: z.ZodString;
92
+ }, z.core.$strip>, z.ZodObject<{
93
+ type: z.ZodLiteral<"comment">;
94
+ value: z.ZodString;
95
+ }, z.core.$strip>, z.ZodObject<{
96
+ type: z.ZodLiteral<"declaration">;
97
+ attributes: z.ZodArray<z.ZodObject<{
98
+ name: z.ZodString;
99
+ value: z.ZodString;
100
+ }, z.core.$strip>>;
101
+ }, z.core.$strip>, z.ZodObject<{
102
+ type: z.ZodLiteral<"pi">;
103
+ target: z.ZodString;
104
+ content: z.ZodString;
105
+ }, z.core.$strip>, z.ZodObject<{
106
+ type: z.ZodLiteral<"element">;
107
+ tag: z.ZodString;
108
+ attributes: z.ZodArray<z.ZodObject<{
109
+ name: z.ZodString;
110
+ value: z.ZodString;
111
+ }, z.core.$strip>>;
112
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
113
+ }, z.core.$strip>], "type">>;
114
+ }, z.core.$strip>;
115
+ type XmlPart = z.infer<typeof XmlPartSchema>;
116
+ declare const BinaryPartSchema: z.ZodObject<{
117
+ kind: z.ZodLiteral<"binary">;
118
+ base64: z.ZodString;
119
+ }, z.core.$strip>;
120
+ type BinaryPart = z.infer<typeof BinaryPartSchema>;
121
+ declare const PartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
122
+ kind: z.ZodLiteral<"xml">;
123
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
124
+ type: z.ZodLiteral<"text">;
125
+ value: z.ZodString;
126
+ }, z.core.$strip>, z.ZodObject<{
127
+ type: z.ZodLiteral<"cdata">;
128
+ value: z.ZodString;
129
+ }, z.core.$strip>, z.ZodObject<{
130
+ type: z.ZodLiteral<"comment">;
131
+ value: z.ZodString;
132
+ }, z.core.$strip>, z.ZodObject<{
133
+ type: z.ZodLiteral<"declaration">;
134
+ attributes: z.ZodArray<z.ZodObject<{
135
+ name: z.ZodString;
136
+ value: z.ZodString;
137
+ }, z.core.$strip>>;
138
+ }, z.core.$strip>, z.ZodObject<{
139
+ type: z.ZodLiteral<"pi">;
140
+ target: z.ZodString;
141
+ content: z.ZodString;
142
+ }, z.core.$strip>, z.ZodObject<{
143
+ type: z.ZodLiteral<"element">;
144
+ tag: z.ZodString;
145
+ attributes: z.ZodArray<z.ZodObject<{
146
+ name: z.ZodString;
147
+ value: z.ZodString;
148
+ }, z.core.$strip>>;
149
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
150
+ }, z.core.$strip>], "type">>;
151
+ }, z.core.$strip>, z.ZodObject<{
152
+ kind: z.ZodLiteral<"binary">;
153
+ base64: z.ZodString;
154
+ }, z.core.$strip>], "kind">;
155
+ type Part = z.infer<typeof PartSchema>;
156
+ declare const PackageSchema: z.ZodObject<{
157
+ parts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
158
+ kind: z.ZodLiteral<"xml">;
159
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
160
+ type: z.ZodLiteral<"text">;
161
+ value: z.ZodString;
162
+ }, z.core.$strip>, z.ZodObject<{
163
+ type: z.ZodLiteral<"cdata">;
164
+ value: z.ZodString;
165
+ }, z.core.$strip>, z.ZodObject<{
166
+ type: z.ZodLiteral<"comment">;
167
+ value: z.ZodString;
168
+ }, z.core.$strip>, z.ZodObject<{
169
+ type: z.ZodLiteral<"declaration">;
170
+ attributes: z.ZodArray<z.ZodObject<{
171
+ name: z.ZodString;
172
+ value: z.ZodString;
173
+ }, z.core.$strip>>;
174
+ }, z.core.$strip>, z.ZodObject<{
175
+ type: z.ZodLiteral<"pi">;
176
+ target: z.ZodString;
177
+ content: z.ZodString;
178
+ }, z.core.$strip>, z.ZodObject<{
179
+ type: z.ZodLiteral<"element">;
180
+ tag: z.ZodString;
181
+ attributes: z.ZodArray<z.ZodObject<{
182
+ name: z.ZodString;
183
+ value: z.ZodString;
184
+ }, z.core.$strip>>;
185
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
186
+ }, z.core.$strip>], "type">>;
187
+ }, z.core.$strip>, z.ZodObject<{
188
+ kind: z.ZodLiteral<"binary">;
189
+ base64: z.ZodString;
190
+ }, z.core.$strip>], "kind">>;
191
+ }, z.core.$strip>;
192
+ type Package = z.infer<typeof PackageSchema>;
193
+ //#endregion
194
+ //#region src/codec.d.ts
195
+ declare const xmlCodec: z.ZodCodec<z.ZodString, z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
196
+ type: z.ZodLiteral<"text">;
197
+ value: z.ZodString;
198
+ }, z.core.$strip>, z.ZodObject<{
199
+ type: z.ZodLiteral<"cdata">;
200
+ value: z.ZodString;
201
+ }, z.core.$strip>, z.ZodObject<{
202
+ type: z.ZodLiteral<"comment">;
203
+ value: z.ZodString;
204
+ }, z.core.$strip>, z.ZodObject<{
205
+ type: z.ZodLiteral<"declaration">;
206
+ attributes: z.ZodArray<z.ZodObject<{
207
+ name: z.ZodString;
208
+ value: z.ZodString;
209
+ }, z.core.$strip>>;
210
+ }, z.core.$strip>, z.ZodObject<{
211
+ type: z.ZodLiteral<"pi">;
212
+ target: z.ZodString;
213
+ content: z.ZodString;
214
+ }, z.core.$strip>, z.ZodObject<{
215
+ type: z.ZodLiteral<"element">;
216
+ tag: z.ZodString;
217
+ attributes: z.ZodArray<z.ZodObject<{
218
+ name: z.ZodString;
219
+ value: z.ZodString;
220
+ }, z.core.$strip>>;
221
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
222
+ }, z.core.$strip>], "type">>>;
223
+ declare const packageCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodObject<{
224
+ parts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
225
+ kind: z.ZodLiteral<"xml">;
226
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
227
+ type: z.ZodLiteral<"text">;
228
+ value: z.ZodString;
229
+ }, z.core.$strip>, z.ZodObject<{
230
+ type: z.ZodLiteral<"cdata">;
231
+ value: z.ZodString;
232
+ }, z.core.$strip>, z.ZodObject<{
233
+ type: z.ZodLiteral<"comment">;
234
+ value: z.ZodString;
235
+ }, z.core.$strip>, z.ZodObject<{
236
+ type: z.ZodLiteral<"declaration">;
237
+ attributes: z.ZodArray<z.ZodObject<{
238
+ name: z.ZodString;
239
+ value: z.ZodString;
240
+ }, z.core.$strip>>;
241
+ }, z.core.$strip>, z.ZodObject<{
242
+ type: z.ZodLiteral<"pi">;
243
+ target: z.ZodString;
244
+ content: z.ZodString;
245
+ }, z.core.$strip>, z.ZodObject<{
246
+ type: z.ZodLiteral<"element">;
247
+ tag: z.ZodString;
248
+ attributes: z.ZodArray<z.ZodObject<{
249
+ name: z.ZodString;
250
+ value: z.ZodString;
251
+ }, z.core.$strip>>;
252
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
253
+ }, z.core.$strip>], "type">>;
254
+ }, z.core.$strip>, z.ZodObject<{
255
+ kind: z.ZodLiteral<"binary">;
256
+ base64: z.ZodString;
257
+ }, z.core.$strip>], "kind">>;
258
+ }, z.core.$strip>>;
259
+ declare function decodePackage(bytes: Uint8Array<ArrayBuffer>): Package;
260
+ declare function encodePackage(pkg: Package): Uint8Array<ArrayBuffer>;
261
+ //#endregion
262
+ //#region src/package-io/read.d.ts
263
+ declare function parsePackage(bytes: Uint8Array<ArrayBuffer>): Package;
264
+ //#endregion
265
+ //#region src/package-io/write.d.ts
266
+ declare function serializePackage(pkg: Package): Uint8Array<ArrayBuffer>;
267
+ //#endregion
268
+ //#region src/xml/parse.d.ts
269
+ declare function parseXml(xml: string): XmlNode[];
270
+ //#endregion
271
+ //#region src/xml/build.d.ts
272
+ declare function buildXml(nodes: XmlNode[]): string;
273
+ //#endregion
274
+ //#region src/zip.d.ts
275
+ interface ZipEntry {
276
+ readonly bytes: Uint8Array<ArrayBuffer>;
277
+ readonly stored?: boolean;
278
+ }
279
+ declare function unzipPackage(bytes: Uint8Array<ArrayBuffer>): Record<string, Uint8Array<ArrayBuffer>>;
280
+ declare function zipPackage(entries: readonly (readonly [string, ZipEntry])[]): Uint8Array<ArrayBuffer>;
281
+ //#endregion
282
+ //#region src/util/base64.d.ts
283
+ declare function bytesToBase64(bytes: Uint8Array<ArrayBuffer>): string;
284
+ declare function base64ToBytes(b64: string): Uint8Array<ArrayBuffer>;
285
+ //#endregion
286
+ export { type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Package, PackageSchema, type Part, PartSchema, 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, base64ToBytes, buildXml, bytesToBase64, decodePackage, encodePackage, isXmlNode, packageCodec, parsePackage, parseXml, serializePackage, unzipPackage, xmlCodec, zipPackage };
@@ -0,0 +1,286 @@
1
+ import { z } from "zod";
2
+ //#region src/model/node.d.ts
3
+ declare const AttributeSchema: z.ZodObject<{
4
+ name: z.ZodString;
5
+ value: z.ZodString;
6
+ }, z.core.$strip>;
7
+ type Attribute = z.infer<typeof AttributeSchema>;
8
+ declare const XmlTextSchema: z.ZodObject<{
9
+ type: z.ZodLiteral<"text">;
10
+ value: z.ZodString;
11
+ }, z.core.$strip>;
12
+ type XmlText = z.infer<typeof XmlTextSchema>;
13
+ declare const XmlCdataSchema: z.ZodObject<{
14
+ type: z.ZodLiteral<"cdata">;
15
+ value: z.ZodString;
16
+ }, z.core.$strip>;
17
+ type XmlCdata = z.infer<typeof XmlCdataSchema>;
18
+ declare const XmlCommentSchema: z.ZodObject<{
19
+ type: z.ZodLiteral<"comment">;
20
+ value: z.ZodString;
21
+ }, z.core.$strip>;
22
+ type XmlComment = z.infer<typeof XmlCommentSchema>;
23
+ declare const XmlDeclarationSchema: z.ZodObject<{
24
+ type: z.ZodLiteral<"declaration">;
25
+ attributes: z.ZodArray<z.ZodObject<{
26
+ name: z.ZodString;
27
+ value: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ }, z.core.$strip>;
30
+ type XmlDeclaration = z.infer<typeof XmlDeclarationSchema>;
31
+ declare const XmlPiSchema: z.ZodObject<{
32
+ type: z.ZodLiteral<"pi">;
33
+ target: z.ZodString;
34
+ content: z.ZodString;
35
+ }, z.core.$strip>;
36
+ type XmlPi = z.infer<typeof XmlPiSchema>;
37
+ interface XmlElement {
38
+ type: 'element';
39
+ tag: string;
40
+ attributes: Attribute[];
41
+ children: XmlNode[];
42
+ }
43
+ type XmlNode = XmlText | XmlCdata | XmlComment | XmlDeclaration | XmlPi | XmlElement;
44
+ declare function isXmlNode(value: unknown): value is XmlNode;
45
+ declare const XmlElementSchema: z.ZodObject<{
46
+ type: z.ZodLiteral<"element">;
47
+ tag: z.ZodString;
48
+ attributes: z.ZodArray<z.ZodObject<{
49
+ name: z.ZodString;
50
+ value: z.ZodString;
51
+ }, z.core.$strip>>;
52
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
53
+ }, z.core.$strip>;
54
+ declare const XmlNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
55
+ type: z.ZodLiteral<"text">;
56
+ value: z.ZodString;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ type: z.ZodLiteral<"cdata">;
59
+ value: z.ZodString;
60
+ }, z.core.$strip>, z.ZodObject<{
61
+ type: z.ZodLiteral<"comment">;
62
+ value: z.ZodString;
63
+ }, z.core.$strip>, z.ZodObject<{
64
+ type: z.ZodLiteral<"declaration">;
65
+ attributes: z.ZodArray<z.ZodObject<{
66
+ name: z.ZodString;
67
+ value: z.ZodString;
68
+ }, z.core.$strip>>;
69
+ }, z.core.$strip>, z.ZodObject<{
70
+ type: z.ZodLiteral<"pi">;
71
+ target: z.ZodString;
72
+ content: z.ZodString;
73
+ }, z.core.$strip>, z.ZodObject<{
74
+ type: z.ZodLiteral<"element">;
75
+ tag: z.ZodString;
76
+ attributes: z.ZodArray<z.ZodObject<{
77
+ name: z.ZodString;
78
+ value: z.ZodString;
79
+ }, z.core.$strip>>;
80
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
81
+ }, z.core.$strip>], "type">;
82
+ //#endregion
83
+ //#region src/model/package.d.ts
84
+ declare const XmlPartSchema: z.ZodObject<{
85
+ kind: z.ZodLiteral<"xml">;
86
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
87
+ type: z.ZodLiteral<"text">;
88
+ value: z.ZodString;
89
+ }, z.core.$strip>, z.ZodObject<{
90
+ type: z.ZodLiteral<"cdata">;
91
+ value: z.ZodString;
92
+ }, z.core.$strip>, z.ZodObject<{
93
+ type: z.ZodLiteral<"comment">;
94
+ value: z.ZodString;
95
+ }, z.core.$strip>, z.ZodObject<{
96
+ type: z.ZodLiteral<"declaration">;
97
+ attributes: z.ZodArray<z.ZodObject<{
98
+ name: z.ZodString;
99
+ value: z.ZodString;
100
+ }, z.core.$strip>>;
101
+ }, z.core.$strip>, z.ZodObject<{
102
+ type: z.ZodLiteral<"pi">;
103
+ target: z.ZodString;
104
+ content: z.ZodString;
105
+ }, z.core.$strip>, z.ZodObject<{
106
+ type: z.ZodLiteral<"element">;
107
+ tag: z.ZodString;
108
+ attributes: z.ZodArray<z.ZodObject<{
109
+ name: z.ZodString;
110
+ value: z.ZodString;
111
+ }, z.core.$strip>>;
112
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
113
+ }, z.core.$strip>], "type">>;
114
+ }, z.core.$strip>;
115
+ type XmlPart = z.infer<typeof XmlPartSchema>;
116
+ declare const BinaryPartSchema: z.ZodObject<{
117
+ kind: z.ZodLiteral<"binary">;
118
+ base64: z.ZodString;
119
+ }, z.core.$strip>;
120
+ type BinaryPart = z.infer<typeof BinaryPartSchema>;
121
+ declare const PartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
122
+ kind: z.ZodLiteral<"xml">;
123
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
124
+ type: z.ZodLiteral<"text">;
125
+ value: z.ZodString;
126
+ }, z.core.$strip>, z.ZodObject<{
127
+ type: z.ZodLiteral<"cdata">;
128
+ value: z.ZodString;
129
+ }, z.core.$strip>, z.ZodObject<{
130
+ type: z.ZodLiteral<"comment">;
131
+ value: z.ZodString;
132
+ }, z.core.$strip>, z.ZodObject<{
133
+ type: z.ZodLiteral<"declaration">;
134
+ attributes: z.ZodArray<z.ZodObject<{
135
+ name: z.ZodString;
136
+ value: z.ZodString;
137
+ }, z.core.$strip>>;
138
+ }, z.core.$strip>, z.ZodObject<{
139
+ type: z.ZodLiteral<"pi">;
140
+ target: z.ZodString;
141
+ content: z.ZodString;
142
+ }, z.core.$strip>, z.ZodObject<{
143
+ type: z.ZodLiteral<"element">;
144
+ tag: z.ZodString;
145
+ attributes: z.ZodArray<z.ZodObject<{
146
+ name: z.ZodString;
147
+ value: z.ZodString;
148
+ }, z.core.$strip>>;
149
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
150
+ }, z.core.$strip>], "type">>;
151
+ }, z.core.$strip>, z.ZodObject<{
152
+ kind: z.ZodLiteral<"binary">;
153
+ base64: z.ZodString;
154
+ }, z.core.$strip>], "kind">;
155
+ type Part = z.infer<typeof PartSchema>;
156
+ declare const PackageSchema: z.ZodObject<{
157
+ parts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
158
+ kind: z.ZodLiteral<"xml">;
159
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
160
+ type: z.ZodLiteral<"text">;
161
+ value: z.ZodString;
162
+ }, z.core.$strip>, z.ZodObject<{
163
+ type: z.ZodLiteral<"cdata">;
164
+ value: z.ZodString;
165
+ }, z.core.$strip>, z.ZodObject<{
166
+ type: z.ZodLiteral<"comment">;
167
+ value: z.ZodString;
168
+ }, z.core.$strip>, z.ZodObject<{
169
+ type: z.ZodLiteral<"declaration">;
170
+ attributes: z.ZodArray<z.ZodObject<{
171
+ name: z.ZodString;
172
+ value: z.ZodString;
173
+ }, z.core.$strip>>;
174
+ }, z.core.$strip>, z.ZodObject<{
175
+ type: z.ZodLiteral<"pi">;
176
+ target: z.ZodString;
177
+ content: z.ZodString;
178
+ }, z.core.$strip>, z.ZodObject<{
179
+ type: z.ZodLiteral<"element">;
180
+ tag: z.ZodString;
181
+ attributes: z.ZodArray<z.ZodObject<{
182
+ name: z.ZodString;
183
+ value: z.ZodString;
184
+ }, z.core.$strip>>;
185
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
186
+ }, z.core.$strip>], "type">>;
187
+ }, z.core.$strip>, z.ZodObject<{
188
+ kind: z.ZodLiteral<"binary">;
189
+ base64: z.ZodString;
190
+ }, z.core.$strip>], "kind">>;
191
+ }, z.core.$strip>;
192
+ type Package = z.infer<typeof PackageSchema>;
193
+ //#endregion
194
+ //#region src/codec.d.ts
195
+ declare const xmlCodec: z.ZodCodec<z.ZodString, z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
196
+ type: z.ZodLiteral<"text">;
197
+ value: z.ZodString;
198
+ }, z.core.$strip>, z.ZodObject<{
199
+ type: z.ZodLiteral<"cdata">;
200
+ value: z.ZodString;
201
+ }, z.core.$strip>, z.ZodObject<{
202
+ type: z.ZodLiteral<"comment">;
203
+ value: z.ZodString;
204
+ }, z.core.$strip>, z.ZodObject<{
205
+ type: z.ZodLiteral<"declaration">;
206
+ attributes: z.ZodArray<z.ZodObject<{
207
+ name: z.ZodString;
208
+ value: z.ZodString;
209
+ }, z.core.$strip>>;
210
+ }, z.core.$strip>, z.ZodObject<{
211
+ type: z.ZodLiteral<"pi">;
212
+ target: z.ZodString;
213
+ content: z.ZodString;
214
+ }, z.core.$strip>, z.ZodObject<{
215
+ type: z.ZodLiteral<"element">;
216
+ tag: z.ZodString;
217
+ attributes: z.ZodArray<z.ZodObject<{
218
+ name: z.ZodString;
219
+ value: z.ZodString;
220
+ }, z.core.$strip>>;
221
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
222
+ }, z.core.$strip>], "type">>>;
223
+ declare const packageCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodObject<{
224
+ parts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
225
+ kind: z.ZodLiteral<"xml">;
226
+ nodes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
227
+ type: z.ZodLiteral<"text">;
228
+ value: z.ZodString;
229
+ }, z.core.$strip>, z.ZodObject<{
230
+ type: z.ZodLiteral<"cdata">;
231
+ value: z.ZodString;
232
+ }, z.core.$strip>, z.ZodObject<{
233
+ type: z.ZodLiteral<"comment">;
234
+ value: z.ZodString;
235
+ }, z.core.$strip>, z.ZodObject<{
236
+ type: z.ZodLiteral<"declaration">;
237
+ attributes: z.ZodArray<z.ZodObject<{
238
+ name: z.ZodString;
239
+ value: z.ZodString;
240
+ }, z.core.$strip>>;
241
+ }, z.core.$strip>, z.ZodObject<{
242
+ type: z.ZodLiteral<"pi">;
243
+ target: z.ZodString;
244
+ content: z.ZodString;
245
+ }, z.core.$strip>, z.ZodObject<{
246
+ type: z.ZodLiteral<"element">;
247
+ tag: z.ZodString;
248
+ attributes: z.ZodArray<z.ZodObject<{
249
+ name: z.ZodString;
250
+ value: z.ZodString;
251
+ }, z.core.$strip>>;
252
+ children: z.ZodArray<z.ZodCustom<XmlNode, XmlNode>>;
253
+ }, z.core.$strip>], "type">>;
254
+ }, z.core.$strip>, z.ZodObject<{
255
+ kind: z.ZodLiteral<"binary">;
256
+ base64: z.ZodString;
257
+ }, z.core.$strip>], "kind">>;
258
+ }, z.core.$strip>>;
259
+ declare function decodePackage(bytes: Uint8Array<ArrayBuffer>): Package;
260
+ declare function encodePackage(pkg: Package): Uint8Array<ArrayBuffer>;
261
+ //#endregion
262
+ //#region src/package-io/read.d.ts
263
+ declare function parsePackage(bytes: Uint8Array<ArrayBuffer>): Package;
264
+ //#endregion
265
+ //#region src/package-io/write.d.ts
266
+ declare function serializePackage(pkg: Package): Uint8Array<ArrayBuffer>;
267
+ //#endregion
268
+ //#region src/xml/parse.d.ts
269
+ declare function parseXml(xml: string): XmlNode[];
270
+ //#endregion
271
+ //#region src/xml/build.d.ts
272
+ declare function buildXml(nodes: XmlNode[]): string;
273
+ //#endregion
274
+ //#region src/zip.d.ts
275
+ interface ZipEntry {
276
+ readonly bytes: Uint8Array<ArrayBuffer>;
277
+ readonly stored?: boolean;
278
+ }
279
+ declare function unzipPackage(bytes: Uint8Array<ArrayBuffer>): Record<string, Uint8Array<ArrayBuffer>>;
280
+ declare function zipPackage(entries: readonly (readonly [string, ZipEntry])[]): Uint8Array<ArrayBuffer>;
281
+ //#endregion
282
+ //#region src/util/base64.d.ts
283
+ declare function bytesToBase64(bytes: Uint8Array<ArrayBuffer>): string;
284
+ declare function base64ToBytes(b64: string): Uint8Array<ArrayBuffer>;
285
+ //#endregion
286
+ export { type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Package, PackageSchema, type Part, PartSchema, 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, base64ToBytes, buildXml, bytesToBase64, decodePackage, encodePackage, isXmlNode, packageCodec, parsePackage, parseXml, serializePackage, unzipPackage, xmlCodec, zipPackage };
package/dist/index.js ADDED
@@ -0,0 +1,331 @@
1
+ import { z } from "zod";
2
+ import { XMLBuilder, XMLParser } from "fast-xml-parser";
3
+ import { unzipSync, zipSync } from "fflate";
4
+ //#region src/model/node.ts
5
+ const AttributeSchema = z.object({
6
+ name: z.string(),
7
+ value: z.string()
8
+ });
9
+ const XmlTextSchema = z.object({
10
+ type: z.literal("text"),
11
+ value: z.string()
12
+ });
13
+ const XmlCdataSchema = z.object({
14
+ type: z.literal("cdata"),
15
+ value: z.string()
16
+ });
17
+ const XmlCommentSchema = z.object({
18
+ type: z.literal("comment"),
19
+ value: z.string()
20
+ });
21
+ const XmlDeclarationSchema = z.object({
22
+ type: z.literal("declaration"),
23
+ attributes: z.array(AttributeSchema)
24
+ });
25
+ const XmlPiSchema = z.object({
26
+ type: z.literal("pi"),
27
+ target: z.string(),
28
+ content: z.string()
29
+ });
30
+ function isRecord$1(value) {
31
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32
+ }
33
+ function isAttribute(value) {
34
+ return isRecord$1(value) && typeof value.name === "string" && typeof value.value === "string";
35
+ }
36
+ function isXmlNode(value) {
37
+ if (!isRecord$1(value)) return false;
38
+ const t = value.type;
39
+ if (t === "text" || t === "cdata" || t === "comment") return typeof value.value === "string";
40
+ if (t === "declaration") return Array.isArray(value.attributes) && value.attributes.every(isAttribute);
41
+ if (t === "pi") return typeof value.target === "string" && typeof value.content === "string";
42
+ if (t === "element") return typeof value.tag === "string" && Array.isArray(value.attributes) && value.attributes.every(isAttribute) && Array.isArray(value.children) && value.children.every(isXmlNode);
43
+ return false;
44
+ }
45
+ const XmlElementSchema = z.object({
46
+ type: z.literal("element"),
47
+ tag: z.string(),
48
+ attributes: z.array(AttributeSchema),
49
+ children: z.array(z.custom(isXmlNode))
50
+ });
51
+ const XmlNodeSchema = z.discriminatedUnion("type", [
52
+ XmlTextSchema,
53
+ XmlCdataSchema,
54
+ XmlCommentSchema,
55
+ XmlDeclarationSchema,
56
+ XmlPiSchema,
57
+ XmlElementSchema
58
+ ]);
59
+ //#endregion
60
+ //#region src/model/package.ts
61
+ const XmlPartSchema = z.object({
62
+ kind: z.literal("xml"),
63
+ nodes: z.array(XmlNodeSchema)
64
+ });
65
+ const BinaryPartSchema = z.object({
66
+ kind: z.literal("binary"),
67
+ base64: z.string()
68
+ });
69
+ const PartSchema = z.discriminatedUnion("kind", [XmlPartSchema, BinaryPartSchema]);
70
+ const PackageSchema = z.object({ parts: z.record(z.string(), PartSchema) });
71
+ //#endregion
72
+ //#region src/util/base64.ts
73
+ const TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
74
+ const DECODE = (() => {
75
+ const map = (/* @__PURE__ */ new Uint8Array(256)).fill(255);
76
+ for (let i = 0; i < 64; i = i + 1) map[TABLE.charCodeAt(i)] = i;
77
+ return map;
78
+ })();
79
+ function bytesToBase64(bytes) {
80
+ let out = "";
81
+ const len = bytes.length;
82
+ for (let i = 0; i < len; i = i + 3) {
83
+ const b0 = bytes[i];
84
+ const b1 = i + 1 < len ? bytes[i + 1] : 0;
85
+ const b2 = i + 2 < len ? bytes[i + 2] : 0;
86
+ out += TABLE[b0 >> 2];
87
+ out += TABLE[(b0 & 3) << 4 | b1 >> 4];
88
+ out += i + 1 < len ? TABLE[(b1 & 15) << 2 | b2 >> 6] : "=";
89
+ out += i + 2 < len ? TABLE[b2 & 63] : "=";
90
+ }
91
+ return out;
92
+ }
93
+ function base64ToBytes(b64) {
94
+ const clean = b64.replace(/[^A-Za-z0-9+/=]/g, "");
95
+ const len = clean.length;
96
+ const out = new Uint8Array(len * 3 / 4 | 0);
97
+ let p = 0;
98
+ for (let i = 0; i < len; i = i + 4) {
99
+ const c0 = DECODE[clean.charCodeAt(i)];
100
+ const c1 = DECODE[clean.charCodeAt(i + 1)];
101
+ const c2 = clean.charCodeAt(i + 2);
102
+ const c3 = clean.charCodeAt(i + 3);
103
+ if (c0 === 255 || c1 === 255) throw new Error("invalid base64 input");
104
+ out[p++] = c0 << 2 | c1 >> 4;
105
+ if (c2 !== 61) {
106
+ const d2 = DECODE[c2];
107
+ out[p++] = (c1 & 15) << 4 | d2 >> 2;
108
+ if (c3 !== 61) {
109
+ const d3 = DECODE[c3];
110
+ out[p++] = (d2 & 3) << 6 | d3;
111
+ }
112
+ }
113
+ }
114
+ return out.subarray(0, p);
115
+ }
116
+ //#endregion
117
+ //#region src/xml/parse.ts
118
+ const PARSER = new XMLParser({
119
+ preserveOrder: true,
120
+ attributeNamePrefix: "@_",
121
+ ignoreAttributes: false,
122
+ textNodeName: "#text",
123
+ cdataPropName: "__cdata",
124
+ commentPropName: "__comment",
125
+ processEntities: false,
126
+ parseTagValue: false,
127
+ trimValues: false
128
+ });
129
+ function parseXml(xml) {
130
+ return parseNodes(PARSER.parse(xml));
131
+ }
132
+ function isRecord(value) {
133
+ return typeof value === "object" && value !== null && !Array.isArray(value);
134
+ }
135
+ function isUnknownArray(value) {
136
+ return Array.isArray(value);
137
+ }
138
+ function asString(value) {
139
+ if (typeof value !== "string") throw new Error(`expected string while parsing XML, got ${typeof value}`);
140
+ return value;
141
+ }
142
+ function parseNodes(raw) {
143
+ if (!isUnknownArray(raw)) throw new Error("fast-xml-parser output was not an ordered array");
144
+ return raw.map(parseNode);
145
+ }
146
+ function parseNode(raw) {
147
+ if (!isRecord(raw)) throw new Error("fast-xml-parser node was not an object");
148
+ let tagKey;
149
+ for (const key of Object.keys(raw)) if (key !== ":@") {
150
+ if (tagKey !== void 0) throw new Error("XML node had multiple tag keys");
151
+ tagKey = key;
152
+ }
153
+ if (tagKey === void 0) throw new Error("XML node had no tag key");
154
+ const attributes = parseAttributes(raw[":@"]);
155
+ if (tagKey === "#text") return {
156
+ type: "text",
157
+ value: asString(raw["#text"])
158
+ };
159
+ if (tagKey === "__comment") return {
160
+ type: "comment",
161
+ value: scalarText(raw.__comment)
162
+ };
163
+ if (tagKey === "__cdata") return {
164
+ type: "cdata",
165
+ value: scalarText(raw.__cdata)
166
+ };
167
+ if (tagKey === "?xml") return {
168
+ type: "declaration",
169
+ attributes
170
+ };
171
+ if (tagKey.startsWith("?")) return {
172
+ type: "pi",
173
+ target: tagKey.slice(1),
174
+ content: scalarText(raw[tagKey])
175
+ };
176
+ return {
177
+ type: "element",
178
+ tag: tagKey,
179
+ attributes,
180
+ children: parseNodes(raw[tagKey])
181
+ };
182
+ }
183
+ function parseAttributes(raw) {
184
+ if (raw === void 0) return [];
185
+ if (!isRecord(raw)) throw new Error("XML attributes were not an object");
186
+ const attrs = [];
187
+ for (const key of Object.keys(raw)) {
188
+ if (!key.startsWith("@_")) throw new Error(`unexpected attribute key without @_ prefix: ${key}`);
189
+ attrs.push({
190
+ name: key.slice(2),
191
+ value: asString(raw[key])
192
+ });
193
+ }
194
+ return attrs;
195
+ }
196
+ function scalarText(raw) {
197
+ if (!isUnknownArray(raw) || raw.length === 0) throw new Error("expected a scalar-text wrapper array");
198
+ const first = raw[0];
199
+ if (!isRecord(first)) throw new Error("scalar-text wrapper was not an object");
200
+ return asString(first["#text"]);
201
+ }
202
+ //#endregion
203
+ //#region src/zip.ts
204
+ function unzipPackage(bytes) {
205
+ return unzipSync(bytes);
206
+ }
207
+ function zipPackage(entries) {
208
+ const data = {};
209
+ for (const [path, entry] of entries) if (entry.stored === true) data[path] = [entry.bytes, { level: 0 }];
210
+ else data[path] = entry.bytes;
211
+ return zipSync(data);
212
+ }
213
+ //#endregion
214
+ //#region src/package-io/read.ts
215
+ function parsePackage(bytes) {
216
+ const entries = unzipPackage(bytes);
217
+ const parts = {};
218
+ for (const [path, partBytes] of Object.entries(entries)) if (looksLikeXml(partBytes)) parts[path] = {
219
+ kind: "xml",
220
+ nodes: parseXml(new TextDecoder("utf-8").decode(partBytes))
221
+ };
222
+ else parts[path] = {
223
+ kind: "binary",
224
+ base64: bytesToBase64(partBytes)
225
+ };
226
+ return { parts };
227
+ }
228
+ function looksLikeXml(bytes) {
229
+ let i = 0;
230
+ if (bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) i = 3;
231
+ while (i < bytes.length) {
232
+ const b = bytes[i];
233
+ if (b === 32 || b === 9 || b === 10 || b === 13) {
234
+ i = i + 1;
235
+ continue;
236
+ }
237
+ return b === 60;
238
+ }
239
+ return false;
240
+ }
241
+ //#endregion
242
+ //#region src/xml/build.ts
243
+ const BUILDER = new XMLBuilder({
244
+ preserveOrder: true,
245
+ attributeNamePrefix: "@_",
246
+ ignoreAttributes: false,
247
+ textNodeName: "#text",
248
+ cdataPropName: "__cdata",
249
+ commentPropName: "__comment",
250
+ processEntities: false,
251
+ format: false,
252
+ suppressEmptyNode: false
253
+ });
254
+ function buildXml(nodes) {
255
+ const out = BUILDER.build(toOrdered(nodes));
256
+ if (typeof out !== "string") throw new Error("XMLBuilder did not return a string");
257
+ return out;
258
+ }
259
+ function toOrdered(nodes) {
260
+ return nodes.map(toOrderedNode);
261
+ }
262
+ function attrsObject(attributes) {
263
+ const obj = {};
264
+ for (const a of attributes) obj[`@_${a.name}`] = a.value;
265
+ return obj;
266
+ }
267
+ function toOrderedNode(node) {
268
+ switch (node.type) {
269
+ case "text": return { "#text": node.value };
270
+ case "comment": return { __comment: [{ "#text": node.value }] };
271
+ case "cdata": return { __cdata: [{ "#text": node.value }] };
272
+ case "pi": return { [`?${node.target}`]: [{ "#text": node.content }] };
273
+ case "declaration": return {
274
+ "?xml": [{ "#text": "" }],
275
+ ":@": attrsObject(node.attributes)
276
+ };
277
+ case "element": {
278
+ const obj = { [node.tag]: toOrdered(node.children) };
279
+ const attrs = attrsObject(node.attributes);
280
+ if (Object.keys(attrs).length > 0) obj[":@"] = attrs;
281
+ return obj;
282
+ }
283
+ }
284
+ }
285
+ //#endregion
286
+ //#region src/package-io/write.ts
287
+ const MIMETYPE_PART = "mimetype";
288
+ const MANIFEST_PART = "META-INF/manifest.xml";
289
+ function serializePackage(pkg) {
290
+ const remaining = new Map(Object.entries(pkg.parts));
291
+ const entries = [];
292
+ const mimetype = remaining.get(MIMETYPE_PART);
293
+ if (mimetype !== void 0) {
294
+ entries.push([MIMETYPE_PART, {
295
+ bytes: partToBytes(mimetype),
296
+ stored: true
297
+ }]);
298
+ remaining.delete(MIMETYPE_PART);
299
+ }
300
+ const manifest = remaining.get(MANIFEST_PART);
301
+ if (manifest !== void 0) {
302
+ entries.push([MANIFEST_PART, { bytes: partToBytes(manifest) }]);
303
+ remaining.delete(MANIFEST_PART);
304
+ }
305
+ for (const [path, part] of remaining) entries.push([path, { bytes: partToBytes(part) }]);
306
+ return zipPackage(entries);
307
+ }
308
+ function partToBytes(part) {
309
+ switch (part.kind) {
310
+ case "xml": return new TextEncoder().encode(buildXml(part.nodes));
311
+ case "binary": return base64ToBytes(part.base64);
312
+ }
313
+ }
314
+ //#endregion
315
+ //#region src/codec.ts
316
+ const xmlCodec = z.codec(z.string(), z.array(XmlNodeSchema), {
317
+ decode: (xml) => parseXml(xml),
318
+ encode: (nodes) => buildXml(nodes)
319
+ });
320
+ const packageCodec = z.codec(z.instanceof(Uint8Array), PackageSchema, {
321
+ decode: (bytes) => parsePackage(bytes),
322
+ encode: (pkg) => serializePackage(pkg)
323
+ });
324
+ function decodePackage(bytes) {
325
+ return z.decode(packageCodec, bytes);
326
+ }
327
+ function encodePackage(pkg) {
328
+ return z.encode(packageCodec, pkg);
329
+ }
330
+ //#endregion
331
+ export { AttributeSchema, BinaryPartSchema, PackageSchema, PartSchema, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, base64ToBytes, buildXml, bytesToBase64, decodePackage, encodePackage, isXmlNode, packageCodec, parsePackage, parseXml, serializePackage, unzipPackage, xmlCodec, zipPackage };
package/package.json CHANGED
@@ -1,5 +1,89 @@
1
1
  {
2
2
  "name": "odf.js",
3
- "version": "0.0.0",
4
- "private": false
3
+ "version": "1.0.0",
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
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ExaDev/odf.js.git"
9
+ },
10
+ "homepage": "https://github.com/ExaDev/odf.js#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/ExaDev/odf.js/issues"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "types": {
17
+ "import": "./dist/index.d.ts",
18
+ "require": "./dist/index.d.cts"
19
+ },
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs"
22
+ }
23
+ },
24
+ "main": "./dist/index.cjs",
25
+ "module": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "provenance": true,
33
+ "registry": "https://registry.npmjs.org/"
34
+ },
35
+ "sideEffects": false,
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "scripts": {
40
+ "build": "tsdown",
41
+ "prepublishOnly": "pnpm run lint && pnpm run typecheck && tsdown && publint && attw --pack",
42
+ "lint": "eslint . --max-warnings 0",
43
+ "typecheck": "tsc --noEmit",
44
+ "test": "vitest run --project unit",
45
+ "test:watch": "vitest --project unit",
46
+ "test:coverage": "vitest run --project unit --coverage",
47
+ "test:smoke": "tsdown && vitest run --project smoke",
48
+ "prepare": "husky",
49
+ "release": "semantic-release"
50
+ },
51
+ "keywords": [
52
+ "odf",
53
+ "opendocument",
54
+ "odt",
55
+ "ods",
56
+ "odp",
57
+ "round-trip",
58
+ "zod",
59
+ "codec"
60
+ ],
61
+ "license": "MIT",
62
+ "packageManager": "pnpm@11.6.0",
63
+ "dependencies": {
64
+ "document-content-model": "^1.1.0",
65
+ "fast-xml-parser": "^5.10.1",
66
+ "fflate": "^0.8.3",
67
+ "zod": "^4.4.3"
68
+ },
69
+ "devDependencies": {
70
+ "@arethetypeswrong/cli": "^0.18.5",
71
+ "@commitlint/cli": "^21.2.1",
72
+ "@commitlint/config-conventional": "^21.2.0",
73
+ "@eslint/js": "^10.0.1",
74
+ "@semantic-release/changelog": "^7.0.0",
75
+ "@semantic-release/git": "^11.0.1",
76
+ "@types/node": "^26.1.1",
77
+ "@vitest/coverage-v8": "^4.1.10",
78
+ "eslint": "^10.8.0",
79
+ "globals": "^17.8.0",
80
+ "husky": "^9.1.7",
81
+ "lint-staged": "^17.2.0",
82
+ "publint": "^0.3.21",
83
+ "semantic-release": "^25.0.8",
84
+ "tsdown": "^0.22.13",
85
+ "typescript": "^6.0.3",
86
+ "typescript-eslint": "^8.65.0",
87
+ "vitest": "^4.1.10"
88
+ }
5
89
  }