-
Notifications
You must be signed in to change notification settings - Fork 1
/
get-meta.ts
55 lines (47 loc) · 1.54 KB
/
get-meta.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import JSZip from 'jszip';
import xml2js from 'xml2js';
const Parser = xml2js.Parser;
import { z } from 'zod';
import { loadBook } from './load-book.js';
export async function getMeta(input: string | JSZip) {
const raw = await getRawMeta(input);
const parser = new Parser({
async: true,
explicitArray: false,
charkey: 'text',
normalize: true,
mergeAttrs: true,
tagNameProcessors: [
(name: string) => name.startsWith('dc:') ? name.replace('dc:', '') : name
]
});
const dom = await parser.parseStringPromise(raw);
const parsed = schema.safeParse(dom);
if (parsed.success) {
return parsed.data.package.metadata;
} else {
console.log(JSON.stringify(dom, undefined, 2));
throw parsed.error;
}
}
export async function getRawMeta(input: string | JSZip) {
return await loadBook(input)
.then(zip => zip.files['OEBPS/content.opf']?.async('string'));
}
const textContent = z.string().or(z.object({ text: z.string() }).transform(o => o.text));
const metadata = z.object({
title: textContent.optional(),
creator: z.array(textContent).or(textContent).optional(),
contributor: z.array(textContent).optional().optional(),
publisher: z.string().optional(),
rights: z.string().optional(),
subject: z.string().or(z.array(z.string())).optional(),
language: textContent.or(z.array(textContent)).optional(),
identifier: textContent,
source: z.string().optional(),
date: z.string()
});
const schema = z.object({
package: z.object({ metadata })
});
export type BookMetadata = z.infer<typeof metadata>;