What's your idea?
Extend server/src/modules/metadata/lib/opf-parser.ts to recognize three additional Calibre-specific metadata encodings that are standard output from Calibre 9.x when EPUBs are exported or modified:
1. Calibre prefix:value identifiers in <dc:identifier>
Calibre 9.x writes provider IDs directly into <dc:identifier> elements using a prefix:value format instead of the opf:scheme attribute or urn: URN prefix already supported by the parser:
<dc:identifier>amazon:B0G3YRNY6Y</dc:identifier>
<dc:identifier>goodreads:244564568</dc:identifier>
<dc:identifier>google:ABCD1234</dc:identifier>
<dc:identifier>openlibrary:OL99999999W</dc:identifier>
<dc:identifier>hardcover:test-book-slug</dc:identifier>
<dc:identifier>kobo:test-kobo-id</dc:identifier>
<dc:identifier>itunes:987654321</dc:identifier>
<dc:identifier>lubimyczytac:lub-99999</dc:identifier>
<dc:identifier>ranobedb:ranobe-999</dc:identifier>
<dc:identifier>asin:B0G3YRNY6Y</dc:identifier>
Currently these are silently ignored by the parser. They should be recognized as fallbacks when opf:scheme and urn: formats are absent.
2. calibre:user_metadata JSON blob for page count
Calibre stores user-defined custom column values in a <meta property="calibre:user_metadata"> JSON blob. Two common column names users create for page count are #pagecount and #page_count. Both should be recognized:
<meta property="calibre:user_metadata">{"#pagecount":{"#value#":353}}</meta>
<!-- or -->
<meta property="calibre:user_metadata">{"#page_count":{"#value#":400}}</meta>
3. calibre:user_metadata JSON blob for subtitle
The same JSON blob can carry a subtitle under a #subtitle key:
<meta property="calibre:user_metadata">{"#subtitle":{"#value#":"A Subtitle"}}</meta>
In all three cases, these Calibre-specific values should only fill fields that are still null after the standard parsing passes (opf:scheme → urn: → Calibre fallback), preserving full backward compatibility.
What problem does it solve?
Users who manage their book library with Calibre 9.x (the current stable release) and import EPUBs into BookOrbit lose all (Except ISBN) provider identifier metadata silently. Calibre writes identifiers in prefix:value format as its default output — not opf:scheme or urn: format — so Amazon IDs, Goodreads IDs, Google Books IDs, and others are all dropped on import.
Similarly, Calibre users who track page count and subtitle via Calibre custom columns (#pagecount, #page_count, #subtitle) see those fields arrive as null in BookOrbit, even though the data is present in the EPUB file.
This affects any self-hosted user who uses Calibre as their primary library management tool before migrating to or alongside BookOrbit.
Anything else? (optional)
Priority order of parsing (no regressions): Existing opf:scheme and urn: formats retain highest priority. The Calibre fallbacks only activate when those fields are still null.
Implementation approach (no new dependencies required): All three additions work within the existing fast-xml-parser + pure TypeScript parsing already in opf-parser.ts. No new packages needed.
Test coverage: A reference implementation has been locally validated with 23 new unit tests (14 for prefix:value identifiers, 9 for user_metadata JSON) alongside all 63 existing tests passing — 86 total.
Calibre version confirmed: Calibre 9.9 (current stable at time of writing).
Sample real-world OPF snippet from Calibre 9.9:
<dc:identifier>amazon:B0G3YRNY6Y</dc:identifier>
<dc:identifier>goodreads:244564568</dc:identifier>
<meta property="calibre:user_metadata">{"#pagecount":{"#value#":353},"#subtitle":{"#value#":"TEST-SUBTITLE"}}</meta>
Also a docker image based on 1.10.0 with proposed enhancement is available here:
docker pull jadehawk/jh-bookorbit:1.10.0-calibre-meta
Want to help?
Yes, I'd like to implement this
Before submitting
What's your idea?
Extend
server/src/modules/metadata/lib/opf-parser.tsto recognize three additional Calibre-specific metadata encodings that are standard output from Calibre 9.x when EPUBs are exported or modified:1. Calibre
prefix:valueidentifiers in<dc:identifier>Calibre 9.x writes provider IDs directly into
<dc:identifier>elements using aprefix:valueformat instead of theopf:schemeattribute orurn:URN prefix already supported by the parser:Currently these are silently ignored by the parser. They should be recognized as fallbacks when
opf:schemeandurn:formats are absent.2.
calibre:user_metadataJSON blob for page countCalibre stores user-defined custom column values in a
<meta property="calibre:user_metadata">JSON blob. Two common column names users create for page count are#pagecountand#page_count. Both should be recognized:3.
calibre:user_metadataJSON blob for subtitleThe same JSON blob can carry a subtitle under a
#subtitlekey:In all three cases, these Calibre-specific values should only fill fields that are still
nullafter the standard parsing passes (opf:scheme→urn:→ Calibre fallback), preserving full backward compatibility.What problem does it solve?
Users who manage their book library with Calibre 9.x (the current stable release) and import EPUBs into BookOrbit lose all (Except ISBN) provider identifier metadata silently. Calibre writes identifiers in
prefix:valueformat as its default output — notopf:schemeorurn:format — so Amazon IDs, Goodreads IDs, Google Books IDs, and others are all dropped on import.Similarly, Calibre users who track page count and subtitle via Calibre custom columns (
#pagecount,#page_count,#subtitle) see those fields arrive asnullin BookOrbit, even though the data is present in the EPUB file.This affects any self-hosted user who uses Calibre as their primary library management tool before migrating to or alongside BookOrbit.
Anything else? (optional)
Priority order of parsing (no regressions): Existing
opf:schemeandurn:formats retain highest priority. The Calibre fallbacks only activate when those fields are stillnull.Implementation approach (no new dependencies required): All three additions work within the existing
fast-xml-parser+ pure TypeScript parsing already inopf-parser.ts. No new packages needed.Test coverage: A reference implementation has been locally validated with 23 new unit tests (14 for
prefix:valueidentifiers, 9 foruser_metadataJSON) alongside all 63 existing tests passing — 86 total.Calibre version confirmed: Calibre 9.9 (current stable at time of writing).
Sample real-world OPF snippet from Calibre 9.9:
Also a docker image based on 1.10.0 with proposed enhancement is available here:
Want to help?
Yes, I'd like to implement this
Before submitting