-
Notifications
You must be signed in to change notification settings - Fork 0
/
metadata.ts
138 lines (126 loc) · 4.32 KB
/
metadata.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import xmldom from '@xmldom/xmldom';
import { promises as fs } from 'fs';
import path from 'path';
// import util from 'util';
import * as utils from './utils.js';
/**
* Defines the data type holding `container.xml` data which
* is returned from {@link readContainerXml}.
*
* Note that `containerXml` is marked as `any`. This is because
* the `@xmldom/xmldom` does not export the internal class, `Document`,
* which is returned by `parseFromString`.
*/
export type ContainerXMLData = {
containerXmlText: string,
containerXml: any
};
/**
* Reads the `container.xml` file from the EPUB directory.
*
* @param epubDir The path name of the directory
* @returns A simple object ({@link ContainerXMLData}) describing the `container.xml` data
*/
export async function readContainerXml(epubDir: string): Promise<ContainerXMLData> {
try {
const data = await fs.readFile(
path.join(epubDir, "META-INF", "container.xml"),
'utf8');
return <ContainerXMLData>{
containerXmlText: data,
containerXml: new xmldom.DOMParser().parseFromString(data, 'text/xml')
};
} catch (e) {
console.error(`readContainerXml WARNING ${e.stack}`);
return undefined;
}
}
export type RootFileData = {
fullpath: string, mime: string
};
/**
* From the `container.xml` file, look for any `rootfile` elements, returning
* a descriptive object ({@link RootFileData}) for each.
*
* @param containerXml The _Document_ of the `container.xml` file
* @returns An array of {@link RootFileData} objects
*/
export function findRootfiles(containerXml) {
const rootfiles = [];
for (const rootfile of utils.nodeListIterator(
containerXml.getElementsByTagName("rootfile")
)) {
rootfiles.push(<RootFileData>{
fullpath: rootfile.getAttribute('full-path'),
mime: rootfile.getAttribute('media-type')
});
}
// console.log(util.inspect(rootfiles));
return rootfiles;
}
// MOOT - finds a single OPF file name
export function findOpfFileName(containerXml) {
const rootfiles = containerXml.getElementsByTagName("rootfile");
// console.log(util.inspect(rootfile));
let rootfile;
for (let rfnum = 0; rfnum < rootfiles.length; rfnum++) {
const elem = rootfiles.item(rfnum);
if (elem.nodeName.toUpperCase() === 'rootfile'.toUpperCase()) rootfile = elem;
}
if (!rootfile) throw new Error('No rootfile element in container.xml');
return rootfile.getAttribute('full-path');
}
type OPFData = {
opfXmlText: string,
opfXml: any
};
/**
* Reads the OPF file from the EPUB, parsing it to an XML Document.
*
* @param epubDir The directory where the EPUB files are stored
* @param opfName The file name of the OPF file
* @returns An object ({@link OPFData}) for the OPF file
*/
export async function readOPF(epubDir: string, opfName: string): Promise<OPFData> {
const file2read = path.join(epubDir, opfName);
try {
// console.log(`readOPF ${file2read}`);
const data = await fs.readFile(file2read, 'utf8');
return <OPFData>{
opfXmlText: data,
opfXml: new xmldom.DOMParser().parseFromString(data, 'text/xml')
};
} catch (e) {
console.log(`readOPF ${file2read} FAIL because ${e.stack}`);
return <OPFData>{
opfXmlText: undefined,
opfXml: undefined
};
}
}
export type XHTMLData = {
xhtmlText: string,
xhtmlDOM: any
};
/**
* Reads the XHTML file, returning an object ({@link XHTMLData}) containing
* the text which was read, and the parsed XML Document.
*
* @param epubDir The directory for the EPUB data
* @param xhtmlName The file name for the file to read
* @returns An object ({@link XHTMLData}) containing data read from the file
*/
export async function readXHTML(epubDir: string, xhtmlName: string): Promise<XHTMLData> {
const file2read = path.join(epubDir, xhtmlName);
// console.log(`readXHTML ${file2read}`);
try {
const data = await fs.readFile(file2read, 'utf8');
return <XHTMLData>{
xhtmlText: data,
xhtmlDOM: new xmldom.DOMParser().parseFromString(data, 'application/xhtml+xml')
};
} catch (e) {
console.error(`epubtools metadata readXHTML ${file2read} FAIL because ${e.stack}`);
return undefined;
}
}