feat(epub): metadata front matter and figure caption dedupe - #4
feat(epub): metadata front matter and figure caption dedupe#4mathurshubham wants to merge 1 commit into
Conversation
d31f7b0 to
7a5327a
Compare
Three EPUB-focused output improvements, targeting the completeness and cleanliness axes where EPUB trailed in the benchmark. - OPF Dublin Core metadata now renders as a YAML front matter block instead of a synthetic title heading. Adds `DocumentMeta` to the model (mirrored in the Node and Python bindings), parses the OPF `<metadata>` descendants (EPUB2 nesting included), selects the main title via the EPUB3 `title-type` refinement, keeps every `dc:creator`, and takes the first `dc:date`. Most books already carry their own title page, so injecting the OPF title as a body heading double-titled them. - Headings no longer emit a redundant whole-heading bold/italic that the `#` prefix already conveys. Done in the Markdown renderer, so it cleans headings from every format (doc, docx, odt, rtf, epub); partial emphasis is kept and the model still carries the resolved style. - A `<figure>`'s `<figcaption>` is dropped when it merely repeats a contained image's alt text (a common export shape that otherwise printed the caption twice); a distinct caption is kept as its own paragraph. Image alts are collected from figure descendants, so wrapped `<a><img></a>` counts. New handmade fixtures cover metadata and figure handling. Snapshots updated; only EPUB output gains front matter, and the heading cleanup accounts for the cross-format snapshot changes.
7a5327a to
8ca81e9
Compare
|
@tomsideguide would appreciate a look at this one when you get a chance, I've kept it current with main and it's ready to review.
One design note worth your eyes specifically: the DocumentMeta model field is deliberately format-agnostic — docx (core.xml), ODF (meta.xml), and RTF (\info) all carry the same Dublin Core-ish metadata, so this is groundwork any of those formats can populate later without another model change. Node and Python bindings are mirrored so to_document stays consistent across surfaces. Happy to split, trim, or rework any part of it if you'd rather take a different shape. |
What
Two EPUB-focused output improvements, targeting the completeness and
cleanliness axes where EPUB trailed the other formats in the benchmark
(README: EPUB 74, the only format anydoc did not lead).
1. OPF metadata → YAML front matter (was: duplicate title, dropped metadata)
epub/mod.rsread only<title>and injected it as a body H1. Most booksalready carry their own title page in the content, so the output was
double-titled; author, language, date, and publisher were dropped entirely.
Now Dublin Core metadata renders as a
----fenced YAML front matter block:DocumentMetaon the model (title,authors,language,date,publisher,description), mirrored in the Node and Python bindings.<metadata>descendants (so EPUB2's<dc-metadata>nesting is covered), scoped to
<metadata>so a stray<title>elsewherecan't leak in.
<meta property="title-type" refines="#id">main</meta>, falling back tothe first non-empty
dc:title.dc:creator; a single author is a scalar, multiple render asa YAML list. Repeated
dc:date(EPUB2opf:event) takes the firstnon-empty.
Only EPUB populates
meta; every other format leaves it default and rendersno front matter.
2. Duplicated figure captions removed
pandoc wraps a lone image as
<figure><img alt="x"><figcaption>x</figcaption></figure>, which theconverter walked transparently, printing the text twice (
tiny dot tiny dot).<figure>now has its own handler: a<figcaption>matching a containedimage's
alt(normalized: trimmed, whitespace-collapsed, case-folded) isdropped; a distinct caption is kept as its own paragraph with its own CSS
styling,
display: nonerespected, and itsidkept as an anchor. Imagealts are collected from figure descendants, so wrapped
<a><img></a>counts.
Real-world before/after
Converted three Project Gutenberg EPUBs with
mainand with this branch;every changed line is one of the intended improvements, with no other drift.
Conversion time is unchanged.
Alice's Adventures in Wonderland — author/date/language were dropped
entirely before:
Pride and Prejudice and Frankenstein gain their
author,date, andlanguagethe same way. (These books contain no<figcaption>, so thecaption dedupe is exercised by the fixtures and the pandoc-built
book.epubsnapshot instead.)
Tests
cargo test --locked);fmt+clippy -D warningsclean.
list / empty-meta.
html.rstests: caption dedupe, distinct caption kept, empty alt,wrapped
<a><img>, hidden figcaption, figcaption's own CSS styling.epub_metadata_is_parsed_into_the_model.index.d.tsregenerated withDocumentMeta.DocumentMetaregistered in
lib.rs,.pyi, and__init__.__all__).handmade-metadata.epubandhandmade-figure.epub.Snapshot changes
book.epubimage line loses its doubled caption.Document.metafield is inerteverywhere except EPUB.
Notes
truth is built from source XHTML and excludes OPF metadata, so front matter
may not raise the score even though the output is more complete.
book.epub's snapshot now includes pandoc's build timestamp(
date: "2026-07-30T23:11:58Z", from thedc:datepandoc stamps at buildtime), so regenerating that fixture will drift this one snapshot line. That
is inherent to reading
dc:date, not a bug.included; happy to iterate if a corpus run surfaces anything.