Skip to content

Commit fe54604

Browse files
committed
Refactor of site config and cleanup
1 parent d7d48d3 commit fe54604

File tree

14 files changed

+196
-288
lines changed

14 files changed

+196
-288
lines changed

build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn main() {
5454
let output_path = std::env::temp_dir().join("style.css");
5555

5656
let tailwind_output = Command::new("npx")
57-
.args(&[
57+
.args([
5858
"tailwindcss",
5959
"-i", "./assets/input.css",
6060
"-o", &output_path.to_string_lossy(),

src/book_scanner.rs

Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::collections::{HashMap, HashSet};
22
use std::path::PathBuf;
33
use anyhow::{Result, bail};
44
use log::{debug, info, warn};
5-
use walkdir;
65

76
use crate::models::Book;
87
use crate::epub_parser::EpubParser;
@@ -11,22 +10,17 @@ use crate::utils::generate_book_id;
1110
use crate::partial_md5::calculate_partial_md5;
1211

1312
/// Configuration for where to find KOReader metadata
14-
#[derive(Clone, Debug)]
13+
#[derive(Clone, Debug, Default)]
1514
pub enum MetadataLocation {
1615
/// Default: metadata stored in .sdr folder next to each book
16+
#[default]
1717
InBookFolder,
1818
/// Metadata stored in docsettings folder with full path structure
1919
DocSettings(PathBuf),
2020
/// Metadata stored in hashdocsettings folder organized by partial MD5 hash
2121
HashDocSettings(PathBuf),
2222
}
2323

24-
impl Default for MetadataLocation {
25-
fn default() -> Self {
26-
MetadataLocation::InBookFolder
27-
}
28-
}
29-
3024
/// Build an index of metadata files in a docsettings folder.
3125
/// Maps the book filename (e.g., "MyBook.epub") to the metadata file path.
3226
/// Returns an error if duplicate filenames are found.
@@ -48,24 +42,24 @@ fn build_docsettings_index(docsettings_path: &PathBuf) -> Result<HashMap<String,
4842
let path = entry.path();
4943

5044
// Look for .sdr directories
51-
if path.is_dir() {
52-
if let Some(dir_name) = path.file_name().and_then(|s| s.to_str()) {
53-
if dir_name.ends_with(".sdr") {
54-
// Extract the book filename from the sdr directory name
55-
// e.g., "MyBook.sdr" -> "MyBook.epub"
56-
let book_stem = &dir_name[..dir_name.len() - 4]; // Remove ".sdr"
57-
58-
// Check for metadata.epub.lua inside the .sdr folder
59-
let metadata_path = path.join("metadata.epub.lua");
60-
if metadata_path.exists() {
61-
let book_filename = format!("{}.epub", book_stem);
62-
63-
if index.contains_key(&book_filename) {
64-
duplicates.push(book_filename.clone());
65-
} else {
66-
debug!("Found docsettings metadata for: {}", book_filename);
67-
index.insert(book_filename, metadata_path);
68-
}
45+
if path.is_dir()
46+
&& let Some(dir_name) = path.file_name().and_then(|s| s.to_str())
47+
&& let Some(book_stem) = dir_name.strip_suffix(".sdr") {
48+
// Extract the book filename from the sdr directory name
49+
// e.g., "MyBook.sdr" -> "MyBook.epub"
50+
51+
// Check for metadata.epub.lua inside the .sdr folder
52+
let metadata_path = path.join("metadata.epub.lua");
53+
if metadata_path.exists() {
54+
let book_filename = format!("{}.epub", book_stem);
55+
56+
match index.entry(book_filename.clone()) {
57+
std::collections::hash_map::Entry::Occupied(_) => {
58+
duplicates.push(book_filename);
59+
}
60+
std::collections::hash_map::Entry::Vacant(entry) => {
61+
debug!("Found docsettings metadata for: {}", book_filename);
62+
entry.insert(metadata_path);
6963
}
7064
}
7165
}
@@ -110,32 +104,28 @@ fn build_hashdocsettings_index(hashdocsettings_path: &PathBuf) -> Result<HashMap
110104
let path = entry.path();
111105

112106
// Look for .sdr directories with hash names
113-
if path.is_dir() {
114-
if let Some(dir_name) = path.file_name().and_then(|s| s.to_str()) {
115-
if dir_name.ends_with(".sdr") {
116-
// Extract the hash from the directory name
117-
// e.g., "570615f811d504e628db1ef262bea270.sdr" -> "570615f811d504e628db1ef262bea270"
118-
let hash = &dir_name[..dir_name.len() - 4]; // Remove ".sdr"
119-
120-
// Validate it looks like an MD5 hash (32 hex characters)
121-
if hash.len() == 32 && hash.chars().all(|c| c.is_ascii_hexdigit()) {
122-
// Check for metadata file (could be .epub.lua or other extensions)
123-
let epub_metadata_path = path.join("metadata.epub.lua");
124-
if epub_metadata_path.exists() {
125-
debug!("Found hashdocsettings metadata for hash: {}", hash);
126-
index.insert(hash.to_lowercase(), epub_metadata_path);
127-
} else {
128-
// Check for any metadata.*.lua file
129-
if let Ok(entries) = std::fs::read_dir(path) {
130-
for entry in entries.flatten() {
131-
if let Some(name) = entry.file_name().to_str() {
132-
if name.starts_with("metadata.") && name.ends_with(".lua") {
133-
debug!("Found hashdocsettings metadata for hash: {} ({})", hash, name);
134-
index.insert(hash.to_lowercase(), entry.path());
135-
break;
136-
}
137-
}
138-
}
107+
if path.is_dir()
108+
&& let Some(dir_name) = path.file_name().and_then(|s| s.to_str())
109+
&& let Some(hash) = dir_name.strip_suffix(".sdr") {
110+
// Extract the hash from the directory name
111+
// e.g., "570615f811d504e628db1ef262bea270.sdr" -> "570615f811d504e628db1ef262bea270"
112+
113+
// Validate it looks like an MD5 hash (32 hex characters)
114+
if hash.len() == 32 && hash.chars().all(|c| c.is_ascii_hexdigit()) {
115+
// Check for metadata file (could be .epub.lua or other extensions)
116+
let epub_metadata_path = path.join("metadata.epub.lua");
117+
if epub_metadata_path.exists() {
118+
debug!("Found hashdocsettings metadata for hash: {}", hash);
119+
index.insert(hash.to_lowercase(), epub_metadata_path);
120+
} else {
121+
// Check for any metadata.*.lua file
122+
if let Ok(entries) = std::fs::read_dir(path) {
123+
for entry in entries.flatten() {
124+
if let Some(name) = entry.file_name().to_str()
125+
&& name.starts_with("metadata.") && name.ends_with(".lua") {
126+
debug!("Found hashdocsettings metadata for hash: {} ({})", hash, name);
127+
index.insert(hash.to_lowercase(), entry.path());
128+
break;
139129
}
140130
}
141131
}

src/config.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! Site configuration module - bundles generator/watcher configuration.
2+
3+
use crate::book_scanner::MetadataLocation;
4+
use crate::time_config::TimeConfig;
5+
use std::path::PathBuf;
6+
7+
/// Configuration for site generation and file watching.
8+
#[derive(Clone)]
9+
pub struct SiteConfig {
10+
/// Output directory for the generated site
11+
pub output_dir: PathBuf,
12+
/// Title for the generated site
13+
pub site_title: String,
14+
/// Whether to include unread books
15+
pub include_unread: bool,
16+
/// Path to the books directory (optional)
17+
pub books_path: Option<PathBuf>,
18+
/// Where to look for KoReader metadata
19+
pub metadata_location: MetadataLocation,
20+
/// Path to the statistics database (optional)
21+
pub statistics_db_path: Option<PathBuf>,
22+
/// Maximum value for heatmap scale (optional)
23+
pub heatmap_scale_max: Option<u32>,
24+
/// Time zone configuration
25+
pub time_config: TimeConfig,
26+
/// Minimum pages per day for statistics filtering (optional)
27+
pub min_pages_per_day: Option<u32>,
28+
/// Minimum time per day in seconds for statistics filtering (optional)
29+
pub min_time_per_day: Option<u32>,
30+
/// Whether to include all stats or filter to library books only
31+
pub include_all_stats: bool,
32+
}

src/epub_parser.rs

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -226,19 +226,15 @@ impl EpubParser {
226226
}
227227

228228
if let Some(prop) = property {
229-
if prop == "belongs-to-collection" {
230-
if let Ok(Event::Text(text)) = reader.read_event_into(&mut buf) {
231-
if let Some(i) = id {
232-
epub3_collections.insert(i, text.unescape().unwrap_or_default().to_string());
233-
}
234-
}
235-
} else if prop == "group-position" {
236-
if let Ok(Event::Text(text)) = reader.read_event_into(&mut buf) {
237-
if let Some(r) = refines {
238-
let clean_refines = r.trim_start_matches('#');
239-
epub3_indices.insert(clean_refines.to_string(), text.unescape().unwrap_or_default().to_string());
240-
}
241-
}
229+
if prop == "belongs-to-collection"
230+
&& let Ok(Event::Text(text)) = reader.read_event_into(&mut buf)
231+
&& let Some(i) = id {
232+
epub3_collections.insert(i, text.unescape().unwrap_or_default().to_string());
233+
} else if prop == "group-position"
234+
&& let Ok(Event::Text(text)) = reader.read_event_into(&mut buf)
235+
&& let Some(r) = refines {
236+
let clean_refines = r.trim_start_matches('#');
237+
epub3_indices.insert(clean_refines.to_string(), text.unescape().unwrap_or_default().to_string());
242238
}
243239
}
244240
}
@@ -348,21 +344,18 @@ impl EpubParser {
348344
}
349345
}
350346

351-
if let (Some(href), Some(media_type)) = (href, media_type) {
352-
if media_type.starts_with("image/") {
353-
// Check if this is the cover using EPUB 3.0 properties
354-
if let Some(props) = &properties {
355-
if props.contains("cover-image") {
356-
return Ok((Some(href), Some(media_type)));
357-
}
358-
}
359-
360-
// Check if this matches the cover_id from meta tags (EPUB 2.0 style)
361-
if let (Some(cover_id), Some(id)) = (cover_id, &id) {
362-
if id == cover_id {
363-
return Ok((Some(href), Some(media_type)));
364-
}
365-
}
347+
if let (Some(href), Some(media_type)) = (href, media_type)
348+
&& media_type.starts_with("image/") {
349+
// Check if this is the cover using EPUB 3.0 properties
350+
if let Some(props) = &properties
351+
&& props.contains("cover-image") {
352+
return Ok((Some(href), Some(media_type)));
353+
}
354+
355+
// Check if this matches the cover_id from meta tags (EPUB 2.0 style)
356+
if let (Some(cover_id), Some(id)) = (cover_id, &id)
357+
&& id == cover_id {
358+
return Ok((Some(href), Some(media_type)));
366359
}
367360
}
368361
}

0 commit comments

Comments
 (0)