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

a bit of cleaning

This commit is contained in:
Elisabeth Henry 2016-02-19 08:05:18 +01:00
parent bcbe3a097b
commit 8709cf3aec
6 changed files with 120 additions and 84 deletions

View File

@ -1,10 +1,8 @@
extern crate crowbook;
extern crate zip;
use crowbook::{HtmlRenderer, Book, EpubRenderer, LatexRenderer};
use crowbook::{HtmlRenderer, Book, EpubRenderer};
use std::env;
use std::io::Write;
use std::fs::File;
fn main() {
let mut args = env::args();
@ -15,10 +13,10 @@ fn main() {
Some(ref s) => {
let book = Book::new_from_file(s).unwrap();
let mut html = HtmlRenderer::new(&book);
let result = html.render_book().unwrap();
let _ = html.render_book().unwrap();
let mut epub = EpubRenderer::new(&book);
let buf = epub.render_book().unwrap();
println!("{}", epub.render_book().unwrap());
// let mut f = File::create("test.epub").unwrap();
// f.write(&buf);

View File

@ -3,18 +3,17 @@ 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::env;
use std::io;
use std::io::{Read,Write};
use std::fs::{self, File,DirBuilder};
use std::path::Path;
use std::process::Command;
use std::fs::File;
/// Renderer for Epub
///
@ -40,25 +39,11 @@ impl<'a> EpubRenderer<'a> {
}
/// Render a book
pub fn render_book(&mut self) -> Result<Vec<u8>> {
let mut args:Vec<String> = vec!();
let path = "/tmp/crowbook/";
let meta_inf = "/tmp/crowbook/META-INF";
DirBuilder::new()
.recursive(true)
.create(meta_inf).unwrap();
pub fn render_book(&mut self) -> Result<String> {
let mut zipper = try!(Zipper::new("/tmp/crowbook"));
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
let mut f = File::create("/tmp/crowbook/mimetype").unwrap();
f.write_all(b"application/epub+zip").unwrap();
args.push(String::from("mimetype"));
try!(zipper.write("mimetype", b"application/epub+zip"));
// Write chapters
let mut parser = Parser::new();
@ -79,85 +64,45 @@ impl<'a> EpubRenderer<'a> {
let v = try!(parser.parse_file(file));
let chapter = try!(self.render_chapter(&v));
let mut f = File::create(&format!("{}{}", path, filenamer(i))).unwrap();
args.push(filenamer(i));
f.write_all(&chapter.as_bytes()).unwrap();
try!(zipper.write(&filenamer(i), &chapter.as_bytes()));
i += 1;
}
// Write CSS file
let mut f = File::create("/tmp/crowbook/stylesheet.css").unwrap();
f.write_all(include_str!("../../templates/epub/stylesheet.css").as_bytes()).unwrap();
args.push(String::from("stylesheet.css"));
try!(zipper.write("stylesheet.css", include_str!("../../templates/epub/stylesheet.css").as_bytes()));
// Write titlepage
let mut f = File::create("/tmp/crowbook/title_page.xhtml").unwrap();
f.write_all(&try!(self.render_titlepage()).as_bytes()).unwrap();
args.push(String::from("title_page.xhtml"));
try!(zipper.write("title_page.xhtml", &try!(self.render_titlepage()).as_bytes()));
// Write file for ibook (why?)
let mut f = File::create("/tmp/crowbook/META-INF/com.apple.ibooks.display-options.xml").unwrap();
try!(f.write_all(include_str!("../../templates/epub/ibookstuff.xml").as_bytes())
.map_err(&error_writing));
args.push(String::from("META-INF/com.apple.ibooks.display-options.xml"));
try!(zipper.write("META-INF/com.apple.ibooks.display-options.xml", include_str!("../../templates/epub/ibookstuff.xml").as_bytes()));
// Write container.xml
let mut f = File::create("/tmp/crowbook/META-INF/container.xml").unwrap();
try!(f.write_all(include_str!("../../templates/epub/container.xml").as_bytes())
.map_err(&error_writing));
args.push(String::from("META-INF/container.xml"));
try!(zipper.write("META-INF/container.xml", include_str!("../../templates/epub/container.xml").as_bytes()));
// Write nav.xhtml
let mut f = File::create("/tmp/crowbook/nav.xhtml").unwrap();
try!(f.write_all(&try!(self.render_nav()).as_bytes())
.map_err(&error_writing));
args.push(String::from("nav.xhtml"));
try!(zipper.write("nav.xhtml", &try!(self.render_nav()).as_bytes()));
// Write content.opf
let mut f = File::create("/tmp/crowbook/content.opf").unwrap();
try!(f.write_all(&try!(self.render_opf()).as_bytes())
.map_err(&error_writing));
args.push(String::from("content.opf"));
try!(zipper.write("content.opf", &try!(self.render_opf()).as_bytes()));
// Write toc.ncx
let mut f = File::create("/tmp/crowbook/toc.ncx").unwrap();
try!(f.write_all(&try!(self.render_toc()).as_bytes())
.map_err(&error_writing));
args.push(String::from("toc.ncx"));
try!(zipper.write("toc.ncx", &try!(self.render_toc()).as_bytes()));
// Write the cover (if needs be)
if let Some(ref cover) = self.book.cover {
let s: &str = &*cover;
let mut f_target = File::create(&format!("{}{}", path, s)).unwrap();
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!(f_target.write_all(&content)
.map_err(&error_writing));
args.push(String::from(s));
try!(zipper.write(s, &content));
// also write cover.xhtml
let mut f = File::create("/tmp/crowbook/cover.xhtml").unwrap();
try!(f.write_all(&try!(self.render_cover()).as_bytes())
.map_err(&error_writing));
args.push(String::from("cover.xhtml"));
try!(zipper.write("over.xhtml", &try!(self.render_cover()).as_bytes()));
}
let dir = env::current_dir().unwrap();
env::set_current_dir(path).unwrap();
let output = Command::new("zip")
.arg("test.epub")
.args(&args)
.output()
.unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
println!("{}", String::from_utf8(output.stdout).unwrap());
env::set_current_dir(dir);
fs::copy("/tmp/crowbook/test.epub", "test.epub").unwrap();
fs::remove_dir_all(path).unwrap();
Ok(vec!())
let res = try!(zipper.generate_epub("test.epub"));
Ok(res)
}
@ -334,7 +279,7 @@ impl<'a> EpubRenderer<'a> {
let mut items = String::new();
let mut itemrefs = String::new();
let mut coverref = String::new();
if let Some(ref s) = self.book.cover {
if let Some(_) = self.book.cover {
items.push_str("<item id = \"cover.xhtml\" href = \"cover.xhtml\" media-type = \"application/xhtml+xml\" />\n");
coverref.push_str("<itemref idref = \"cover.xhtml\" />");
}

View File

@ -32,7 +32,7 @@ impl<'a> LatexRenderer<'a> {
}
let mut tex_lang = String::from(match &*self.book.lang {
let tex_lang = String::from(match &*self.book.lang {
"en" => "english",
"fr" => "francais",
_ => {
@ -72,12 +72,20 @@ impl<'a> LatexRenderer<'a> {
self.render_vec(vec)),
Token::Header(n, ref vec) => {
let mut content = String::new();
if let Number::Specified(n) = self.current_chapter {
content.push_str(r"\setcounter{chapter}{");
content.push_str(&format!("{}", n - 1));
content.push_str("}\n");
if n == 1 {
if let Number::Specified(n) = self.current_chapter {
content.push_str(r"\setcounter{chapter}{");
content.push_str(&format!("{}", n - 1));
content.push_str("}\n");
}
}
match n {
1 => content.push_str(r"\chapter"),
2 => content.push_str(r"\section"),
3 => content.push_str(r"\subsection"),
4 => content.push_str(r"\subsubsection"),
_ => panic!("header level not implemented"),
}
content.push_str(r"\chapter");
if self.current_chapter == Number::Unnumbered {
content.push_str("*");
}

View File

@ -24,3 +24,5 @@ pub use error::{Result, Error};
pub use book::Book;
pub use epub::EpubRenderer;
pub use latex::LatexRenderer;
mod zipper;

66
src/lib/zipper.rs Normal file
View File

@ -0,0 +1,66 @@
use error::{Error,Result};
use std::env;
use std::path::{Path,PathBuf};
use std::io::Write;
use std::process::Command;
use std::fs::{self, File,DirBuilder};
use uuid;
/// Struct used to create zip (using filesystem and zip command)
pub struct Zipper {
args: Vec<String>,
path: PathBuf,
}
impl Zipper {
/// creates new zipper
pub fn new(path: &str) -> Result<Zipper> {
let uuid = uuid::Uuid::new_v4();
let zipper = Zipper {
args:vec!(),
path: Path::new(path).join(uuid.to_simple_string())
};
let res = DirBuilder::new()
.recursive(true)
.create(zipper.path.join("META-INF"));
if !res.is_ok() {
Err(Error::Render("could not create temporary directory for generating epub"))
} else {
Ok(zipper)
}
}
/// writes a content to a temporary file
pub fn write(&mut self, file: &str, content: &[u8]) -> Result<()> {
if let Ok(mut f) = File::create(self.path.join(file)) {
if f.write_all(content).is_ok() {
self.args.push(String::from(file));
Ok(())
} else {
Err(Error::Render("could not write to temporary file while generating epub"))
}
} else {
Err(Error::Render("could not create temporary file for generating epub"))
}
}
/// generate an epub into given file name
pub fn generate_epub(&mut self, file: &str) -> Result<String> {
let dir = try!(env::current_dir().map_err(|_| Error::Render("could not get current directory")));
try!(env::set_current_dir(&self.path).map_err(|_| Error::Render("could not change current directory")));
let output = Command::new("zip")
.arg("-X")
.arg(file)
.args(&self.args)
.output()
.unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
try!(env::set_current_dir(dir).map_err(|_| Error::Render("could not change back to old directory")));
try!(fs::copy(self.path.join(file), file).map_err(|_| Error::Render("could not copy epub file")));
try!(fs::remove_dir_all(&self.path).map_err(|_| Error::Render("could not delete temporary directory")));
String::from_utf8(output.stdout).map_err(|_| Error::Render("invalid utf-8 code in command output"))
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{lang}}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="crowbook" />
<title>{{title}}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
</head>
<body>
<div id="cover">
<img src="{{cover}}" alt="{{title}}" />
</div>
</body>
</html>