frond-js 0.4.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/README.en.md +247 -0
- package/README.md +211 -0
- package/dist/abort-BY8vBk0v.d.cts +99 -0
- package/dist/abort-BY8vBk0v.d.ts +99 -0
- package/dist/adapter-3G46J3CA.cjs +503 -0
- package/dist/adapter-3ONQWJVQ.js +501 -0
- package/dist/adapter-55QHWRSE.js +124 -0
- package/dist/adapter-DF34GBWJ.cjs +19 -0
- package/dist/adapter-EXTNILTC.cjs +126 -0
- package/dist/adapter-GOFC7TMC.js +284 -0
- package/dist/adapter-LRJTQ47I.cjs +286 -0
- package/dist/adapter-TWWZML4A.js +17 -0
- package/dist/adapter-ZM5FQTJT.js +1415 -0
- package/dist/adapter-ZRNSDQUV.cjs +1417 -0
- package/dist/chunk-2SUG7YFZ.cjs +108 -0
- package/dist/chunk-B2L2YVXD.js +89 -0
- package/dist/chunk-D4KWSEZD.js +393 -0
- package/dist/chunk-EZTIZO6R.cjs +430 -0
- package/dist/chunk-G7DLWGBW.cjs +103 -0
- package/dist/chunk-GTGLDLJD.cjs +479 -0
- package/dist/chunk-IIV6VIUJ.cjs +83 -0
- package/dist/chunk-JDTHZQUK.js +102 -0
- package/dist/chunk-JJVXT3AC.js +30 -0
- package/dist/chunk-LIXRYQL2.js +473 -0
- package/dist/chunk-NABYHI6X.cjs +400 -0
- package/dist/chunk-SJVOYNTF.js +425 -0
- package/dist/chunk-SLI2YL25.cjs +252 -0
- package/dist/chunk-U4264IQH.js +78 -0
- package/dist/chunk-UY2YRCFC.js +250 -0
- package/dist/chunk-WCZTTQ7Z.cjs +32 -0
- package/dist/core/index.cjs +162 -0
- package/dist/core/index.d.cts +321 -0
- package/dist/core/index.d.ts +321 -0
- package/dist/core/index.js +49 -0
- package/dist/default-DRLIJX73.js +1183 -0
- package/dist/default-UK52WOO5.cjs +1192 -0
- package/dist/formats/epub/index.cjs +29 -0
- package/dist/formats/epub/index.d.cts +286 -0
- package/dist/formats/epub/index.d.ts +286 -0
- package/dist/formats/epub/index.js +11 -0
- package/dist/index.cjs +655 -0
- package/dist/index.d.cts +335 -0
- package/dist/index.d.ts +335 -0
- package/dist/index.js +600 -0
- package/dist/render/index.cjs +2 -0
- package/dist/render/index.d.cts +116 -0
- package/dist/render/index.d.ts +116 -0
- package/dist/render/index.js +1 -0
- package/dist/types-B76GOMxj.d.ts +129 -0
- package/dist/types-B7mslPBY.d.cts +166 -0
- package/dist/types-B7mslPBY.d.ts +166 -0
- package/dist/types-BH88rUYt.d.cts +129 -0
- package/dist/types-C-5eHSRH.d.ts +379 -0
- package/dist/types-CPUqTEPW.d.cts +379 -0
- package/dist/types-DQYmArgv.d.cts +17 -0
- package/dist/types-DQYmArgv.d.ts +17 -0
- package/package.json +115 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWCZTTQ7Z_cjs = require('./chunk-WCZTTQ7Z.cjs');
|
|
4
|
+
var chunkNABYHI6X_cjs = require('./chunk-NABYHI6X.cjs');
|
|
5
|
+
var chunkSLI2YL25_cjs = require('./chunk-SLI2YL25.cjs');
|
|
6
|
+
var chunkIIV6VIUJ_cjs = require('./chunk-IIV6VIUJ.cjs');
|
|
7
|
+
var chunkG7DLWGBW_cjs = require('./chunk-G7DLWGBW.cjs');
|
|
8
|
+
|
|
9
|
+
// src/formats/epub/container.ts
|
|
10
|
+
var EPUB_PACKAGE_MEDIA_TYPE = "application/oebps-package+xml";
|
|
11
|
+
var DEFAULT_CONTAINER_PATH = "META-INF/container.xml";
|
|
12
|
+
function formatError(message, source) {
|
|
13
|
+
return new chunkG7DLWGBW_cjs.FormatError(`${message}\uFF08\u6E90: ${source}\uFF09`);
|
|
14
|
+
}
|
|
15
|
+
function toContainerError(error, source, containerPath) {
|
|
16
|
+
const detail = error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF";
|
|
17
|
+
const message = `${detail}\uFF08container: ${containerPath}\uFF0C\u6E90: ${source}\uFF09`;
|
|
18
|
+
return error instanceof chunkG7DLWGBW_cjs.ParseError ? new chunkG7DLWGBW_cjs.ParseError(message, { cause: error }) : new chunkG7DLWGBW_cjs.FormatError(message, { cause: error });
|
|
19
|
+
}
|
|
20
|
+
async function parseContainer(archive, options = {}) {
|
|
21
|
+
const containerPath = options.containerPath ?? DEFAULT_CONTAINER_PATH;
|
|
22
|
+
const source = options.source ?? containerPath;
|
|
23
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
24
|
+
let xml;
|
|
25
|
+
try {
|
|
26
|
+
xml = await archive.readText(
|
|
27
|
+
containerPath,
|
|
28
|
+
options.signal === void 0 ? {} : { signal: options.signal }
|
|
29
|
+
);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (chunkG7DLWGBW_cjs.isAbortError(error)) throw error;
|
|
32
|
+
throw toContainerError(error, source, containerPath);
|
|
33
|
+
}
|
|
34
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
35
|
+
const document = chunkNABYHI6X_cjs.parseXml(xml, { source });
|
|
36
|
+
for (const rootfile of chunkNABYHI6X_cjs.findAll(document, "rootfile")) {
|
|
37
|
+
if (chunkNABYHI6X_cjs.getAttribute(rootfile, "media-type") !== EPUB_PACKAGE_MEDIA_TYPE) continue;
|
|
38
|
+
const rawPath = chunkNABYHI6X_cjs.getAttribute(rootfile, "full-path");
|
|
39
|
+
if (rawPath === void 0) {
|
|
40
|
+
throw formatError("rootfile \u7F3A\u5C11 full-path \u5C5E\u6027", source);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
opfPath: chunkIIV6VIUJ_cjs.resolveArchivePath("", rawPath, {
|
|
44
|
+
label: "rootfile \u7684 full-path",
|
|
45
|
+
source
|
|
46
|
+
}),
|
|
47
|
+
mediaType: EPUB_PACKAGE_MEDIA_TYPE
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
throw formatError(
|
|
51
|
+
`container \u4E2D\u6CA1\u6709\u53D7\u652F\u6301\u7684 package rootfile\uFF08\u671F\u671B media-type="${EPUB_PACKAGE_MEDIA_TYPE}"\uFF09`,
|
|
52
|
+
source
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/formats/epub/opf.ts
|
|
57
|
+
var PACKAGE_LOCAL_NAME = "package";
|
|
58
|
+
function formatError2(message, source) {
|
|
59
|
+
return new chunkG7DLWGBW_cjs.FormatError(`${message}\uFF08\u6E90: ${source}\uFF09`);
|
|
60
|
+
}
|
|
61
|
+
function toOpfError(error, source, opfPath) {
|
|
62
|
+
const detail = error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF";
|
|
63
|
+
const message = `${detail}\uFF08OPF: ${opfPath}\uFF0C\u6E90: ${source}\uFF09`;
|
|
64
|
+
return error instanceof chunkG7DLWGBW_cjs.ParseError ? new chunkG7DLWGBW_cjs.ParseError(message, { cause: error }) : new chunkG7DLWGBW_cjs.FormatError(message, { cause: error });
|
|
65
|
+
}
|
|
66
|
+
function textOf(element) {
|
|
67
|
+
return chunkNABYHI6X_cjs.getText(element).trim();
|
|
68
|
+
}
|
|
69
|
+
function firstNonEmptyText(root, localName) {
|
|
70
|
+
for (const element of chunkNABYHI6X_cjs.findAll(root, localName)) {
|
|
71
|
+
const text = textOf(element);
|
|
72
|
+
if (text !== "") return text;
|
|
73
|
+
}
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
function stripFragment(href) {
|
|
77
|
+
const index = href.indexOf("#");
|
|
78
|
+
return index === -1 ? href : href.slice(0, index);
|
|
79
|
+
}
|
|
80
|
+
function resolveIdentifier(metadataElement, packageElement, source) {
|
|
81
|
+
const identifiers = chunkNABYHI6X_cjs.findAll(metadataElement, "identifier");
|
|
82
|
+
if (identifiers.length === 0) {
|
|
83
|
+
throw formatError2("\u7F3A\u5C11\u5FC5\u9700\u7684 dc:identifier", source);
|
|
84
|
+
}
|
|
85
|
+
const uniqueId = chunkNABYHI6X_cjs.getAttribute(packageElement, "unique-identifier");
|
|
86
|
+
if (uniqueId !== void 0 && uniqueId !== "") {
|
|
87
|
+
const matched = identifiers.find((element) => chunkNABYHI6X_cjs.getAttribute(element, "id") === uniqueId);
|
|
88
|
+
if (matched === void 0) {
|
|
89
|
+
throw formatError2(
|
|
90
|
+
`package@unique-identifier \u6307\u5411\u4E0D\u5B58\u5728\u7684 dc:identifier\uFF08id="${uniqueId}"\uFF09`,
|
|
91
|
+
source
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
const text = textOf(matched);
|
|
95
|
+
if (text === "") {
|
|
96
|
+
throw formatError2(`dc:identifier\uFF08id="${uniqueId}"\uFF09\u4E3A\u7A7A`, source);
|
|
97
|
+
}
|
|
98
|
+
return text;
|
|
99
|
+
}
|
|
100
|
+
const fallback = identifiers.map(textOf).find((text) => text !== "");
|
|
101
|
+
if (fallback === void 0) {
|
|
102
|
+
throw formatError2("\u7F3A\u5C11\u5FC5\u9700\u7684 dc:identifier", source);
|
|
103
|
+
}
|
|
104
|
+
return fallback;
|
|
105
|
+
}
|
|
106
|
+
function resolveModified(metadataElement) {
|
|
107
|
+
for (const element of chunkNABYHI6X_cjs.findAll(metadataElement, "meta")) {
|
|
108
|
+
if (chunkNABYHI6X_cjs.getAttribute(element, "property") !== "dcterms:modified") continue;
|
|
109
|
+
const text = textOf(element);
|
|
110
|
+
if (text !== "") return text;
|
|
111
|
+
}
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
function buildMetadata(metadataElement, packageElement, source) {
|
|
115
|
+
const title = firstNonEmptyText(metadataElement, "title");
|
|
116
|
+
if (title === void 0) {
|
|
117
|
+
throw formatError2("\u7F3A\u5C11\u5FC5\u9700\u7684 dc:title", source);
|
|
118
|
+
}
|
|
119
|
+
const language = firstNonEmptyText(metadataElement, "language");
|
|
120
|
+
if (language === void 0) {
|
|
121
|
+
throw formatError2("\u7F3A\u5C11\u5FC5\u9700\u7684 dc:language", source);
|
|
122
|
+
}
|
|
123
|
+
const creators = chunkNABYHI6X_cjs.findAll(metadataElement, "creator").map(textOf).filter((text) => text !== "");
|
|
124
|
+
const identifier = resolveIdentifier(metadataElement, packageElement, source);
|
|
125
|
+
const modified = resolveModified(metadataElement);
|
|
126
|
+
return {
|
|
127
|
+
title,
|
|
128
|
+
creators,
|
|
129
|
+
language,
|
|
130
|
+
identifier,
|
|
131
|
+
...modified === void 0 ? {} : { modified }
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function buildManifest(manifestElement, basePath, source, signal) {
|
|
135
|
+
const items = [];
|
|
136
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
137
|
+
for (const element of chunkNABYHI6X_cjs.findAll(manifestElement, "item")) {
|
|
138
|
+
chunkG7DLWGBW_cjs.throwIfAborted(signal);
|
|
139
|
+
const id = chunkNABYHI6X_cjs.getAttribute(element, "id");
|
|
140
|
+
if (id === void 0 || id === "") {
|
|
141
|
+
throw formatError2("manifest \u7684 <item> \u7F3A\u5C11 id \u5C5E\u6027", source);
|
|
142
|
+
}
|
|
143
|
+
if (seenIds.has(id)) {
|
|
144
|
+
throw formatError2(`manifest \u4E2D\u5B58\u5728\u91CD\u590D id="${id}"`, source);
|
|
145
|
+
}
|
|
146
|
+
seenIds.add(id);
|
|
147
|
+
const rawHref = chunkNABYHI6X_cjs.getAttribute(element, "href");
|
|
148
|
+
if (rawHref === void 0 || rawHref === "") {
|
|
149
|
+
throw formatError2(`manifest item "${id}" \u7F3A\u5C11 href \u5C5E\u6027`, source);
|
|
150
|
+
}
|
|
151
|
+
const mediaType = chunkNABYHI6X_cjs.getAttribute(element, "media-type");
|
|
152
|
+
if (mediaType === void 0 || mediaType === "") {
|
|
153
|
+
throw formatError2(`manifest item "${id}" \u7F3A\u5C11 media-type \u5C5E\u6027`, source);
|
|
154
|
+
}
|
|
155
|
+
const properties = (chunkNABYHI6X_cjs.getAttribute(element, "properties") ?? "").split(/\s+/).filter((property) => property !== "");
|
|
156
|
+
const href = chunkIIV6VIUJ_cjs.resolveArchivePath(basePath, stripFragment(rawHref), {
|
|
157
|
+
label: `manifest item "${id}" \u7684 href`,
|
|
158
|
+
source
|
|
159
|
+
});
|
|
160
|
+
items.push({ id, href, mediaType, properties });
|
|
161
|
+
}
|
|
162
|
+
return items;
|
|
163
|
+
}
|
|
164
|
+
function buildSpine(spineElement, manifestIndex, source, signal) {
|
|
165
|
+
const spine = [];
|
|
166
|
+
let index = 0;
|
|
167
|
+
for (const element of chunkNABYHI6X_cjs.findAll(spineElement, "itemref")) {
|
|
168
|
+
chunkG7DLWGBW_cjs.throwIfAborted(signal);
|
|
169
|
+
const idref = chunkNABYHI6X_cjs.getAttribute(element, "idref");
|
|
170
|
+
if (idref === void 0 || idref === "") {
|
|
171
|
+
throw formatError2("spine \u7684 <itemref> \u7F3A\u5C11 idref \u5C5E\u6027", source);
|
|
172
|
+
}
|
|
173
|
+
const item = manifestIndex.get(idref);
|
|
174
|
+
if (item === void 0) {
|
|
175
|
+
throw formatError2(`spine \u7684 <itemref> \u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 manifest id="${idref}"`, source);
|
|
176
|
+
}
|
|
177
|
+
const linear = chunkNABYHI6X_cjs.getAttribute(element, "linear") !== "no";
|
|
178
|
+
spine.push({ idref, linear, index, item });
|
|
179
|
+
index += 1;
|
|
180
|
+
}
|
|
181
|
+
return spine;
|
|
182
|
+
}
|
|
183
|
+
function resolveNcxPath(spineElement, manifestIndex) {
|
|
184
|
+
const tocId = chunkNABYHI6X_cjs.getAttribute(spineElement, "toc");
|
|
185
|
+
if (tocId === void 0 || tocId === "") return void 0;
|
|
186
|
+
return manifestIndex.get(tocId)?.href;
|
|
187
|
+
}
|
|
188
|
+
function resolveDirection(spineElement) {
|
|
189
|
+
const raw = chunkNABYHI6X_cjs.getAttribute(spineElement, "page-progression-direction")?.trim().toLowerCase();
|
|
190
|
+
return raw === "ltr" || raw === "rtl" ? raw : void 0;
|
|
191
|
+
}
|
|
192
|
+
function buildBook(document, opfPath, source, signal) {
|
|
193
|
+
if (document.localName !== PACKAGE_LOCAL_NAME) {
|
|
194
|
+
throw formatError2(`OPF \u6839\u5143\u7D20\u5E94\u4E3A <package>\uFF0C\u5B9E\u9645\u4E3A <${document.name}>`, source);
|
|
195
|
+
}
|
|
196
|
+
const metadataElement = chunkNABYHI6X_cjs.findFirst(document, "metadata");
|
|
197
|
+
if (metadataElement === void 0) {
|
|
198
|
+
throw formatError2("\u7F3A\u5C11 <metadata> \u5143\u7D20", source);
|
|
199
|
+
}
|
|
200
|
+
const manifestElement = chunkNABYHI6X_cjs.findFirst(document, "manifest");
|
|
201
|
+
if (manifestElement === void 0) {
|
|
202
|
+
throw formatError2("\u7F3A\u5C11 <manifest> \u5143\u7D20", source);
|
|
203
|
+
}
|
|
204
|
+
const spineElement = chunkNABYHI6X_cjs.findFirst(document, "spine");
|
|
205
|
+
if (spineElement === void 0) {
|
|
206
|
+
throw formatError2("\u7F3A\u5C11 <spine> \u5143\u7D20", source);
|
|
207
|
+
}
|
|
208
|
+
const basePath = chunkIIV6VIUJ_cjs.directoryOf(opfPath);
|
|
209
|
+
const metadata = buildMetadata(metadataElement, document, source);
|
|
210
|
+
const manifest = buildManifest(manifestElement, basePath, source, signal);
|
|
211
|
+
const manifestIndex = new Map(manifest.map((item) => [item.id, item]));
|
|
212
|
+
const spine = buildSpine(spineElement, manifestIndex, source, signal);
|
|
213
|
+
const ncxPath = resolveNcxPath(spineElement, manifestIndex);
|
|
214
|
+
const direction = resolveDirection(spineElement);
|
|
215
|
+
const tocItem = manifest.find((item) => item.properties.includes("nav"));
|
|
216
|
+
const resources = manifest.map(({ href, mediaType }) => ({ href, mediaType }));
|
|
217
|
+
const chapters = spine.map(({ item, linear }) => ({
|
|
218
|
+
href: item.href,
|
|
219
|
+
mediaType: item.mediaType,
|
|
220
|
+
linear
|
|
221
|
+
}));
|
|
222
|
+
return {
|
|
223
|
+
format: "epub",
|
|
224
|
+
metadata,
|
|
225
|
+
resources,
|
|
226
|
+
chapters,
|
|
227
|
+
opfPath,
|
|
228
|
+
basePath,
|
|
229
|
+
manifest,
|
|
230
|
+
spine,
|
|
231
|
+
manifestIndex,
|
|
232
|
+
// exactOptionalPropertyTypes:可选字段不能显式传 `undefined`。
|
|
233
|
+
...tocItem === void 0 ? {} : { tocItem },
|
|
234
|
+
...ncxPath === void 0 ? {} : { ncxPath },
|
|
235
|
+
// 同上。`direction` 在「缺省 / `default` / 非法值」三种情况下都缺席(见 `resolveDirection`)。
|
|
236
|
+
...direction === void 0 ? {} : { direction }
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async function parseOpf(archive, opfPath, options = {}) {
|
|
240
|
+
const source = options.source ?? opfPath;
|
|
241
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
242
|
+
let xml;
|
|
243
|
+
try {
|
|
244
|
+
xml = await archive.readText(
|
|
245
|
+
opfPath,
|
|
246
|
+
options.signal === void 0 ? {} : { signal: options.signal }
|
|
247
|
+
);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (chunkG7DLWGBW_cjs.isAbortError(error)) throw error;
|
|
250
|
+
throw toOpfError(error, source, opfPath);
|
|
251
|
+
}
|
|
252
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
253
|
+
const document = chunkNABYHI6X_cjs.parseXml(xml, { source });
|
|
254
|
+
return buildBook(document, opfPath, source, options.signal);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/formats/epub/nav.ts
|
|
258
|
+
function formatError3(message, source) {
|
|
259
|
+
return new chunkG7DLWGBW_cjs.FormatError(`${message}\uFF08\u6E90: ${source}\uFF09`);
|
|
260
|
+
}
|
|
261
|
+
function toTocError(error, source, documentPath) {
|
|
262
|
+
const detail = error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF";
|
|
263
|
+
const message = `${detail}\uFF08\u76EE\u5F55: ${documentPath}\uFF0C\u6E90: ${source}\uFF09`;
|
|
264
|
+
return error instanceof chunkG7DLWGBW_cjs.ParseError ? new chunkG7DLWGBW_cjs.ParseError(message, { cause: error }) : new chunkG7DLWGBW_cjs.FormatError(message, { cause: error });
|
|
265
|
+
}
|
|
266
|
+
function directChildren(element, localName) {
|
|
267
|
+
const matched = [];
|
|
268
|
+
for (const child of element.children) {
|
|
269
|
+
if (child.type !== "element") continue;
|
|
270
|
+
if (child.localName === localName) matched.push(child);
|
|
271
|
+
}
|
|
272
|
+
return matched;
|
|
273
|
+
}
|
|
274
|
+
function firstDirectChild(element, localName) {
|
|
275
|
+
for (const child of element.children) {
|
|
276
|
+
if (child.type === "element" && child.localName === localName) return child;
|
|
277
|
+
}
|
|
278
|
+
return void 0;
|
|
279
|
+
}
|
|
280
|
+
function typeTokens(element) {
|
|
281
|
+
for (const [name, value] of element.attributes) {
|
|
282
|
+
if (name === "epub:type" || name.endsWith(":type")) {
|
|
283
|
+
return value.split(/\s+/).filter((token) => token !== "");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
function textOf2(element) {
|
|
289
|
+
return chunkNABYHI6X_cjs.getText(element).trim();
|
|
290
|
+
}
|
|
291
|
+
function splitReference(raw) {
|
|
292
|
+
const index = raw.indexOf("#");
|
|
293
|
+
if (index === -1) return { path: raw };
|
|
294
|
+
const fragment = raw.slice(index + 1);
|
|
295
|
+
return { path: raw.slice(0, index), ...fragment === "" ? {} : { fragment } };
|
|
296
|
+
}
|
|
297
|
+
function resolveTarget(raw, context, label) {
|
|
298
|
+
const { path, fragment } = splitReference(raw);
|
|
299
|
+
const href = path === "" ? context.documentPath : chunkIIV6VIUJ_cjs.resolveArchivePath(chunkIIV6VIUJ_cjs.directoryOf(context.documentPath), path, {
|
|
300
|
+
label,
|
|
301
|
+
source: context.source
|
|
302
|
+
});
|
|
303
|
+
return { href, ...fragment === void 0 ? {} : { fragment } };
|
|
304
|
+
}
|
|
305
|
+
function buildItem(label, target, children) {
|
|
306
|
+
return {
|
|
307
|
+
label,
|
|
308
|
+
href: target.href,
|
|
309
|
+
...target.fragment === void 0 ? {} : { fragment: target.fragment },
|
|
310
|
+
children
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function selectTocNav(document) {
|
|
314
|
+
const navs = chunkNABYHI6X_cjs.findAll(document, "nav");
|
|
315
|
+
if (navs.length === 0) return void 0;
|
|
316
|
+
return navs.find((nav) => typeTokens(nav).includes("toc")) ?? navs[0];
|
|
317
|
+
}
|
|
318
|
+
function parseNavList(olElement, context) {
|
|
319
|
+
const items = [];
|
|
320
|
+
for (const li of directChildren(olElement, "li")) {
|
|
321
|
+
chunkG7DLWGBW_cjs.throwIfAborted(context.signal);
|
|
322
|
+
items.push(parseNavItem(li, context));
|
|
323
|
+
}
|
|
324
|
+
return items;
|
|
325
|
+
}
|
|
326
|
+
function parseNavItem(li, context) {
|
|
327
|
+
const anchor = firstDirectChild(li, "a");
|
|
328
|
+
if (anchor === void 0) {
|
|
329
|
+
const span = firstDirectChild(li, "span");
|
|
330
|
+
throw formatError3(
|
|
331
|
+
span === void 0 ? "\u76EE\u5F55\u9879\u7684 <li> \u5185\u7F3A\u5C11 <a> \u5143\u7D20" : "\u76EE\u5F55\u9879\u53EA\u6709 <span>\uFF08\u65E0\u76EE\u6807\u94FE\u63A5\uFF09\uFF0C\u672C\u5B9E\u73B0\u8981\u6C42\u76EE\u5F55\u9879\u5FC5\u987B\u6307\u5411\u5177\u4F53\u6587\u6863",
|
|
332
|
+
context.source
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
const label = textOf2(anchor);
|
|
336
|
+
const rawHref = chunkNABYHI6X_cjs.getAttribute(anchor, "href");
|
|
337
|
+
if (rawHref === void 0 || rawHref === "") {
|
|
338
|
+
throw formatError3(`\u76EE\u5F55\u9879\u7684 <a> \u7F3A\u5C11 href \u5C5E\u6027\uFF08label: "${label}"\uFF09`, context.source);
|
|
339
|
+
}
|
|
340
|
+
const target = resolveTarget(rawHref, context, `\u76EE\u5F55\u9879 "${label}" \u7684 href`);
|
|
341
|
+
const children = [];
|
|
342
|
+
for (const nested of directChildren(li, "ol")) {
|
|
343
|
+
children.push(...parseNavList(nested, context));
|
|
344
|
+
}
|
|
345
|
+
return buildItem(label, target, children);
|
|
346
|
+
}
|
|
347
|
+
function parseNavDocument(document, context) {
|
|
348
|
+
const nav = selectTocNav(document);
|
|
349
|
+
if (nav === void 0) return [];
|
|
350
|
+
const items = [];
|
|
351
|
+
for (const ol of directChildren(nav, "ol")) {
|
|
352
|
+
items.push(...parseNavList(ol, context));
|
|
353
|
+
}
|
|
354
|
+
return items;
|
|
355
|
+
}
|
|
356
|
+
function parseNcxPoints(points, context) {
|
|
357
|
+
const items = [];
|
|
358
|
+
for (const point of points) {
|
|
359
|
+
chunkG7DLWGBW_cjs.throwIfAborted(context.signal);
|
|
360
|
+
const labelElement = firstDirectChild(point, "navLabel");
|
|
361
|
+
const label = labelElement === void 0 ? "" : textOf2(labelElement);
|
|
362
|
+
const content = firstDirectChild(point, "content");
|
|
363
|
+
const rawSrc = content === void 0 ? void 0 : chunkNABYHI6X_cjs.getAttribute(content, "src");
|
|
364
|
+
if (rawSrc === void 0 || rawSrc === "") {
|
|
365
|
+
throw formatError3(`navPoint \u7F3A\u5C11 content@src\uFF08label: "${label}"\uFF09`, context.source);
|
|
366
|
+
}
|
|
367
|
+
const target = resolveTarget(rawSrc, context, `navPoint "${label}" \u7684 content@src`);
|
|
368
|
+
const children = parseNcxPoints(directChildren(point, "navPoint"), context);
|
|
369
|
+
items.push(buildItem(label, target, children));
|
|
370
|
+
}
|
|
371
|
+
return items;
|
|
372
|
+
}
|
|
373
|
+
function parseNcxDocument(document, context) {
|
|
374
|
+
const navMap = firstDirectChild(document, "navMap");
|
|
375
|
+
if (navMap === void 0) return [];
|
|
376
|
+
return parseNcxPoints(directChildren(navMap, "navPoint"), context);
|
|
377
|
+
}
|
|
378
|
+
async function readAndParse(archive, documentPath, context, parse) {
|
|
379
|
+
chunkG7DLWGBW_cjs.throwIfAborted(context.signal);
|
|
380
|
+
let xml;
|
|
381
|
+
try {
|
|
382
|
+
xml = await archive.readText(
|
|
383
|
+
documentPath,
|
|
384
|
+
context.signal === void 0 ? {} : { signal: context.signal }
|
|
385
|
+
);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
if (chunkG7DLWGBW_cjs.isAbortError(error)) throw error;
|
|
388
|
+
throw toTocError(error, context.source, documentPath);
|
|
389
|
+
}
|
|
390
|
+
chunkG7DLWGBW_cjs.throwIfAborted(context.signal);
|
|
391
|
+
return parse(chunkNABYHI6X_cjs.parseXml(xml, { source: context.source }), context);
|
|
392
|
+
}
|
|
393
|
+
async function parseToc(archive, book, options = {}) {
|
|
394
|
+
const navItem = book.tocItem;
|
|
395
|
+
if (navItem !== void 0) {
|
|
396
|
+
const context = {
|
|
397
|
+
documentPath: navItem.href,
|
|
398
|
+
source: options.source ?? navItem.href,
|
|
399
|
+
signal: options.signal
|
|
400
|
+
};
|
|
401
|
+
return readAndParse(archive, navItem.href, context, parseNavDocument);
|
|
402
|
+
}
|
|
403
|
+
const ncxPath = book.ncxPath;
|
|
404
|
+
if (ncxPath !== void 0) {
|
|
405
|
+
const context = {
|
|
406
|
+
documentPath: ncxPath,
|
|
407
|
+
source: options.source ?? ncxPath,
|
|
408
|
+
signal: options.signal
|
|
409
|
+
};
|
|
410
|
+
return readAndParse(archive, ncxPath, context, parseNcxDocument);
|
|
411
|
+
}
|
|
412
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
413
|
+
return [];
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/formats/epub/open.ts
|
|
417
|
+
async function openBook(source, options = {}) {
|
|
418
|
+
chunkG7DLWGBW_cjs.throwIfAborted(options.signal);
|
|
419
|
+
const bytes = await chunkWCZTTQ7Z_cjs.resolveBookBytes(source, options);
|
|
420
|
+
const archive = chunkSLI2YL25_cjs.parseZip(bytes, options);
|
|
421
|
+
const container = await parseContainer(archive, options);
|
|
422
|
+
const book = await parseOpf(archive, container.opfPath, options);
|
|
423
|
+
const toc = await parseToc(archive, book, options);
|
|
424
|
+
return { archive, book, toc };
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
exports.openBook = openBook;
|
|
428
|
+
exports.parseContainer = parseContainer;
|
|
429
|
+
exports.parseOpf = parseOpf;
|
|
430
|
+
exports.parseToc = parseToc;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/errors.ts
|
|
4
|
+
var FrondError = class extends Error {
|
|
5
|
+
/** 稳定错误码,用于程序化分支。 */
|
|
6
|
+
code;
|
|
7
|
+
constructor(code, message, options) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "FrondError";
|
|
10
|
+
this.code = code;
|
|
11
|
+
if (options?.cause !== void 0) {
|
|
12
|
+
this.cause = options.cause;
|
|
13
|
+
}
|
|
14
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var ParseError = class extends FrondError {
|
|
18
|
+
constructor(message, options) {
|
|
19
|
+
super("ERR_PARSE", message, options);
|
|
20
|
+
this.name = "ParseError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var FormatError = class extends FrondError {
|
|
24
|
+
constructor(message, options) {
|
|
25
|
+
super("ERR_FORMAT", message, options);
|
|
26
|
+
this.name = "FormatError";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var NetworkError = class extends FrondError {
|
|
30
|
+
constructor(message, options) {
|
|
31
|
+
super("ERR_NETWORK", message, options);
|
|
32
|
+
this.name = "NetworkError";
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var SecurityError = class extends FrondError {
|
|
36
|
+
constructor(message, options) {
|
|
37
|
+
super("ERR_SECURITY", message, options);
|
|
38
|
+
this.name = "SecurityError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var AbortError = class extends FrondError {
|
|
42
|
+
constructor(message = "\u64CD\u4F5C\u5DF2\u53D6\u6D88", options) {
|
|
43
|
+
super("ERR_ABORT", message, options);
|
|
44
|
+
this.name = "AbortError";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var StateError = class extends FrondError {
|
|
48
|
+
constructor(message, options) {
|
|
49
|
+
super("ERR_STATE", message, options);
|
|
50
|
+
this.name = "StateError";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function isFrondError(value) {
|
|
54
|
+
return value instanceof FrondError;
|
|
55
|
+
}
|
|
56
|
+
function isAbortError(value) {
|
|
57
|
+
if (value instanceof AbortError) return true;
|
|
58
|
+
return value instanceof Error && value.name === "AbortError";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/core/abort.ts
|
|
62
|
+
function createAbortError(reason) {
|
|
63
|
+
const message = reason instanceof Error && reason.message !== "" ? reason.message : "\u64CD\u4F5C\u5DF2\u53D6\u6D88";
|
|
64
|
+
return new AbortError(message, reason === void 0 ? void 0 : { cause: reason });
|
|
65
|
+
}
|
|
66
|
+
function throwIfAborted(signal) {
|
|
67
|
+
if (signal === void 0 || !signal.aborted) return;
|
|
68
|
+
throw createAbortError(signal.reason);
|
|
69
|
+
}
|
|
70
|
+
function linkSignals(...signals) {
|
|
71
|
+
const active = signals.filter((signal) => signal !== void 0);
|
|
72
|
+
if (active.length === 0) return void 0;
|
|
73
|
+
if (active.length === 1) return active[0];
|
|
74
|
+
return AbortSignal.any(active);
|
|
75
|
+
}
|
|
76
|
+
function onAbort(signal, handler) {
|
|
77
|
+
if (signal === void 0) return () => void 0;
|
|
78
|
+
if (signal.aborted) {
|
|
79
|
+
handler();
|
|
80
|
+
return () => void 0;
|
|
81
|
+
}
|
|
82
|
+
const listener = () => {
|
|
83
|
+
handler();
|
|
84
|
+
};
|
|
85
|
+
signal.addEventListener("abort", listener, { once: true });
|
|
86
|
+
return () => {
|
|
87
|
+
signal.removeEventListener("abort", listener);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
exports.AbortError = AbortError;
|
|
92
|
+
exports.FormatError = FormatError;
|
|
93
|
+
exports.FrondError = FrondError;
|
|
94
|
+
exports.NetworkError = NetworkError;
|
|
95
|
+
exports.ParseError = ParseError;
|
|
96
|
+
exports.SecurityError = SecurityError;
|
|
97
|
+
exports.StateError = StateError;
|
|
98
|
+
exports.createAbortError = createAbortError;
|
|
99
|
+
exports.isAbortError = isAbortError;
|
|
100
|
+
exports.isFrondError = isFrondError;
|
|
101
|
+
exports.linkSignals = linkSignals;
|
|
102
|
+
exports.onAbort = onAbort;
|
|
103
|
+
exports.throwIfAborted = throwIfAborted;
|