aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/epub.rs204
-rw-r--r--src/main.rs3
2 files changed, 101 insertions, 106 deletions
diff --git a/src/epub.rs b/src/epub.rs
index c4f79e3..882175e 100644
--- a/src/epub.rs
+++ b/src/epub.rs
@@ -8,18 +8,30 @@ pub struct Epub {
}
impl Epub {
- pub fn new(path: &str) -> std::io::Result<Self> {
+ pub fn new(path: &str, meta: bool) -> std::io::Result<Self> {
let file = File::open(path)?;
let mut epub = Epub {
container: zip::ZipArchive::new(file)?,
chapters: Vec::new(),
meta: String::new(),
};
- epub.get_rootfile();
+ let chapters = epub.get_rootfile();
+ if !meta {
+ epub.get_chapters(chapters);
+ }
Ok(epub)
}
- pub fn get_chapters(&mut self) {
- self.chapters = std::mem::take(&mut self.chapters)
+ fn get_text(&mut self, name: &str) -> String {
+ let mut text = String::new();
+ self.container
+ .by_name(name)
+ .unwrap()
+ .read_to_string(&mut text)
+ .unwrap();
+ text
+ }
+ fn get_chapters(&mut self, chapters: Vec<(String, String)>) {
+ self.chapters = chapters
.into_iter()
.filter_map(|(path, title)| {
let xml = self.get_text(&path);
@@ -28,7 +40,7 @@ impl Epub {
let doc = Document::parse(&xml).unwrap();
let body = doc.root_element().last_element_child().unwrap();
let mut chapter = String::new();
- Epub::render(&mut chapter, body);
+ render(body, &mut chapter);
if chapter.is_empty() {
None
} else {
@@ -37,55 +49,7 @@ impl Epub {
})
.collect();
}
- fn render(buf: &mut String, n: Node) {
- if n.is_text() {
- let text = n.text().unwrap();
- if !text.trim().is_empty() {
- buf.push_str(text);
- }
- return;
- }
-
- match n.tag_name().name() {
- "h1" | "h2" | "h3" | "h4" | "h5" | "h6" => {
- buf.push_str("\n\x1b[1m");
- for c in n.children() {
- Self::render(buf, c);
- }
- buf.push_str("\x1b[0m\n");
- }
- "blockquote" | "p" | "tr" => {
- buf.push('\n');
- for c in n.children() {
- Self::render(buf, c);
- }
- buf.push('\n');
- }
- "li" => {
- buf.push_str("\n- ");
- for c in n.children() {
- Self::render(buf, c);
- }
- buf.push('\n');
- }
- "br" => buf.push('\n'),
- _ => {
- for c in n.children() {
- Self::render(buf, c);
- }
- }
- }
- }
- fn get_text(&mut self, name: &str) -> String {
- let mut text = String::new();
- self.container
- .by_name(name)
- .unwrap()
- .read_to_string(&mut text)
- .unwrap();
- text
- }
- fn get_rootfile(&mut self) {
+ fn get_rootfile(&mut self) -> Vec<(String, String)> {
let xml = self.get_text("META-INF/container.xml");
let doc = Document::parse(&xml).unwrap();
let path = doc
@@ -123,7 +87,6 @@ impl Epub {
.for_each(|n| {
manifest.insert(n.attribute("id").unwrap(), n.attribute("href").unwrap());
});
-
if doc.root_element().attribute("version") == Some("3.0") {
let path = manifest_node
.children()
@@ -133,52 +96,15 @@ impl Epub {
.unwrap();
let xml = self.get_text(&format!("{}{}", rootdir, path));
let doc = Document::parse(&xml).unwrap();
-
- doc.descendants()
- .find(|n| n.has_tag_name("nav"))
- .unwrap()
- .descendants()
- .filter(|n| n.has_tag_name("a"))
- .for_each(|n| {
- let path = n.attribute("href").unwrap().to_string();
- let text = n
- .descendants()
- .filter(Node::is_text)
- .map(|n| n.text().unwrap())
- .collect();
- nav.insert(path, text);
- })
+ epub3(doc, &mut nav);
} else {
let toc = spine_node.attribute("toc").unwrap_or("ncx");
let path = manifest.get(toc).unwrap();
let xml = self.get_text(&format!("{}{}", rootdir, path));
let doc = Document::parse(&xml).unwrap();
-
- doc.descendants()
- .find(|n| n.has_tag_name("navMap"))
- .unwrap()
- .descendants()
- .filter(|n| n.has_tag_name("navPoint"))
- .for_each(|n| {
- let path = n
- .descendants()
- .find(|n| n.has_tag_name("content"))
- .unwrap()
- .attribute("src")
- .unwrap()
- .to_string();
- let text = n
- .descendants()
- .find(|n| n.has_tag_name("text"))
- .unwrap()
- .text()
- .unwrap()
- .to_string();
- nav.insert(path, text);
- })
+ epub2(doc, &mut nav);
}
-
- self.chapters = spine_node
+ spine_node
.children()
.filter(Node::is_element)
.enumerate()
@@ -189,17 +115,87 @@ impl Epub {
let path = format!("{}{}", rootdir, path);
(path, label)
})
- .collect();
+ .collect()
}
}
-#[test]
-fn test_dir() {
- let path = "/mnt/lit/read";
- for entry in std::fs::read_dir(path).unwrap() {
- let path = entry.unwrap().path();
- let s = path.to_str().unwrap();
- println!("testing: {}", s);
- Epub::new(s).unwrap();
+fn render(n: Node, buf: &mut String) {
+ if n.is_text() {
+ let text = n.text().unwrap();
+ if !text.trim().is_empty() {
+ buf.push_str(text);
+ }
+ return;
}
+
+ match n.tag_name().name() {
+ "h1" | "h2" | "h3" | "h4" | "h5" | "h6" => {
+ buf.push_str("\n\x1b[1m");
+ for c in n.children() {
+ render(c, buf);
+ }
+ buf.push_str("\x1b[0m\n");
+ }
+ "blockquote" | "p" | "tr" => {
+ buf.push('\n');
+ for c in n.children() {
+ render(c, buf);
+ }
+ buf.push('\n');
+ }
+ "li" => {
+ buf.push_str("\n- ");
+ for c in n.children() {
+ render(c, buf);
+ }
+ buf.push('\n');
+ }
+ "br" => buf.push('\n'),
+ _ => {
+ for c in n.children() {
+ render(c, buf);
+ }
+ }
+ }
+}
+
+fn epub2(doc: Document, nav: &mut HashMap<String, String>) {
+ doc.descendants()
+ .find(|n| n.has_tag_name("navMap"))
+ .unwrap()
+ .descendants()
+ .filter(|n| n.has_tag_name("navPoint"))
+ .for_each(|n| {
+ let path = n
+ .descendants()
+ .find(|n| n.has_tag_name("content"))
+ .unwrap()
+ .attribute("src")
+ .unwrap()
+ .to_string();
+ let text = n
+ .descendants()
+ .find(|n| n.has_tag_name("text"))
+ .unwrap()
+ .text()
+ .unwrap()
+ .to_string();
+ nav.insert(path, text);
+ });
+}
+fn epub3(doc: Document, nav: &mut HashMap<String, String>) {
+ doc.descendants()
+ .find(|n| n.has_tag_name("nav"))
+ .unwrap()
+ .descendants()
+ .filter(|n| n.has_tag_name("a"))
+ .for_each(|n| {
+ let path = n.attribute("href").unwrap().to_string();
+ let text = n
+ .descendants()
+ .filter(Node::is_text)
+ .map(|n| n.text().unwrap())
+ .collect();
+ nav.insert(path, text);
+ });
}
diff --git a/src/main.rs b/src/main.rs
index 7e16c74..8626541 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -656,7 +656,7 @@ fn main() {
exit(1);
});
- let mut epub = epub::Epub::new(&path).unwrap_or_else(|e| {
+ let epub = epub::Epub::new(&path, meta).unwrap_or_else(|e| {
println!("error reading epub: {}", e);
exit(1);
});
@@ -666,7 +666,6 @@ fn main() {
exit(0);
}
- epub.get_chapters();
let mut bk = Bk::new(epub, args);
// i have never seen crossterm error
bk.run().unwrap();