diff options
author | Thomas Letan <contact@thomasletan.fr> | 2019-08-04 19:58:57 +0200 |
---|---|---|
committer | Thomas Letan <contact@thomasletan.fr> | 2019-08-04 19:58:57 +0200 |
commit | 0bf4bba687829ff71ed8e5e3943948ce03812087 (patch) | |
tree | b26883de9273c7dc2ca87d379c0ec39b9828bc66 | |
parent | feature: Generate a table of contents (diff) |
feature: Allows for specifying a cover image for your book
-rw-r--r-- | src/epub.rs | 20 | ||||
-rw-r--r-- | src/project.rs | 11 | ||||
-rw-r--r-- | templates/content.opf | 6 |
3 files changed, 35 insertions, 2 deletions
diff --git a/src/epub.rs b/src/epub.rs index 10e5937..765f213 100644 --- a/src/epub.rs +++ b/src/epub.rs @@ -100,6 +100,21 @@ fn install_fonts(assets : &PathBuf, fonts : &Vec<&str>) -> Result<(), Error> { Ok(()) } +fn install_cover(cover : &PathBuf) -> Result<String, Error> { + let extension = cover.extension() + .ok_or(Error(String::from("cover lacks an extension")))? + .to_str() + .ok_or(Error(String::from("cover extension is not valid utf-8")))?; + + let mut dst = PathBuf::from("OEBPS"); + dst.push(format!("cover.{}", extension)); + + std::fs::copy(cover, dst) + .map_err(|_| Error(format!("cannot copy {:?}", cover)))?; + + Ok(extension.into()) +} + pub fn generate(project : &Project<String>, assets : &PathBuf) -> Result<(), Error> { let tera = compile_templates!(template_dir(assets)?.as_str()); @@ -116,6 +131,10 @@ pub fn generate(project : &Project<String>, assets : &PathBuf) -> Result<(), Err &PathBuf::from("OEBPS/Style/main.css") )?; + let cover_extension = project.cover.clone().map(|cov| install_cover(&cov)) + // from Option<Result<_, E>> to Result<Option<_>, E> + .map_or(Ok(None), |r| r.map(Some))?; + let fonts = vec![ "et-book-roman-line-figures.ttf", "et-book-bold-line-figures.ttf", @@ -127,6 +146,7 @@ pub fn generate(project : &Project<String>, assets : &PathBuf) -> Result<(), Err let mut ctx = Context::new(); ctx.insert("title", &project.title); ctx.insert("author", &project.author); + ctx.insert("cover_extension", &cover_extension); ctx.insert("files", &files); ctx.insert("fonts", &fonts); write_template_to( diff --git a/src/project.rs b/src/project.rs index a0a9aed..05d0f33 100644 --- a/src/project.rs +++ b/src/project.rs @@ -56,7 +56,8 @@ impl Chapter<Vec<PathBuf>> { pub struct Project<A> { pub author: String, pub title: String, - pub chapters: Vec<Chapter<A>> + pub chapters: Vec<Chapter<A>>, + pub cover: Option<PathBuf>, } impl Project<Vec<PathBuf>> { @@ -108,6 +109,11 @@ impl Project<Vec<PathBuf>> { { let author = self.author; let title = self.title; + let cover = self.cover + .map(|x| fs::canonicalize(&x) + .map_err(|_| Error(String::from("cannot compute a canonical path for the cover")))) + // from Option<Result<_, E>> to Result<Option<_>, E> + .map_or(Ok(None), |r| r.map(Some))?; self.chapters.into_iter() .map(|chapter| chapter.load_and_render(typo)) @@ -115,7 +121,8 @@ impl Project<Vec<PathBuf>> { .map(|x| Project { author: author, title: title, - chapters: x + chapters: x, + cover: cover, }) } } diff --git a/templates/content.opf b/templates/content.opf index 823f9d6..b5dad1c 100644 --- a/templates/content.opf +++ b/templates/content.opf @@ -6,6 +6,9 @@ <dc:creator opf:role="aut">{{ author }}</dc:creator> <dc:type>text</dc:type> <dc:description>Ceci est une description</dc:description> + {% if cover_extension %} + <meta name="cover" content="coverimage"/> + {% endif %} </metadata> <manifest> <item href="toc.ncx" id="ncx" media-type="application/x-dtbncx+xml" /> @@ -16,6 +19,9 @@ {% for f in files %} <item href="Text/{{ f }}" id="{{ f }}" media-type="application/xhtml+xml" /> {% endfor %} + {% if cover_extension %} + <item href="cover.{{ cover_extension }}" id="coverimage" media-type="image/jpeg" properties="cover-image" /> + {% endif %} </manifest> <spine toc="ncx"> {% for f in files %} |