epub-codec 1.2.1 → 1.2.3

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
@@ -139,6 +139,7 @@ Every construct this package's XHTML mapping cannot represent losslessly is a do
139
139
  - **Image dimensions are derived from pixel size via the CSS reference-pixel ratio (1px = 1/96in)**, not read from any `<img width>`/`<img height>` attribute or CSS: an EPUB's own XHTML/CSS carries no reliable point-based sizing of its own, so the image's natural pixel size is the one dimension every manifest image reliably has.
140
140
  - **A GIF or SVG manifest image is not yet decoded** — `document-schema.js`'s `ContentImageBlockSchema` widened its `format` field to admit `"svg"`/`"gif"` alongside `"png"`/`"jpeg"` specifically for this package's own manifest image kinds, but this package's reader does not yet decode either one; it degrades to alt text with an `epub/image-format-unsupported` diagnostic until that decode work lands.
141
141
  - **A table cell's own construct-boundary marker (if a foreign producer's `ContentDocument` carries one) has no XHTML representation on write** and is dropped with a diagnostic — `document-schema.js`'s own `decompose` never descends into a table cell, so a cell's blocks are never grouped the way a section's are, and this package's own reader never emits one there either.
142
+ - **A run-level anchor extent whose `anchorType` is `bookmark`, `endnote`, or `comment` (only `footnote` is recognised) has no representable EPUB spelling this package's own reader understands yet** and is reported through `epub/construct-unrepresented` on write rather than silently dropped — genuinely reachable via a cross-format bridge, since `ooxml.js`'s own docx reader emits exactly this shape for a bookmark or `w:commentRangeStart`/`End` pair whose two halves sit inside one paragraph. The run text the extent wraps is unaffected either way; only its own marker (and, for a comment, the definitions-table link a same-format write would need) goes unwritten.
142
143
  - **`dc:publisher`/`dc:contributor`/`dc:rights` have no `LayoutMetadata` field to land in** and are reported as `epub/metadata-field-unmapped` rather than silently dropped.
143
144
 
144
145
  ## Fidelity
package/dist/codec.d.cts CHANGED
@@ -1425,10 +1425,10 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1425
1425
  endColumn: z.ZodNumber;
1426
1426
  }, z.core.$strip>>;
1427
1427
  type: z.ZodEnum<{
1428
- date: "date";
1429
- custom: "custom";
1430
1428
  decimal: "decimal";
1431
1429
  list: "list";
1430
+ date: "date";
1431
+ custom: "custom";
1432
1432
  time: "time";
1433
1433
  whole: "whole";
1434
1434
  textLength: "textLength";
package/dist/codec.d.ts CHANGED
@@ -1425,10 +1425,10 @@ declare const epubContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>,
1425
1425
  endColumn: z.ZodNumber;
1426
1426
  }, z.core.$strip>>;
1427
1427
  type: z.ZodEnum<{
1428
- date: "date";
1429
- custom: "custom";
1430
1428
  decimal: "decimal";
1431
1429
  list: "list";
1430
+ date: "date";
1431
+ custom: "custom";
1432
1432
  time: "time";
1433
1433
  whole: "whole";
1434
1434
  textLength: "textLength";
@@ -142,11 +142,23 @@ function writeParagraphAsEmbeddedNodes(paragraph, context, wrapOrdinaryInParagra
142
142
  function isFootnoteExtent(construct) {
143
143
  return construct.descriptor.kind === "anchor" && construct.descriptor.anchorType === "footnote";
144
144
  }
145
+ function reportUnhandledAnchorExtents(constructs, context) {
146
+ for (const construct of constructs ?? []) {
147
+ if (construct.descriptor.kind !== "anchor" || construct.descriptor.anchorType === "footnote") continue;
148
+ context.sink({
149
+ code: require_diagnostics.EpubDiagnosticCodes.CONSTRUCT_UNREPRESENTED,
150
+ severity: "info",
151
+ message: `a run-level '${construct.descriptor.anchorType}' anchor ('${construct.descriptor.name}') has no representable EPUB spelling this writer states yet, so its own marker is dropped -- the run text it wraps is unaffected`,
152
+ href: context.sourceHref
153
+ });
154
+ }
155
+ }
145
156
  function describeUnrepresentedFootnoteExtent(extent) {
146
157
  if (extent.endRun === extent.startRun) return `a footnote reference ('${extent.descriptor.name}') marking the boundary before run ${extent.startRun} is never reached by the write walk -- either because it sits inside another footnote reference's own winning run range, or because its own run range falls outside this paragraph's actual runs; a point anchor wraps no run text of its own, so nothing besides this reference's own <a> link is missing from the output`;
147
158
  return `a footnote reference ('${extent.descriptor.name}') is never reached by the write walk and cannot be represented as its own <a> element -- either because it overlaps another footnote reference's own winning run range, or because its own run range falls outside this paragraph's actual runs; wherever an overlap is the cause, the run text underneath it is not lost, since it is still written, wrapped by whichever extent's range actually claims it, or written unwrapped past it, but this reference's own anchor link is not emitted regardless of cause`;
148
159
  }
149
160
  function writeRunRangeNodes(runs, constructs, renderRun, renderExtentRange, context) {
161
+ reportUnhandledAnchorExtents(constructs, context);
150
162
  const footnoteExtents = (constructs ?? []).filter(isFootnoteExtent);
151
163
  const emittedExtents = /* @__PURE__ */ new Set();
152
164
  const out = [];
@@ -141,11 +141,23 @@ function writeParagraphAsEmbeddedNodes(paragraph, context, wrapOrdinaryInParagra
141
141
  function isFootnoteExtent(construct) {
142
142
  return construct.descriptor.kind === "anchor" && construct.descriptor.anchorType === "footnote";
143
143
  }
144
+ function reportUnhandledAnchorExtents(constructs, context) {
145
+ for (const construct of constructs ?? []) {
146
+ if (construct.descriptor.kind !== "anchor" || construct.descriptor.anchorType === "footnote") continue;
147
+ context.sink({
148
+ code: EpubDiagnosticCodes.CONSTRUCT_UNREPRESENTED,
149
+ severity: "info",
150
+ message: `a run-level '${construct.descriptor.anchorType}' anchor ('${construct.descriptor.name}') has no representable EPUB spelling this writer states yet, so its own marker is dropped -- the run text it wraps is unaffected`,
151
+ href: context.sourceHref
152
+ });
153
+ }
154
+ }
144
155
  function describeUnrepresentedFootnoteExtent(extent) {
145
156
  if (extent.endRun === extent.startRun) return `a footnote reference ('${extent.descriptor.name}') marking the boundary before run ${extent.startRun} is never reached by the write walk -- either because it sits inside another footnote reference's own winning run range, or because its own run range falls outside this paragraph's actual runs; a point anchor wraps no run text of its own, so nothing besides this reference's own <a> link is missing from the output`;
146
157
  return `a footnote reference ('${extent.descriptor.name}') is never reached by the write walk and cannot be represented as its own <a> element -- either because it overlaps another footnote reference's own winning run range, or because its own run range falls outside this paragraph's actual runs; wherever an overlap is the cause, the run text underneath it is not lost, since it is still written, wrapped by whichever extent's range actually claims it, or written unwrapped past it, but this reference's own anchor link is not emitted regardless of cause`;
147
158
  }
148
159
  function writeRunRangeNodes(runs, constructs, renderRun, renderExtentRange, context) {
160
+ reportUnhandledAnchorExtents(constructs, context);
149
161
  const footnoteExtents = (constructs ?? []).filter(isFootnoteExtent);
150
162
  const emittedExtents = /* @__PURE__ */ new Set();
151
163
  const out = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epub-codec",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
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": "^6.2.0",
81
+ "document-schema.js": "^6.2.1",
82
82
  "entities": "^8.0.0",
83
83
  "fast-xml-parser": "^5.10.1",
84
84
  "fflate": "^0.8.3",