summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-11-04 15:25:31 +0300
committerA Farzat <a@farzat.xyz>2026-11-04 15:35:27 +0300
commit3d54b73266646f73e855a175dbfd86ca2d50ba96 (patch)
tree07708ce988d1d70b2d79af360338398a640975ad /src
parent1020098497c37b7acfe3ff70845db58c3de22f98 (diff)
downloadoreilly-epub-3d54b73266646f73e855a175dbfd86ca2d50ba96.tar.gz
oreilly-epub-3d54b73266646f73e855a175dbfd86ca2d50ba96.zip
Record the O'Reilly bookid in the generated EPUBHEADv0.1.4master
Store the O'Reilly bookid as EPUB metadata instead of relying solely on the filename. Preserving the original bookid makes it possible to look up additional information from the upstream O'Reilly resource later, even if the EPUB is renamed or imported into a library manager.
Diffstat (limited to 'src')
-rw-r--r--src/epub.rs3
-rw-r--r--src/main.rs9
-rw-r--r--src/xml.rs21
3 files changed, 26 insertions, 7 deletions
diff --git a/src/epub.rs b/src/epub.rs
index 1336115..96b1f2c 100644
--- a/src/epub.rs
+++ b/src/epub.rs
@@ -96,6 +96,7 @@ pub async fn download_one_file(
/// Creates the EPUB archive (creates zip and includes all files in it).
pub fn create_epub_archive(
+ bookid: &str,
epub_data: &EpubResponse,
epub_root: &Path,
output_epub: &Path,
@@ -154,7 +155,7 @@ pub fn create_epub_archive(
&mut zip,
)?;
} else if entry.ourn == opf_entry.ourn {
- write_modified_opf(buf_reader, &mut zip, &epub_data.descriptions.plain)?;
+ write_modified_opf(buf_reader, &mut zip, bookid, &epub_data.descriptions.plain)?;
} else {
std::io::copy(&mut buf_reader, &mut zip)?;
}
diff --git a/src/main.rs b/src/main.rs
index 141fd12..5b0a2be 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -148,7 +148,14 @@ async fn main() -> Result<()> {
.await?;
}
println!("Generating the EPUB file...");
- create_epub_archive(&epub_data, &epub_root, &epub_path, &file_entries, &chapters)?;
+ create_epub_archive(
+ &args.bookid,
+ &epub_data,
+ &epub_root,
+ &epub_path,
+ &file_entries,
+ &chapters,
+ )?;
Ok(())
}
diff --git a/src/xml.rs b/src/xml.rs
index 239fac3..f37b169 100644
--- a/src/xml.rs
+++ b/src/xml.rs
@@ -124,6 +124,7 @@ pub fn build_epub_chapter<R: BufRead, W: Write>(
pub fn write_modified_opf<R: BufRead, W: Write>(
opf_input: R,
mut out: &mut W,
+ bookid: &str,
description: &str,
) -> Result<()> {
// Setup the XML Reader and Writer.
@@ -146,11 +147,21 @@ pub fn write_modified_opf<R: BufRead, W: Write>(
writer.write_event(Event::Start(tag_data))?;
}
Ok(Event::End(tag_data)) => {
- // Write description if end of metadata is reached without finding one.
- if tag_data.name().as_ref() == b"metadata" && !desc_found {
- writer.write_event(Event::Start(BytesStart::new("dc:description")))?;
- writer.write_event(Event::Text(BytesText::new(description)))?;
- writer.write_event(Event::End(BytesEnd::new("dc:description")))?;
+ // Extra attributes are added just before the closing metadata tag.
+ if tag_data.name().as_ref() == b"metadata" {
+ // A new dc:identifier records the O'Reilly resource ID used to obtain the book.
+ let mut start_elem = BytesStart::new("dc:identifier");
+ start_elem.push_attribute(("id", "oreilly-id"));
+ writer.write_event(Event::Start(start_elem))?;
+ let oreilly_id = &format!("urn:orm:book:{bookid}");
+ writer.write_event(Event::Text(BytesText::new(oreilly_id)))?;
+ writer.write_event(Event::End(BytesEnd::new("dc:identifier")))?;
+ // Write description if end of metadata is reached without finding one.
+ if !desc_found {
+ writer.write_event(Event::Start(BytesStart::new("dc:description")))?;
+ writer.write_event(Event::Text(BytesText::new(description)))?;
+ writer.write_event(Event::End(BytesEnd::new("dc:description")))?;
+ }
}
// Pass through unmodified.
writer.write_event(Event::End(tag_data))?;