Skip to content

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 07 Aug 11:01
· 12 commits to main since this release

Two fixers, twenty-five to twenty-six, and the epubveri 0.9.9 bump. Measured
on the shared shelf — which grew to 115 books the same week — errors fall
6220 → 4475 over the 25 books epubsana touches, 5 books reach fully
valid, and both whole-shelf instruments report nothing introduced anywhere.

The release's own lesson is in the second fixer: reference_missing_resource was
investigated on 2026-08-06, found to be nine unrepairable bare hostnames, and
written off as human-only. The shelf grew, the new books carried a different
shape entirely, and a fixer shipped for it a day later with the detector
unchanged. A rule closed as unrepairable is closed for that corpus, not for
good
— recorded in docs/COVERAGE.md with the habit it argues for.

Added

  • A fixer for a reference whose path is stale but whose target is still in the
    book
    (opf.content_document.reference_missing_resource) — and the reason it
    exists is that a rule closed as unrepairable is not closed for good. On
    2026-08-06 all nine findings on the 94-book shelf were scheme-less bare
    hostnames or placeholder junk, so this rule was written off as human-only. The
    shelf grew to 115 books and brought a different shape entirely: a real internal
    link left behind by a restructured book —

    1/Bolum013.xhtml links to  ../Text/DiPNOTLAR.xhtml#a8
    the file actually lives at 1/DiPNOTLAR.xhtml
    

    The path portion is repointed at the entry that carries the name, expressed
    relative to the referring document, and the fragment is carried across
    untouched
    . It is determinate because exactly one container entry has that
    basename, so the target is not chosen from a set.

    The fragment does double duty. Repointing could have traded this finding for
    a dangling RSC-012, so the fragment must already exist in the chosen target
    before anything is proposed — and that check is also evidence, since a
    same-named file that merely happened to be elsewhere would not carry #a8. All
    24 repairable cases pass it, and the shelf run introduces no RSC-012.

    Declined: a basename matching nothing (the file is genuinely absent) or several
    entries, an external URL, a bare hostname, placeholder junk, a percent-encoded
    path, and a reference not visible as a quoted attribute value.

    Measured: 36 findings across 8 books, of which 24 in 3 books are the
    repairable shape and clear completely.

  • A fixer for a duplicate id in a content document
    (opf.content_document.duplicate_id). The first occurrence in document order
    keeps the id; every later one is renamed to a unique value.

    No reference is rewritten, and the reason is the fixer's whole argument.
    Content-document ids are reference targets — unlike the NCX ids of the
    sibling fixer — so "rename and touch nothing else" needed justifying rather
    than asserting. It holds because a fragment into a document with a duplicated
    id already resolves to the first element in tree order carrying it, which
    is what every conforming processor does and what a reader has been seeing.
    Keeping the first therefore leaves every #fragment pointing at exactly the
    element it already pointed at; renaming the first and moving references would
    be the riskier repair for no gain.

    Disjoint from the invalid-id fixer by construction: that one renames an id it
    can prove occurs exactly once and declines a duplicated one, because which
    element a reference meant would then be a guess. Where a value is both
    duplicated and not a valid NCName, the new names are built from the sanitized
    stem, so the repair cannot manufacture more invalid names than it found.

    Measured: 53 findings across 21 distinct ids in one book, ids repeating
    two to four times each, and none of them referenced anywhere in its book
    so the reasoning carries this fixer, not the corpus. All 53 clear; both
    whole-shelf instruments report nothing introduced.

Changed

  • Tracks epubveri 0.9.9 (from 0.9.7). Two releases, zero source change,
    all tests green — the rule/params contract held again. Re-measured on the
    shared shelf, which grew the same week: 115 books (was 94), errors
    6220 → 4552 over the 25 books epubsana touches, 5 books taken from
    invalid to fully valid, 1,668 findings cleared, and nothing introduced
    by either whole-shelf instrument. Two fixers fired on real books for the first
    time — fix.manifest_dangling_item and fix.mimetype_packaging — because the
    new books exercise them, not because anything changed here.

    The dependency floor stays at 0.9.7, per the tracking policy: it is a
    correctness floor, and nothing in 0.9.8/0.9.9 makes an older detector cause
    epubsana to repair something wrongly. The caret picks the newer one up anyway.

    What moved upstream, and what it meant here:

    • epubveri #66 landed in full, ARIA included. EPUB 2 documents no longer
      accept 195 global attributes — event handlers, RDFa, microdata, ITS, and now
      role plus all 47 aria-*. This is the tightening epubsana cited on
      2026-08-06 as one of three reasons not to build an
      HTML5-element-downgrade fixer. The forecast is now fact: that surface would
      today include stripping ARIA from books where it was retrofitted for
      accessibility. The decision stands, and is recorded with its evidence in
      docs/COVERAGE.md.
    • New lettered message IDs (OPF-004af, OPF-007ac, RSC-006b,
      RSC-007w, HTM_060a/b). Audited: every rule epubsana consumes still
      maps to exactly one id on the shelf
      , so no fixer publishes a wrong code.
      Worth keeping in view, because 23 of 24 fixers assert their addresses_id
      rather than inheriting it from the finding — correct today, and the reason
      the spine-duplicate fixer is the one exception is that its condition really
      does arrive under two ids.
    • RSC-026 now fires on any reference that escapes the container root, not
      only manifest hrefs, and is additive with the missing-resource rules. On the
      shelf that is one book, 8 findings, all css.font_face.leaks_container_root
      — a stylesheet at the container root asking for url(../Fonts/…). No fixer
      of ours is keyed on it and none collides with it.
    • Smaller upstream corrections that change what a repairer sees but ask nothing
      of it: an obsolete attribute is no longer reported twice, RSC-025 no longer
      fires on EPUB 2 at all, an empty dc:identifier no longer cascades into three
      extra findings, and epub:trigger is accepted.

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