Skip to content

v0.15.0

Latest

Choose a tag to compare

@github-actions github-actions released this 12 Sep 11:36
· 1 commit to main since this release

Added

  • fix.fragment_wrong_path — a link whose #fragment is real but has moved
    to another document
    (RSC-012 / opf.content_document.dangling_fragment,
    ConfirmNeeded). If exactly one document in the book defines that anchor, the
    path is written in front of the fragment, relative to the referring document;
    where the anchor turns out to be in the referring document itself, the link
    becomes a plain same-document #fragment.

    On real books this is an editor splitting a file at a page break and leaving a
    footnote link and its return link as bare fragments pointing into the wrong
    half. Third member of the family beside fix.reference_wrong_path and
    fix.ncx_src_wrong_path, sharing their machinery and their discipline:
    exactly one answer, or decline.

    It declines an anchor defined in several documents (which one the link meant
    is a guess), an anchor defined nowhere (only "drop the fragment" is available,
    and that loses the author's target), a target outside the reading order, and a
    reference not visible as a whole quoted attribute value.

  • --format json's summary reports every counter it has a concept of.
    Seven fields appear: proposed, and warnings_before/warnings_after,
    infos_before/infos_after, usages_before/usages_after.

    Under --dry-run the summary used to say applied: 0, skipped: 0 while every
    item carried "outcome": "proposed" — so the summary and the items disagreed
    about the size of the run, and a consumer asking the summary how many fixes
    there were got zero while two sat in items. Every number was true and the
    document misled. The identity a consumer may now rely on is
    applied + skipped + proposed == items.len().

    The severity counters are the same defect one field over. Three fixers here
    dispatch on usage or warning findings, so a run can clear real work while
    errors_before/errors_after do not move at all — and the summary described
    that as no change whatsoever. reverted stays absent rather than zero: a build
    that cannot revert has no concept of the value, and 0 would claim no revert
    happened where the truth is that none could.

    The wasm binding's Summary gains the same seven fields, its skipped
    remaining zero because the browser never declines.

Changed

  • The envelope claims convention 0.5. The stability key is an assertion
    about this crate, not about its detector: it moves when epubsana implements a
    convention release, and the seven counters above are that release.

  • fix.non_preferred_media_type takes the replacement from the finding
    instead of from a table of its own.
    epubveri has named the preferred media
    type in params[1] since 0.12.3; this crate went on consulting a five-row
    table written before that existed, which made it a second answer to a question
    the detector was already answering.

    It closes a hole the table could not see. Where epubveri declines to name a
    replacement — because the resource's own signature rules the candidate out, an
    OTTO (CFF) font declared application/x-font-ttf being the shape — a
    table-driven fixer renamed it anyway. No book on the 474-book shelf carries
    that shape (121 application/vnd.ms-opentype + 285 application/x-font-ttf
    declarations, none contradicted by its own bytes), so this closes a hole
    rather than repairing damage.

    Two declines are new and deliberate: a finding that names no replacement, and
    two findings about one declared type that name different replacements —
    which epubveri 0.14.1 can now legitimately produce for
    application/font-sfnt, because it answers that row from each file's own
    signature. The fix renames per declared type across a manifest, so it cannot
    honour both and proposes neither.

  • application/font-sfnt is now repaired where the detector decides it. It
    was declined outright because SFNT is the container TrueType and OpenType
    share and EPUB 3.3 lists the spelling on both rows — the name cannot say
    which the file is. epubveri 0.14.1 answers it from the font's own signature
    (only font/otf admits OTTO), on its side of the boundary, where deciding
    what the defect is belongs. This crate still never opens a font. Zero books on
    the shelf carry the spelling, so nothing here moves today.

  • The envelope states epubsana's own convention version. epubveri 0.13.x
    hard-coded its own key into every envelope built through
    Envelope::for_tool, so this crate's --format json was claiming epubveri's
    convention version; it happened to be right, both being v0.4. 0.14.0 made
    the key a required parameter. epubsana claims "0.4" and will move it
    when it implements v0.5.0, not when its dependency does. No output changes.

Dependencies

  • epubveri floor raised to 0.14 (from 0.13.7) — a capability floor: the
    params contract the OPF-090 fixer now reads (an absent params[1] meaning
    decline, and only a real media type ever appearing in it) does not exist
    below it. Measured across the boundary on 474 books: the whole-shelf plan
    digest and the entire regression audit are byte-identical — 194 books planned,
    2,337 proposals, errors 40,584 → 15,719, 73 books fully valid, zero
    regressions at any severity.

Documentation

  • fix.navdoc_empty_nav's safety argument was overstated in 0.14.0 and is
    corrected.
    That entry says the finding cannot say which <ol> it means. Only
    params cannot: navdoc.ol.empty is emitted with an element_path, which on
    every shelf book names the exact node. The fixer does not read it — a choice,
    not an absence.

    What actually makes its file dispatch safe is a subset property: for a
    typed <nav> whose single element child is an <ol>, epubveri always reaches
    the check that reports an empty list, so every node this fixer selects is one
    epubveri reported. No code changed and no behaviour was wrong; the reasoning
    was, and it is the reasoning a future session would rely on.

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