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 +21 -0
- package/dist/index.cjs +356 -0
- package/dist/index.d.cts +286 -0
- package/dist/index.d.ts +286 -0
- package/dist/index.js +331 -0
- package/package.json +86 -2
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;
|
package/dist/index.d.cts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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": "
|
|
4
|
-
"
|
|
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
|
}
|