Skip to content

v0.9.18

Latest

Choose a tag to compare

@github-actions github-actions released this 14 Aug 08:42
· 2 commits to main since this release

A false-positive release: four fixes, none of which the corpus or the shelf
could see on its own, and each of the last three found while verifying the
one before it.

text/html is a media type Calibre emits and epubcheck has always treated as
a deprecated content type: it warns once and then goes on validating the
document. We treated it as a foreign resource instead, and that single
difference cost in both directions at once — we invented errors about the
item, and skipped every check that belonged inside it.

Fixed

  • text/html items in an EPUB 2 book are content documents again (#72).
    Found by running --bin compare over ten books newly added to the shelf:
    eight agreed with epubcheck exactly and one did not. It declares
    media-type="text/html" on all 91 of its spine items, and drew 94
    findings epubcheck does not report
    — 91 OPF-043, 3 RSC-010, and an
    OPF-032 — while every reference inside those 91 documents went unchecked.
    On a minimal book the verdicts differed outright: epubcheck accepted it, we
    rejected it.

    Four things changed, each measured against epubcheck one book at a time:

    • A text/html spine item needs no fallback, so no OPF-043 — and only in
      EPUB 2
      . epubcheck's two branches genuinely differ (OPFChecker:419
      consults isDeprecatedBlessedItemType, OPFChecker30:251 does not), so
      the same book is an error at 3.0 and clean at 2.0. Likewise no RSC-010
      for an NCX or nav link pointing at one.
    • A <guide> reference to one is no longer OPF-032, but it is RSC-032.
      Replacing one with silence would have turned a wrong ID into a false
      negative: epubcheck registers guide references as GENERIC and asks the
      foreign-resource fallback question about them separately. That question
      had never been asked here, so a guide reference to a DTBook or a PDF was
      also missing its RSC-032 — both now reported.
    • The documents are parsed and their references, fragments and DOM-level
      checks run. The one real book hid 91 missing resources this way, and
      a text/html document that is not even well-formed XML used to report
      nothing at all.
    • The XHTML grammar stays off them, along with the duplicate-id and
      ID-reference checks, which belong to the same validator set in epubcheck
      (IDUNIQUE_20_SCH is keyed on application/xhtml+xml exactly as the
      grammar is). Measured: the identical document draws three RSC-005
      declared application/xhtml+xml and none declared text/html. Running
      the grammar over them anyway would have replaced 94 false positives with
      a larger number of them.
  • OPF-035 no longer depends on the file's contents, and is EPUB 2 only.
    Both halves were wrong, in opposite directions. epubcheck emits it from the
    declared media-type alone without opening the file, so a text/html item
    holding something that is not markup drew nothing from us — the one shape
    where the author most needs telling. And OPFChecker30.checkItem never
    calls super, so the message is unreachable for EPUB 3, where we were
    reporting it. It is now anchored at the manifest item in the package
    document, which is where epubcheck reports it, rather than in the content
    document.

  • A valid image in a format we did not recognise is no longer called
    corrupt
    (#75). sniff_image_type knew four formats, and anything else
    took the "unrecognised" path, which reports PKG-021 corrupt as an ERROR.
    One real book carries a valid little-endian TIFF named .png and declared
    image/png; we called it corrupt where epubcheck reports PKG-022 wrong
    file extension
    as a WARNING. It is mislabelled twice over and not corrupt
    at all. TIFF (both byte orders) and BMP are now sniffed, with the matching
    file extensions so a correctly-named file stays silent.

    The unrecognised path itself was already right and is unchanged: a file
    whose content matches nothing still draws PKG-021 from both tools, measured
    with a garbage file named .png. Only the set of formats we can name was
    too small. All six shapes now agree with epubcheck exactly — garbage,
    little- and big-endian TIFF under a .png name, TIFF under a .tif name,
    BMP, and the real book's image.

  • ID-reference resolution is EPUB 3 only (#74). We resolved
    aria-labelledby, for and their relatives against the document's own
    id values in every version and reported RSC-005 when the target was
    missing; epubcheck does this for EPUB 3 alone. Its sibling check already
    carried the version condition — this block was simply missed.

    Nothing real is lost: every attribute the block names is absent from XHTML
    1.1 (ARIA entirely, and for only via the Forms module, which OPS 2.0.1
    does not include), so in an EPUB 2 book the grammar has already rejected
    the attribute and this only added a second message about the same defect.
    The opposite direction was checked as well — headers is in XHTML 1.1
    and takes IDREFS, and a dangling headers reference draws nothing from
    epubcheck either, so there is no gap to fill.

  • An EPUB 3 dangling ID reference is reported once, not twice (#76), and
    aria-details is no longer reported at all. Two implementations of the same
    rule had always overlapped in EPUB 3; gating one of them for #74 is what
    made the overlap visible. The thinner one — existence only, none of the type
    constraints — was deleted rather than merged, because everything it covered
    is handled by the survivor except aria-details, which epubcheck does not
    check.

    Probed one book each, counting RSC-005: a dangling aria-details draws
    nothing from epubcheck, while @form, @list, label/@for and @headers
    each draw exactly one. Six of the seven shapes now agree exactly; the
    seventh is a known under-report of ours (an element carrying
    @aria-activedescendant must also declare @role, which is a grammar rule
    we do not implement).

Notes for consumers

  • opf.content_document.dangling_id_reference no longer exists. The rule
    it keyed was a duplicate of opf.content_document.idref_unresolved, which
    survives and covers every case it did (bar aria-details, a false
    positive). Nothing keyed on the removed slug can match any more — an
    allowlist naming it needs the surviving slug instead. Not in any known
    downstream consumer's rule list, and the direction is a strict reduction.
  • opf.content_document.duplicate_id no longer fires for a text/html
    document. No message, id or position moves for any other document; this is
    a strict reduction, in the direction of what epubcheck reports.
  • The OPF-035 message wording and position both changed (see above). It
    carries no rule slug, so nothing can be keyed on it today.

Full notes: CHANGELOG.md. Also on crates.io.