Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Formats > ePub

Notices

Reply
 
Thread Tools Search this Thread
Old 08-12-2026, 05:22 PM   #16
KevinH
Sigil Developer
KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.
 
Posts: 10,009
Karma: 7518950
Join Date: Nov 2009
Device: many
Quote:
Originally Posted by Kayadelenium View Post
Kevin — the FAQ is up, so you can hold me to it rather than to a forum post:

https://github.com/veripublica/epubs...CENSING-FAQ.md

Same answers as above, in writing and linkable: the books you repair are yours unconditionally, commercial use of the tool needs no commercial license, an arm's-length CLI call forms no combined work so a plugin's licence is its author's choice, and the commercial licence covers only closed-source embedding or serving a modified version over a network. It quotes both section 13 clauses exactly, including the asymmetry, rather than paraphrasing them in my favour.

It covers epubveri as well as epubsana — same licence structure, and epubveri never writes to your book at all. It says explicitly that it does not modify LICENSE, and that LICENSE governs anywhere the two could be read differently.

If a plugin author ever needs a sentence in there sharpened, or you spot wording that still leaves room to worry, say so and I will change it. It is meant to be something you can point people at without having to explain it afterwards.
Thank you for your clear answers!
KevinH is offline   Reply With Quote
Old 08-12-2026, 06:49 PM   #17
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
Doitsu — both of the things you asked for are in 0.10.0, published a few minutes ago.

Code:
cargo install epubsana
1. Your plugin no longer has to apply everything.

That it does is my fault, not a choice you made: the only non-interactive mode was -y, which approves every fix. There was no way to show someone a plan and then act on the part they picked.

There is now. --apply takes a list and approves exactly those:

Code:
$ epubsana -i book.epub --dry-run
[1] WOULD APPLY Make 1 invalid NCX id a valid XML NCName in toc.ncx
[2] WOULD APPLY Drop 25 legacy <a name> attributes in chapter-04.html
[3] WOULD APPLY Drop 19 legacy <a name> attributes in chapter-05.html

$ epubsana -i book.epub --apply 1,3
[1] APPLIED Make 1 invalid NCX id a valid XML NCName in toc.ncx
[2] SKIPPED Drop 25 legacy <a name> attributes in chapter-04.html
[3] APPLIED Drop 19 legacy <a name> attributes in chapter-05.html
A selector is a plan index or a fix id (--apply 2,fix.html_entities works). Under --format json each item now carries data.index, so you round-trip the number rather than counting items.

A selector that matches nothing fails the whole run and writes no file. Applying the half of a list that happened to match would tell you something untrue about a book you are about to hand back to someone.

The two calls only line up because planning is deterministic — same input and same epubveri version, same fixes in the same order. That is now a documented guarantee rather than something that happens to be true, because your workflow depends on it.

2. Every edit now names its file.

You were right that this was the real problem, and right about where it was: the path was already there internally and the JSON emitter was dropping it. So data.changes entries are no longer bare strings:

Code:
"changes": [
  { "path": "toc.ncx", "note": "rename NCX id \"59a835d2…\" → \"id_59a835d2…\"" }
]
Which means the set of files a run touched is one expression, and you never open the repaired EPUB to find out:

Code:
touched = {c["path"] for it in items for c in it["data"]["changes"]}
Those paths are in the --dry-run output too, so you can tell a user which files a fix would touch before anything happens.

Heads-up: this will break code that reads those strings. They used to be plain strings; each one is now an object. Read .note and you get the old string back, unchanged.

I could have left changes alone and added a second field beside it with the paths in. I did not, because a duplicate field can never be taken out again once anyone depends on it — you end up with two ways of saying one thing, permanently. Breaking it is only cheap before 1.0, so it was now or never. Sorry if it costs you an edit.

One thing to watch when copying files back. The packaging fix (PKG-006) reports "path": "mimetype", but that file's content does not change — what changes is where it sits in the ZIP and whether it is compressed. Copying mimetype across will not reproduce it. If you see that fix, either re-save the container yourself or take epubsana's own output for that book. It is the only fix in the set that behaves this way.

Also worth knowing: entries epubsana did not touch are copied through byte-for-byte — same bytes, same compression, same timestamps — so an untouched file compares equal without inflating anything. Not that you should need to compare at all now.

The per-fix unified diff is not in this release.

I am not quietly dropping it — I want you to decide. You asked for it first, but then said that for a small file you would rather replace the whole thing than apply a diff, and Kevin pointed out that Sigil Checkpoints already show a user what changed. Between those two the case for it got a lot weaker.

So: does the file list cover what you need? If it does, I would rather not build something nobody ends up using. If you still want the diffs, say so and I will put them back on the list.

There are also two new fixers in 0.10.0 (empty optional Dublin Core elements, and superseded media-type names like application/vnd.ms-opentypefont/otf). Both clear usage-severity findings, so neither makes a book valid that was not — they remove lines from an epubcheck report that describe nothing.

The full --apply documentation, with the error cases spelled out, is in docs/USAGE.md:
https://github.com/veripublica/epubs.../docs/USAGE.md

If something in the JSON is still awkward to consume, tell me — it is much easier to change now than once more than one plugin depends on it.
Kayadelenium is offline   Reply With Quote
Old 08-13-2026, 01:27 AM   #18
Doitsu
Grand Sorcerer
Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.Doitsu ought to be getting tired of karma fortunes by now.
 
Doitsu's Avatar
 
Posts: 5,917
Karma: 24240563
Join Date: Dec 2010
Device: Kindle PW2
Quote:
Originally Posted by Kayadelenium View Post
So: does the file list cover what you need? If it does, I would rather not build something nobody ends up using. If you still want the diffs, say so and I will put them back on the list.
I erroneously assumed that applying diffs might be faster than replacing whole files, but during my tests, I found out that this was not the case. As for me, the JSON file now contains all the information that I need.

I have a recommendation regarding one of the fixes.

Quote:
Originally Posted by Kayadelenium View Post
RSC-005 / empty lang — an empty lang="" / xml:lang="", which EPUB 2 doesn't allow → deleted, so the element inherits its parent's language. A malformed tag is never guessed at.
Instead of deleting the attributes, I'd suggest adding the <dc:language>...</dc:language> value if it's a valid language code.

Last edited by Doitsu; 09-07-2026 at 04:34 AM.
Doitsu is offline   Reply With Quote
Old 08-13-2026, 05:00 AM   #19
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
Doitsu — your suggestion was right, and it is in 0.11.0.

Code:
cargo install epubsana
Filling an empty lang instead of deleting it.

I measured before answering, because the answer depends entirely on which element carries the empty attribute — and it turned out to be unanimous. All 447 empty lang/xml:lang attributes on my 157-book shelf sit on the root html element. Not one on a span or a paragraph. All three affected books declare a valid dc:language.

That inverts the reasoning the fixer was built on. My own notes argued: a paragraph with lang="" inside html lang="tr" currently declares "undetermined", so deleting it makes the paragraph inherit tr — which a reading system acts on for hyphenation and text-to-speech. Sound, and about a shape that does not occur in any book I have.

On the root there is nothing to inherit from. Deleting left the document declaring no language at all. Filling it states the language the book itself states — read out of the book, not invented, exactly the way the empty-title fixer takes a title from the book's own table of contents. Those two now follow one rule instead of two.

It keeps the original spelling and quote character, so an xml:lang stays xml:lang. It falls back to deleting when the package declares no language, more than one (which is the document's root language is then editorial), an empty one, or something that is not a language tag — en_US and turkish both fail that check, and writing either would trade an invalid empty attribute for an invalid non-empty one.

Off the root it still deletes, because there an empty tag may have been an unfinished attempt to say "this part is not in the book's language", and filling it would assert the opposite.

Also in 0.11.0: a @font-face whose font file is not in the book.

The rule is dropped whole. The font cannot load and never could, so text using that family already falls back to whatever the reading system substitutes — removing a rule that never applied changes nothing a reader sees.

This one had been sitting unbuilt behind a sensible objection: a @font-face can carry several src entries, so deleting the whole rule might throw away a font that works. True in principle. Measured: every affected rule on the shelf holds exactly one url(). A rule with a second source is declined rather than half-handled, and no CSS parser was added — it finds an at-rule's braces and nothing more. The rest of the css.* family stays out of scope.

Unlike the last two fixers this one is error severity, so it moves the validity line: one book on my shelf goes from invalid to fully valid, and the deleted rules take 8 leaks-outside-the-container errors with them.

And I closed the diff issue (#8), quoting your test result as the reason. #7 — the speculative-apply groundwork — stays open, but on its own merit now: per-fix rollback, which this tool owes regardless of whether anything ever renders a diff.

Thank you for the suggestion. It is the first time someone has looked at what a fixer does and told me it was doing the wrong thing, which is more useful than a bug report — a bug I would have found eventually.
Kayadelenium is offline   Reply With Quote
Old 08-22-2026, 02:46 PM   #20
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
epubsana 0.12.0 is out — crates.io, npm, prebuilt binaries, and the in-browser demo. The first thing in it is a repair that was wrong, so that goes first.

A bad repair, shipped in 0.11.0 and fixed in 0.12.0

If you ran 0.11.0 on an EPUB 2 book, fix.content_properties could write properties="remote-resources" onto a manifest item in a version="2.0" package. That attribute does not exist in OPS 2.0.1. It cleared a real OPF-014 and authored an RSC-005 in its place.

Three things about it are worth more than the fix itself:
- The chain was correct at every step. epubveri 0.9.20 widened its remote-URL test to match epubcheck's, which made Calibre's url(res:///system/fonts/...) remote and raised a genuine OPF-014. Nothing upstream was wrong. What was wrong is that EPUB 2 has nowhere to record the answer.
- Two of our own fixers were undoing each other. fix.epub3_attr_in_epub2_package exists to remove exactly the attribute the other one was adding. Neither read the package version.
- The book's error count was identical before and after. A real finding traded for an authored one, at net zero. Any instrument watching totals would have called that a success. It was caught by re-running every fix across a shelf of real books and diffing per book, which is the only thing that could have seen it. No unit test could.

0.12.0 declines instead. On an EPUB 2 package there is no correct edit — the defect is real, and the only honest repair available is to leave it alone and say so.
Kayadelenium is offline   Reply With Quote
Old 09-09-2026, 03:09 PM   #21
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
epubsana 0.14.0 — and an invitation to point it at a book you know.

https://github.com/veripublica/epubs...es/tag/v0.14.0

Most of what epubveri gets right, it owes to people in these forums running it on real books and saying what looked wrong. epubsana is the other half of that pair — it repairs what epubveri reports — and it has had far less of that attention. This post is mainly an invitation to change that, and it is genuinely low-risk to accept.

Your original file is never touched

epubsana never edits a book in place. It writes a repaired copy next to the input as name_fixed.epub, and it will not overwrite anything without an explicit flag. Every fix is proposed to you first, one at a time, with a plain description of what it would change; you approve or decline each one, and the run ends with a report of exactly what was done.

The easiest way to try it takes about a minute
  • Open https://veripublica.github.io/epubsana/ and load a book. Nothing is uploaded — it is WebAssembly running inside your browser, and the file never leaves the page.
  • Look at what it proposes and approve what you like. You get a repaired copy back; your own file is untouched either way.
  • Then check the result the way you would check anyone's work — run epubveri or epubcheck over it, or just open it in Sigil or calibre and see whether it looks and behaves the way it should.

That last step is the one that matters most to me, and it is why your eye is worth more here than mine. epubsana verifies its own repairs with epubveri, which means it is structurally blind to any damage epubveri cannot see. If a repair leaves a book worse in a way that still validates, nothing in my toolchain will notice. Someone opening the book has to say so.

What it is for

Not editing — it is not an editor and is not trying to become one. It is for the mechanical, repetitive part: the same small correction made forty times across a book, the kind that is tedious rather than interesting. The idea is that it clears those before you open the book in Sigil or calibre, so what is left in front of you is the part that actually needs judgement. It repairs only what has exactly one correct answer, and reports the rest untouched rather than guessing.

What is new in 0.14.0

One new fixer, thirty-six in total: an optional nav in the navigation document whose list is empty — the empty landmarks nav some tools leave behind. The whole nav element goes, not just the list, because a nav without an ol is itself invalid.

What it declines is the more useful half, since the same message appears in four different situations: the toc nav is never touched (deleting it would cost you the table of contents), nor a list nested inside an li, nor a nav carrying a heading, nor anything with an id that something else might link to.

Two repairs that were wrong, found and fixed

I would rather you heard this from me than found it yourself. Two repairs in 0.13.0 were wrong, both in the fixer that drops a manifest item whose file is missing:
  • When two manifest items shared an id, it could delete the wrong one — removing the declaration of a font the book actually contains. What made it hard to see is that the book's error count went down, so anything watching totals would have called it an improvement.
  • When a spine attribute named the item, dropping it traded one error for another rather than fixing anything.

Separately, an element whose entire content was a single no-break space looked empty to four places in epubsana, because Rust's standard trim treats it as whitespace and epubcheck does not. Two of those four delete on that judgement and one overwrites, so a description or a chapter title deliberately holding one could have been dropped or replaced. epubveri found this was four sites and not the two I had reported to it, and fixed its own half in 0.13.7.

All of it is fixed in 0.14.0. I mention it because a repair tool that only tells you about its wins is not worth pointing at your library — and because every one of these was caught by re-running each fix over a shelf of books and diffing the result, which is exactly the check that cannot catch the class a human would spot in a second.

On the pace, since epubveri is moving faster

epubveri has had several releases and now has Sigil and calibre plugins; epubsana has not kept up, and that is deliberate rather than neglect. A repair can only be as good as the detection behind it — if the detector reports something that is not really wrong, a repairer will faithfully "fix" a book that was fine, and that has happened here more than once. So epubveri goes first and gets the finding exactly right, and epubsana follows.

When epubveri settles into maintenance, I expect epubsana to get the same treatment the plugins gave it: repairs offered from inside the editor you already use, instead of a separate step. No timeline promised — I would rather land it correctly than quickly.

Until then, the browser page is the whole of what you need to try it, and a report that a repair looked wrong is worth more to this project than any feature request.

crates.io: https://crates.io/crates/epubsana — command-line and prebuilt binaries for Windows, macOS and Linux are on the releases page.
Kayadelenium is offline   Reply With Quote
Old 09-10-2026, 02:17 PM   #22
JSWolf
Resident Curmudgeon
JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.
 
JSWolf's Avatar
 
Posts: 84,866
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
I've found an error in epubsana.

This is the original OPF. Look at the fonts.
Code:
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="eisbn" version="3.0" xml:lang="en-us">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<meta content="cover-image" name="cover"/>
<dc:title id="t1">To Defy Fate</dc:title>
<meta property="title-type" refines="#t1">main</meta>
<dc:creator id="creator01">Dayton Ward</dc:creator>
<meta property="role" refines="#creator01" scheme="marc:relators">aut</meta>
<dc:publisher>Pocket Books/Star Trek</dc:publisher>
<dc:identifier id="eisbn">9781668097816</dc:identifier>
<meta property="pageBreakSource">9781668097793</meta>
<dc:language>EN-US</dc:language>
<dc:date>2026-04-28</dc:date>
<meta property="dcterms:modified">2026-04-28T12:00:00Z</meta>
<meta property="schema:accessMode">textual</meta>
<meta property="schema:accessModeSufficient">textual</meta>
<meta property="schema:accessibilityFeature">ARIA</meta>
<meta property="schema:accessibilityFeature">alternativeText</meta>
<meta property="schema:accessibilityFeature">displayTransformability</meta>
<meta property="schema:accessibilityFeature">readingOrder</meta>
<meta property="schema:accessibilityFeature">structuralNavigation</meta>
<meta property="schema:accessibilityFeature">tableOfContents</meta>
<meta property="schema:accessibilityFeature">pageBreakMarkers</meta>
<meta property="schema:accessibilityFeature">pageNavigation</meta>
<meta property="schema:accessibilityHazard">none</meta>
<meta property="schema:accessibilitySummary">A simple complexity publication with images and logos, converted to meet EPUB Accessibility specifications of WCAG-AA level. Blank pages from print have been removed in this ebook, with related page number spans set on the first following in-spine page. Certain front and back matter pages have been adjusted in the reading order sequence from print, with related page references reordered in the page-list order.</meta>
<meta id="conf" property="dcterms:conformsTo">EPUB Accessibility 1.1 - WCAG 2.2 Level AA</meta>
<meta id="certifier" property="a11y:certifiedBy" refines="#conf">Benetech</meta>
<meta property="a11y:certifierCredential" refines="#certifier">https://bornaccessible.org/certification/gca-credential/</meta>
<description xmlns="http://purl.org/dc/elements/1.1/">&lt;B&gt;&lt;b&gt;A thrilling new adventure based on the acclaimed TV series &lt;I&gt;Star Trek: Picard&lt;/I&gt;!&lt;/b&gt;&lt;/B&gt;&lt;BR&gt;2401: Just weeks after defeating a devastating joint attack by rogue Changelings and remnants of the Borg Collective, Starfleet and the Federation face a long period of recovery that requires replacing lost personnel and ships. While touring the &lt;I&gt;U.S.S. Titan&lt;/I&gt;-A, which is just beginning an extensive repair-and-refit process that will take nearly a year to complete, newly promoted Captain Seven of Nine and her first officer, Commander Raffi Musiker, experience a bizarre temporal event which renders them both unconscious and sends Seven into a deep coma.&lt;BR&gt; &lt;BR&gt; In the aftermath of this inexplicable attack, Admirals Jean-Luc Picard and Beverly Crusher are surprised by the appearance of Crusher's son, Wesley. Now a Traveler capable of traversing through all of space and time, he warns them that forces he cannot identify are working to disrupt time for unknown and potentially...</description>
</metadata>
<manifest>
<item href="toc.ncx" id="ncx" media-type="application/x-dtbncx+xml"/>
<item href="e9781668097816/xhtml/nav.xhtml" id="nav" media-type="application/xhtml+xml" properties="nav"/>
<item href="e9781668097816/styles/9781668097816.css" id="css" media-type="text/css"/>
<item href="e9781668097816/styles/SS_global.css" id="css1" media-type="text/css"/>
<item href="e9781668097816/xhtml/cover.xhtml" id="cover" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/title.xhtml" id="title" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/dedication.xhtml" id="dedication" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/note.xhtml" id="note" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/authornote.xhtml" id="authornote" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/epigraph.xhtml" id="epigraph" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/prologue.xhtml" id="prologue" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch01.xhtml" id="ch01" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch02.xhtml" id="ch02" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch03.xhtml" id="ch03" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch04.xhtml" id="ch04" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch05.xhtml" id="ch05" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch06.xhtml" id="ch06" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch07.xhtml" id="ch07" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch08.xhtml" id="ch08" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch09.xhtml" id="ch09" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch10.xhtml" id="ch10" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch11.xhtml" id="ch11" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch12.xhtml" id="ch12" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch13.xhtml" id="ch13" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch14.xhtml" id="ch14" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch15.xhtml" id="ch15" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch16.xhtml" id="ch16" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch17.xhtml" id="ch17" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch18.xhtml" id="ch18" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch19.xhtml" id="ch19" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch20.xhtml" id="ch20" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch21.xhtml" id="ch21" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch22.xhtml" id="ch22" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch23.xhtml" id="ch23" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch24.xhtml" id="ch24" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch25.xhtml" id="ch25" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch26.xhtml" id="ch26" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch27.xhtml" id="ch27" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch28.xhtml" id="ch28" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch29.xhtml" id="ch29" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch30.xhtml" id="ch30" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch31.xhtml" id="ch31" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch32.xhtml" id="ch32" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch33.xhtml" id="ch33" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch34.xhtml" id="ch34" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch35.xhtml" id="ch35" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch36.xhtml" id="ch36" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch37.xhtml" id="ch37" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch38.xhtml" id="ch38" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch39.xhtml" id="ch39" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch40.xhtml" id="ch40" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch41.xhtml" id="ch41" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/epilogue.xhtml" id="epilogue" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ack.xhtml" id="ack" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/authorbio.xhtml" id="authorbio" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/adcard.xhtml" id="adcard" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/copyright.xhtml" id="copyright" media-type="application/xhtml+xml"/>
<item href="e9781668097816/images/9781668097816.jpg" id="cover-image" media-type="image/jpeg" properties="cover-image"/>
<item href="e9781668097816/images/logo.jpg" id="logoa" media-type="image/jpeg"/>
<item href="e9781668097816/images/title.jpg" id="titlea" media-type="image/jpeg"/>
<item href="e9781668097816/images/f00ii-01.jpg" id="f00ii-01" media-type="image/jpeg"/>
<item href="e9781668097816/fonts/EBGaramond-Bold.ttf" id="EBGaramond-Bold" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/EBGaramond-BoldItalic.ttf" id="EBGaramond-BoldItalic" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/EBGaramond-Italic.ttf" id="EBGaramond-Italic" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/EBGaramond-Regular.ttf" id="EBGaramond-Regular" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/EBGaramond-SemiBold.ttf" id="EBGaramond-SemiBold" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/EBGaramond-SemiBoldItalic.ttf" id="EBGaramond-SemiBoldItalic" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/Saira_Expanded-Bold.ttf" id="Saira_Expanded-Bold" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/Saira_Expanded-BoldItalic.ttf" id="Saira_Expanded-BoldItalic" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/Tomorrow-Regular.ttf" id="Tomorrow-Regular" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/fonts/NotoSerif-Regular.ttf" id="NotoSerif-Regular" media-type="application/vnd.ms-opentype"/>
<item href="e9781668097816/xhtml/SS_US_adult_signup_front.xhtml" id="SS_US_adult_signup_front" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/SS_US_adult_signup_back.xhtml" id="SS_US_adult_signup_back" media-type="application/xhtml+xml"/>
<item href="e9781668097816/styles/SS_signup.css" id="SS_signup" media-type="text/css"/>
<item href="e9781668097816/xhtml/SS_recommendpage.xhtml" id="SS_recommendpage" media-type="application/xhtml+xml"/>
<item href="e9781668097816/styles/SS_recommendpage.css" id="SS_recommendpage_1" media-type="text/css"/>
<item href="e9781668097816/images/buylink_9781668046371_cover.jpg" id="buylink_9781668046371_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781668096949_cover.jpg" id="buylink_9781668096949_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982139452_cover.jpg" id="buylink_9781982139452_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982154134_cover.jpg" id="buylink_9781982154134_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982175214_cover.jpg" id="buylink_9781982175214_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982194840_cover.jpg" id="buylink_9781982194840_cover" media-type="image/jpeg"/>
</manifest>
<spine toc="ncx">
<itemref idref="cover"/>
<itemref idref="SS_US_adult_signup_front"/>
<itemref idref="title"/>
<itemref idref="dedication"/>
<itemref idref="note"/>
<itemref idref="authornote"/>
<itemref idref="epigraph"/>
<itemref idref="prologue"/>
<itemref idref="ch01"/>
<itemref idref="ch02"/>
<itemref idref="ch03"/>
<itemref idref="ch04"/>
<itemref idref="ch05"/>
<itemref idref="ch06"/>
<itemref idref="ch07"/>
<itemref idref="ch08"/>
<itemref idref="ch09"/>
<itemref idref="ch10"/>
<itemref idref="ch11"/>
<itemref idref="ch12"/>
<itemref idref="ch13"/>
<itemref idref="ch14"/>
<itemref idref="ch15"/>
<itemref idref="ch16"/>
<itemref idref="ch17"/>
<itemref idref="ch18"/>
<itemref idref="ch19"/>
<itemref idref="ch20"/>
<itemref idref="ch21"/>
<itemref idref="ch22"/>
<itemref idref="ch23"/>
<itemref idref="ch24"/>
<itemref idref="ch25"/>
<itemref idref="ch26"/>
<itemref idref="ch27"/>
<itemref idref="ch28"/>
<itemref idref="ch29"/>
<itemref idref="ch30"/>
<itemref idref="ch31"/>
<itemref idref="ch32"/>
<itemref idref="ch33"/>
<itemref idref="ch34"/>
<itemref idref="ch35"/>
<itemref idref="ch36"/>
<itemref idref="ch37"/>
<itemref idref="ch38"/>
<itemref idref="ch39"/>
<itemref idref="ch40"/>
<itemref idref="ch41"/>
<itemref idref="epilogue"/>
<itemref idref="ack"/>
<itemref idref="SS_recommendpage"/>
<itemref idref="authorbio"/>
<itemref idref="adcard"/>
<itemref idref="SS_US_adult_signup_back"/>
<itemref idref="copyright"/>
</spine>
	<guide>
		<reference href="e9781668097816/xhtml/cover.xhtml" title="Cover" type="cover"/>
		<reference href="e9781668097816/xhtml/cover.xhtml" title="SRL" type="text"/>
	</guide>
</package>
epubsansa wants to change the media type for the fonts.
Code:
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="eisbn" version="3.0" xml:lang="en-us">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<meta content="cover-image" name="cover"/>
<dc:title id="t1">To Defy Fate</dc:title>
<meta property="title-type" refines="#t1">main</meta>
<dc:creator id="creator01">Dayton Ward</dc:creator>
<meta property="role" refines="#creator01" scheme="marc:relators">aut</meta>
<dc:publisher>Pocket Books/Star Trek</dc:publisher>
<dc:identifier id="eisbn">9781668097816</dc:identifier>
<meta property="pageBreakSource">9781668097793</meta>
<dc:language>EN-US</dc:language>
<dc:date>2026-04-28</dc:date>
<meta property="dcterms:modified">2026-04-28T12:00:00Z</meta>
<meta property="schema:accessMode">textual</meta>
<meta property="schema:accessModeSufficient">textual</meta>
<meta property="schema:accessibilityFeature">ARIA</meta>
<meta property="schema:accessibilityFeature">alternativeText</meta>
<meta property="schema:accessibilityFeature">displayTransformability</meta>
<meta property="schema:accessibilityFeature">readingOrder</meta>
<meta property="schema:accessibilityFeature">structuralNavigation</meta>
<meta property="schema:accessibilityFeature">tableOfContents</meta>
<meta property="schema:accessibilityFeature">pageBreakMarkers</meta>
<meta property="schema:accessibilityFeature">pageNavigation</meta>
<meta property="schema:accessibilityHazard">none</meta>
<meta property="schema:accessibilitySummary">A simple complexity publication with images and logos, converted to meet EPUB Accessibility specifications of WCAG-AA level. Blank pages from print have been removed in this ebook, with related page number spans set on the first following in-spine page. Certain front and back matter pages have been adjusted in the reading order sequence from print, with related page references reordered in the page-list order.</meta>
<meta id="conf" property="dcterms:conformsTo">EPUB Accessibility 1.1 - WCAG 2.2 Level AA</meta>
<meta id="certifier" property="a11y:certifiedBy" refines="#conf">Benetech</meta>
<meta property="a11y:certifierCredential" refines="#certifier">https://bornaccessible.org/certification/gca-credential/</meta>
<description xmlns="http://purl.org/dc/elements/1.1/">&lt;B&gt;&lt;b&gt;A thrilling new adventure based on the acclaimed TV series &lt;I&gt;Star Trek: Picard&lt;/I&gt;!&lt;/b&gt;&lt;/B&gt;&lt;BR&gt;2401: Just weeks after defeating a devastating joint attack by rogue Changelings and remnants of the Borg Collective, Starfleet and the Federation face a long period of recovery that requires replacing lost personnel and ships. While touring the &lt;I&gt;U.S.S. Titan&lt;/I&gt;-A, which is just beginning an extensive repair-and-refit process that will take nearly a year to complete, newly promoted Captain Seven of Nine and her first officer, Commander Raffi Musiker, experience a bizarre temporal event which renders them both unconscious and sends Seven into a deep coma.&lt;BR&gt; &lt;BR&gt; In the aftermath of this inexplicable attack, Admirals Jean-Luc Picard and Beverly Crusher are surprised by the appearance of Crusher's son, Wesley. Now a Traveler capable of traversing through all of space and time, he warns them that forces he cannot identify are working to disrupt time for unknown and potentially...</description>
</metadata>
<manifest>
<item href="toc.ncx" id="ncx" media-type="application/x-dtbncx+xml"/>
<item href="e9781668097816/xhtml/nav.xhtml" id="nav" media-type="application/xhtml+xml" properties="nav"/>
<item href="e9781668097816/styles/9781668097816.css" id="css" media-type="text/css"/>
<item href="e9781668097816/styles/SS_global.css" id="css1" media-type="text/css"/>
<item href="e9781668097816/xhtml/cover.xhtml" id="cover" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/title.xhtml" id="title" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/dedication.xhtml" id="dedication" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/note.xhtml" id="note" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/authornote.xhtml" id="authornote" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/epigraph.xhtml" id="epigraph" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/prologue.xhtml" id="prologue" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch01.xhtml" id="ch01" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch02.xhtml" id="ch02" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch03.xhtml" id="ch03" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch04.xhtml" id="ch04" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch05.xhtml" id="ch05" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch06.xhtml" id="ch06" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch07.xhtml" id="ch07" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch08.xhtml" id="ch08" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch09.xhtml" id="ch09" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch10.xhtml" id="ch10" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch11.xhtml" id="ch11" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch12.xhtml" id="ch12" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch13.xhtml" id="ch13" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch14.xhtml" id="ch14" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch15.xhtml" id="ch15" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch16.xhtml" id="ch16" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch17.xhtml" id="ch17" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch18.xhtml" id="ch18" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch19.xhtml" id="ch19" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch20.xhtml" id="ch20" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch21.xhtml" id="ch21" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch22.xhtml" id="ch22" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch23.xhtml" id="ch23" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch24.xhtml" id="ch24" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch25.xhtml" id="ch25" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch26.xhtml" id="ch26" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch27.xhtml" id="ch27" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch28.xhtml" id="ch28" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch29.xhtml" id="ch29" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch30.xhtml" id="ch30" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch31.xhtml" id="ch31" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch32.xhtml" id="ch32" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch33.xhtml" id="ch33" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch34.xhtml" id="ch34" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch35.xhtml" id="ch35" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch36.xhtml" id="ch36" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch37.xhtml" id="ch37" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch38.xhtml" id="ch38" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch39.xhtml" id="ch39" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch40.xhtml" id="ch40" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ch41.xhtml" id="ch41" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/epilogue.xhtml" id="epilogue" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/ack.xhtml" id="ack" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/authorbio.xhtml" id="authorbio" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/adcard.xhtml" id="adcard" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/copyright.xhtml" id="copyright" media-type="application/xhtml+xml"/>
<item href="e9781668097816/images/9781668097816.jpg" id="cover-image" media-type="image/jpeg" properties="cover-image"/>
<item href="e9781668097816/images/logo.jpg" id="logoa" media-type="image/jpeg"/>
<item href="e9781668097816/images/title.jpg" id="titlea" media-type="image/jpeg"/>
<item href="e9781668097816/images/f00ii-01.jpg" id="f00ii-01" media-type="image/jpeg"/>
<item href="e9781668097816/fonts/EBGaramond-Bold.ttf" id="EBGaramond-Bold" media-type="font/otf"/>
<item href="e9781668097816/fonts/EBGaramond-BoldItalic.ttf" id="EBGaramond-BoldItalic" media-type="font/otf"/>
<item href="e9781668097816/fonts/EBGaramond-Italic.ttf" id="EBGaramond-Italic" media-type="font/otf"/>
<item href="e9781668097816/fonts/EBGaramond-Regular.ttf" id="EBGaramond-Regular" media-type="font/otf"/>
<item href="e9781668097816/fonts/EBGaramond-SemiBold.ttf" id="EBGaramond-SemiBold" media-type="font/otf"/>
<item href="e9781668097816/fonts/EBGaramond-SemiBoldItalic.ttf" id="EBGaramond-SemiBoldItalic" media-type="font/otf"/>
<item href="e9781668097816/fonts/Saira_Expanded-Bold.ttf" id="Saira_Expanded-Bold" media-type="font/otf"/>
<item href="e9781668097816/fonts/Saira_Expanded-BoldItalic.ttf" id="Saira_Expanded-BoldItalic" media-type="font/otf"/>
<item href="e9781668097816/fonts/Tomorrow-Regular.ttf" id="Tomorrow-Regular" media-type="font/otf"/>
<item href="e9781668097816/fonts/NotoSerif-Regular.ttf" id="NotoSerif-Regular" media-type="font/otf"/>
<item href="e9781668097816/xhtml/SS_US_adult_signup_front.xhtml" id="SS_US_adult_signup_front" media-type="application/xhtml+xml"/>
<item href="e9781668097816/xhtml/SS_US_adult_signup_back.xhtml" id="SS_US_adult_signup_back" media-type="application/xhtml+xml"/>
<item href="e9781668097816/styles/SS_signup.css" id="SS_signup" media-type="text/css"/>
<item href="e9781668097816/xhtml/SS_recommendpage.xhtml" id="SS_recommendpage" media-type="application/xhtml+xml"/>
<item href="e9781668097816/styles/SS_recommendpage.css" id="SS_recommendpage_1" media-type="text/css"/>
<item href="e9781668097816/images/buylink_9781668046371_cover.jpg" id="buylink_9781668046371_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781668096949_cover.jpg" id="buylink_9781668096949_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982139452_cover.jpg" id="buylink_9781982139452_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982154134_cover.jpg" id="buylink_9781982154134_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982175214_cover.jpg" id="buylink_9781982175214_cover" media-type="image/jpeg"/>
<item href="e9781668097816/images/buylink_9781982194840_cover.jpg" id="buylink_9781982194840_cover" media-type="image/jpeg"/>
</manifest>
<spine toc="ncx">
<itemref idref="cover"/>
<itemref idref="SS_US_adult_signup_front"/>
<itemref idref="title"/>
<itemref idref="dedication"/>
<itemref idref="note"/>
<itemref idref="authornote"/>
<itemref idref="epigraph"/>
<itemref idref="prologue"/>
<itemref idref="ch01"/>
<itemref idref="ch02"/>
<itemref idref="ch03"/>
<itemref idref="ch04"/>
<itemref idref="ch05"/>
<itemref idref="ch06"/>
<itemref idref="ch07"/>
<itemref idref="ch08"/>
<itemref idref="ch09"/>
<itemref idref="ch10"/>
<itemref idref="ch11"/>
<itemref idref="ch12"/>
<itemref idref="ch13"/>
<itemref idref="ch14"/>
<itemref idref="ch15"/>
<itemref idref="ch16"/>
<itemref idref="ch17"/>
<itemref idref="ch18"/>
<itemref idref="ch19"/>
<itemref idref="ch20"/>
<itemref idref="ch21"/>
<itemref idref="ch22"/>
<itemref idref="ch23"/>
<itemref idref="ch24"/>
<itemref idref="ch25"/>
<itemref idref="ch26"/>
<itemref idref="ch27"/>
<itemref idref="ch28"/>
<itemref idref="ch29"/>
<itemref idref="ch30"/>
<itemref idref="ch31"/>
<itemref idref="ch32"/>
<itemref idref="ch33"/>
<itemref idref="ch34"/>
<itemref idref="ch35"/>
<itemref idref="ch36"/>
<itemref idref="ch37"/>
<itemref idref="ch38"/>
<itemref idref="ch39"/>
<itemref idref="ch40"/>
<itemref idref="ch41"/>
<itemref idref="epilogue"/>
<itemref idref="ack"/>
<itemref idref="SS_recommendpage"/>
<itemref idref="authorbio"/>
<itemref idref="adcard"/>
<itemref idref="SS_US_adult_signup_back"/>
<itemref idref="copyright"/>
</spine>
	<guide>
		<reference href="e9781668097816/xhtml/cover.xhtml" title="Cover" type="cover"/>
		<reference href="e9781668097816/xhtml/cover.xhtml" title="SRL" type="text"/>
	</guide>
</package>
Both versions of the OPF are wrong. The original has the wrong media type. epubsana changed it to yet another incorrecty media type. For truetype fonts, the media type should be media-type="font/ttf"/>.

This is the list of media types in the ePub 3.3 spec. https://www.w3.org/TR/epub-33/#sec-core-media-types
JSWolf is online now   Reply With Quote
Old 09-10-2026, 04:41 PM   #23
JSWolf
Resident Curmudgeon
JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.
 
JSWolf's Avatar
 
Posts: 84,866
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
Oh and so I don't have to report the error report a second time, epubveri and epubcheck get this wrong. They are TrueType fonts, not OpenType fonts. So an error should be reported about the media type being incorrect.
JSWolf is online now   Reply With Quote
Old 09-11-2026, 07:46 PM   #24
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
I haven't been able to write because I've been busy with epubveri. I will write as soon as possible.
Kayadelenium is offline   Reply With Quote
Old 09-11-2026, 08:33 PM   #25
JSWolf
Resident Curmudgeon
JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.
 
JSWolf's Avatar
 
Posts: 84,866
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
Quote:
Originally Posted by Kayadelenium View Post
I haven't been able to write because I've been busy with epubveri. I will write as soon as possible.
This error also is part of epubveri as epubveri doesn't say it's wrong when it is.
JSWolf is online now   Reply With Quote
Old Yesterday, 07:51 AM   #26
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
JSWolf — sorry for the delay, and thank you for pushing on it. I went and checked properly rather than answering from memory, and the short version is that I think the rename is right and the original declaration is not an error. Here is the reasoning, so you can tell me where it is wrong.

First, I measured the fonts in my own library, concluded that epubsana was renaming TrueType files to an OpenType media type, and opened an issue against epubveri asking for a rule. That issue was closed as not a defect, and after reading the specifications rather than the file names I agree with the closure.

The premise we were both working from is that a font with glyf outlines is a TrueType font and therefore not an OpenType font. That is the part that does not hold:

1. The OpenType specification says an OpenType font containing TrueType outlines should use the value 0x00010000 for sfntVersion. So a file starting with those four bytes is not thereby excluded from being an OpenType font — that signature is exactly what OpenType prescribes for the glyf flavour.

2. RFC 8081, which registers the font top-level type, gives font/otf a magic number list containing both 0x00010000 and OTTO. Only font/ttf is restricted to 0x00010000 alone. So the bytes rule spellings out, not in: an OTTO file cannot be font/ttf under any reading, but a 0x00010000 file is admitted by both.

3. EPUB 3.3's Core Media Types table lists media types in rows, and says the first entry in a row is the preferred one. application/vnd.ms-opentype appears only on the OpenType row, and that row's first entry is font/otf. Renaming it to font/ttf would move the file off the row its own declaration sits on, which is a bigger change than correcting a spelling.

So the declaration in your book is a valid Core Media Type under a name the specification has superseded, and font/otf is the name it says to prefer. That is also why epubveri reports it at usage severity rather than as an error, and why epubcheck does not complain: nothing is wrong with the file, only with the spelling.

On the "epubveri gets this wrong" half: if the original declaration were genuinely contradicted by the file, epubveri would be wrong not to say so, and I would want to fix it. So I measured my own library rather than arguing about it, reading the sfnt table directory of every font a manifest declares.

Of the files declared application/vnd.ms-opentype whose bytes I could read, the majority are CFF-flavoured — they start with OTTO, and nobody disputes that those are OpenType. The rest are the glyf ones you are describing, sitting on the same row of the same table under the same declaration. Every one of them, both flavours, carries an OS/2 table, which OpenType requires and Apple's TrueType reference does not; most carry GSUB and GPOS as well.

The direction that would be a genuine error is the other one: a file whose first four bytes are OTTO, which is CFF and cannot be TrueType, declared under a ttf spelling. Not one font in my library is that.

If you have a book where that is not true, I would very much like it. A font whose first four bytes are OTTO under a ttf media type, or a WOFF under an sfnt one, is a real defect and I will chase it. That is a concrete thing to look for rather than a general suspicion, and it is the kind of report I cannot generate myself.

Your report did change something, for what it is worth. application/font-sfnt is a spelling that genuinely does not say which flavour it is, and epubveri now answers that row from the file's own signature instead of guessing — and it stops proposing a replacement the bytes rule out. epubsana 0.15.0 will take the replacement from the finding rather than from a table of its own, so the two tools can no longer disagree about what to write.
Kayadelenium is offline   Reply With Quote
Old Yesterday, 07:56 AM   #27
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
epubsana 0.15.0

https://github.com/veripublica/epubs...es/tag/v0.15.0

One new fixer, a change plugin authors will care about, and the media-type question from a few posts up.

A fragment that is real but has moved

The new fixer, thirty-seven in total. A link points at a #fragment that the target document does not define — but exactly one document in the book does define that anchor. The fragment did not die; it moved.

On real books this is almost always the same accident: an editor split a file at a page break, and a footnote link and its return link were left pointing into the wrong half. Ten links in one book on my shelf are in exactly that state: five notes and the five return links that go with them, each pointing at the wrong side of the same split. The repair writes the path of the document that actually holds the anchor in front of the fragment, relative to the referring document. Nothing else in the link changes. Where the anchor turns out to be in the referring document itself, the link becomes a plain same-document #fragment, which is what a bare fragment means.

What it declines is the more useful half, and it is most of the population:
  • An anchor defined in several documents. Which one the link meant is a guess, and a guess that silently relinks a footnote is worse than a broken link you can see.
  • An anchor defined nowhere in the book. The only repair available is to drop the fragment, and that throws away the author's target — the one piece of evidence about where the link was supposed to go.
  • A target the spine leaves out of the reading order, and a reference that is not visible as a whole quoted attribute value.

The last two decline nothing in my own library and are there anyway, because each of them names a defect the repair would otherwise create. That is the recurring lesson here: a repair that clears one finding and authors another can leave a book's error count unchanged, so a total is not evidence that anything got better.

For anyone reading the JSON

The summary now reports every counter it has a concept of, including zero. Under --dry-run it used to say applied 0, skipped 0 while every item in the same document was marked proposed — so the summary and the items disagreed about the size of the run, and a tool asking the summary how many fixes there were got zero while two sat in the list. Every number in it was true and the document still misled.

There is now a proposed counter beside applied and skipped, and this holds: applied plus skipped plus proposed equals the number of items.

The same gap one field over: only fatals and errors were counted, in a tool where some fixes clear a warning or a usage finding and move the error line not at all. All five severities are now reported, before and after. If you were inferring "nothing happened" from an unchanged error count, that inference was wrong and is now unnecessary.

Both are additive — nothing that was there has moved or changed meaning.

The font media type

JSWolf reported that the rename of application/vnd.ms-opentype to font/otf was wrong. I have answered that separately just above; the short version is that I went and checked, the rename follows EPUB 3.3's own table, and I was wrong to think otherwise at first.

One thing did change because of it. epubsana used to decide these renames from a small table of its own, written before epubveri started naming the preferred type itself. It now takes the replacement from the finding. That removes a real hazard rather than a theoretical one: with two tables there were inputs where epubsana would have named a replacement that epubveri had deliberately refused to name, because the file's own bytes ruled it out. No book in my library is in that state — this closes the hole rather than repairing damage — but the two tools can no longer disagree about what to write.

As always

Your original file is never touched: a repaired copy is written beside it, every fix is proposed before it is made, and the run ends with a report of exactly what changed. The browser version needs no install and uploads nothing: https://veripublica.github.io/epubsana/

And the ask is unchanged, because it is the only check this project has that is not circular: epubsana verifies its own repairs with epubveri, so it cannot see damage epubveri cannot see. If a repair leaves a book worse in a way that still validates, only someone opening the book will notice. Please say so if you do.

crates.io: https://crates.io/crates/epubsana — command-line binaries for Windows, macOS and Linux are on the releases page.
Kayadelenium is offline   Reply With Quote
Old Yesterday, 10:13 AM   #28
JSWolf
Resident Curmudgeon
JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.
 
JSWolf's Avatar
 
Posts: 84,866
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
Quote:
Originally Posted by Kayadelenium View Post
If you have a book where that is not true, I would very much like it. A font whose first four bytes are OTTO under a ttf media type, or a WOFF under an sfnt one, is a real defect and I will chase it. That is a concrete thing to look for rather than a general suspicion, and it is the kind of report I cannot generate myself.
The ePub I posted is one I ripped apart to make this test. It has an embedded font that is a 100% TrueType font.

When I run epubsana on it, it comes up with the media type of font/oft instead of font/ttf. epubveri and epubcheck then go on the validate this as correct. epubveri and epubcheck also validate this ePub as correct with a media type of application/vnd.ms-opentype.

Is there a way to fix this without having to look inside every font file?
Attached Files
File Type: epub test.epub (323.3 KB, 4 views)

Last edited by JSWolf; Yesterday at 11:00 AM.
JSWolf is online now   Reply With Quote
Old Yesterday, 12:34 PM   #29
Kayadelenium
Groupie
Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.Kayadelenium ought to be getting tired of karma fortunes by now.
 
Kayadelenium's Avatar
 
Posts: 157
Karma: 363834
Join Date: Jul 2026
Location: Planet Earth
Device: Kobo Forma
JSWolf — thank you for the file. That is exactly the right way to settle this, and it did settle it, though not in the direction either of us expected.

I ran epubcheck on your test.epub with usage messages turned on, before running epubsana on it at all. Here is what epubcheck says about that manifest entry:
USAGE(OPF-090): 9781668097816.opf(39,106): It is encouraged to use MIME media type "font/otf" instead of "application/vnd.ms-opentype".
That is epubcheck's own recommendation, on your own file, naming font/otf specifically. epubsana does exactly what that line asks and nothing else: after the repair, epubcheck reports the same book with that message gone and every other message unchanged. So the rename is not epubsana having an opinion about your font — it is epubsana carrying out epubcheck's instruction. epubveri arrives at the same answer from the same place, EPUB 3.3's Core Media Types table, where application/vnd.ms-opentype appears on the OpenType row and nowhere else, and font/otf is that row's first entry.

You are right about the font itself, and I want to say so plainly. comic.ttf begins 00 01 00 00, carries a glyf table and no CFF table. It has TrueType outlines. font/ttf would be a narrower true statement about that file than font/otf is.

Now your actual question: can this be fixed without inspecting individual font files? No — and reading the font would not settle it either, which is the part I had not made clear enough before.

The signature can only rule spellings out, never choose between them. RFC 8081 gives font/ttf one magic number, 00 01 00 00, and gives font/otf two, 00 01 00 00 and OTTO. So an OTTO file is excluded from font/ttf, but a 00 01 00 00 file is admitted by both names. Your font is admitted by both. Opening it tells us nothing we could act on.

Outside the bytes there are two signals. One is the file name, which is a naming convention rather than a fact about the file — epubcheck itself falls back to the extension only for application/font-sfnt, which sits on both rows of the table, and there it has nothing else to go on. The other is the declaration already in your manifest, which names the OpenType row. Between a guess from a file name and the statement the book itself makes, epubsana takes the statement. Overruling an author's own declaration on a filename is the kind of guess the tool is built not to make.

If you would rather the manifest said font/ttf, that is a one-line edit in Sigil and nothing will object: I checked, and epubcheck is silent on font/ttf for this book too. Both names are valid for it. Which one describes your font better is a judgement about your book, and that is yours rather than a repair tool's.

One thing your report did change, and it is not nothing. The direction that would be a genuine error — an OTTO file, which cannot be TrueType, declared under a ttf spelling — is now blocked at the source. Since 0.14.1 epubveri refuses to name a replacement the file's own signature rules out, and since 0.15.0 epubsana takes the replacement from the finding rather than from a table of its own, so it can no longer write one on its own authority. I still have not seen a book with that shape. If one turns up, send it the way you sent this one.
Kayadelenium is offline   Reply With Quote
Old Today, 06:03 AM   #30
JSWolf
Resident Curmudgeon
JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.JSWolf ought to be getting tired of karma fortunes by now.
 
JSWolf's Avatar
 
Posts: 84,866
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
If I come across such, I'll create another ePub and send it your way. Thanks for taking a look at this. I just wish MS had not screwed up and used .TTF for TT/OT fonts and instead used something like .TTO to show it's a combo font. Then .OTF and .TTF would actually have the correct meanings.
JSWolf is online now   Reply With Quote
Reply

Tags
epub, epub2, epub3, epubsana, epubveri


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Editor Plugin] EpubCheck Doitsu Plugins 232 08-30-2026 12:22 PM
squashed images in Editor/Tools/Reports after search rjwse@aol.com Calibre 1 12-18-2019 12:00 PM
Possible bug in editor (reports) ratanplan Editor 2 02-18-2015 06:22 AM
Reports of 3.1 being pushed out for automatic upgrade Tiersten Amazon Kindle 33 02-20-2011 10:37 AM
Web-based epubcheck upgraded to epubcheck 1.0.5 kjk ePub 4 02-09-2010 09:53 PM


All times are GMT -4. The time now is 06:34 AM.


MobileRead.com is a privately owned, operated and funded community.