1
0
Fork 0
mirror of https://github.com/lise-henry/crowbook synced 2024-05-28 18:16:32 +02:00

added support for customized header numbering

This commit is contained in:
Elisabeth Henry 2016-02-19 04:37:15 +01:00
parent 3a1afc011c
commit 54d4cbecdb
3 changed files with 41 additions and 14 deletions

View File

@ -6,7 +6,9 @@ use std::io::Read;
use std::env;
use std::path::Path;
use mustache;
use mustache::MapBuilder;
use zip::CompressionMethod;
// Numbering for a given chapter
#[derive(Debug, PartialEq, Clone, Copy)]
@ -17,7 +19,6 @@ pub enum Number {
}
// Configuration of the book
#[derive(Debug)]
pub struct Book {
// Generic options
pub numbering: bool, // turns on/off chapter numbering (individual chapters may still avoid it)
@ -30,6 +31,8 @@ pub struct Book {
pub subject: Option<String>,
pub cover: Option<String>,
pub nb_char: char,
pub zip_compression: CompressionMethod,
pub numbering_template: String, // template for chapter numbering
}
impl Book {
@ -46,6 +49,8 @@ impl Book {
subject: None,
cover: None,
nb_char: '',
zip_compression: CompressionMethod::Stored,
numbering_template: String::from("{{number}}. {{title}}"),
}
}
@ -96,6 +101,21 @@ impl Book {
}
}
/// Returns the string corresponding to a number, title, and the numbering template
pub fn get_header(&self, n: i32, title: &str) -> Result<String> {
let template = mustache::compile_str(&self.numbering_template);
let data = MapBuilder::new()
.insert_str("title", String::from(title))
.insert_str("number", format!("{}", n))
.build();
let mut res:Vec<u8> = vec!();
template.render_data(&mut res, &data);
match String::from_utf8(res) {
Err(_) => Err(Error::Render("header generated by mustache was not valid utf-8")),
Ok(res) => Ok(res)
}
}
/// Sets options according to configuration file
///
/// A line with "option: value" sets the option to value
@ -159,6 +179,13 @@ impl Book {
let value = parts[1].trim();
match option {
"nb-char" | "nb_char" => self.set_nb_char(try!(get_char(value))),
"zip-compression" | "zip_compression" => self.zip_compression = match value {
"stored" => CompressionMethod::Stored,
"deflated" => CompressionMethod::Deflated,
"bzip2" => CompressionMethod::Bzip2,
_ => return Err(Error::ConfigParser("unrecognized compression method", String::from(value))),
},
"numbering-template" | "numbering_template" => self.numbering_template = String::from(value),
"numbering" => self.set_numbering(try!(value.parse::<bool>().map_err(bool_error))),
"autoclean" => self.set_autoclean(try!(value.parse::<bool>().map_err(bool_error))),
"author" => self.set_author(String::from(value)),

View File

@ -32,7 +32,7 @@ impl<'a> EpubRenderer<'a> {
book: book,
html: HtmlRenderer::new(book),
current_numbering: book.numbering,
current_chapter: 0,
current_chapter: 1,
toc: vec!(),
}
}
@ -47,7 +47,7 @@ impl<'a> EpubRenderer<'a> {
let mut zip = zip::ZipWriter::new(cursor);
// Write mimetype
try!(zip.start_file("mimetype", zip::CompressionMethod::Stored)
try!(zip.start_file("mimetype", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(b"application/epub+zip")
.map_err(&error_writing));
@ -71,7 +71,7 @@ impl<'a> EpubRenderer<'a> {
let v = try!(parser.parse_file(file));
let chapter = try!(self.render_chapter(&v));
try!(zip.start_file(filenamer(i), zip::CompressionMethod::Stored)
try!(zip.start_file(filenamer(i), self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(chapter.as_bytes())
.map_err(&error_writing));
@ -79,43 +79,43 @@ impl<'a> EpubRenderer<'a> {
}
// Write CSS file
try!(zip.start_file("stylesheet.css", zip::CompressionMethod::Stored)
try!(zip.start_file("stylesheet.css", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(include_str!("../../templates/epub/stylesheet.css").as_bytes())
.map_err(&error_writing));
// Write titlepage
try!(zip.start_file("title_page.xhtml", zip::CompressionMethod::Stored)
try!(zip.start_file("title_page.xhtml", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_titlepage()).as_bytes())
.map_err(&error_writing));
// Write file for ibook (why?)
try!(zip.start_file("META-INF/com.apple.ibooks.display-options.xml", zip::CompressionMethod::Stored)
try!(zip.start_file("META-INF/com.apple.ibooks.display-options.xml", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(include_str!("../../templates/epub/ibookstuff.xml").as_bytes())
.map_err(&error_writing));
// Write container.xml
try!(zip.start_file("META-INF/container.xml", zip::CompressionMethod::Stored)
try!(zip.start_file("META-INF/container.xml", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(include_str!("../../templates/epub/container.xml").as_bytes())
.map_err(&error_writing));
// Write nav.xhtml
try!(zip.start_file("nav.xhtml", zip::CompressionMethod::Stored)
try!(zip.start_file("nav.xhtml", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_nav()).as_bytes())
.map_err(&error_writing));
// Write content.opf
try!(zip.start_file("content.opf", zip::CompressionMethod::Stored)
try!(zip.start_file("content.opf", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_opf()).as_bytes())
.map_err(&error_writing));
// Write toc.ncx
try!(zip.start_file("toc.ncx", zip::CompressionMethod::Stored)
try!(zip.start_file("toc.ncx", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_toc()).as_bytes())
.map_err(&error_writing));
@ -123,7 +123,7 @@ impl<'a> EpubRenderer<'a> {
// Write the cover (if needs be)
if let Some(ref cover) = self.book.cover {
let s: &str = &*cover;
try!(zip.start_file(s, zip::CompressionMethod::Stored)
try!(zip.start_file(s, self.book.zip_compression)
.map_err(&error_creating));
let mut f = try!(File::open(s).map_err(|_| Error::FileNotFound(String::from(s))));
let mut content = vec!();
@ -307,7 +307,7 @@ impl<'a> EpubRenderer<'a> {
let s = if n == 1 && self.current_numbering {
let chapter = self.current_chapter;
self.current_chapter += 1;
format!("Chapitre {}: {}", chapter, self.html.render_vec(vec)) // todo: allow customization
self.book.get_header(chapter, &self.html.render_vec(vec)).unwrap()
} else {
self.html.render_vec(vec)
};

View File

@ -83,7 +83,7 @@ impl<'a> HtmlRenderer<'a> {
let s = if n == 1 && self.current_numbering {
let chapter = self.current_chapter;
self.current_chapter += 1;
format!("Chapitre {}: {}", chapter, self.render_vec(vec)) // todo: allow customization
self.book.get_header(chapter, &self.render_vec(vec)).unwrap()
} else {
self.render_vec(vec)
};