v0.14.0
Minor rather than patch, and the reason is the dependency again. epubveri
types are in this crate's public API — ChangeReport::before is an
epubveri::report::Report and fixers::plan takes one — so moving the floor
from ^0.13.2 to ^0.13.7 breaks a library consumer even though the CLI looks
unchanged. Same reasoning as 0.10.0, 0.12.0 and 0.13.0, each of which carried a
detector floor. This one goes further than tracking: it consumes
epubveri::xmlext::is_xml_blank, so the floor is load-bearing at compile time.
Two bad repairs that shipped in 0.13.0 are fixed here, both found by
whole-shelf audit rather than by any test, and both in fixers that looked
finished.
Added
-
fix.navdoc_empty_nav— an optional<nav>in the navigation document
whose<ol>holds no<li>(RSC-005/navdoc.ol.empty, error). The
whole<nav>is deleted, not just the list: leaving the<nav>behind
producesnavdoc.nav.missing_olandnavdoc.nav.not_flatin its place. A
landmarksorpage-listnav is optional, and one whose list is empty states
nothing.The finding cannot say which
<ol>it means —paramsis empty, and
epubsana never reads a finding's position — so the fixer re-derives the target
from the document. Four shapes emit the identical message and only one is
repairable, so it declines thetocnav (deleting it would author
navdoc.document.missing_toc), a list nested inside an<li>, a nav carrying
a heading, and any subtree holding anidthat a fragment link could name. A
<nav>with noepub:typeis never touched at all: its content model is
unrestricted, so the detector reports nothing about it. Each decline is an
answer the detector gave to a fixture, and each is pinned by a
mutation-checked test.Measured on 474 books: 3 proposals on 3 books, exactly the finding count,
three errors cleared, nothing authored at any severity, and one book becomes
fully valid (72 → 73). All three books are one producer's output, so the
shape is not known to generalise.
Fixed
-
fix.manifest_dangling_itemno longer deletes the wrong item when two share
anid. One book on the 474-book shelf declares two<item id="added2">—
one naming the missing font the finding is about, one naming a font the
container really holds. The lookup took the first match and deleted the
present one: the reportedRSC-001never moved, anOPF-003was authored,
and a real resource lost its only manifest declaration. The fixer now declines
when the id is not unique, because<itemref idref>and
<meta name="cover" content>are ambiguous on exactly the same book.The error count went down while the book got worse — deleting one of the
two items cleared bothduplicate id "added2"errors as a side effect — which
is why onlyregression_audit, which watches for findings that did not exist
before, could see it. -
fix.manifest_dangling_itemno longer drops an item named by a<spine>
attribute.toc(the NCX) andpage-map(Adobe's extension) both hold a
manifest id and neither is an<itemref>, so the spine walk the fixer's other
checks use cannot see them. Dropping the item named by
<spine page-map="_page_map_">clearedRSC-001and authoredOPF-063in its
place — the same trade the navigation-document guard already refuses.tocis
guarded on the argument that it is the same shape; no shelf book has a dangling
NCX item.Both defects are live in 0.13.0 on crates.io. Together the guards cost exactly
two of the fixer's eight whole-shelf proposals — the plan digest over 474
books loses those two lines and nothing else — and takeregression_auditback
to introducing nothing at any severity. -
Four sites no longer treat a NO-BREAK SPACE as emptiness.
str::trim
strips Unicode whitespace, so an element whose entire content is 
looked empty. epubcheck 5.3.0 does not agree, and epubveri stopped agreeing at
0.13.7. Two of the four sites delete on that judgement
(fix.empty_metadata_element,fix.empty_dc_date), one decides whether to
overwrite a<title>(fix.empty_title), and one decides whether to
unwrap a nested anchor — where the argument is not epubcheck parity but simply
that an NBSP is a space a reader can see.The upstream fix does not cover this, which is the part worth knowing.
fix.empty_metadata_elementdispatches per file and then re-derives every
droppable element itself, so a finding disappearing upstream does not stop the
deletion: with an NBSP-only<dc:description>beside a genuinely empty
<dc:source>, epubveri reports only the second and epubsana dropped both.All four now read
epubveri::xmlext::is_xml_blank, rather than a local copy,
so the family has one spelling for "is this element empty". Verified by
fixture, because no book on the 474-book shelf holds the shape — the
whole-shelf plan digest is byte-identical across the change.
Changed
- The epubveri floor is
0.13.7(from0.13.2, five upstream releases).
Through 0.13.6 this was tracking only: no source change was needed, and both
the whole-shelf plan digest and the wholerule_censusare byte-identical
across that boundary — none of the eleven false positives 0.13.3 closed had a
population on this shelf. 0.13.7 is a correctness floor, and the first that
is also an API floor: the NBSP predicate above is consumed from it.
Full notes: CHANGELOG.md. Also on crates.io.