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: 9,961
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
Connoisseur
Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!
 
Kayadelenium's Avatar
 
Posts: 88
Karma: 100000
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,896
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.

FYI: For Sigil users, here's again the link to my post with the beta version of the Sigil epubsana plugin.
Doitsu is offline   Reply With Quote
Old 08-13-2026, 05:00 AM   #19
Kayadelenium
Connoisseur
Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!
 
Kayadelenium's Avatar
 
Posts: 88
Karma: 100000
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 Yesterday, 02:46 PM   #20
Kayadelenium
Connoisseur
Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!Kayadelenium rocks like Gibraltar!
 
Kayadelenium's Avatar
 
Posts: 88
Karma: 100000
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
Reply

Tags
epub, epub2, epub3, epubsana, epubveri


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Editor Plugin] EpubCheck Doitsu Plugins 230 04-10-2026 03:19 AM
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 11:01 PM.


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