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

parsing in now done in book, once and for all

This commit is contained in:
Elisabeth Henry 2016-02-19 14:59:37 +01:00
parent 8709cf3aec
commit c2b71fdd39
4 changed files with 38 additions and 151 deletions

View File

@ -1,5 +1,7 @@
use error::{Error,Result};
use cleaner::{Cleaner, French};
use parser::Parser;
use token::Token;
use std::fs::File;
use std::io::Read;
@ -8,7 +10,6 @@ use std::path::Path;
use mustache;
use mustache::MapBuilder;
use zip::CompressionMethod;
// Numbering for a given chapter
#[derive(Debug, PartialEq, Clone, Copy)]
@ -19,11 +20,12 @@ 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)
pub autoclean: bool,
pub chapters: Vec<(Number, String)>, // list of the markdown files to process
pub chapters: Vec<(Number, Vec<Token>)>, // list of the markdown files to process
pub lang: String,
pub author: String,
pub title: String,
@ -31,8 +33,13 @@ 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
pub temp_dir: String,
pub output_epub: Option<String>,
pub output_html: Option<String>,
pub output_pdf: Option<String>,
pub output_tex: Option<String>,
}
impl Book {
@ -49,8 +56,12 @@ impl Book {
subject: None,
cover: None,
nb_char: '',
zip_compression: CompressionMethod::Stored,
numbering_template: String::from("{{number}}. {{title}}"),
temp_dir: String::from("/tmp/"),
output_epub: None,
output_html: None,
output_pdf: None,
output_tex: None,
}
}
@ -154,11 +165,11 @@ impl Book {
if line.starts_with('-') {
//unnumbered chapter
let file = try!(get_filename(line));
self.add_chapter(Number::Unnumbered, String::from(file));
try!(self.add_chapter(Number::Unnumbered, file));
} else if line.starts_with('+') {
//nunmbered chapter
let file = try!(get_filename(line));
self.add_chapter(Number::Default, String::from(file));
try!(self.add_chapter(Number::Default, file));
} else if line.starts_with(|c: char| c.is_digit(10)) {
// chapter with specific number
let parts:Vec<_> = line.splitn(2, |c: char| c == '.' || c == ':' || c == '+').collect();
@ -167,7 +178,7 @@ impl Book {
} else {
let file = try!(get_filename(parts[1]));
let number = try!(parts[0].parse::<i32>().map_err(|_| Error::ConfigParser("Error parsing integer", String::from(line))));
self.add_chapter(Number::Specified(number), String::from(file));
try!(self.add_chapter(Number::Specified(number), file));
}
} else {
// standard case: "option: value"
@ -179,15 +190,14 @@ 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))),
"temp_dir" | "temp-dir" => self.temp_dir = String::from(value),
"output_epub" | "output-epub" => self.output_epub = Some(String::from(value)),
"output_html" | "output-html" => self.output_html = Some(String::from(value)),
"output_tex" | "output-tex" => self.output_tex = Some(String::from(value)),
"output_pdf" | "output-pdf" => self.output_pdf = Some(String::from(value)),
"author" => self.set_author(String::from(value)),
"title" => self.set_title(String::from(value)),
"cover" => self.set_cover(Some(String::from(value))),
@ -270,7 +280,13 @@ impl Book {
///
/// Number: either Default, Unnumbered or Specified(number)
/// File: location of the file for this chapter
pub fn add_chapter(&mut self, number: Number, file: String) {
self.chapters.push((number, file));
pub fn add_chapter(&mut self, number: Number, file: &str) -> Result<()> {
let mut parser = Parser::new();
if let Some(cleaner) = self.get_cleaner() {
parser = parser.with_cleaner(cleaner)
}
let v = try!(parser.parse_file(file));
self.chapters.push((number, v));
Ok(())
}
}

View File

@ -1,16 +1,13 @@
use error::{Error,Result};
use token::Token;
use parser::Parser;
use html::HtmlRenderer;
use book::{Book,Number};
use zipper::Zipper;
use zip;
use mustache;
use chrono;
use uuid;
use std::io;
use std::io::{Read,Write};
use std::path::Path;
use std::fs::File;
@ -46,13 +43,8 @@ impl<'a> EpubRenderer<'a> {
try!(zipper.write("mimetype", b"application/epub+zip"));
// Write chapters
let mut parser = Parser::new();
if let Some(cleaner) = self.book.get_cleaner() {
parser = parser.with_cleaner(cleaner);
}
let mut i = 0;
for &(ref n, ref file) in &self.book.chapters {
for &(ref n, ref v) in &self.book.chapters {
match n {
&Number::Unnumbered => self.current_numbering = false,
&Number::Default => self.current_numbering = self.book.numbering,
@ -61,8 +53,7 @@ impl<'a> EpubRenderer<'a> {
self.current_chapter = n;
}
}
let v = try!(parser.parse_file(file));
let chapter = try!(self.render_chapter(&v));
let chapter = try!(self.render_chapter(v));
try!(zipper.write(&filenamer(i), &chapter.as_bytes()));
i += 1;
@ -105,115 +96,6 @@ impl<'a> EpubRenderer<'a> {
Ok(res)
}
/// Render a book
pub fn render_book_old(&mut self) -> Result<Vec<u8>> {
let error_creating = |_| Error::Render("Error creating new file in zip");
let error_writing = |_| Error::Render("Error writing to file in zip");
let buffer: Vec<u8> = vec!();
let cursor = io::Cursor::new(buffer);
let mut zip = zip::ZipWriter::new(cursor);
// Write mimetype
try!(zip.start_file("mimetype", zip::CompressionMethod::Stored)
.map_err(&error_creating));
try!(zip.write(b"application/epub+zip")
.map_err(&error_writing));
// Write chapters
let mut parser = Parser::new();
if let Some(cleaner) = self.book.get_cleaner() {
parser = parser.with_cleaner(cleaner);
}
let mut i = 0;
for &(ref n, ref file) in &self.book.chapters {
match n {
&Number::Unnumbered => self.current_numbering = false,
&Number::Default => self.current_numbering = self.book.numbering,
&Number::Specified(n) => {
self.current_numbering = self.book.numbering;
self.current_chapter = n;
}
}
let v = try!(parser.parse_file(file));
let chapter = try!(self.render_chapter(&v));
try!(zip.start_file(filenamer(i), self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(chapter.as_bytes())
.map_err(&error_writing));
i += 1;
}
// Write CSS file
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", 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", 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", 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", 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", 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", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_toc()).as_bytes())
.map_err(&error_writing));
// Write the cover (if needs be)
if let Some(ref cover) = self.book.cover {
let s: &str = &*cover;
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!();
try!(f.read_to_end(&mut content).map_err(|_| Error::Render("Error while reading cover file")));
try!(zip.write(&content)
.map_err(&error_writing));
// also write cover.xhtml
try!(zip.start_file("cover.xhtml", self.book.zip_compression)
.map_err(&error_creating));
try!(zip.write(try!(self.render_cover()).as_bytes())
.map_err(&error_writing));
}
// Get back the buffer
let buf = try!(zip.finish()
.map_err(|_| Error::Render("Error finishing zip file")));
Ok(buf.into_inner())
}
/// Render the titlepgae
fn render_titlepage(&self) -> Result<String> {
let template = mustache::compile_str(include_str!("../../templates/epub/titlepage.xhtml"));

View File

@ -1,7 +1,6 @@
use escape::escape_html;
use token::Token;
use book::{Book, Number};
use parser::Parser;
use error::{Error,Result};
use mustache;
@ -27,14 +26,9 @@ impl<'a> HtmlRenderer<'a> {
/// Render books as a standalone HTML file
pub fn render_book(&mut self) -> Result<String> {
let mut parser = Parser::new();
if let Some(cleaner) = self.book.get_cleaner() {
parser = parser.with_cleaner(cleaner);
}
let mut content = String::new();
for &(ref n, ref file) in &self.book.chapters {
for &(ref n, ref v) in &self.book.chapters {
match n {
&Number::Unnumbered => self.current_numbering = false,
&Number::Default => self.current_numbering = self.book.numbering,
@ -43,8 +37,7 @@ impl<'a> HtmlRenderer<'a> {
self.current_chapter = n;
}
}
let v = try!(parser.parse_file(file));
for token in &v {
for token in v {
content.push_str(&self.parse_token(token));
}
}

View File

@ -1,6 +1,5 @@
use book::{Book, Number};
use error::{Error,Result};
use parser::Parser;
use token::Token;
use mustache;
@ -23,12 +22,9 @@ impl<'a> LatexRenderer<'a> {
/// Render latex in a string
pub fn render_book(&mut self) -> Result<String> {
let mut content = String::from("");
let mut parser = Parser::new();
for &(ref n, ref file) in &self.book.chapters {
self.current_chapter = *n;
let v = try!(parser.parse_file(file));
content.push_str(&self.render_vec(&v));
for &(n, ref v) in &self.book.chapters {
self.current_chapter = n;
content.push_str(&self.render_vec(v));
}