@storyteller-platform/epub 0.8.2 → 1.0.1

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.
@@ -8,6 +8,25 @@
8
8
  * reads only
9
9
  */
10
10
  export type EpubStorageKind = "tmp-dir" | "in-memory" | (string & {});
11
+ export type ArchiveSource = string | Uint8Array | Blob;
12
+ /**
13
+ * A file in an opened zip archive. Directory entries are left out.
14
+ */
15
+ export interface ZipEntry {
16
+ readonly filename: string;
17
+ readonly compressedSize: number;
18
+ readonly uncompressedSize: number;
19
+ /** rejects when the data doesn't match the CRC32 or size in the central directory */
20
+ read(): Promise<Uint8Array>;
21
+ }
22
+ /**
23
+ * An opened zip archive. The `#zip` import picks the reader:
24
+ * yauzl-promise in Node, zip.js everywhere else.
25
+ */
26
+ export interface ZipArchive {
27
+ readonly entries: readonly ZipEntry[];
28
+ close(): Promise<void>;
29
+ }
11
30
  export interface EpubStorageCapabilities {
12
31
  /** when false, the Epub class refuses every mutation method at runtime */
13
32
  readonly writable: boolean;
@@ -63,7 +82,7 @@ export interface EpubStorageAdapterClass<Opts extends object = object> {
63
82
  * Open an archive from a path or buffer.
64
83
  * Will throw if the archive is not a valid EPUB 3
65
84
  */
66
- init(source: string | Uint8Array, opts?: Opts): Promise<EpubStorageAdapter>;
85
+ init(source: ArchiveSource, opts?: Opts): Promise<EpubStorageAdapter>;
67
86
  /**
68
87
  * Initialize an empty extract root for {@link Epub.create}.
69
88
  * Only necessary for adapters that can write
@@ -1,4 +1,4 @@
1
- import type { EpubStorageAdapter } from "./interface.ts";
1
+ import type { ArchiveSource, EpubStorageAdapter } from "./interface.ts";
2
2
  export interface MemoryAdapterOptions {
3
3
  /**
4
4
  * per-entry decompressed buffer cache
@@ -23,7 +23,7 @@ export declare class MemoryAdapter implements EpubStorageAdapter {
23
23
  static readonly capabilities: {
24
24
  readonly writable: false;
25
25
  };
26
- static init(source: string | Uint8Array, opts?: MemoryAdapterOptions): Promise<MemoryAdapter>;
26
+ static init(source: ArchiveSource, opts?: MemoryAdapterOptions): Promise<MemoryAdapter>;
27
27
  private constructor();
28
28
  read(entry: string): Promise<Uint8Array>;
29
29
  read(entry: string, encoding: "utf-8"): Promise<string>;
@@ -1,4 +1,5 @@
1
- import { openZip } from "../zip.js";
1
+ import { openZip } from "#zip";
2
+ const utf8 = new TextDecoder("utf-8", { ignoreBOM: true });
2
3
  /**
3
4
  * Loads an EPUB archive into memory and serves all I/O off the in-memory zip handle.
4
5
  *
@@ -15,20 +16,11 @@ export class MemoryAdapter {
15
16
  const { cache = true, signal } = opts;
16
17
  signal?.throwIfAborted();
17
18
  const zip = await openZip(source);
18
- const entries = new Map();
19
- try {
20
- for await (const entry of zip) {
21
- signal?.throwIfAborted();
22
- if (entry.filename.endsWith("/"))
23
- continue;
24
- entries.set(entry.filename, entry);
25
- }
26
- }
27
- catch (error) {
19
+ if (signal?.aborted) {
28
20
  await zip.close();
29
- throw error;
21
+ signal.throwIfAborted();
30
22
  }
31
- return new MemoryAdapter(zip, entries, cache ? new Map() : null);
23
+ return new MemoryAdapter(zip, new Map(zip.entries.map((entry) => [entry.filename, entry])), cache ? new Map() : null);
32
24
  }
33
25
  constructor(zip, entries, cache) {
34
26
  this.zip = zip;
@@ -36,24 +28,18 @@ export class MemoryAdapter {
36
28
  this.cache = cache;
37
29
  }
38
30
  async read(entry, encoding) {
39
- const cached = this.cache?.get(entry);
40
- if (cached) {
41
- return encoding ? cached.toString(encoding) : new Uint8Array(cached);
42
- }
43
- const zipEntry = this.entries.get(entry);
44
- if (!zipEntry) {
45
- const err = new Error(`ENOENT: zip entry not found in EPUB archive: ${entry}`);
46
- err.code = "ENOENT";
47
- throw err;
48
- }
49
- const stream = await zipEntry.openReadStream();
50
- const chunks = [];
51
- for await (const chunk of stream) {
52
- chunks.push(chunk);
31
+ let data = this.cache?.get(entry);
32
+ if (!data) {
33
+ const zipEntry = this.entries.get(entry);
34
+ if (!zipEntry) {
35
+ const err = new Error(`ENOENT: zip entry not found in EPUB archive: ${entry}`);
36
+ err.code = "ENOENT";
37
+ throw err;
38
+ }
39
+ data = await zipEntry.read();
40
+ this.cache?.set(entry, data);
53
41
  }
54
- const buf = Buffer.concat(chunks);
55
- this.cache?.set(entry, buf);
56
- return encoding ? buf.toString(encoding) : new Uint8Array(buf);
42
+ return encoding ? utf8.decode(data) : new Uint8Array(data);
57
43
  }
58
44
  // eslint-disable-next-line @typescript-eslint/require-await
59
45
  async exists(entry) {
@@ -0,0 +1,11 @@
1
+ import type { EpubStorageAdapter } from "./interface.ts";
2
+ declare function unavailable(): Promise<EpubStorageAdapter>;
3
+ export declare const TmpFsAdapter: {
4
+ readonly kind: "extracted-dir";
5
+ readonly capabilities: {
6
+ readonly writable: true;
7
+ };
8
+ readonly init: typeof unavailable;
9
+ readonly initEmpty: typeof unavailable;
10
+ };
11
+ export {};
@@ -0,0 +1,9 @@
1
+ function unavailable() {
2
+ return Promise.reject(new Error("TmpFsAdapter extracts EPUBs to a temp directory and only works in Node.js. Use Epub.using(MemoryAdapter) instead."));
3
+ }
4
+ export const TmpFsAdapter = {
5
+ kind: "extracted-dir",
6
+ capabilities: { writable: true },
7
+ init: unavailable,
8
+ initEmpty: unavailable,
9
+ };
@@ -1,4 +1,4 @@
1
- import type { EpubListEntry, EpubStorageAdapter } from "./interface.ts";
1
+ import type { ArchiveSource, EpubListEntry, EpubStorageAdapter } from "./interface.ts";
2
2
  /**
3
3
  * Extracts an EPUB archive to a temp directory and serves all I/O off
4
4
  * the real filesystem.
@@ -10,7 +10,7 @@ export declare class TmpFsAdapter implements EpubStorageAdapter {
10
10
  static readonly capabilities: {
11
11
  readonly writable: true;
12
12
  };
13
- static init(source: string | Uint8Array): Promise<TmpFsAdapter>;
13
+ static init(source: ArchiveSource): Promise<TmpFsAdapter>;
14
14
  static initEmpty(): Promise<TmpFsAdapter>;
15
15
  private constructor();
16
16
  private diskPath;
@@ -58,7 +58,7 @@ import { ZipFile } from "yazl";
58
58
  import { scratchPath } from "@storyteller-platform/fs";
59
59
  import { MediaType } from "@storyteller-platform/media-types";
60
60
  import { dirname, join, sep } from "@storyteller-platform/path";
61
- import { openZip } from "../zip.js";
61
+ import { openZip } from "../zip.node.js";
62
62
  const PRECOMPRESSED_KINDS = new Set([
63
63
  "audio",
64
64
  "image",
@@ -90,44 +90,31 @@ export class TmpFsAdapter {
90
90
  static kind = "extracted-dir";
91
91
  static capabilities = { writable: true };
92
92
  static async init(source) {
93
- const rootPath = mintRootPath();
93
+ const env_1 = { stack: [], error: void 0, hasError: false };
94
94
  try {
95
- const env_1 = { stack: [], error: void 0, hasError: false };
96
- try {
97
- const zipfile = await openZip(source);
98
- const stack = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
99
- stack.defer(async () => {
100
- await zipfile.close();
101
- });
102
- for await (const entry of zipfile) {
103
- if (entry.filename.endsWith("/")) {
104
- // directory entries are skipped; parent dirs are created implicitly
105
- continue;
106
- }
107
- if (!isStorableEntryName(entry.filename))
108
- continue;
109
- const writePath = join(rootPath, ...entry.filename.split("/"));
110
- const readStream = await entry.openReadStream();
111
- await mkdir(dirname(writePath), { recursive: true });
112
- const writeStream = createWriteStream(writePath);
113
- await pipeline(readStream, writeStream);
114
- }
115
- }
116
- catch (e_1) {
117
- env_1.error = e_1;
118
- env_1.hasError = true;
119
- }
120
- finally {
121
- const result_1 = __disposeResources(env_1);
122
- if (result_1)
123
- await result_1;
95
+ const cleanup = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
96
+ const rootPath = mintRootPath();
97
+ cleanup.defer(() => rm(rootPath, { force: true, recursive: true }));
98
+ const zip = __addDisposableResource(env_1, await openZip(source), true);
99
+ for (const entry of zip.entries) {
100
+ if (!isStorableEntryName(entry.filename))
101
+ continue;
102
+ const writePath = join(rootPath, ...entry.filename.split("/"));
103
+ await mkdir(dirname(writePath), { recursive: true });
104
+ await pipeline(await entry.openReadStream(), createWriteStream(writePath));
124
105
  }
106
+ cleanup.move();
107
+ return new TmpFsAdapter(rootPath);
125
108
  }
126
- catch (error) {
127
- rmSync(rootPath, { force: true, recursive: true });
128
- throw error;
109
+ catch (e_1) {
110
+ env_1.error = e_1;
111
+ env_1.hasError = true;
112
+ }
113
+ finally {
114
+ const result_1 = __disposeResources(env_1);
115
+ if (result_1)
116
+ await result_1;
129
117
  }
130
- return new TmpFsAdapter(rootPath);
131
118
  }
132
119
  static async initEmpty() {
133
120
  const rootPath = mintRootPath();
@@ -0,0 +1,2 @@
1
+ export declare function openFile(path: string): Promise<Blob>;
2
+ export declare function copyFile(from: string, to: string): Promise<void>;
@@ -0,0 +1,7 @@
1
+ const PATHS_NEED_NODE = "File paths only work in Node.js. Pass the EPUB as a Blob, File or Uint8Array instead.";
2
+ export function openFile(path) {
3
+ return Promise.reject(new Error(`Cannot open "${path}". ${PATHS_NEED_NODE}`));
4
+ }
5
+ export function copyFile(from, to) {
6
+ return Promise.reject(new Error(`Cannot copy "${from}" to "${to}". ${PATHS_NEED_NODE}`));
7
+ }
@@ -0,0 +1,2 @@
1
+ export declare function openFile(path: string): Promise<Blob>;
2
+ export declare function copyFile(from: string, to: string): Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { openAsBlob } from "node:fs";
2
+ import { cp, mkdir } from "node:fs/promises";
3
+ import { dirname } from "@storyteller-platform/path";
4
+ export async function openFile(path) {
5
+ return await openAsBlob(path);
6
+ }
7
+ export async function copyFile(from, to) {
8
+ await mkdir(dirname(to), { recursive: true });
9
+ await cp(from, to, { force: true });
10
+ }
package/dist/index.d.ts CHANGED
@@ -1,38 +1,29 @@
1
- import { XMLParser } from "fast-xml-parser";
2
- import type { AdapterOptions, EpubStorageAdapter, EpubStorageAdapterClass, EpubStorageKind } from "./adapters/interface.ts";
3
- import * as Upgrade from "./upgrade.ts";
4
- export type { EpubStorageKind } from "./adapters/interface.ts";
5
- export { type AdapterOptions, type EpubListEntry, type EpubStorageAdapter, type EpubStorageAdapterClass, type EpubStorageCapabilities, } from "./adapters/interface.ts";
1
+ /** @jsxImportSource @storyteller-platform/epub */
2
+ import type { Document, Element, Node } from "@xmldom/xmldom";
3
+ import type { AdapterOptions, ArchiveSource, EpubStorageAdapter, EpubStorageAdapterClass, EpubStorageKind } from "./adapters/interface.ts";
4
+ import * as Upgrade from "./upgrade.tsx";
5
+ export { TmpFsAdapter } from "#tmpfs";
6
+ export type { AdapterOptions, ArchiveSource, EpubListEntry, EpubStorageAdapter, EpubStorageAdapterClass, EpubStorageCapabilities, EpubStorageKind, } from "./adapters/interface.ts";
6
7
  export { MemoryAdapter, type MemoryAdapterOptions } from "./adapters/memory.ts";
7
- export { TmpFsAdapter } from "./adapters/tmpfs.ts";
8
+ /**
9
+ * The XML surface. Publication-level operations live on {@link Epub}; for
10
+ * building and inspecting XML trees directly, use these.
11
+ *
12
+ * The DOM node types are re-exported so that callers do not need to depend on
13
+ * `@xmldom/xmldom` themselves.
14
+ */
15
+ export { addLinkToXhtmlHead, adoptNamespaces, createDocument, createDocumentType, declareDefaultNamespace, findXmlChildByName, findXmlChildByNameNS, findXmlDescendantByName, findXmlDescendantByNameNS, getXhtmlBody, insert, isCdata, isComment, isElement, isText, NS, parse, replace, serialize, text, x, XMLSerializer, } from "./xml.ts";
16
+ export type { XmlDiagnostic } from "./xml.ts";
17
+ export type { Attr, Document, DocumentType, Element, Node, Text, } from "@xmldom/xmldom";
8
18
  declare global {
9
19
  namespace Intl {
10
20
  interface Locale {
11
- textInfo: {
21
+ textInfo?: {
12
22
  direction: "rtl" | "ltr";
13
23
  };
14
24
  }
15
25
  }
16
26
  }
17
- type Letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
18
- type QuestionMark = "?";
19
- /** A valid name for an XML element (must start with a letter) */
20
- export type ElementName = `${Letter | Uppercase<Letter> | QuestionMark}${string}`;
21
- type PropertyPrefix = "@_";
22
- /** An XML element */
23
- export type XmlElement<Name extends ElementName = ElementName> = {
24
- ":@"?: Record<`${PropertyPrefix}${string}`, string>;
25
- } & {
26
- [key in Name]: ParsedXml;
27
- };
28
- /** A text node in an XML document */
29
- export type XmlTextNode = {
30
- "#text": string;
31
- };
32
- /** A valid XML node. May be either an element or a text node. */
33
- export type XmlNode = XmlElement | XmlTextNode;
34
- /** An XML structure */
35
- export type ParsedXml = Array<XmlNode>;
36
27
  export type ManifestItem = {
37
28
  id: string;
38
29
  href: string;
@@ -44,7 +35,7 @@ export type ManifestItem = {
44
35
  };
45
36
  export type MetadataEntry = {
46
37
  id?: string | undefined;
47
- type: ElementName;
38
+ type: string;
48
39
  properties: Record<string, string>;
49
40
  value: string | undefined;
50
41
  };
@@ -122,7 +113,6 @@ export interface GuideItem {
122
113
  title: string;
123
114
  type: string;
124
115
  }
125
- export type PackageElement = XmlElement<"package">;
126
116
  export interface FromOptions {
127
117
  /**
128
118
  * when true, mutation methods throw {@link EpubReadOnlyError} at runtime
@@ -156,19 +146,18 @@ export declare class EpubReadOnlyError extends Error {
156
146
  * ```ts
157
147
  * import { Epub, getBody, findByName, textContent } from '@storyteller-platform/epub';
158
148
  *
159
- * const epub = await Epub.from('./path/to/book.epub');
149
+ * using epub = await Epub.from('./path/to/book.epub');
160
150
  * const title = await epub.getTitle();
161
151
  * const spineItems = await epub.getSpineItems();
162
152
  * const chptOne = spineItems[0];
163
153
  * const chptOneXml = await epub.readXhtmlItemContents(chptOne.id);
164
154
  *
165
155
  * const body = getBody(chptOneXml);
166
- * const h1 = Epub.findXmlChildByName('h1', body);
156
+ * const h1 = findXmlChildByName('h1', body);
167
157
  * const headingText = textContent(h1);
168
158
  *
169
159
  * await epub.setTitle(headingText);
170
- * await epub.writeToFile('./path/to/updated.epub');
171
- * await epub.close();
160
+ * await epub.saveAndClose();
172
161
  * ```
173
162
  *
174
163
  * @link https://www.w3.org/TR/epub-33/
@@ -178,10 +167,6 @@ export declare class Epub {
178
167
  protected adapter: EpubStorageAdapter;
179
168
  protected inputPath: string | undefined;
180
169
  protected readonlyOverride: boolean;
181
- static xmlParser: XMLParser;
182
- static xhtmlParser: XMLParser;
183
- static xmlBuilder: import("fast-xml-builder").XMLBuilder;
184
- static xhtmlBuilder: import("fast-xml-builder").XMLBuilder;
185
170
  /**
186
171
  * Format a duration, provided as a number of seconds, as
187
172
  * a SMIL clock value, to be used for Media Overlays.
@@ -189,62 +174,6 @@ export declare class Epub {
189
174
  * @link https://www.w3.org/TR/epub-33/#sec-duration
190
175
  */
191
176
  static formatSmilDuration(duration: number): string;
192
- /**
193
- * Given an XML structure representing a complete XHTML document,
194
- * add a `link` element to the `head` of the document.
195
- *
196
- * This method modifies the provided XML structure.
197
- */
198
- static addLinkToXhtmlHead(xml: ParsedXml, link: {
199
- rel: string;
200
- href: string;
201
- type: string;
202
- }): void;
203
- /**
204
- * Given an XML structure representing a complete XHTML document,
205
- * return the sub-structure representing the children of the
206
- * document's body element.
207
- */
208
- static getXhtmlBody(xml: ParsedXml): ParsedXml;
209
- static createXmlElement<Name extends ElementName>(name: Name, properties: Record<string, string>, children?: XmlNode[]): XmlElement<Name>;
210
- static createXmlTextNode(text: string): XmlTextNode;
211
- /**
212
- * Given an XML structure representing a complete XHTML document,
213
- * return a string representing the concatenation of all text nodes
214
- * in the document.
215
- */
216
- static getXhtmlTextContent(xml: ParsedXml): string;
217
- /**
218
- * Given an XMLElement, return its attributes.
219
- */
220
- static getXmlAttributes(element: XmlElement): Record<string, string>;
221
- /**
222
- * Given an XMLElement, return its tag name.
223
- */
224
- static getXmlElementName<Name extends ElementName>(element: XmlElement<Name>): Name;
225
- /**
226
- * Given an XMLElement, return a list of its children
227
- */
228
- static getXmlChildren<Name extends ElementName>(element: XmlElement<Name>): ParsedXml;
229
- static replaceXmlChildren<Name extends ElementName>(element: XmlElement<Name>, children: XmlNode[]): void;
230
- /**
231
- * Given an XML structure, find the first child matching
232
- * the provided name and optional filter.
233
- */
234
- static findXmlChildByName<Name extends ElementName>(name: Name, xml: ParsedXml, filter?: (node: XmlElement<Name>) => boolean): XmlElement<Name> | undefined;
235
- /**
236
- * Given an XML structure, find the first descendant matching
237
- * the provided name and optional filter.
238
- *
239
- * Will perform a breadth first search for the element, returning
240
- * the highest element in the tree matching the name and filter.
241
- */
242
- static findXmlDescendantByName<Name extends ElementName>(name: Name, xml: ParsedXml, filter?: (node: XmlElement<Name>) => boolean): XmlElement<Name> | undefined;
243
- /**
244
- * Given an XMLNode, determine whether it represents
245
- * a text node or an XML element.
246
- */
247
- static isXmlTextNode(node: XmlNode): node is XmlTextNode;
248
177
  private rootfile;
249
178
  private manifest;
250
179
  private spine;
@@ -300,11 +229,11 @@ export declare class Epub {
300
229
  * `Epub.using(MemoryAdapter).from(path)` for read-only, in-memory access)
301
230
  * @throws {EpubVersionError} when the archive is not a valid EPUB 3
302
231
  */
303
- static from(pathOrData: string | Uint8Array): Promise<Epub>;
304
- static from(pathOrData: string | Uint8Array, options: FromOptions & {
232
+ static from(pathOrData: ArchiveSource): Promise<Epub>;
233
+ static from(pathOrData: ArchiveSource, options: FromOptions & {
305
234
  readonly: true;
306
235
  }): Promise<EpubReader>;
307
- static from(pathOrData: string | Uint8Array, options?: FromOptions): Promise<Epub | EpubReader>;
236
+ static from(pathOrData: ArchiveSource, options?: FromOptions): Promise<Epub | EpubReader>;
308
237
  static assertEpub3(epub: Epub): Promise<void>;
309
238
  copy(path?: string): Promise<Epub>;
310
239
  private removeEntry;
@@ -317,7 +246,7 @@ export declare class Epub {
317
246
  getRootfile(): Promise<string>;
318
247
  getPackageDocumentSource(): Promise<string>;
319
248
  private getPackageDocument;
320
- getPackageElement(): Promise<XmlElement<"package">>;
249
+ getPackageElement(): Promise<Element>;
321
250
  /**
322
251
  * Safely modify the package document, without race conditions.
323
252
  *
@@ -330,7 +259,7 @@ export declare class Epub {
330
259
  * it returns a new package document, that will be persisted, otherwise
331
260
  * it will be assumed that the package document was modified in place.
332
261
  */
333
- withPackage(producer: ((packageElement: PackageElement) => void) | ((packageElement: PackageElement) => PackageElement) | ((packageElement: PackageElement) => Promise<PackageElement>) | ((packageElement: PackageElement) => Promise<void>)): Promise<void>;
262
+ withPackage(producer: ((packageElement: Element) => void) | ((packageElement: Element) => Element) | ((packageElement: Element) => Promise<Element>) | ((packageElement: Element) => Promise<void>)): Promise<void>;
334
263
  /**
335
264
  * Retrieve the manifest for the Epub.
336
265
  *
@@ -355,26 +284,12 @@ export declare class Epub {
355
284
  * Returns the item in the metadata element's children array
356
285
  * that matches the provided predicate.
357
286
  */
358
- findMetadataItem(predicate: (entry: MetadataEntry) => boolean): Promise<{
359
- id: string | undefined;
360
- type: `?${string}` | `A${string}` | `B${string}` | `C${string}` | `D${string}` | `E${string}` | `F${string}` | `G${string}` | `H${string}` | `I${string}` | `J${string}` | `K${string}` | `L${string}` | `M${string}` | `N${string}` | `O${string}` | `P${string}` | `Q${string}` | `R${string}` | `S${string}` | `T${string}` | `U${string}` | `V${string}` | `W${string}` | `X${string}` | `Y${string}` | `Z${string}` | `a${string}` | `b${string}` | `c${string}` | `d${string}` | `e${string}` | `f${string}` | `g${string}` | `h${string}` | `i${string}` | `j${string}` | `k${string}` | `l${string}` | `m${string}` | `n${string}` | `o${string}` | `p${string}` | `q${string}` | `r${string}` | `s${string}` | `t${string}` | `u${string}` | `v${string}` | `w${string}` | `x${string}` | `y${string}` | `z${string}`;
361
- properties: {
362
- [k: string]: string;
363
- };
364
- value: string | undefined;
365
- } | null>;
287
+ findMetadataItem(predicate: (entry: MetadataEntry) => boolean): Promise<MetadataEntry | null>;
366
288
  /**
367
289
  * Returns the item in the metadata element's children array
368
290
  * that matches the provided predicate.
369
291
  */
370
- findAllMetadataItems(predicate: (entry: MetadataEntry) => boolean): Promise<{
371
- id: string | undefined;
372
- type: `?${string}` | `A${string}` | `B${string}` | `C${string}` | `D${string}` | `E${string}` | `F${string}` | `G${string}` | `H${string}` | `I${string}` | `J${string}` | `K${string}` | `L${string}` | `M${string}` | `N${string}` | `O${string}` | `P${string}` | `Q${string}` | `R${string}` | `S${string}` | `T${string}` | `U${string}` | `V${string}` | `W${string}` | `X${string}` | `Y${string}` | `Z${string}` | `a${string}` | `b${string}` | `c${string}` | `d${string}` | `e${string}` | `f${string}` | `g${string}` | `h${string}` | `i${string}` | `j${string}` | `k${string}` | `l${string}` | `m${string}` | `n${string}` | `o${string}` | `p${string}` | `q${string}` | `r${string}` | `s${string}` | `t${string}` | `u${string}` | `v${string}` | `w${string}` | `x${string}` | `y${string}` | `z${string}`;
373
- properties: {
374
- [k: string]: string;
375
- };
376
- value: string | undefined;
377
- }[]>;
292
+ findAllMetadataItems(predicate: (entry: MetadataEntry) => boolean): Promise<MetadataEntry[]>;
378
293
  private static parseMetadataItem;
379
294
  /**
380
295
  * Retrieve the metadata entries for the Epub.
@@ -513,7 +428,7 @@ export declare class Epub {
513
428
  /**
514
429
  * Remove `meta` refinements pointing at any of the given ids,
515
430
  * restricted to the given `property` values as a cleanup step
516
- * Mutates `children` in place.
431
+ * Mutates `metadata` in place.
517
432
  */
518
433
  private static removeRefiningMetas;
519
434
  /**
@@ -949,6 +864,13 @@ export declare class Epub {
949
864
  */
950
865
  readItemContents(id: string): Promise<Uint8Array>;
951
866
  readItemContents(id: string, encoding: "utf-8"): Promise<string>;
867
+ /**
868
+ * Create a new XML document with the given root node.
869
+ *
870
+ * @param root The XML node to use as the document element
871
+ * @param language Optional - defaults to the EPUB's language
872
+ */
873
+ createXmlDocument(root: Element): Document;
952
874
  /**
953
875
  * Create a new XHTML document with the given body
954
876
  * and head.
@@ -957,7 +879,7 @@ export declare class Epub {
957
879
  * @param head Optional - the XMl nodes to place in the head
958
880
  * @param language Optional - defaults to the EPUB's language
959
881
  */
960
- createXhtmlDocument(body: ParsedXml, head?: ParsedXml, language?: Intl.Locale): Promise<(XmlElement<"?xml"> | XmlElement<"html">)[]>;
882
+ createXhtmlDocument(body: Node[], head?: Node[], language?: Intl.Locale): Promise<Document>;
961
883
  /**
962
884
  * Retrieves the contents of an XHTML item, given its manifest id.
963
885
  *
@@ -967,7 +889,7 @@ export declare class Epub {
967
889
  *
968
890
  * @link https://www.w3.org/TR/epub-33/#sec-xhtml
969
891
  */
970
- readXhtmlItemContents(id: string, as?: "xhtml"): Promise<ParsedXml>;
892
+ readXhtmlItemContents(id: string, as?: "xhtml"): Promise<Document>;
971
893
  readXhtmlItemContents(id: string, as: "text"): Promise<string>;
972
894
  private writeEntryContents;
973
895
  /**
@@ -1000,7 +922,7 @@ export declare class Epub {
1000
922
  *
1001
923
  * @link https://www.w3.org/TR/epub-33/#sec-xhtml
1002
924
  */
1003
- writeXhtmlItemContents(id: string, contents: ParsedXml): Promise<void>;
925
+ writeXhtmlItemContents(id: string, contents: Document): Promise<void>;
1004
926
  removeManifestItem(id: string): Promise<void>;
1005
927
  /**
1006
928
  * Create a new manifest item and write its contents to a
@@ -1015,7 +937,7 @@ export declare class Epub {
1015
937
  * @link https://www.w3.org/TR/epub-33/#sec-pkg-manifest
1016
938
  * @link https://www.w3.org/TR/epub-33/#sec-contentdocs
1017
939
  */
1018
- addManifestItem(item: ManifestItem, contents: ParsedXml, encoding: "xml"): Promise<void>;
940
+ addManifestItem(item: ManifestItem, contents: Document, encoding: "xml"): Promise<void>;
1019
941
  addManifestItem(item: ManifestItem, contents: string, encoding: "utf-8"): Promise<void>;
1020
942
  addManifestItem(item: ManifestItem, contents: Uint8Array): Promise<void>;
1021
943
  /**
@@ -1127,15 +1049,15 @@ export declare class EpubFactory<A extends EpubStorageAdapterClass> {
1127
1049
  *
1128
1050
  * @throws {EpubVersionError} when the archive is not a valid EPUB 3
1129
1051
  */
1130
- from(source: string | Uint8Array, options: FromOptions & {
1052
+ from(source: ArchiveSource, options: FromOptions & {
1131
1053
  readonly: true;
1132
1054
  } & AdapterOptions<A>): Promise<EpubReader & {
1133
1055
  storage: A["kind"];
1134
1056
  }>;
1135
- from(source: string | Uint8Array, options?: FromOptions & AdapterOptions<A>): Promise<EpubInstanceFor<A> & {
1057
+ from(source: ArchiveSource, options?: FromOptions & AdapterOptions<A>): Promise<EpubInstanceFor<A> & {
1136
1058
  storage: A["kind"];
1137
1059
  }>;
1138
- readPackageDocumentSource(source: string | Uint8Array, options?: AdapterOptions<A>): Promise<string>;
1060
+ readPackageDocumentSource(source: ArchiveSource, options?: AdapterOptions<A>): Promise<string>;
1139
1061
  /**
1140
1062
  * Construct a new EPUB on this factory's adapter, optionally seeded
1141
1063
  * with the provided metadata. Requires a writable adapter that
@@ -1165,4 +1087,4 @@ export declare class EpubFactory<A extends EpubStorageAdapterClass> {
1165
1087
  */
1166
1088
  upgrade(path: string, options?: Upgrade.Epub2UpgradeOptions): Promise<EpubInstanceFor<A>>;
1167
1089
  }
1168
- export type { Epub2UpgradeOptions, Landmark } from "./upgrade.ts";
1090
+ export type { Epub2UpgradeOptions, Landmark } from "./upgrade.tsx";