aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Letan <contact@thomasletan.fr>2019-08-04 19:58:57 +0200
committerThomas Letan <contact@thomasletan.fr>2019-08-04 19:58:57 +0200
commit0bf4bba687829ff71ed8e5e3943948ce03812087 (patch)
treeb26883de9273c7dc2ca87d379c0ec39b9828bc66
parentfeature: Generate a table of contents (diff)
feature: Allows for specifying a cover image for your book
-rw-r--r--src/epub.rs20
-rw-r--r--src/project.rs11
-rw-r--r--templates/content.opf6
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 %}