Skip to content

fix(metadata): ensure EPUB version-aware metadata writing#2998

Draft
Shaglock wants to merge 1 commit intobooklore-app:developfrom
Shaglock:fix/epub-version-compliance
Draft

fix(metadata): ensure EPUB version-aware metadata writing#2998
Shaglock wants to merge 1 commit intobooklore-app:developfrom
Shaglock:fix/epub-version-compliance

Conversation

@Shaglock
Copy link

Summary

Fixes #2997

EpubMetadataWriter unconditionally wrote EPUB3-only constructs into all EPUB files regardless of version. This produced invalid OPF documents that fail Amazon's Send to Kindle validation (error E999) and epubcheck validation (RSC-005, PKG-007).

Root Cause

When Booklore modifies EPUB metadata, it always wrote EPUB3 constructs (e.g., opf:file-as/opf:role attributes on dc:creator, <meta property="..."> elements, prefix attribute on <package>) regardless of whether the EPUB is version 2.0 or 3.0. For EPUB3 files, using opf: attributes on dc:creator is invalid per the spec — EPUB3 requires <meta refines="#id"> elements instead.

Changes

All changes are in EpubMetadataWriter.java (source) and EpubMetadataWriterTest.java (tests):

  • createCreatorElement: EPUB3 now uses <meta refines="#id"> for file-as and role with marc:relators scheme; EPUB2 keeps opf: attributes on dc:creator
  • addFolderContentsToZip: mimetype is now STORED (uncompressed) and written as the first ZIP entry per EPUB spec
  • replaceBelongsToCollection: EPUB3 uses belongs-to-collection with refines; EPUB2 uses calibre:series/calibre:series_index convention (widely supported by e-readers)
  • addSubtitleToTitle: EPUB3 uses separate dc:title with title-type refinement; EPUB2 stores subtitle via booklore:subtitle metadata only (preserves round-trip fidelity)
  • addBookloreMetadata / createBookloreMetaElement: EPUB3 uses property attribute with prefix; EPUB2 uses name/content attribute form. Also now writes booklore:subtitle for extraction round-trip.
  • removeAllBookloreMetadata: Now handles both EPUB3 property and EPUB2 name attributes
  • cleanupCalibreArtifacts: Preserves calibre:series and calibre:series_index metas (used for EPUB2 series)
  • organizeMetadataElements: Correctly categorizes EPUB2-style series and booklore metas into their respective buckets
  • Added isEpub3() helper method used throughout

Verification

Verified with epubcheck v5.3.0 — EPUB3 files modified by Booklore now produce 0 errors, 0 warnings.

Test Output

> Task :test
BUILD SUCCESSFUL in 41s
6 actionable tasks: 2 executed, 4 up-to-date

All 2570+ existing tests pass. 14 new tests added covering:

  • EPUB3 creator metadata (meta refines for file-as, role with marc:relators scheme)
  • EPUB2 creator metadata (opf: attributes, no EPUB3 constructs)
  • Mimetype ZIP handling (stored first, no duplicates)
  • EPUB3/EPUB2 series metadata
  • EPUB3/EPUB2 subtitle handling
  • EPUB3/EPUB2 booklore metadata format

EpubMetadataWriter unconditionally wrote EPUB3-only constructs into
all EPUB files regardless of version, producing invalid OPF documents
for EPUB3 files (e.g. opf:file-as/opf:role attributes on dc:creator)
and writing EPUB3-only elements into EPUB2 files.

Changes:
- createCreatorElement: EPUB3 uses <meta refines="#id"> for file-as/role;
  EPUB2 uses opf: attributes on dc:creator
- addFolderContentsToZip: mimetype is now STORED (uncompressed) and
  written as the first ZIP entry per EPUB spec
- replaceBelongsToCollection: EPUB3 uses belongs-to-collection with
  refines; EPUB2 uses calibre:series/calibre:series_index convention
- addSubtitleToTitle: EPUB3 uses separate dc:title with title-type
  refinement; EPUB2 stores subtitle via booklore:subtitle metadata only
- addBookloreMetadata/createBookloreMetaElement: EPUB3 uses property
  attribute with prefix; EPUB2 uses name/content attribute form
- removeAllBookloreMetadata: now handles both EPUB3 property and EPUB2
  name attributes
- cleanupCalibreArtifacts: preserves calibre:series and
  calibre:series_index metas used for EPUB2 series
- organizeMetadataElements: correctly categorizes EPUB2-style series
  and booklore metas into their respective buckets
- addBookloreMetadata: writes booklore:subtitle for round-trip fidelity
- Added isEpub3() helper method

Closes booklore-app#2997
@balazs-szucs
Copy link
Collaborator

Hi,

thank you for your submission. Please note that we require all PRs to use our standard message template and include proof of task completion. Could you please update your PR description to meet these guidelines? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] EpubMetadataWriter produces invalid EPUB3: OPF2-style attributes on dc:creator + compressed mimetype cause Kindle E999 rejection

2 participants