|
|||||||
![]() |
|
|
Thread Tools | Search this Thread |
|
|
#16 | |
|
Sigil Developer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 10,010
Karma: 7518950
Join Date: Nov 2009
Device: many
|
Quote:
|
|
|
|
|
|
|
#17 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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 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 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…\"" }
]
Code:
touched = {c["path"] for it in items for c in it["data"]["changes"]}
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-opentype → font/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. |
|
|
|
|
|
#18 | |
|
Grand Sorcerer
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 5,914
Karma: 24240563
Join Date: Dec 2010
Device: Kindle PW2
|
Quote:
I have a recommendation regarding one of the fixes. 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. |
|
|
|
|
|
|
#19 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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 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. |
|
|
|
|
|
#20 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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. |
|
|
|
|
|
#21 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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
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:
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. |
|
|
|
|
|
#22 |
|
Resident Curmudgeon
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 84,869
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/"><B><b>A thrilling new adventure based on the acclaimed TV series <I>Star Trek: Picard</I>!</b></B><BR>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 <I>U.S.S. Titan</I>-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.<BR> <BR> 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> 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/"><B><b>A thrilling new adventure based on the acclaimed TV series <I>Star Trek: Picard</I>!</b></B><BR>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 <I>U.S.S. Titan</I>-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.<BR> <BR> 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> This is the list of media types in the ePub 3.3 spec. https://www.w3.org/TR/epub-33/#sec-core-media-types |
|
|
|
|
|
#23 |
|
Resident Curmudgeon
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 84,869
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.
|
|
|
|
|
|
#24 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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.
|
|
|
|
|
|
#25 |
|
Resident Curmudgeon
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 84,869
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
|
|
|
|
|
|
|
#26 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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. |
|
|
|
|
|
#27 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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:
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. |
|
|
|
|
|
#28 | |
|
Resident Curmudgeon
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 84,869
Karma: 153788249
Join Date: Nov 2006
Location: Roslindale, Massachusetts
Device: Kobo Libra 2, Kobo Aura H2O, PRS-650, PRS-T1, nook STR, PW3
|
Quote:
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? Last edited by JSWolf; Yesterday at 11:00 AM. |
|
|
|
|
|
|
#29 |
|
Groupie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 158
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. |
|
|
|
|
|
#30 |
|
Resident Curmudgeon
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 84,869
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.
|
|
|
|
![]() |
| Tags |
| epub, epub2, epub3, epubsana, epubveri |
|
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 |