epub-codec 1.3.9 → 1.5.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/README.md CHANGED
@@ -138,7 +138,8 @@ The issue that created this package ([ExaDev/documents.js#801](https://github.co
138
138
 
139
139
  Every construct this package's XHTML mapping cannot represent losslessly is a documented `EpubDiagnosticCodes` entry — see `src/diagnostics.ts` for the full table, and each module's own top-of-file comment for which side (read/write) it belongs to:
140
140
 
141
- - **`epub/element-unmapped`** — `<sub>`/`<sup>` degrade to plain text: `document-schema.js`'s `ContentRun` carries no subscript/superscript field at all, a genuine family-wide schema gap (no sibling codec has ever needed one; `ooxml.js`'s own docx reader has no `w:vertAlign` handling either), not something specific to this package.
141
+ - **`epub/element-unmapped`** — a write-side-only code now: an `embeddedObject` block has no XHTML representation in this package's writer and is dropped, and a construct-boundary marker recovered into a table cell has no XHTML spelling either. (`<sub>`/`<sup>` used to fire it on read, before `ContentRun` gained a `verticalAlign` field for them to land in — they now round-trip as ordinary run styling.)
142
+ - **Text direction (the global `dir` attribute) rides `ContentParagraph.direction` at block scope and `ContentRun.direction` at inline scope** — `dir` is legal on any XHTML element and inherits, so a container's own stated direction (on `<body>`, a `div`, a `p`, a heading, `<pre>`, an `li`, a `dt`/`dd`, a table cell) reaches every paragraph produced beneath it until a nearer element states one of its own, exactly the inheritance rule a browser applies. A run-level `dir` (a `<span dir="rtl">` inside an LTR paragraph) lands on the run the way `<strong>`'s bold does, and the writer wraps such a run in its own `<span dir>` on the way out. `dir="auto"` maps to nothing: its direction is resolved at render time from the content's own first strong character, a fact the schema's closed `ltr`/`rtl` vocabulary has no member for. EPUB names no document-level text direction to read into `LayoutMetadata.direction` — the OPF's own `dir` attribute governs metadata display order only, and a spine's `page-progression-direction` is page order, not text direction — so that field stays unset by this package.
142
143
  - **Internal-link semantics** (ExaDev/documents.js#963) — a same-document fragment href, or a cross-document href naming another spine document's own id, that resolves to a real, block-level element anywhere in the spine builds `document-schema.js`'s own internal-target `link` construct (a run-level extent, `target: { kind: "internal", anchor }`) rather than riding `ContentRun.hyperlink` as a plain string; the target element itself is wrapped in its own `anchor` construct (`anchorType: "bookmark"`) so the two ends of the link are both addressable. A cross-document target's own name is qualified with its owning document's own path (`"OEBPS/chapter2.xhtml#sec2"`, never a bare `"sec2"`) precisely because two different target documents can otherwise legitimately reuse the identical id; a same-document target keeps the bare fragment. `src/write.ts`'s own whole-document anchor-section index resolves a reference back to either a same-file `"#name"` href or a cross-file `"sectionN.xhtml#name"` one on write, so this round-trips through a same-format write. `epub/link-target-external-only` remains the diagnostic for what's left: an href genuinely external (a URI scheme), or an internal-looking href this package cannot resolve to a real element at all (a nonexistent fragment, or one with no fragment naming only a whole document) — that still rides `ContentRun.hyperlink` verbatim, restoring byte-for-byte either way.
143
144
  - **Footnotes recognise a cross-document body** (ExaDev/documents.js#963). Both the EPUB 3 structured idiom (`epub:type="noteref"`/`"footnote"`) and the EPUB 2 linked-anchor idiom (a `class="footnote"`/`"noteref"` convention with no `epub:type` vocabulary at all, recognised by `src/xhtml/footnote.ts`'s `isFootnoteReference`) map onto the identical `anchor` construct — a run-level point extent at the reference site, a `constructStart`/blocks/`constructEnd` triple around the body. A reference and its own body need not live in the same spine document: `document-schema.js`'s own construct-marker contract still forbids a single bracket pair from straddling a block-list boundary (each `ContentSection` is its own block list), but this was never that — the reference's own point extent and the body's own `constructStart`/`constructEnd` pair are two independently well-formed markers in two different sections, connected only by sharing one `name`. `src/read.ts`'s own whole-spine pass resolves every href (same- and cross-document) before any section is read, so a cross-document footnote (a separate "notes.xhtml", the more common real-world EPUB 2 shape) is recognised and linked exactly like a same-document one; a cross-document name is qualified with its owning document's own path (`"OEBPS/notes.xhtml#note1"`) to keep it distinct from a same-named footnote in a different document, and `src/write.ts`'s own whole-document anchor-section index resolves the reference back to a working same-file or cross-file href on every write.
144
145
  - **`epub/style-residue`** — a document's own `<head>` style declarations (`<link rel="stylesheet">`, `<style>`) are quarantined verbatim as `SourceResidue` on the owning `ContentSection`, never interpreted: CSS is residue, not content. `writeEpubContent` re-emits it into the written `<head>` on a same-format write (this family's standard restorable-fidelity re-emission contract).
@@ -157,9 +158,9 @@ Every construct this package's XHTML mapping cannot represent losslessly is a do
157
158
 
158
159
  ## Fidelity
159
160
 
160
- **Semantic fidelity** — headings, paragraphs, lists (nested, bullet/ordered), definition lists, tables, images, hyperlinks (external and internal, same- or cross-document — ExaDev/documents.js#963), text styling (bold/italic/underline/strike/monospace), blockquotes, pre/code blocks, horizontal rules, figure/figcaption, and footnotes (both EPUB 2 and EPUB 3 idioms, same- or cross-document — ExaDev/documents.js#963) all survive as first-class `document-schema.js` nodes or constructs — see [ExaDev/documents.js#801](https://github.com/ExaDev/documents.js/issues/801) for the full acceptance list this package was built against, and `src/roundtrip.test.ts` for the real end-to-end proof (a hand-built `ContentDocument` covering nearly all of it, written to a genuine EPUB 3 zip and read back unchanged).
161
+ **Semantic fidelity** — headings, paragraphs, lists (nested, bullet/ordered), definition lists, tables, images, hyperlinks (external and internal, same- or cross-document — ExaDev/documents.js#963), text styling (bold/italic/underline/strike/monospace, sub/superscript vertical position, and text direction at both paragraph and run scope), blockquotes, pre/code blocks, horizontal rules, figure/figcaption, and footnotes (both EPUB 2 and EPUB 3 idioms, same- or cross-document — ExaDev/documents.js#963) all survive as first-class `document-schema.js` nodes or constructs — see [ExaDev/documents.js#801](https://github.com/ExaDev/documents.js/issues/801) for the full acceptance list this package was built against, and `src/roundtrip.test.ts` for the real end-to-end proof (a hand-built `ContentDocument` covering nearly all of it, written to a genuine EPUB 3 zip and read back unchanged).
161
162
 
162
- **Restorable fidelity** — a same-format (EPUB-to-EPUB) round trip re-emits quarantined CSS residue verbatim, and re-resolves an internal link/bookmark or footnote reference/body pair to a working same-file or cross-file href on every write (ExaDev/documents.js#963); the one remaining documented gap above (sub/sup styling) is a permanent, structural limit rather than a restorable one, since the source construct itself has nowhere in the schema to ride.
163
+ **Restorable fidelity** — a same-format (EPUB-to-EPUB) round trip re-emits quarantined CSS residue verbatim, and re-resolves an internal link/bookmark or footnote reference/body pair to a working same-file or cross-file href on every write (ExaDev/documents.js#963).
163
164
 
164
165
  **Byte fidelity, at the Package level** (ExaDev/documents.js#963). This package now has the same lossless byte-level `Package` model `ooxml.js`/`odf.js` do — a `decodePackage`/`encodePackage` pair, mirroring theirs exactly, that reads every OCF zip entry into a generic `Part` (an XML entry as an ordered `XmlNode[]` forest, anything else as raw base64 bytes) and writes it straight back, with no EPUB-specific interpretation in between. `decodePackage(bytes) |> encodePackage` is a genuine fixed point: `src/package-round-trip.test.ts` pins `decode -> encode -> decode` idempotence, per-part content preservation (an XML part's own entities/structure, a binary part's own bytes verbatim), and the one deliberate departure from a generic zip-of-XML writer this format shares with ODF's identical requirement — the `mimetype` part hoisted first and stored uncompressed (EPUB 3.3 §6.3), regardless of the input zip's own entry order, and never fabricated if the input never carried one. `readEpub(Content)`/`writeEpubContent` cross this identical boundary internally (`decodePackage` first, `encodePackage` last) rather than talking to the zip layer directly, so the two are the same lossless core, not two independent implementations that happen to agree.
165
166
 
@@ -3,10 +3,10 @@ import { d as XmlNode } from "./node-CJLSSs1k.cjs";
3
3
  import "./metadata-DXto7sM6.cjs";
4
4
  import "./parse-Bkkb7qXz.cjs";
5
5
  import "./write-B89sagtw.cjs";
6
- import "./context-CXs2Yc9w.cjs";
6
+ import "./context-BW0aBtcw.cjs";
7
7
  import "./footnote-CxsO5tCV.cjs";
8
- import "./inline-YZOQY2wR.cjs";
9
- import "./read-BMGq_D9y.cjs";
8
+ import "./inline-C_pkrFBl.cjs";
9
+ import "./read-AZmpNjIa.cjs";
10
10
  import "./write-WSIgARHT.cjs";
11
11
  import "./write-COdkb8lG.cjs";
12
12
  import "./read-B7kc_MeO.cjs";
@@ -143,6 +143,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
143
143
  widthPt: z.ZodNumber;
144
144
  heightPt: z.ZodNumber;
145
145
  }, z.core.$strip>>>;
146
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
147
+ family: z.ZodString;
148
+ bold: z.ZodBoolean;
149
+ italic: z.ZodBoolean;
150
+ base64: z.ZodString;
151
+ }, z.core.$strip>>>;
146
152
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
147
153
  paragraph: z.ZodOptional<z.ZodObject<{
148
154
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -292,6 +298,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
292
298
  widthPt: z.ZodNumber;
293
299
  heightPt: z.ZodNumber;
294
300
  }, z.core.$strip>>>;
301
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
302
+ family: z.ZodString;
303
+ bold: z.ZodBoolean;
304
+ italic: z.ZodBoolean;
305
+ base64: z.ZodString;
306
+ }, z.core.$strip>>>;
295
307
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
296
308
  paragraph: z.ZodOptional<z.ZodObject<{
297
309
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -446,6 +458,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
446
458
  widthPt: z.ZodNumber;
447
459
  heightPt: z.ZodNumber;
448
460
  }, z.core.$strip>>>;
461
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
462
+ family: z.ZodString;
463
+ bold: z.ZodBoolean;
464
+ italic: z.ZodBoolean;
465
+ base64: z.ZodString;
466
+ }, z.core.$strip>>>;
449
467
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
450
468
  paragraph: z.ZodOptional<z.ZodObject<{
451
469
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -595,6 +613,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
595
613
  widthPt: z.ZodNumber;
596
614
  heightPt: z.ZodNumber;
597
615
  }, z.core.$strip>>>;
616
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
617
+ family: z.ZodString;
618
+ bold: z.ZodBoolean;
619
+ italic: z.ZodBoolean;
620
+ base64: z.ZodString;
621
+ }, z.core.$strip>>>;
598
622
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
599
623
  paragraph: z.ZodOptional<z.ZodObject<{
600
624
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -803,6 +827,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
803
827
  widthPt: z.ZodNumber;
804
828
  heightPt: z.ZodNumber;
805
829
  }, z.core.$strip>>>;
830
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
831
+ family: z.ZodString;
832
+ bold: z.ZodBoolean;
833
+ italic: z.ZodBoolean;
834
+ base64: z.ZodString;
835
+ }, z.core.$strip>>>;
806
836
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
807
837
  paragraph: z.ZodOptional<z.ZodObject<{
808
838
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -1003,6 +1033,11 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1003
1033
  even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1004
1034
  first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1005
1035
  }, z.core.$strip>>;
1036
+ watermarks: z.ZodOptional<z.ZodObject<{
1037
+ default: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1038
+ even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1039
+ first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1040
+ }, z.core.$strip>>;
1006
1041
  source: z.ZodOptional<z.ZodObject<{
1007
1042
  format: z.ZodEnum<{
1008
1043
  docx: "docx";
@@ -1168,6 +1203,7 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1168
1203
  fontScale: z.ZodOptional<z.ZodNumber>;
1169
1204
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
1170
1205
  paintOrder: z.ZodOptional<z.ZodNumber>;
1206
+ readingOrder: z.ZodOptional<z.ZodNumber>;
1171
1207
  sourcePath: z.ZodOptional<z.ZodString>;
1172
1208
  source: z.ZodOptional<z.ZodObject<{
1173
1209
  format: z.ZodEnum<{
@@ -2708,6 +2744,7 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
2708
2744
  fontScale: z.ZodOptional<z.ZodNumber>;
2709
2745
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
2710
2746
  paintOrder: z.ZodOptional<z.ZodNumber>;
2747
+ readingOrder: z.ZodOptional<z.ZodNumber>;
2711
2748
  sourcePath: z.ZodOptional<z.ZodString>;
2712
2749
  source: z.ZodOptional<z.ZodObject<{
2713
2750
  format: z.ZodEnum<{
@@ -3,10 +3,10 @@ import { d as XmlNode } from "./node-CJLSSs1k.js";
3
3
  import "./metadata-T5V2ovtS.js";
4
4
  import "./parse-C5GxodcX.js";
5
5
  import "./write-DwaEwwgZ.js";
6
- import "./context-CTgx7PwU.js";
6
+ import "./context-BhPj0M2Y.js";
7
7
  import "./footnote-iZAPC_NT.js";
8
- import "./inline-DDj6Sl3e.js";
9
- import "./read-Czqr3aop.js";
8
+ import "./inline-B0FFnyYJ.js";
9
+ import "./read-51pAwb-0.js";
10
10
  import "./write-Klo0WDhT.js";
11
11
  import "./write-COdkb8lG.js";
12
12
  import "./read-DPkpZsYG.js";
@@ -143,6 +143,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
143
143
  widthPt: z.ZodNumber;
144
144
  heightPt: z.ZodNumber;
145
145
  }, z.core.$strip>>>;
146
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
147
+ family: z.ZodString;
148
+ bold: z.ZodBoolean;
149
+ italic: z.ZodBoolean;
150
+ base64: z.ZodString;
151
+ }, z.core.$strip>>>;
146
152
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
147
153
  paragraph: z.ZodOptional<z.ZodObject<{
148
154
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -292,6 +298,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
292
298
  widthPt: z.ZodNumber;
293
299
  heightPt: z.ZodNumber;
294
300
  }, z.core.$strip>>>;
301
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
302
+ family: z.ZodString;
303
+ bold: z.ZodBoolean;
304
+ italic: z.ZodBoolean;
305
+ base64: z.ZodString;
306
+ }, z.core.$strip>>>;
295
307
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
296
308
  paragraph: z.ZodOptional<z.ZodObject<{
297
309
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -446,6 +458,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
446
458
  widthPt: z.ZodNumber;
447
459
  heightPt: z.ZodNumber;
448
460
  }, z.core.$strip>>>;
461
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
462
+ family: z.ZodString;
463
+ bold: z.ZodBoolean;
464
+ italic: z.ZodBoolean;
465
+ base64: z.ZodString;
466
+ }, z.core.$strip>>>;
449
467
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
450
468
  paragraph: z.ZodOptional<z.ZodObject<{
451
469
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -595,6 +613,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
595
613
  widthPt: z.ZodNumber;
596
614
  heightPt: z.ZodNumber;
597
615
  }, z.core.$strip>>>;
616
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
617
+ family: z.ZodString;
618
+ bold: z.ZodBoolean;
619
+ italic: z.ZodBoolean;
620
+ base64: z.ZodString;
621
+ }, z.core.$strip>>>;
598
622
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
599
623
  paragraph: z.ZodOptional<z.ZodObject<{
600
624
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -803,6 +827,12 @@ declare const epubCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Ar
803
827
  widthPt: z.ZodNumber;
804
828
  heightPt: z.ZodNumber;
805
829
  }, z.core.$strip>>>;
830
+ fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
831
+ family: z.ZodString;
832
+ bold: z.ZodBoolean;
833
+ italic: z.ZodBoolean;
834
+ base64: z.ZodString;
835
+ }, z.core.$strip>>>;
806
836
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
807
837
  paragraph: z.ZodOptional<z.ZodObject<{
808
838
  alignment: z.ZodOptional<z.ZodEnum<{
@@ -1003,6 +1033,11 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1003
1033
  even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1004
1034
  first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1005
1035
  }, z.core.$strip>>;
1036
+ watermarks: z.ZodOptional<z.ZodObject<{
1037
+ default: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1038
+ even: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1039
+ first: z.ZodOptional<z.ZodLazy<z.ZodArray<z.ZodType<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock, z.core.$ZodTypeInternals<import("document-schema.js").ContentBlock, import("document-schema.js").ContentBlock>>>>>;
1040
+ }, z.core.$strip>>;
1006
1041
  source: z.ZodOptional<z.ZodObject<{
1007
1042
  format: z.ZodEnum<{
1008
1043
  docx: "docx";
@@ -1168,6 +1203,7 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1168
1203
  fontScale: z.ZodOptional<z.ZodNumber>;
1169
1204
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
1170
1205
  paintOrder: z.ZodOptional<z.ZodNumber>;
1206
+ readingOrder: z.ZodOptional<z.ZodNumber>;
1171
1207
  sourcePath: z.ZodOptional<z.ZodString>;
1172
1208
  source: z.ZodOptional<z.ZodObject<{
1173
1209
  format: z.ZodEnum<{
@@ -2708,6 +2744,7 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
2708
2744
  fontScale: z.ZodOptional<z.ZodNumber>;
2709
2745
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
2710
2746
  paintOrder: z.ZodOptional<z.ZodNumber>;
2747
+ readingOrder: z.ZodOptional<z.ZodNumber>;
2711
2748
  sourcePath: z.ZodOptional<z.ZodString>;
2712
2749
  source: z.ZodOptional<z.ZodObject<{
2713
2750
  format: z.ZodEnum<{
package/dist/codec.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as epubContentCodec, i as epubCodec, n as decodePackage, o as packageCodec, r as encodePackage, t as EpubBytesSchema } from "./codec-DS1GA490.cjs";
1
+ import { a as epubContentCodec, i as epubCodec, n as decodePackage, o as packageCodec, r as encodePackage, t as EpubBytesSchema } from "./codec-Ci-wcMHH.cjs";
2
2
  export { EpubBytesSchema, decodePackage, encodePackage, epubCodec, epubContentCodec, packageCodec };
package/dist/codec.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as epubContentCodec, i as epubCodec, n as decodePackage, o as packageCodec, r as encodePackage, t as EpubBytesSchema } from "./codec-DF9r4Fkv.js";
1
+ import { a as epubContentCodec, i as epubCodec, n as decodePackage, o as packageCodec, r as encodePackage, t as EpubBytesSchema } from "./codec-DhdADrEb.js";
2
2
  export { EpubBytesSchema, decodePackage, encodePackage, epubCodec, epubContentCodec, packageCodec };
@@ -1,6 +1,6 @@
1
1
  import { i as EpubDiagnosticSink } from "./diagnostics-C0CRdoda.cjs";
2
2
  import { l as XmlElement } from "./node-CJLSSs1k.cjs";
3
- import { AnchorType } from "document-schema.js";
3
+ import { AnchorType, TextDirection } from "document-schema.js";
4
4
  //#region src/xhtml/context.d.ts
5
5
  interface ResolvedAnchorTarget {
6
6
  readonly anchorType: AnchorType;
@@ -21,6 +21,8 @@ interface InlineStyle {
21
21
  readonly underline?: boolean;
22
22
  readonly strike?: boolean;
23
23
  readonly fontFamily?: string;
24
+ readonly verticalAlign?: "superscript" | "subscript";
25
+ readonly direction?: TextDirection;
24
26
  }
25
27
  declare function isInertElement(tag: string): boolean;
26
28
  declare function reportInertElementSkip(tag: string, context: XhtmlReadContext): void;
@@ -1,6 +1,6 @@
1
1
  import { i as EpubDiagnosticSink } from "./diagnostics-C0CRdoda.js";
2
2
  import { l as XmlElement } from "./node-CJLSSs1k.js";
3
- import { AnchorType } from "document-schema.js";
3
+ import { AnchorType, TextDirection } from "document-schema.js";
4
4
  //#region src/xhtml/context.d.ts
5
5
  interface ResolvedAnchorTarget {
6
6
  readonly anchorType: AnchorType;
@@ -21,6 +21,8 @@ interface InlineStyle {
21
21
  readonly underline?: boolean;
22
22
  readonly strike?: boolean;
23
23
  readonly fontFamily?: string;
24
+ readonly verticalAlign?: "superscript" | "subscript";
25
+ readonly direction?: TextDirection;
24
26
  }
25
27
  declare function isInertElement(tag: string): boolean;
26
28
  declare function reportInertElementSkip(tag: string, context: XhtmlReadContext): void;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as OCF_CONTAINER_PATH, r as OCF_MIMETYPE_PATH, t as EPUB_MIME_TYPE } from "./format-DxUddUPj.cjs";
2
2
  import { n as unzipPackage, r as zipPackage, t as ZipEntry } from "./zip-ie17sOo5.cjs";
3
- import { _ as XmlPart, a as epubContentCodec, c as serializePackage, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, i as epubCodec, l as packageFromEntries, m as EpubPackageSchema, n as decodePackage, o as packageCodec, p as EpubPackage, r as encodePackage, s as packageToEntries, t as EpubBytesSchema, u as parsePackage, v as XmlPartSchema } from "./codec-DS1GA490.cjs";
3
+ import { _ as XmlPart, a as epubContentCodec, c as serializePackage, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, i as epubCodec, l as packageFromEntries, m as EpubPackageSchema, n as decodePackage, o as packageCodec, p as EpubPackage, r as encodePackage, s as packageToEntries, t as EpubBytesSchema, u as parsePackage, v as XmlPartSchema } from "./codec-Ci-wcMHH.cjs";
4
4
  import { a as EpubEmptySpineError, c as EpubInvalidOpfError, d as EpubUnbalancedConstructMarkersError, f as EpubUnsupportedDocumentKindError, i as EpubDiagnosticSink, l as EpubPackageFlattenError, m as NOOP_EPUB_DIAGNOSTIC_SINK, n as EpubDiagnosticCodes, o as EpubInvalidContainerError, p as EpubWriteError, r as EpubDiagnosticSeverity, s as EpubInvalidMimetypeError, t as EpubDiagnostic, u as EpubParseError } from "./diagnostics-C0CRdoda.cjs";
5
5
  import { t as resolveOpfPath } from "./container-B6cHHiY9.cjs";
6
6
  import { n as OpfPackage, r as OpfSpineItemRef, t as OpfManifestItem } from "./types-BxmkPT_F.cjs";
@@ -10,11 +10,11 @@ import { t as parseOpf } from "./parse-Bkkb7qXz.cjs";
10
10
  import { n as writeOpf, t as WriteOpfInput } from "./write-B89sagtw.cjs";
11
11
  import { n as bytesToBase64, t as base64ToBytes } from "./base64--HuymRl_.cjs";
12
12
  import { a as readImageDimensions, i as detectImageFormat, n as ImageDimensions, r as POINTS_PER_PIXEL, t as EpubImageFormat } from "./dimensions-B7ogpvKQ.cjs";
13
- import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "./context-CXs2Yc9w.cjs";
13
+ import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "./context-BW0aBtcw.cjs";
14
14
  import { n as isFootnoteReference, r as sameDocumentFragment, t as isFootnoteAside } from "./footnote-CxsO5tCV.cjs";
15
- import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "./inline-YZOQY2wR.cjs";
15
+ import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "./inline-C_pkrFBl.cjs";
16
16
  import { i as parseListNumId, n as MintListNumIdOptions, r as mintListNumId, t as ListNumIdInfo } from "./list-id-BB_yxm1H.cjs";
17
- import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "./read-BMGq_D9y.cjs";
17
+ import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "./read-AZmpNjIa.cjs";
18
18
  import { a as QUOTE_STYLE_ID, i as QUOTE_INDENT_PT, n as HORIZONTAL_RULE_STYLE_ID, r as MONOSPACE_FONT_FAMILY, t as DEFINITION_BODY_INDENT_PT } from "./style-constants-RVoHdmju.cjs";
19
19
  import { n as writeXhtmlBody, t as XhtmlWriteContext } from "./write-WSIgARHT.cjs";
20
20
  import { t as readNav3TocHrefs } from "./nav3-SbAp8zlu.cjs";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as OCF_CONTAINER_PATH, r as OCF_MIMETYPE_PATH, t as EPUB_MIME_TYPE } from "./format-DxUddUPj.js";
2
2
  import { n as unzipPackage, r as zipPackage, t as ZipEntry } from "./zip-ie17sOo5.js";
3
- import { _ as XmlPart, a as epubContentCodec, c as serializePackage, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, i as epubCodec, l as packageFromEntries, m as EpubPackageSchema, n as decodePackage, o as packageCodec, p as EpubPackage, r as encodePackage, s as packageToEntries, t as EpubBytesSchema, u as parsePackage, v as XmlPartSchema } from "./codec-DF9r4Fkv.js";
3
+ import { _ as XmlPart, a as epubContentCodec, c as serializePackage, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, i as epubCodec, l as packageFromEntries, m as EpubPackageSchema, n as decodePackage, o as packageCodec, p as EpubPackage, r as encodePackage, s as packageToEntries, t as EpubBytesSchema, u as parsePackage, v as XmlPartSchema } from "./codec-DhdADrEb.js";
4
4
  import { a as EpubEmptySpineError, c as EpubInvalidOpfError, d as EpubUnbalancedConstructMarkersError, f as EpubUnsupportedDocumentKindError, i as EpubDiagnosticSink, l as EpubPackageFlattenError, m as NOOP_EPUB_DIAGNOSTIC_SINK, n as EpubDiagnosticCodes, o as EpubInvalidContainerError, p as EpubWriteError, r as EpubDiagnosticSeverity, s as EpubInvalidMimetypeError, t as EpubDiagnostic, u as EpubParseError } from "./diagnostics-C0CRdoda.js";
5
5
  import { t as resolveOpfPath } from "./container-B6cHHiY9.js";
6
6
  import { n as OpfPackage, r as OpfSpineItemRef, t as OpfManifestItem } from "./types-BxmkPT_F.js";
@@ -10,11 +10,11 @@ import { t as parseOpf } from "./parse-C5GxodcX.js";
10
10
  import { n as writeOpf, t as WriteOpfInput } from "./write-DwaEwwgZ.js";
11
11
  import { n as bytesToBase64, t as base64ToBytes } from "./base64--HuymRl_.js";
12
12
  import { a as readImageDimensions, i as detectImageFormat, n as ImageDimensions, r as POINTS_PER_PIXEL, t as EpubImageFormat } from "./dimensions-B7ogpvKQ.js";
13
- import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "./context-CTgx7PwU.js";
13
+ import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "./context-BhPj0M2Y.js";
14
14
  import { n as isFootnoteReference, r as sameDocumentFragment, t as isFootnoteAside } from "./footnote-iZAPC_NT.js";
15
- import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "./inline-DDj6Sl3e.js";
15
+ import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "./inline-B0FFnyYJ.js";
16
16
  import { i as parseListNumId, n as MintListNumIdOptions, r as mintListNumId, t as ListNumIdInfo } from "./list-id-BB_yxm1H.js";
17
- import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "./read-Czqr3aop.js";
17
+ import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "./read-51pAwb-0.js";
18
18
  import { a as QUOTE_STYLE_ID, i as QUOTE_INDENT_PT, n as HORIZONTAL_RULE_STYLE_ID, r as MONOSPACE_FONT_FAMILY, t as DEFINITION_BODY_INDENT_PT } from "./style-constants-RVoHdmju.js";
19
19
  import { n as writeXhtmlBody, t as XhtmlWriteContext } from "./write-Klo0WDhT.js";
20
20
  import { t as readNav3TocHrefs } from "./nav3-SbAp8zlu.js";
@@ -1,5 +1,5 @@
1
1
  import { d as XmlNode } from "./node-CJLSSs1k.js";
2
- import { r as XhtmlReadContext, t as InlineStyle } from "./context-CTgx7PwU.js";
2
+ import { r as XhtmlReadContext, t as InlineStyle } from "./context-BhPj0M2Y.js";
3
3
  import { ContentRun, RunConstructExtent } from "document-schema.js";
4
4
  //#region src/xhtml/inline.d.ts
5
5
  interface InlineResult {
@@ -1,5 +1,5 @@
1
1
  import { d as XmlNode } from "./node-CJLSSs1k.cjs";
2
- import { r as XhtmlReadContext, t as InlineStyle } from "./context-CXs2Yc9w.cjs";
2
+ import { r as XhtmlReadContext, t as InlineStyle } from "./context-BW0aBtcw.cjs";
3
3
  import { ContentRun, RunConstructExtent } from "document-schema.js";
4
4
  //#region src/xhtml/inline.d.ts
5
5
  interface InlineResult {
@@ -1,2 +1,2 @@
1
- import { _ as XmlPart, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, m as EpubPackageSchema, p as EpubPackage, v as XmlPartSchema } from "../codec-DS1GA490.cjs";
1
+ import { _ as XmlPart, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, m as EpubPackageSchema, p as EpubPackage, v as XmlPartSchema } from "../codec-Ci-wcMHH.cjs";
2
2
  export { BinaryPart, BinaryPartSchema, EpubPackage, EpubPackageSchema, Part, PartSchema, XmlPart, XmlPartSchema };
@@ -1,2 +1,2 @@
1
- import { _ as XmlPart, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, m as EpubPackageSchema, p as EpubPackage, v as XmlPartSchema } from "../codec-DF9r4Fkv.js";
1
+ import { _ as XmlPart, d as BinaryPart, f as BinaryPartSchema, g as PartSchema, h as Part, m as EpubPackageSchema, p as EpubPackage, v as XmlPartSchema } from "../codec-DhdADrEb.js";
2
2
  export { BinaryPart, BinaryPartSchema, EpubPackage, EpubPackageSchema, Part, PartSchema, XmlPart, XmlPartSchema };
@@ -1,2 +1,2 @@
1
- import { l as packageFromEntries, u as parsePackage } from "../codec-DS1GA490.cjs";
1
+ import { l as packageFromEntries, u as parsePackage } from "../codec-Ci-wcMHH.cjs";
2
2
  export { packageFromEntries, parsePackage };
@@ -1,2 +1,2 @@
1
- import { l as packageFromEntries, u as parsePackage } from "../codec-DF9r4Fkv.js";
1
+ import { l as packageFromEntries, u as parsePackage } from "../codec-DhdADrEb.js";
2
2
  export { packageFromEntries, parsePackage };
@@ -1,2 +1,2 @@
1
- import { c as serializePackage, s as packageToEntries } from "../codec-DS1GA490.cjs";
1
+ import { c as serializePackage, s as packageToEntries } from "../codec-Ci-wcMHH.cjs";
2
2
  export { packageToEntries, serializePackage };
@@ -1,2 +1,2 @@
1
- import { c as serializePackage, s as packageToEntries } from "../codec-DF9r4Fkv.js";
1
+ import { c as serializePackage, s as packageToEntries } from "../codec-DhdADrEb.js";
2
2
  export { packageToEntries, serializePackage };
@@ -1,5 +1,5 @@
1
1
  import { l as XmlElement } from "./node-CJLSSs1k.js";
2
- import { n as ResolvedAnchorTarget } from "./context-CTgx7PwU.js";
2
+ import { n as ResolvedAnchorTarget } from "./context-BhPj0M2Y.js";
3
3
  import { ContentBlock, SourceResidue } from "document-schema.js";
4
4
  //#region src/xhtml/read.d.ts
5
5
  interface ReadXhtmlBodyOptions {
@@ -1,5 +1,5 @@
1
1
  import { l as XmlElement } from "./node-CJLSSs1k.cjs";
2
- import { n as ResolvedAnchorTarget } from "./context-CXs2Yc9w.cjs";
2
+ import { n as ResolvedAnchorTarget } from "./context-BW0aBtcw.cjs";
3
3
  import { ContentBlock, SourceResidue } from "document-schema.js";
4
4
  //#region src/xhtml/read.d.ts
5
5
  interface ReadXhtmlBodyOptions {
@@ -1,2 +1,2 @@
1
- import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "../context-CXs2Yc9w.cjs";
1
+ import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "../context-BW0aBtcw.cjs";
2
2
  export { InlineStyle, ResolvedAnchorTarget, XhtmlReadContext, isInertElement, reportInertElementSkip };
@@ -1,2 +1,2 @@
1
- import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "../context-CTgx7PwU.js";
1
+ import { a as reportInertElementSkip, i as isInertElement, n as ResolvedAnchorTarget, r as XhtmlReadContext, t as InlineStyle } from "../context-BhPj0M2Y.js";
2
2
  export { InlineStyle, ResolvedAnchorTarget, XhtmlReadContext, isInertElement, reportInertElementSkip };
@@ -23,9 +23,16 @@ function styledRun(text, style, hyperlink) {
23
23
  if (style.underline === true) run.underline = true;
24
24
  if (style.strike === true) run.strike = true;
25
25
  if (style.fontFamily !== void 0) run.fontFamily = style.fontFamily;
26
+ if (style.verticalAlign !== void 0) run.verticalAlign = style.verticalAlign;
27
+ if (style.direction !== void 0) run.direction = style.direction;
26
28
  if (hyperlink !== void 0) run.hyperlink = hyperlink;
27
29
  return run;
28
30
  }
31
+ function withDirStyle(element, style) {
32
+ const dir = require_xml_query.attrValue(element, "dir");
33
+ if (dir === "ltr" || dir === "rtl") return mergeStyle(style, { direction: dir });
34
+ return style;
35
+ }
29
36
  function buildInlineRuns(nodes, style, context) {
30
37
  const runs = [];
31
38
  const constructs = [];
@@ -48,48 +55,43 @@ function appendElement(element, style, context, runs, constructs) {
48
55
  require_xhtml_context.reportInertElementSkip(element.tag, context);
49
56
  return;
50
57
  }
58
+ const styled = withDirStyle(element, style);
51
59
  switch (element.tag) {
52
60
  case "strong":
53
61
  case "b":
54
- appendNested(element, mergeStyle(style, { bold: true }), context, runs, constructs);
62
+ appendNested(element, mergeStyle(styled, { bold: true }), context, runs, constructs);
55
63
  return;
56
64
  case "em":
57
65
  case "i":
58
- appendNested(element, mergeStyle(style, { italic: true }), context, runs, constructs);
66
+ appendNested(element, mergeStyle(styled, { italic: true }), context, runs, constructs);
59
67
  return;
60
68
  case "u":
61
- appendNested(element, mergeStyle(style, { underline: true }), context, runs, constructs);
69
+ appendNested(element, mergeStyle(styled, { underline: true }), context, runs, constructs);
62
70
  return;
63
71
  case "s":
64
72
  case "strike":
65
73
  case "del":
66
- appendNested(element, mergeStyle(style, { strike: true }), context, runs, constructs);
74
+ appendNested(element, mergeStyle(styled, { strike: true }), context, runs, constructs);
67
75
  return;
68
76
  case "code":
69
77
  case "kbd":
70
78
  case "samp":
71
- appendNested(element, mergeStyle(style, { fontFamily: require_xhtml_style_constants.MONOSPACE_FONT_FAMILY }), context, runs, constructs);
79
+ appendNested(element, mergeStyle(styled, { fontFamily: require_xhtml_style_constants.MONOSPACE_FONT_FAMILY }), context, runs, constructs);
72
80
  return;
73
81
  case "sub":
74
82
  case "sup":
75
- context.sink({
76
- code: require_diagnostics.EpubDiagnosticCodes.ELEMENT_UNMAPPED,
77
- severity: "info",
78
- message: `<${element.tag}> has no document-schema.js run-level field to carry its vertical position; the text is kept, the styling is not`,
79
- href: context.sourceHref
80
- });
81
- appendNested(element, style, context, runs, constructs);
83
+ appendNested(element, mergeStyle(styled, { verticalAlign: element.tag === "sup" ? "superscript" : "subscript" }), context, runs, constructs);
82
84
  return;
83
85
  case "br":
84
- runs.push(styledRun("\n", style));
86
+ runs.push(styledRun("\n", styled));
85
87
  return;
86
88
  case "a":
87
- appendAnchor(element, style, context, runs, constructs);
89
+ appendAnchor(element, styled, context, runs, constructs);
88
90
  return;
89
91
  case "img":
90
- appendImageFallback(element, style, context, runs);
92
+ appendImageFallback(element, styled, context, runs);
91
93
  return;
92
- default: appendNested(element, style, context, runs, constructs);
94
+ default: appendNested(element, styled, context, runs, constructs);
93
95
  }
94
96
  }
95
97
  function appendImageFallback(element, style, context, runs) {
@@ -1,2 +1,2 @@
1
- import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "../inline-YZOQY2wR.cjs";
1
+ import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "../inline-C_pkrFBl.cjs";
2
2
  export { InlineResult, buildInlineRuns, rebaseConstructs };
@@ -1,2 +1,2 @@
1
- import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "../inline-DDj6Sl3e.js";
1
+ import { n as buildInlineRuns, r as rebaseConstructs, t as InlineResult } from "../inline-B0FFnyYJ.js";
2
2
  export { InlineResult, buildInlineRuns, rebaseConstructs };
@@ -22,9 +22,16 @@ function styledRun(text, style, hyperlink) {
22
22
  if (style.underline === true) run.underline = true;
23
23
  if (style.strike === true) run.strike = true;
24
24
  if (style.fontFamily !== void 0) run.fontFamily = style.fontFamily;
25
+ if (style.verticalAlign !== void 0) run.verticalAlign = style.verticalAlign;
26
+ if (style.direction !== void 0) run.direction = style.direction;
25
27
  if (hyperlink !== void 0) run.hyperlink = hyperlink;
26
28
  return run;
27
29
  }
30
+ function withDirStyle(element, style) {
31
+ const dir = attrValue(element, "dir");
32
+ if (dir === "ltr" || dir === "rtl") return mergeStyle(style, { direction: dir });
33
+ return style;
34
+ }
28
35
  function buildInlineRuns(nodes, style, context) {
29
36
  const runs = [];
30
37
  const constructs = [];
@@ -47,48 +54,43 @@ function appendElement(element, style, context, runs, constructs) {
47
54
  reportInertElementSkip(element.tag, context);
48
55
  return;
49
56
  }
57
+ const styled = withDirStyle(element, style);
50
58
  switch (element.tag) {
51
59
  case "strong":
52
60
  case "b":
53
- appendNested(element, mergeStyle(style, { bold: true }), context, runs, constructs);
61
+ appendNested(element, mergeStyle(styled, { bold: true }), context, runs, constructs);
54
62
  return;
55
63
  case "em":
56
64
  case "i":
57
- appendNested(element, mergeStyle(style, { italic: true }), context, runs, constructs);
65
+ appendNested(element, mergeStyle(styled, { italic: true }), context, runs, constructs);
58
66
  return;
59
67
  case "u":
60
- appendNested(element, mergeStyle(style, { underline: true }), context, runs, constructs);
68
+ appendNested(element, mergeStyle(styled, { underline: true }), context, runs, constructs);
61
69
  return;
62
70
  case "s":
63
71
  case "strike":
64
72
  case "del":
65
- appendNested(element, mergeStyle(style, { strike: true }), context, runs, constructs);
73
+ appendNested(element, mergeStyle(styled, { strike: true }), context, runs, constructs);
66
74
  return;
67
75
  case "code":
68
76
  case "kbd":
69
77
  case "samp":
70
- appendNested(element, mergeStyle(style, { fontFamily: MONOSPACE_FONT_FAMILY }), context, runs, constructs);
78
+ appendNested(element, mergeStyle(styled, { fontFamily: MONOSPACE_FONT_FAMILY }), context, runs, constructs);
71
79
  return;
72
80
  case "sub":
73
81
  case "sup":
74
- context.sink({
75
- code: EpubDiagnosticCodes.ELEMENT_UNMAPPED,
76
- severity: "info",
77
- message: `<${element.tag}> has no document-schema.js run-level field to carry its vertical position; the text is kept, the styling is not`,
78
- href: context.sourceHref
79
- });
80
- appendNested(element, style, context, runs, constructs);
82
+ appendNested(element, mergeStyle(styled, { verticalAlign: element.tag === "sup" ? "superscript" : "subscript" }), context, runs, constructs);
81
83
  return;
82
84
  case "br":
83
- runs.push(styledRun("\n", style));
85
+ runs.push(styledRun("\n", styled));
84
86
  return;
85
87
  case "a":
86
- appendAnchor(element, style, context, runs, constructs);
88
+ appendAnchor(element, styled, context, runs, constructs);
87
89
  return;
88
90
  case "img":
89
- appendImageFallback(element, style, context, runs);
91
+ appendImageFallback(element, styled, context, runs);
90
92
  return;
91
- default: appendNested(element, style, context, runs, constructs);
93
+ default: appendNested(element, styled, context, runs, constructs);
92
94
  }
93
95
  }
94
96
  function appendImageFallback(element, style, context, runs) {
@@ -40,6 +40,14 @@ function withExtraIndent(state, pt) {
40
40
  extraIndentPt: state.extraIndentPt + pt
41
41
  };
42
42
  }
43
+ function withDirection(state, element) {
44
+ const dir = require_xml_query.attrValue(element, "dir");
45
+ if (dir === "ltr" || dir === "rtl") return {
46
+ ...state,
47
+ direction: dir
48
+ };
49
+ return state;
50
+ }
43
51
  function withListItem(state, listItem) {
44
52
  return {
45
53
  ...state,
@@ -72,6 +80,10 @@ function decorateParagraph(paragraph, state) {
72
80
  list: membership
73
81
  };
74
82
  }
83
+ if (state.direction !== void 0) decorated = {
84
+ ...decorated,
85
+ direction: state.direction
86
+ };
75
87
  return decorated;
76
88
  }
77
89
  function constructsField(inline) {
@@ -168,10 +180,11 @@ function readXhtmlBody(xml, options) {
168
180
  extraIndentPt: 0,
169
181
  listItem: void 0,
170
182
  list: void 0,
171
- contentWidthPt: options.contentWidthPt
183
+ contentWidthPt: options.contentWidthPt,
184
+ direction: void 0
172
185
  };
173
186
  return {
174
- blocks: readContainerChildren(body.children, state),
187
+ blocks: readContainerChildren(body.children, withDirection(state, body)),
175
188
  source: readStyleResidue(html, context)
176
189
  };
177
190
  }
@@ -231,7 +244,7 @@ function headingLevelOf(tag) {
231
244
  }
232
245
  function readBlockElement(element, state) {
233
246
  const id = require_xml_query.attrValue(element, "id");
234
- const blocks = readBlockElementInner(element, state);
247
+ const blocks = readBlockElementInner(element, withDirection(state, element));
235
248
  if (id === void 0) return blocks;
236
249
  const target = state.context.anchorTargets.get(id);
237
250
  if (target === void 0 || require_xhtml_footnote.isFootnoteAside(element)) return blocks;
@@ -440,7 +453,7 @@ function readList(element, state) {
440
453
  level,
441
454
  itemId: state.minter.mintItemId()
442
455
  };
443
- blocks.push(...readContainerChildren(child.children, withListItem(state, previousItem)));
456
+ blocks.push(...readContainerChildren(child.children, withListItem(withDirection(state, child), previousItem)));
444
457
  continue;
445
458
  }
446
459
  if (child.type === "element" && require_xhtml_context.isInertElement(child.tag)) {
@@ -480,12 +493,12 @@ function readDefinitionListEntries(nodes, state) {
480
493
  for (const child of nodes) {
481
494
  if (child.type === "element" && child.tag === "dt") {
482
495
  flushStray();
483
- blocks.push(...readContainerChildren(child.children, state));
496
+ blocks.push(...readContainerChildren(child.children, withDirection(state, child)));
484
497
  continue;
485
498
  }
486
499
  if (child.type === "element" && child.tag === "dd") {
487
500
  flushStray();
488
- blocks.push(...readContainerChildren(child.children, withExtraIndent(state, 36)));
501
+ blocks.push(...readContainerChildren(child.children, withExtraIndent(withDirection(state, child), 36)));
489
502
  continue;
490
503
  }
491
504
  if (child.type === "element" && child.tag === "div") {
@@ -558,7 +571,7 @@ function readTable(element, state) {
558
571
  if (cellNode.type === "element" && (cellNode.tag === "td" || cellNode.tag === "th")) {
559
572
  flushStrayCell();
560
573
  const cellStyle = cellNode.tag === "th" ? { bold: true } : {};
561
- const cellBlocks = readContainerChildren(cellNode.children, state, cellStyle);
574
+ const cellBlocks = readContainerChildren(cellNode.children, withDirection(state, cellNode), cellStyle);
562
575
  const colSpan = positiveIntAttr(cellNode, "colspan");
563
576
  const rowSpan = positiveIntAttr(cellNode, "rowspan");
564
577
  cells.push({
@@ -592,7 +605,7 @@ function readTable(element, state) {
592
605
  rows,
593
606
  columnWidthsPt: new Array(Math.max(columnCount, 1)).fill(width)
594
607
  };
595
- const captionBlocks = captionElements.flatMap((captionElement, index) => readTableCaption(captionElement, index > 0, state));
608
+ const captionBlocks = captionElements.flatMap((captionElement, index) => readTableCaption(captionElement, index > 0, withDirection(state, captionElement)));
596
609
  return [
597
610
  ...strayBlocks,
598
611
  ...captionBlocks,
@@ -1,2 +1,2 @@
1
- import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "../read-BMGq_D9y.cjs";
1
+ import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "../read-AZmpNjIa.cjs";
2
2
  export { BLOCK_LEVEL_TAGS, ReadXhtmlBodyOptions, ReadXhtmlBodyResult, XhtmlAnchorScan, readXhtmlBody, scanXhtmlAnchors };
@@ -1,2 +1,2 @@
1
- import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "../read-Czqr3aop.js";
1
+ import { a as readXhtmlBody, i as XhtmlAnchorScan, n as ReadXhtmlBodyOptions, o as scanXhtmlAnchors, r as ReadXhtmlBodyResult, t as BLOCK_LEVEL_TAGS } from "../read-51pAwb-0.js";
2
2
  export { BLOCK_LEVEL_TAGS, ReadXhtmlBodyOptions, ReadXhtmlBodyResult, XhtmlAnchorScan, readXhtmlBody, scanXhtmlAnchors };
@@ -39,6 +39,14 @@ function withExtraIndent(state, pt) {
39
39
  extraIndentPt: state.extraIndentPt + pt
40
40
  };
41
41
  }
42
+ function withDirection(state, element) {
43
+ const dir = attrValue(element, "dir");
44
+ if (dir === "ltr" || dir === "rtl") return {
45
+ ...state,
46
+ direction: dir
47
+ };
48
+ return state;
49
+ }
42
50
  function withListItem(state, listItem) {
43
51
  return {
44
52
  ...state,
@@ -71,6 +79,10 @@ function decorateParagraph(paragraph, state) {
71
79
  list: membership
72
80
  };
73
81
  }
82
+ if (state.direction !== void 0) decorated = {
83
+ ...decorated,
84
+ direction: state.direction
85
+ };
74
86
  return decorated;
75
87
  }
76
88
  function constructsField(inline) {
@@ -167,10 +179,11 @@ function readXhtmlBody(xml, options) {
167
179
  extraIndentPt: 0,
168
180
  listItem: void 0,
169
181
  list: void 0,
170
- contentWidthPt: options.contentWidthPt
182
+ contentWidthPt: options.contentWidthPt,
183
+ direction: void 0
171
184
  };
172
185
  return {
173
- blocks: readContainerChildren(body.children, state),
186
+ blocks: readContainerChildren(body.children, withDirection(state, body)),
174
187
  source: readStyleResidue(html, context)
175
188
  };
176
189
  }
@@ -230,7 +243,7 @@ function headingLevelOf(tag) {
230
243
  }
231
244
  function readBlockElement(element, state) {
232
245
  const id = attrValue(element, "id");
233
- const blocks = readBlockElementInner(element, state);
246
+ const blocks = readBlockElementInner(element, withDirection(state, element));
234
247
  if (id === void 0) return blocks;
235
248
  const target = state.context.anchorTargets.get(id);
236
249
  if (target === void 0 || isFootnoteAside(element)) return blocks;
@@ -439,7 +452,7 @@ function readList(element, state) {
439
452
  level,
440
453
  itemId: state.minter.mintItemId()
441
454
  };
442
- blocks.push(...readContainerChildren(child.children, withListItem(state, previousItem)));
455
+ blocks.push(...readContainerChildren(child.children, withListItem(withDirection(state, child), previousItem)));
443
456
  continue;
444
457
  }
445
458
  if (child.type === "element" && isInertElement(child.tag)) {
@@ -479,12 +492,12 @@ function readDefinitionListEntries(nodes, state) {
479
492
  for (const child of nodes) {
480
493
  if (child.type === "element" && child.tag === "dt") {
481
494
  flushStray();
482
- blocks.push(...readContainerChildren(child.children, state));
495
+ blocks.push(...readContainerChildren(child.children, withDirection(state, child)));
483
496
  continue;
484
497
  }
485
498
  if (child.type === "element" && child.tag === "dd") {
486
499
  flushStray();
487
- blocks.push(...readContainerChildren(child.children, withExtraIndent(state, 36)));
500
+ blocks.push(...readContainerChildren(child.children, withExtraIndent(withDirection(state, child), 36)));
488
501
  continue;
489
502
  }
490
503
  if (child.type === "element" && child.tag === "div") {
@@ -557,7 +570,7 @@ function readTable(element, state) {
557
570
  if (cellNode.type === "element" && (cellNode.tag === "td" || cellNode.tag === "th")) {
558
571
  flushStrayCell();
559
572
  const cellStyle = cellNode.tag === "th" ? { bold: true } : {};
560
- const cellBlocks = readContainerChildren(cellNode.children, state, cellStyle);
573
+ const cellBlocks = readContainerChildren(cellNode.children, withDirection(state, cellNode), cellStyle);
561
574
  const colSpan = positiveIntAttr(cellNode, "colspan");
562
575
  const rowSpan = positiveIntAttr(cellNode, "rowspan");
563
576
  cells.push({
@@ -591,7 +604,7 @@ function readTable(element, state) {
591
604
  rows,
592
605
  columnWidthsPt: new Array(Math.max(columnCount, 1)).fill(width)
593
606
  };
594
- const captionBlocks = captionElements.flatMap((captionElement, index) => readTableCaption(captionElement, index > 0, state));
607
+ const captionBlocks = captionElements.flatMap((captionElement, index) => readTableCaption(captionElement, index > 0, withDirection(state, captionElement)));
595
608
  return [
596
609
  ...strayBlocks,
597
610
  ...captionBlocks,
@@ -67,7 +67,7 @@ function writeSectionChild(child, context) {
67
67
  }
68
68
  function writeHeading(group, context) {
69
69
  const level = Math.min(6, Math.max(1, group.node.headingLevel));
70
- return element(`h${String(level)}`, {}, writeRunsToNodes(group.node.runs, group.node.constructs, context));
70
+ return element(`h${String(level)}`, directionAttrs(group.node), writeRunsToNodes(group.node.runs, group.node.constructs, context));
71
71
  }
72
72
  function writeList(items, context) {
73
73
  const numId = items[0]?.node.list.numId;
@@ -144,19 +144,23 @@ function isPreBlockParagraph(paragraph) {
144
144
  function isHorizontalRuleParagraph(paragraph) {
145
145
  return paragraph.styleId === "HorizontalRule" && paragraph.runs.length === 0;
146
146
  }
147
+ function directionAttrs(paragraph) {
148
+ return paragraph.direction === void 0 ? {} : { dir: paragraph.direction };
149
+ }
147
150
  function writePreElement(paragraph, context) {
148
- return element("pre", {}, [element("code", paragraph.codeLanguage === void 0 ? {} : { class: `language-${paragraph.codeLanguage}` }, writePreRunsToNodes(paragraph.runs, paragraph.constructs, context))]);
151
+ const codeAttrs = paragraph.codeLanguage === void 0 ? {} : { class: `language-${paragraph.codeLanguage}` };
152
+ return element("pre", directionAttrs(paragraph), [element("code", codeAttrs, writePreRunsToNodes(paragraph.runs, paragraph.constructs, context))]);
149
153
  }
150
154
  function writeParagraph(paragraph, context) {
151
155
  if (isHorizontalRuleParagraph(paragraph)) return element("hr");
152
156
  if (isPreBlockParagraph(paragraph)) return writePreElement(paragraph, context);
153
- return element("p", {}, writeRunsToNodes(paragraph.runs, paragraph.constructs, context));
157
+ return element("p", directionAttrs(paragraph), writeRunsToNodes(paragraph.runs, paragraph.constructs, context));
154
158
  }
155
159
  function writeParagraphAsEmbeddedNodes(paragraph, context, wrapOrdinaryInParagraph) {
156
160
  if (isHorizontalRuleParagraph(paragraph)) return [element("hr")];
157
161
  if (isPreBlockParagraph(paragraph)) return [writePreElement(paragraph, context)];
158
162
  const runNodes = writeRunsToNodes(paragraph.runs, paragraph.constructs, context);
159
- return wrapOrdinaryInParagraph ? [element("p", {}, runNodes)] : runNodes;
163
+ return wrapOrdinaryInParagraph || paragraph.direction !== void 0 ? [element("p", directionAttrs(paragraph), runNodes)] : runNodes;
160
164
  }
161
165
  function isReferenceExtent(construct) {
162
166
  return construct.descriptor.kind === "anchor" && construct.descriptor.anchorType === "footnote" || construct.descriptor.kind === "link" && construct.descriptor.target.kind === "internal";
@@ -237,7 +241,10 @@ function writeRunNodes(run) {
237
241
  if (segment.length > 0) nodes.push(text(segment));
238
242
  });
239
243
  if (nodes.length === 0) nodes = [text("")];
244
+ if (run.direction !== void 0) nodes = [element("span", { dir: run.direction }, nodes)];
240
245
  if (run.fontFamily === "Courier New") nodes = [element("code", {}, nodes)];
246
+ if (run.verticalAlign === "superscript") nodes = [element("sup", {}, nodes)];
247
+ else if (run.verticalAlign === "subscript") nodes = [element("sub", {}, nodes)];
241
248
  if (run.bold === true) nodes = [element("strong", {}, nodes)];
242
249
  if (run.italic === true) nodes = [element("em", {}, nodes)];
243
250
  if (run.underline === true) nodes = [element("u", {}, nodes)];
@@ -66,7 +66,7 @@ function writeSectionChild(child, context) {
66
66
  }
67
67
  function writeHeading(group, context) {
68
68
  const level = Math.min(6, Math.max(1, group.node.headingLevel));
69
- return element(`h${String(level)}`, {}, writeRunsToNodes(group.node.runs, group.node.constructs, context));
69
+ return element(`h${String(level)}`, directionAttrs(group.node), writeRunsToNodes(group.node.runs, group.node.constructs, context));
70
70
  }
71
71
  function writeList(items, context) {
72
72
  const numId = items[0]?.node.list.numId;
@@ -143,19 +143,23 @@ function isPreBlockParagraph(paragraph) {
143
143
  function isHorizontalRuleParagraph(paragraph) {
144
144
  return paragraph.styleId === "HorizontalRule" && paragraph.runs.length === 0;
145
145
  }
146
+ function directionAttrs(paragraph) {
147
+ return paragraph.direction === void 0 ? {} : { dir: paragraph.direction };
148
+ }
146
149
  function writePreElement(paragraph, context) {
147
- return element("pre", {}, [element("code", paragraph.codeLanguage === void 0 ? {} : { class: `language-${paragraph.codeLanguage}` }, writePreRunsToNodes(paragraph.runs, paragraph.constructs, context))]);
150
+ const codeAttrs = paragraph.codeLanguage === void 0 ? {} : { class: `language-${paragraph.codeLanguage}` };
151
+ return element("pre", directionAttrs(paragraph), [element("code", codeAttrs, writePreRunsToNodes(paragraph.runs, paragraph.constructs, context))]);
148
152
  }
149
153
  function writeParagraph(paragraph, context) {
150
154
  if (isHorizontalRuleParagraph(paragraph)) return element("hr");
151
155
  if (isPreBlockParagraph(paragraph)) return writePreElement(paragraph, context);
152
- return element("p", {}, writeRunsToNodes(paragraph.runs, paragraph.constructs, context));
156
+ return element("p", directionAttrs(paragraph), writeRunsToNodes(paragraph.runs, paragraph.constructs, context));
153
157
  }
154
158
  function writeParagraphAsEmbeddedNodes(paragraph, context, wrapOrdinaryInParagraph) {
155
159
  if (isHorizontalRuleParagraph(paragraph)) return [element("hr")];
156
160
  if (isPreBlockParagraph(paragraph)) return [writePreElement(paragraph, context)];
157
161
  const runNodes = writeRunsToNodes(paragraph.runs, paragraph.constructs, context);
158
- return wrapOrdinaryInParagraph ? [element("p", {}, runNodes)] : runNodes;
162
+ return wrapOrdinaryInParagraph || paragraph.direction !== void 0 ? [element("p", directionAttrs(paragraph), runNodes)] : runNodes;
159
163
  }
160
164
  function isReferenceExtent(construct) {
161
165
  return construct.descriptor.kind === "anchor" && construct.descriptor.anchorType === "footnote" || construct.descriptor.kind === "link" && construct.descriptor.target.kind === "internal";
@@ -236,7 +240,10 @@ function writeRunNodes(run) {
236
240
  if (segment.length > 0) nodes.push(text(segment));
237
241
  });
238
242
  if (nodes.length === 0) nodes = [text("")];
243
+ if (run.direction !== void 0) nodes = [element("span", { dir: run.direction }, nodes)];
239
244
  if (run.fontFamily === "Courier New") nodes = [element("code", {}, nodes)];
245
+ if (run.verticalAlign === "superscript") nodes = [element("sup", {}, nodes)];
246
+ else if (run.verticalAlign === "subscript") nodes = [element("sub", {}, nodes)];
240
247
  if (run.bold === true) nodes = [element("strong", {}, nodes)];
241
248
  if (run.italic === true) nodes = [element("em", {}, nodes)];
242
249
  if (run.underline === true) nodes = [element("u", {}, nodes)];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epub-codec",
3
- "version": "1.3.9",
3
+ "version": "1.5.0",
4
4
  "description": "EPUB 2/3 reading and deterministic EPUB 3 writing against the shared document-schema.js content pivot.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -78,7 +78,7 @@
78
78
  "license": "MIT",
79
79
  "packageManager": "pnpm@11.6.0",
80
80
  "dependencies": {
81
- "document-schema.js": "7.9.1",
81
+ "document-schema.js": "7.11.0",
82
82
  "entities": "8.0.0",
83
83
  "fast-xml-parser": "5.10.1",
84
84
  "fflate": "0.8.3",