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:
parent
8709cf3aec
commit
c2b71fdd39
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
122
src/lib/epub.rs
122
src/lib/epub.rs
|
@ -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"));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue