feat(layout): detect reflowable vs fixed-layout EPUB, fix pagination overflow
This commit is contained in:
37
src/book.rs
37
src/book.rs
@@ -187,22 +187,57 @@ pub struct Section {
|
||||
pub pages: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum BookLayout {
|
||||
Reflowable,
|
||||
FixedLayout,
|
||||
}
|
||||
|
||||
impl BookLayout {
|
||||
pub fn label(&self) -> &str {
|
||||
match self {
|
||||
BookLayout::Reflowable => "重排",
|
||||
BookLayout::FixedLayout => "固定",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Book {
|
||||
pub title: String,
|
||||
pub author: String,
|
||||
pub cover: Option<Vec<u8>>,
|
||||
pub layout: BookLayout,
|
||||
pub sections: Vec<Section>,
|
||||
pub toc: Vec<TocEntry>,
|
||||
}
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
fn detect_layout(doc: &mut epub::doc::EpubDoc<std::io::BufReader<std::fs::File>>) -> BookLayout {
|
||||
if let Some(vals) = doc.metadata.get("rendition:layout") {
|
||||
if vals.iter().any(|v| v == "pre-paginated") {
|
||||
return BookLayout::FixedLayout;
|
||||
}
|
||||
}
|
||||
if let Ok(opf) = doc.get_resource_str_by_path(&doc.root_file.clone()) {
|
||||
if opf.contains("rendition:layout") && opf.contains("pre-paginated") {
|
||||
return BookLayout::FixedLayout;
|
||||
}
|
||||
if opf.contains("rendition:layout-pre-paginated") {
|
||||
return BookLayout::FixedLayout;
|
||||
}
|
||||
}
|
||||
BookLayout::Reflowable
|
||||
}
|
||||
|
||||
pub fn load_epub(path: impl AsRef<Path>) -> Result<Book, String> {
|
||||
let path = path.as_ref();
|
||||
let mut doc = epub::doc::EpubDoc::new(path)
|
||||
.map_err(|e| format!("无法打开文件: {}", e))?;
|
||||
|
||||
let layout = detect_layout(&mut doc);
|
||||
|
||||
let title = doc.mdata("title").unwrap_or_else(|| "未知标题".to_string());
|
||||
let author = doc.mdata("creator").unwrap_or_else(|| "未知作者".to_string());
|
||||
let cover = doc.get_cover().ok();
|
||||
@@ -225,7 +260,7 @@ pub fn load_epub(path: impl AsRef<Path>) -> Result<Book, String> {
|
||||
let raw_toc = std::mem::take(&mut doc.toc);
|
||||
let toc = build_toc(&raw_toc, &spine);
|
||||
|
||||
Ok(Book { title, author, cover, sections, toc })
|
||||
Ok(Book { title, author, cover, layout, sections, toc })
|
||||
}
|
||||
|
||||
fn extract_title(html: &str) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user