wolfy-reader 0.1.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.md +277 -0
- package/dist/core/book.d.ts +75 -0
- package/dist/core/book.d.ts.map +1 -0
- package/dist/core/book.js +2 -0
- package/dist/core/book.js.map +1 -0
- package/dist/core/errors.d.ts +17 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +29 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/format.d.ts +13 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +2 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/graphemes.d.ts +36 -0
- package/dist/core/graphemes.d.ts.map +1 -0
- package/dist/core/graphemes.js +62 -0
- package/dist/core/graphemes.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lookup.d.ts +10 -0
- package/dist/core/lookup.d.ts.map +1 -0
- package/dist/core/lookup.js +16 -0
- package/dist/core/lookup.js.map +1 -0
- package/dist/core/open.d.ts +12 -0
- package/dist/core/open.d.ts.map +1 -0
- package/dist/core/open.js +23 -0
- package/dist/core/open.js.map +1 -0
- package/dist/core/position.d.ts +121 -0
- package/dist/core/position.d.ts.map +1 -0
- package/dist/core/position.js +327 -0
- package/dist/core/position.js.map +1 -0
- package/dist/core/reading-text.d.ts +77 -0
- package/dist/core/reading-text.d.ts.map +1 -0
- package/dist/core/reading-text.js +144 -0
- package/dist/core/reading-text.js.map +1 -0
- package/dist/core/source.d.ts +17 -0
- package/dist/core/source.d.ts.map +1 -0
- package/dist/core/source.js +39 -0
- package/dist/core/source.js.map +1 -0
- package/dist/core/storage.d.ts +7 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +2 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/text.d.ts +18 -0
- package/dist/core/text.d.ts.map +1 -0
- package/dist/core/text.js +32 -0
- package/dist/core/text.js.map +1 -0
- package/dist/formats/epub/href.d.ts +14 -0
- package/dist/formats/epub/href.d.ts.map +1 -0
- package/dist/formats/epub/href.js +52 -0
- package/dist/formats/epub/href.js.map +1 -0
- package/dist/formats/epub/index.d.ts +3 -0
- package/dist/formats/epub/index.d.ts.map +1 -0
- package/dist/formats/epub/index.js +223 -0
- package/dist/formats/epub/index.js.map +1 -0
- package/dist/formats/epub/opf.d.ts +27 -0
- package/dist/formats/epub/opf.d.ts.map +1 -0
- package/dist/formats/epub/opf.js +110 -0
- package/dist/formats/epub/opf.js.map +1 -0
- package/dist/formats/epub/toc.d.ts +6 -0
- package/dist/formats/epub/toc.d.ts.map +1 -0
- package/dist/formats/epub/toc.js +88 -0
- package/dist/formats/epub/toc.js.map +1 -0
- package/dist/formats/fb2/index.d.ts +13 -0
- package/dist/formats/fb2/index.d.ts.map +1 -0
- package/dist/formats/fb2/index.js +317 -0
- package/dist/formats/fb2/index.js.map +1 -0
- package/dist/formats/index.d.ts +4 -0
- package/dist/formats/index.d.ts.map +1 -0
- package/dist/formats/index.js +4 -0
- package/dist/formats/index.js.map +1 -0
- package/dist/formats/text/index.d.ts +11 -0
- package/dist/formats/text/index.d.ts.map +1 -0
- package/dist/formats/text/index.js +201 -0
- package/dist/formats/text/index.js.map +1 -0
- package/dist/formats/xml.d.ts +33 -0
- package/dist/formats/xml.d.ts.map +1 -0
- package/dist/formats/xml.js +321 -0
- package/dist/formats/xml.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/chunk.d.ts +51 -0
- package/dist/layout/chunk.d.ts.map +1 -0
- package/dist/layout/chunk.js +131 -0
- package/dist/layout/chunk.js.map +1 -0
- package/dist/layout/index.d.ts +238 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +476 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/reader/index.d.ts +231 -0
- package/dist/reader/index.d.ts.map +1 -0
- package/dist/reader/index.js +958 -0
- package/dist/reader/index.js.map +1 -0
- package/dist/reader/input.d.ts +69 -0
- package/dist/reader/input.d.ts.map +1 -0
- package/dist/reader/input.js +75 -0
- package/dist/reader/input.js.map +1 -0
- package/dist/search/extract.d.ts +51 -0
- package/dist/search/extract.d.ts.map +1 -0
- package/dist/search/extract.js +401 -0
- package/dist/search/extract.js.map +1 -0
- package/dist/search/index.d.ts +11 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +11 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/matcher.d.ts +56 -0
- package/dist/search/matcher.d.ts.map +1 -0
- package/dist/search/matcher.js +128 -0
- package/dist/search/matcher.js.map +1 -0
- package/dist/search/normalize.d.ts +48 -0
- package/dist/search/normalize.d.ts.map +1 -0
- package/dist/search/normalize.js +103 -0
- package/dist/search/normalize.js.map +1 -0
- package/dist/view/allowlist.d.ts +59 -0
- package/dist/view/allowlist.d.ts.map +1 -0
- package/dist/view/allowlist.js +198 -0
- package/dist/view/allowlist.js.map +1 -0
- package/dist/view/appearance.d.ts +137 -0
- package/dist/view/appearance.d.ts.map +1 -0
- package/dist/view/appearance.js +274 -0
- package/dist/view/appearance.js.map +1 -0
- package/dist/view/css.d.ts +24 -0
- package/dist/view/css.d.ts.map +1 -0
- package/dist/view/css.js +153 -0
- package/dist/view/css.js.map +1 -0
- package/dist/view/frame.d.ts +54 -0
- package/dist/view/frame.d.ts.map +1 -0
- package/dist/view/frame.js +980 -0
- package/dist/view/frame.js.map +1 -0
- package/dist/view/host.d.ts +160 -0
- package/dist/view/host.d.ts.map +1 -0
- package/dist/view/host.js +385 -0
- package/dist/view/host.js.map +1 -0
- package/dist/view/index.d.ts +12 -0
- package/dist/view/index.d.ts.map +1 -0
- package/dist/view/index.js +7 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/protocol.d.ts +220 -0
- package/dist/view/protocol.d.ts.map +1 -0
- package/dist/view/protocol.js +246 -0
- package/dist/view/protocol.js.map +1 -0
- package/dist/view/reference.d.ts +18 -0
- package/dist/view/reference.d.ts.map +1 -0
- package/dist/view/reference.js +25 -0
- package/dist/view/reference.js.map +1 -0
- package/dist/view/resources.d.ts +51 -0
- package/dist/view/resources.d.ts.map +1 -0
- package/dist/view/resources.js +242 -0
- package/dist/view/resources.js.map +1 -0
- package/dist/view/sanitize.d.ts +32 -0
- package/dist/view/sanitize.d.ts.map +1 -0
- package/dist/view/sanitize.js +226 -0
- package/dist/view/sanitize.js.map +1 -0
- package/dist/zip/central.d.ts +12 -0
- package/dist/zip/central.d.ts.map +1 -0
- package/dist/zip/central.js +72 -0
- package/dist/zip/central.js.map +1 -0
- package/dist/zip/crc32.d.ts +3 -0
- package/dist/zip/crc32.d.ts.map +1 -0
- package/dist/zip/crc32.js +28 -0
- package/dist/zip/crc32.js.map +1 -0
- package/dist/zip/eocd.d.ts +9 -0
- package/dist/zip/eocd.d.ts.map +1 -0
- package/dist/zip/eocd.js +84 -0
- package/dist/zip/eocd.js.map +1 -0
- package/dist/zip/errors.d.ts +19 -0
- package/dist/zip/errors.d.ts.map +1 -0
- package/dist/zip/errors.js +37 -0
- package/dist/zip/errors.js.map +1 -0
- package/dist/zip/index.d.ts +18 -0
- package/dist/zip/index.d.ts.map +1 -0
- package/dist/zip/index.js +78 -0
- package/dist/zip/index.js.map +1 -0
- package/dist/zip/inflate.d.ts +2 -0
- package/dist/zip/inflate.d.ts.map +1 -0
- package/dist/zip/inflate.js +43 -0
- package/dist/zip/inflate.js.map +1 -0
- package/dist/zip/source.d.ts +15 -0
- package/dist/zip/source.d.ts.map +1 -0
- package/dist/zip/source.js +34 -0
- package/dist/zip/source.js.map +1 -0
- package/package.json +75 -0
- package/src/core/book.ts +80 -0
- package/src/core/errors.ts +31 -0
- package/src/core/format.ts +14 -0
- package/src/core/graphemes.ts +73 -0
- package/src/core/index.ts +27 -0
- package/src/core/lookup.ts +16 -0
- package/src/core/open.ts +31 -0
- package/src/core/position.ts +485 -0
- package/src/core/reading-text.ts +200 -0
- package/src/core/source.ts +61 -0
- package/src/core/storage.ts +6 -0
- package/src/core/text.ts +35 -0
- package/src/formats/epub/href.ts +54 -0
- package/src/formats/epub/index.ts +235 -0
- package/src/formats/epub/opf.ts +143 -0
- package/src/formats/epub/toc.ts +120 -0
- package/src/formats/fb2/index.ts +348 -0
- package/src/formats/index.ts +3 -0
- package/src/formats/text/index.ts +208 -0
- package/src/formats/xml.ts +326 -0
- package/src/index.ts +26 -0
- package/src/layout/chunk.ts +169 -0
- package/src/layout/index.ts +573 -0
- package/src/reader/index.ts +1206 -0
- package/src/reader/input.ts +122 -0
- package/src/search/extract.ts +403 -0
- package/src/search/index.ts +10 -0
- package/src/search/matcher.ts +187 -0
- package/src/search/normalize.ts +122 -0
- package/src/view/allowlist.ts +273 -0
- package/src/view/appearance.ts +380 -0
- package/src/view/css.ts +172 -0
- package/src/view/frame.ts +1018 -0
- package/src/view/host.ts +527 -0
- package/src/view/index.ts +24 -0
- package/src/view/protocol.ts +412 -0
- package/src/view/reference.ts +30 -0
- package/src/view/resources.ts +265 -0
- package/src/view/sanitize.ts +266 -0
- package/src/zip/central.ts +85 -0
- package/src/zip/crc32.ts +30 -0
- package/src/zip/eocd.ts +97 -0
- package/src/zip/errors.ts +41 -0
- package/src/zip/index.ts +114 -0
- package/src/zip/inflate.ts +41 -0
- package/src/zip/source.ts +51 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BookFormat } from '../../core/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Plain-text format. The seam probe (PLAN M4-1): TXT synthesizes everything the
|
|
4
|
+
* `Book` model needs — id-addressed sections, a coarse TOC, minimal metadata —
|
|
5
|
+
* from a byte stream that has no container, no manifest and no markup, proving the
|
|
6
|
+
* decoder seam is not EPUB-shaped. Sections are emitted as XHTML (paragraphs and
|
|
7
|
+
* chapter headings) so the existing view renders them untouched; the format holds
|
|
8
|
+
* no `resolve` (plain text references nothing) and no resources.
|
|
9
|
+
*/
|
|
10
|
+
export declare const text: BookFormat;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/formats/text/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,UAAU,EAA8C,MAAM,qBAAqB,CAAC;AAIxG;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,EAAE,UAoClB,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/*! wolfy-reader v0.1.0 | @license MIT | (c) Vitaliy Tkachuk | github.com/vitaliy-tkachuk/wolfy-reader */
|
|
2
|
+
import { sectionLookup } from '../../core/lookup.js';
|
|
3
|
+
import { collapseWhitespace, escapeXmlText } from '../../core/text.js';
|
|
4
|
+
/**
|
|
5
|
+
* Plain-text format. The seam probe (PLAN M4-1): TXT synthesizes everything the
|
|
6
|
+
* `Book` model needs — id-addressed sections, a coarse TOC, minimal metadata —
|
|
7
|
+
* from a byte stream that has no container, no manifest and no markup, proving the
|
|
8
|
+
* decoder seam is not EPUB-shaped. Sections are emitted as XHTML (paragraphs and
|
|
9
|
+
* chapter headings) so the existing view renders them untouched; the format holds
|
|
10
|
+
* no `resolve` (plain text references nothing) and no resources.
|
|
11
|
+
*/
|
|
12
|
+
export const text = {
|
|
13
|
+
name: 'text',
|
|
14
|
+
async sniff(source) {
|
|
15
|
+
// A conservative last-resort claim: reject anything that is plainly another
|
|
16
|
+
// format (zip/EPUB, PDF, an XML/HTML document like FB2/XHTML) or binary
|
|
17
|
+
// (an unmarked NUL byte), and otherwise accept. Registered after richer
|
|
18
|
+
// formats, so this only sees bytes nothing else claimed.
|
|
19
|
+
const head = await source.read(0, Math.min(source.size, 512));
|
|
20
|
+
if (head.length === 0)
|
|
21
|
+
return false;
|
|
22
|
+
if (hasBom(head))
|
|
23
|
+
return true; // a Unicode BOM is a positive text signal
|
|
24
|
+
// Zip (PK\x03\x04) and PDF (%PDF) are not text.
|
|
25
|
+
if (head[0] === 0x50 && head[1] === 0x4b && head[2] === 0x03 && head[3] === 0x04)
|
|
26
|
+
return false;
|
|
27
|
+
if (head[0] === 0x25 && head[1] === 0x50 && head[2] === 0x44 && head[3] === 0x46)
|
|
28
|
+
return false;
|
|
29
|
+
// An XML/HTML document (FB2, XHTML) opens with '<' after optional whitespace.
|
|
30
|
+
const firstGlyph = head.find((b) => b !== 0x20 && b !== 0x09 && b !== 0x0a && b !== 0x0d && b !== 0xef && b !== 0xbb && b !== 0xbf);
|
|
31
|
+
if (firstGlyph === 0x3c)
|
|
32
|
+
return false;
|
|
33
|
+
// An unmarked NUL byte means binary (or UTF-16 without a BOM we do not guess).
|
|
34
|
+
if (head.includes(0x00))
|
|
35
|
+
return false;
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
async decode(source) {
|
|
39
|
+
const bytes = await source.read(0, source.size);
|
|
40
|
+
const raw = decodeText(bytes);
|
|
41
|
+
const normalized = raw.replace(/\r\n?/g, '\n');
|
|
42
|
+
const metadata = readGutenbergMetadata(normalized);
|
|
43
|
+
const built = buildSections(normalized);
|
|
44
|
+
const toc = buildToc(built);
|
|
45
|
+
const sections = built.map((s) => s.section);
|
|
46
|
+
return {
|
|
47
|
+
metadata,
|
|
48
|
+
toc,
|
|
49
|
+
sections,
|
|
50
|
+
section: sectionLookup(sections),
|
|
51
|
+
resources: new Map(),
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
// --- encoding ---------------------------------------------------------------
|
|
56
|
+
function hasBom(head) {
|
|
57
|
+
return ((head[0] === 0xef && head[1] === 0xbb && head[2] === 0xbf) || // UTF-8
|
|
58
|
+
(head[0] === 0xff && head[1] === 0xfe) || // UTF-16LE
|
|
59
|
+
(head[0] === 0xfe && head[1] === 0xff) // UTF-16BE
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decodes text bytes: a BOM picks the encoding outright; otherwise UTF-8 is tried
|
|
64
|
+
* strictly and windows-1252 is the legacy fallback (the codepage most non-UTF-8
|
|
65
|
+
* English/Western TXT actually uses). The BOM bytes are stripped with the decoder's
|
|
66
|
+
* default BOM handling for UTF-8/16.
|
|
67
|
+
*/
|
|
68
|
+
function decodeText(bytes) {
|
|
69
|
+
if (bytes[0] === 0xff && bytes[1] === 0xfe)
|
|
70
|
+
return new TextDecoder('utf-16le').decode(bytes);
|
|
71
|
+
if (bytes[0] === 0xfe && bytes[1] === 0xff)
|
|
72
|
+
return new TextDecoder('utf-16be').decode(bytes);
|
|
73
|
+
if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) {
|
|
74
|
+
return new TextDecoder('utf-8').decode(bytes.subarray(3));
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return new TextDecoder('windows-1252').decode(bytes);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const HEADING_KEYWORD = /^(chapter|book|part|canto|letter|volume|section|prologue|epilogue|introduction|preface|foreword|afterword)\b/i;
|
|
84
|
+
/**
|
|
85
|
+
* Coarse Gutenberg-style split: blocks are separated by blank lines; a short block
|
|
86
|
+
* that reads as a chapter heading (a keyword line like "CHAPTER I", or a short
|
|
87
|
+
* all-caps/titley line) starts a new section. When no heading is ever found the
|
|
88
|
+
* whole text becomes one synthetic section, so a headingless file still reads.
|
|
89
|
+
*/
|
|
90
|
+
function buildSections(normalized) {
|
|
91
|
+
const blocks = normalized
|
|
92
|
+
.split(/\n[ \t]*\n+/)
|
|
93
|
+
.map((b) => b.replace(/^\n+|\n+$/g, '').trim())
|
|
94
|
+
.filter((b) => b.length > 0);
|
|
95
|
+
const sections = [];
|
|
96
|
+
let heading;
|
|
97
|
+
let paragraphs = [];
|
|
98
|
+
let index = 0;
|
|
99
|
+
const flush = () => {
|
|
100
|
+
if (heading === undefined && paragraphs.length === 0)
|
|
101
|
+
return;
|
|
102
|
+
const id = `s${index}`;
|
|
103
|
+
index += 1;
|
|
104
|
+
const html = renderXhtml(heading, paragraphs);
|
|
105
|
+
const captured = heading;
|
|
106
|
+
sections.push({
|
|
107
|
+
section: {
|
|
108
|
+
id,
|
|
109
|
+
mediaType: 'application/xhtml+xml',
|
|
110
|
+
load: () => Promise.resolve(new TextEncoder().encode(html)),
|
|
111
|
+
},
|
|
112
|
+
...(captured === undefined ? {} : { heading: captured }),
|
|
113
|
+
});
|
|
114
|
+
heading = undefined;
|
|
115
|
+
paragraphs = [];
|
|
116
|
+
};
|
|
117
|
+
for (const block of blocks) {
|
|
118
|
+
if (isHeading(block)) {
|
|
119
|
+
flush();
|
|
120
|
+
heading = collapseWhitespace(block);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
paragraphs.push(block);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
flush();
|
|
127
|
+
if (sections.length === 0) {
|
|
128
|
+
// Empty or whitespace-only input still yields one (empty) readable section.
|
|
129
|
+
sections.push({
|
|
130
|
+
section: {
|
|
131
|
+
id: 's0',
|
|
132
|
+
mediaType: 'application/xhtml+xml',
|
|
133
|
+
load: () => Promise.resolve(new TextEncoder().encode(renderXhtml(undefined, []))),
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return sections;
|
|
138
|
+
}
|
|
139
|
+
function isHeading(block) {
|
|
140
|
+
if (block.includes('\n'))
|
|
141
|
+
return false; // a heading is a single short line
|
|
142
|
+
const line = block.trim();
|
|
143
|
+
if (line.length === 0 || line.length > 60)
|
|
144
|
+
return false;
|
|
145
|
+
if (HEADING_KEYWORD.test(line))
|
|
146
|
+
return true;
|
|
147
|
+
// A short line in all caps (letters present, no lowercase) reads as a heading.
|
|
148
|
+
return /[A-Z]/.test(line) && !/[a-z]/.test(line) && line.length <= 48;
|
|
149
|
+
}
|
|
150
|
+
function buildToc(sections) {
|
|
151
|
+
const toc = [];
|
|
152
|
+
for (const s of sections) {
|
|
153
|
+
if (s.heading === undefined)
|
|
154
|
+
continue;
|
|
155
|
+
toc.push({ label: s.heading, sectionId: s.section.id, children: [] });
|
|
156
|
+
}
|
|
157
|
+
return toc;
|
|
158
|
+
}
|
|
159
|
+
// --- metadata ---------------------------------------------------------------
|
|
160
|
+
/**
|
|
161
|
+
* Best-effort metadata from Project Gutenberg's plain-text header conventions:
|
|
162
|
+
* either the "Title: X / Author: Y" block or the "The Project Gutenberg eBook of
|
|
163
|
+
* TITLE, by AUTHOR" line. Anything not found is omitted, never set to undefined.
|
|
164
|
+
*/
|
|
165
|
+
function readGutenbergMetadata(normalized) {
|
|
166
|
+
const head = normalized.slice(0, 4000);
|
|
167
|
+
let title;
|
|
168
|
+
let author;
|
|
169
|
+
const titleField = head.match(/^Title:\s*(.+)$/im);
|
|
170
|
+
if (titleField?.[1] !== undefined)
|
|
171
|
+
title = collapseWhitespace(titleField[1]);
|
|
172
|
+
const authorField = head.match(/^Author:\s*(.+)$/im);
|
|
173
|
+
if (authorField?.[1] !== undefined)
|
|
174
|
+
author = collapseWhitespace(authorField[1]);
|
|
175
|
+
if (title === undefined) {
|
|
176
|
+
const banner = head.match(/Project Gutenberg eBook of\s+(.+?)(?:,\s*by\s+(.+?))?[\r\n]/i);
|
|
177
|
+
if (banner?.[1] !== undefined)
|
|
178
|
+
title = collapseWhitespace(banner[1]);
|
|
179
|
+
if (author === undefined && banner?.[2] !== undefined)
|
|
180
|
+
author = collapseWhitespace(banner[2]);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
...(title === undefined ? {} : { title }),
|
|
184
|
+
...(author === undefined ? {} : { author }),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// --- rendering --------------------------------------------------------------
|
|
188
|
+
function renderXhtml(heading, paragraphs) {
|
|
189
|
+
const body = [];
|
|
190
|
+
if (heading !== undefined)
|
|
191
|
+
body.push(`<h2>${escapeXmlText(heading)}</h2>`);
|
|
192
|
+
for (const p of paragraphs) {
|
|
193
|
+
// A block's internal newlines are soft line breaks within one paragraph.
|
|
194
|
+
body.push(`<p>${escapeXmlText(collapseParagraph(p))}</p>`);
|
|
195
|
+
}
|
|
196
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<html xmlns="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"/></head><body>${body.join('')}</body></html>`;
|
|
197
|
+
}
|
|
198
|
+
function collapseParagraph(s) {
|
|
199
|
+
return s.replace(/\s*\n\s*/g, ' ').replace(/[ \t]+/g, ' ').trim();
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/formats/text/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface XmlElement {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly localName: string;
|
|
4
|
+
readonly attributes: ReadonlyMap<string, string>;
|
|
5
|
+
readonly children: readonly XmlElement[];
|
|
6
|
+
/** Child elements and text chunks in document order. */
|
|
7
|
+
readonly content: readonly (XmlElement | string)[];
|
|
8
|
+
/** Concatenated direct text content, entity-decoded, CDATA included. */
|
|
9
|
+
readonly text: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function decodeXml(bytes: Uint8Array): string;
|
|
12
|
+
export declare function localNameOf(name: string): string;
|
|
13
|
+
/** Attribute by exact name first, then by local name ignoring any prefix. */
|
|
14
|
+
export declare function attribute(element: XmlElement, name: string): string | undefined;
|
|
15
|
+
export declare function childrenNamed(element: XmlElement, localName: string): readonly XmlElement[];
|
|
16
|
+
export declare function firstChildNamed(element: XmlElement, localName: string): XmlElement | undefined;
|
|
17
|
+
/** All text within the element in document order, entity-decoded. */
|
|
18
|
+
export declare function deepText(element: XmlElement): string;
|
|
19
|
+
export declare function descendantsNamed(element: XmlElement, localName: string): readonly XmlElement[];
|
|
20
|
+
export interface ParseXmlOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Recover from light well-formedness slips instead of throwing: a valueless
|
|
23
|
+
* (HTML-boolean-style) attribute becomes an empty-string attribute, an unquoted
|
|
24
|
+
* attribute value reads to the next whitespace or tag end, a close tag that
|
|
25
|
+
* mismatches the open stack closes the nearest matching ancestor (or is ignored
|
|
26
|
+
* when nothing matches), and elements left open at end of input are auto-closed.
|
|
27
|
+
* Strict is the default; tolerance is opt-in per caller so strict guarantees
|
|
28
|
+
* (EPUB's container/OPF/nav parsing) are unchanged.
|
|
29
|
+
*/
|
|
30
|
+
readonly tolerant?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function parseXml(input: string, options?: ParseXmlOptions): XmlElement;
|
|
33
|
+
//# sourceMappingURL=xml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../src/formats/xml.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC;IACnD,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAWD,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAmBnD;AAaD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO/E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAE3F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE9F;AAED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAMpD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAU9F;AAID,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,UAAU,CAkL7E"}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
export function decodeXml(bytes) {
|
|
2
|
+
if (bytes.length >= 2) {
|
|
3
|
+
if (bytes[0] === 0xff && bytes[1] === 0xfe)
|
|
4
|
+
return new TextDecoder('utf-16le').decode(bytes);
|
|
5
|
+
if (bytes[0] === 0xfe && bytes[1] === 0xff)
|
|
6
|
+
return new TextDecoder('utf-16be').decode(bytes);
|
|
7
|
+
}
|
|
8
|
+
// A BOM decides outright; otherwise honor the XML declaration's encoding label
|
|
9
|
+
// for non-Unicode codepages — real FB2 is frequently windows-1251, and assuming
|
|
10
|
+
// UTF-8 would mojibake every Cyrillic character. The label is read from the
|
|
11
|
+
// prolog as Latin-1 (one byte → one char) so it is legible before the true
|
|
12
|
+
// encoding is known. An unknown label falls back to UTF-8.
|
|
13
|
+
const label = encodingFromProlog(bytes);
|
|
14
|
+
if (label !== undefined && !/^utf-?8$/i.test(label) && !/^utf-?16/i.test(label)) {
|
|
15
|
+
try {
|
|
16
|
+
return new TextDecoder(label).decode(bytes);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Unsupported label — fall through to UTF-8.
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return new TextDecoder().decode(bytes);
|
|
23
|
+
}
|
|
24
|
+
function encodingFromProlog(bytes) {
|
|
25
|
+
const head = bytes.subarray(0, Math.min(bytes.length, 200));
|
|
26
|
+
let prolog = '';
|
|
27
|
+
for (let i = 0; i < head.length; i += 1)
|
|
28
|
+
prolog += String.fromCharCode(head[i]);
|
|
29
|
+
if (!prolog.startsWith('<?xml'))
|
|
30
|
+
return undefined;
|
|
31
|
+
const end = prolog.indexOf('?>');
|
|
32
|
+
if (end === -1)
|
|
33
|
+
return undefined;
|
|
34
|
+
const match = prolog.slice(0, end).match(/encoding\s*=\s*["']([^"']+)["']/i);
|
|
35
|
+
return match?.[1];
|
|
36
|
+
}
|
|
37
|
+
export function localNameOf(name) {
|
|
38
|
+
const colon = name.indexOf(':');
|
|
39
|
+
return colon === -1 ? name : name.slice(colon + 1);
|
|
40
|
+
}
|
|
41
|
+
/** Attribute by exact name first, then by local name ignoring any prefix. */
|
|
42
|
+
export function attribute(element, name) {
|
|
43
|
+
const exact = element.attributes.get(name);
|
|
44
|
+
if (exact !== undefined)
|
|
45
|
+
return exact;
|
|
46
|
+
for (const [key, value] of element.attributes) {
|
|
47
|
+
if (localNameOf(key) === name)
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
export function childrenNamed(element, localName) {
|
|
53
|
+
return element.children.filter((child) => child.localName === localName);
|
|
54
|
+
}
|
|
55
|
+
export function firstChildNamed(element, localName) {
|
|
56
|
+
return element.children.find((child) => child.localName === localName);
|
|
57
|
+
}
|
|
58
|
+
/** All text within the element in document order, entity-decoded. */
|
|
59
|
+
export function deepText(element) {
|
|
60
|
+
let out = '';
|
|
61
|
+
for (const node of element.content) {
|
|
62
|
+
out += typeof node === 'string' ? node : deepText(node);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
export function descendantsNamed(element, localName) {
|
|
67
|
+
const found = [];
|
|
68
|
+
const walk = (parent) => {
|
|
69
|
+
for (const child of parent.children) {
|
|
70
|
+
if (child.localName === localName)
|
|
71
|
+
found.push(child);
|
|
72
|
+
walk(child);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walk(element);
|
|
76
|
+
return found;
|
|
77
|
+
}
|
|
78
|
+
const NAME_END = new Set([' ', '\t', '\n', '\r', '>', '/', '=']);
|
|
79
|
+
export function parseXml(input, options) {
|
|
80
|
+
const tolerant = options?.tolerant === true;
|
|
81
|
+
let pos = input.charCodeAt(0) === 0xfeff ? 1 : 0;
|
|
82
|
+
let root;
|
|
83
|
+
const stack = [];
|
|
84
|
+
const fail = (message) => {
|
|
85
|
+
throw new Error(`malformed XML at offset ${pos}: ${message}`);
|
|
86
|
+
};
|
|
87
|
+
const skipWhitespace = () => {
|
|
88
|
+
while (pos < input.length && isWhitespace(input[pos]))
|
|
89
|
+
pos++;
|
|
90
|
+
};
|
|
91
|
+
const readName = () => {
|
|
92
|
+
const start = pos;
|
|
93
|
+
while (pos < input.length && !NAME_END.has(input[pos]))
|
|
94
|
+
pos++;
|
|
95
|
+
if (pos === start)
|
|
96
|
+
fail('expected a name');
|
|
97
|
+
return input.slice(start, pos);
|
|
98
|
+
};
|
|
99
|
+
const skipPast = (terminator, what) => {
|
|
100
|
+
const end = input.indexOf(terminator, pos);
|
|
101
|
+
if (end === -1)
|
|
102
|
+
fail(`unterminated ${what}`);
|
|
103
|
+
pos = end + terminator.length;
|
|
104
|
+
};
|
|
105
|
+
const skipMarkupDeclaration = () => {
|
|
106
|
+
let depth = 0;
|
|
107
|
+
for (; pos < input.length; pos++) {
|
|
108
|
+
const ch = input[pos];
|
|
109
|
+
if (ch === '[')
|
|
110
|
+
depth++;
|
|
111
|
+
else if (ch === ']')
|
|
112
|
+
depth--;
|
|
113
|
+
else if (ch === '>' && depth <= 0) {
|
|
114
|
+
pos++;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
fail('unterminated markup declaration');
|
|
119
|
+
};
|
|
120
|
+
const readAttributes = (element) => {
|
|
121
|
+
for (;;) {
|
|
122
|
+
skipWhitespace();
|
|
123
|
+
if (pos >= input.length) {
|
|
124
|
+
if (!tolerant)
|
|
125
|
+
fail(`unterminated <${element.name}> tag`);
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
if (input[pos] === '>') {
|
|
129
|
+
pos++;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (input[pos] === '/') {
|
|
133
|
+
pos++;
|
|
134
|
+
if (input[pos] !== '>') {
|
|
135
|
+
if (!tolerant)
|
|
136
|
+
fail(`expected "/>" in <${element.name}>`);
|
|
137
|
+
continue; // stray slash inside the tag — drop it
|
|
138
|
+
}
|
|
139
|
+
pos++;
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
const name = readName();
|
|
143
|
+
skipWhitespace();
|
|
144
|
+
if (input[pos] !== '=') {
|
|
145
|
+
if (!tolerant)
|
|
146
|
+
fail(`attribute ${name} has no value`);
|
|
147
|
+
// Valueless (HTML-boolean-style) attribute — keep it as an empty string.
|
|
148
|
+
element.attributes.set(name, '');
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
pos++;
|
|
152
|
+
skipWhitespace();
|
|
153
|
+
const quote = input[pos];
|
|
154
|
+
if (quote !== '"' && quote !== "'") {
|
|
155
|
+
if (!tolerant)
|
|
156
|
+
fail(`attribute ${name} value is not quoted`);
|
|
157
|
+
// Unquoted value — read to the next whitespace or tag end.
|
|
158
|
+
const start = pos;
|
|
159
|
+
while (pos < input.length && !isWhitespace(input[pos]) && input[pos] !== '>')
|
|
160
|
+
pos++;
|
|
161
|
+
let raw = input.slice(start, pos);
|
|
162
|
+
if (raw.endsWith('/') && input[pos] === '>') {
|
|
163
|
+
raw = raw.slice(0, -1);
|
|
164
|
+
pos -= 1; // leave "/>" for the self-closing check
|
|
165
|
+
}
|
|
166
|
+
element.attributes.set(name, decodeEntities(raw));
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
pos++;
|
|
170
|
+
const end = input.indexOf(quote, pos);
|
|
171
|
+
if (end === -1) {
|
|
172
|
+
if (!tolerant)
|
|
173
|
+
fail(`unterminated value for attribute ${name}`);
|
|
174
|
+
// Unterminated quote — take what is there up to the tag end.
|
|
175
|
+
const gt = input.indexOf('>', pos);
|
|
176
|
+
const stop = gt === -1 ? input.length : gt;
|
|
177
|
+
element.attributes.set(name, decodeEntities(input.slice(pos, stop)));
|
|
178
|
+
pos = stop;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
element.attributes.set(name, decodeEntities(input.slice(pos, end)));
|
|
182
|
+
pos = end + 1;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
while (pos < input.length) {
|
|
186
|
+
const lt = input.indexOf('<', pos);
|
|
187
|
+
if (lt === -1)
|
|
188
|
+
break;
|
|
189
|
+
if (lt > pos) {
|
|
190
|
+
const parent = stack[stack.length - 1];
|
|
191
|
+
if (parent !== undefined)
|
|
192
|
+
appendText(parent, decodeEntities(input.slice(pos, lt)));
|
|
193
|
+
}
|
|
194
|
+
pos = lt;
|
|
195
|
+
if (input.startsWith('<?', pos)) {
|
|
196
|
+
pos += 2;
|
|
197
|
+
skipPast('?>', 'processing instruction');
|
|
198
|
+
}
|
|
199
|
+
else if (input.startsWith('<!--', pos)) {
|
|
200
|
+
pos += 4;
|
|
201
|
+
skipPast('-->', 'comment');
|
|
202
|
+
}
|
|
203
|
+
else if (input.startsWith('<![CDATA[', pos)) {
|
|
204
|
+
pos += 9;
|
|
205
|
+
const end = input.indexOf(']]>', pos);
|
|
206
|
+
if (end === -1)
|
|
207
|
+
fail('unterminated CDATA section');
|
|
208
|
+
const parent = stack[stack.length - 1];
|
|
209
|
+
if (parent !== undefined)
|
|
210
|
+
appendText(parent, input.slice(pos, end));
|
|
211
|
+
pos = end + 3;
|
|
212
|
+
}
|
|
213
|
+
else if (input.startsWith('<!', pos)) {
|
|
214
|
+
pos += 2;
|
|
215
|
+
skipMarkupDeclaration();
|
|
216
|
+
}
|
|
217
|
+
else if (input.startsWith('</', pos)) {
|
|
218
|
+
pos += 2;
|
|
219
|
+
const name = readName();
|
|
220
|
+
skipWhitespace();
|
|
221
|
+
if (input[pos] !== '>') {
|
|
222
|
+
if (!tolerant)
|
|
223
|
+
fail(`unterminated </${name}>`);
|
|
224
|
+
const gt = input.indexOf('>', pos);
|
|
225
|
+
pos = gt === -1 ? input.length : gt + 1;
|
|
226
|
+
}
|
|
227
|
+
else
|
|
228
|
+
pos++;
|
|
229
|
+
const open = stack.pop();
|
|
230
|
+
if (open === undefined) {
|
|
231
|
+
// Tolerant: a stray close with nothing open is ignored.
|
|
232
|
+
if (!tolerant)
|
|
233
|
+
fail(`</${name}> has no matching open tag`);
|
|
234
|
+
}
|
|
235
|
+
else if (open.name !== name) {
|
|
236
|
+
if (!tolerant)
|
|
237
|
+
fail(`</${name}> closes <${open.name}>`);
|
|
238
|
+
if (stack.some((el) => el.name === name)) {
|
|
239
|
+
// Close the nearest matching ancestor, auto-closing what it skipped
|
|
240
|
+
// (children were attached at open time, so popping loses nothing).
|
|
241
|
+
while (stack.length > 0 && stack[stack.length - 1].name !== name)
|
|
242
|
+
stack.pop();
|
|
243
|
+
stack.pop();
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// No matching open tag anywhere above — ignore the stray close.
|
|
247
|
+
stack.push(open);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
pos++;
|
|
253
|
+
const name = readName();
|
|
254
|
+
const element = {
|
|
255
|
+
name,
|
|
256
|
+
localName: localNameOf(name),
|
|
257
|
+
attributes: new Map(),
|
|
258
|
+
children: [],
|
|
259
|
+
content: [],
|
|
260
|
+
text: '',
|
|
261
|
+
};
|
|
262
|
+
const selfClosing = readAttributes(element);
|
|
263
|
+
const parent = stack[stack.length - 1];
|
|
264
|
+
if (parent !== undefined) {
|
|
265
|
+
parent.children.push(element);
|
|
266
|
+
parent.content.push(element);
|
|
267
|
+
}
|
|
268
|
+
else if (root === undefined)
|
|
269
|
+
root = element;
|
|
270
|
+
else if (!tolerant)
|
|
271
|
+
fail(`second root element <${name}>`);
|
|
272
|
+
// Tolerant: trailing junk after the root parses but is discarded.
|
|
273
|
+
if (!selfClosing)
|
|
274
|
+
stack.push(element);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const open = stack[stack.length - 1];
|
|
278
|
+
// Tolerant: elements left open at end of input are auto-closed.
|
|
279
|
+
if (open !== undefined && !tolerant)
|
|
280
|
+
fail(`unclosed element <${open.name}>`);
|
|
281
|
+
if (root === undefined)
|
|
282
|
+
fail('no root element');
|
|
283
|
+
return root;
|
|
284
|
+
}
|
|
285
|
+
function appendText(parent, text) {
|
|
286
|
+
parent.text += text;
|
|
287
|
+
const last = parent.content[parent.content.length - 1];
|
|
288
|
+
if (typeof last === 'string')
|
|
289
|
+
parent.content[parent.content.length - 1] = last + text;
|
|
290
|
+
else
|
|
291
|
+
parent.content.push(text);
|
|
292
|
+
}
|
|
293
|
+
function isWhitespace(ch) {
|
|
294
|
+
return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r';
|
|
295
|
+
}
|
|
296
|
+
// nbsp is the one HTML entity that shows up in real nav-document labels.
|
|
297
|
+
const NAMED_ENTITIES = {
|
|
298
|
+
amp: '&',
|
|
299
|
+
lt: '<',
|
|
300
|
+
gt: '>',
|
|
301
|
+
quot: '"',
|
|
302
|
+
apos: "'",
|
|
303
|
+
nbsp: ' ',
|
|
304
|
+
};
|
|
305
|
+
function decodeEntities(text) {
|
|
306
|
+
if (!text.includes('&'))
|
|
307
|
+
return text;
|
|
308
|
+
return text.replace(/&(#x[0-9a-fA-F]+|#[0-9]+|[a-zA-Z][a-zA-Z0-9]*);/g, (match, body) => {
|
|
309
|
+
if (body.startsWith('#')) {
|
|
310
|
+
const code = body[1] === 'x' ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10);
|
|
311
|
+
try {
|
|
312
|
+
return String.fromCodePoint(code);
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return match;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return NAMED_ENTITIES[body] ?? match;
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=xml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.js","sourceRoot":"","sources":["../../src/formats/xml.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package root: the browser-facing reader facade plus the headless core it
|
|
3
|
+
* operates on.
|
|
4
|
+
*
|
|
5
|
+
* import { open, render } from 'wolfy-reader';
|
|
6
|
+
* import { epub } from 'wolfy-reader/epub';
|
|
7
|
+
*
|
|
8
|
+
* Core travels with the facade because `render` takes a `Book` and `open` is the
|
|
9
|
+
* only public way to make one — splitting them would make the common case a
|
|
10
|
+
* three-import dance, and the facade's own surface already names `Position`,
|
|
11
|
+
* `TocItem` and `SentenceRange` in its signatures.
|
|
12
|
+
*
|
|
13
|
+
* Both re-exports resolve to the same emitted modules as `wolfy-reader/core`, so
|
|
14
|
+
* there is one `open`, one `Position` model and one set of error constructors
|
|
15
|
+
* however a consumer reaches them — `instanceof BookError` holds across entries.
|
|
16
|
+
*
|
|
17
|
+
* Headless consumers should import `wolfy-reader/core` instead. This root reaches
|
|
18
|
+
* `src/layout` and `src/view`; it is import-safe under Node today and the pack
|
|
19
|
+
* fidelity check keeps it that way, but only `/core` carries the guarantee.
|
|
20
|
+
*
|
|
21
|
+
* Format decoders are deliberately absent: each is its own subpath because their
|
|
22
|
+
* closures differ by an order of magnitude — only `epub` pulls the ZIP reader —
|
|
23
|
+
* and `open(input, { formats })` takes an explicit list by design.
|
|
24
|
+
*/
|
|
25
|
+
export * from './core/index.ts';
|
|
26
|
+
export * from './reader/index.ts';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
|