v0.8.0
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.xhtmlThe 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 danglingRSC-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 noRSC-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
idin 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#fragmentpointing 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
epubveri0.9.9 (from 0.9.7). Two releases, zero source change,
all tests green — therule/paramscontract 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_itemandfix.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
roleplus all 47aria-*. 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-004a–f,OPF-007a–c,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 theiraddresses_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-026now 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, allcss.font_face.leaks_container_root
— a stylesheet at the container root asking forurl(../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-025no longer
fires on EPUB 2 at all, an emptydc:identifierno longer cascades into three
extra findings, andepub:triggeris accepted.
- epubveri #66 landed in full, ARIA included. EPUB 2 documents no longer
Full notes: CHANGELOG.md. Also on crates.io.