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:
parent
bcbe3a097b
commit
8709cf3aec
|
@ -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);
|
||||
|
|
|
@ -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\" />");
|
||||
}
|
||||
|
|
|
@ -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("*");
|
||||
}
|
||||
|
|
|
@ -24,3 +24,5 @@ pub use error::{Result, Error};
|
|||
pub use book::Book;
|
||||
pub use epub::EpubRenderer;
|
||||
pub use latex::LatexRenderer;
|
||||
|
||||
mod zipper;
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
Loading…
Reference in New Issue