novel_cli/renderer/
mod.rs

1mod mdbook;
2mod pandoc;
3
4use std::{fs, path::Path, thread};
5
6use color_eyre::eyre::{self, Result};
7use image::DynamicImage;
8
9pub use self::{mdbook::*, pandoc::*};
10use crate::{
11    utils,
12    utils::{Content, Novel},
13};
14
15#[must_use]
16fn image_markdown_str<T>(path: T) -> String
17where
18    T: AsRef<str>,
19{
20    format!("![]({})", path.as_ref())
21}
22
23fn cover_image_name(cover_image: &DynamicImage) -> Result<String> {
24    let image_ext = utils::new_image_ext(cover_image);
25
26    if image_ext.is_ok() {
27        Ok(format!("cover.{}", image_ext.unwrap()))
28    } else {
29        eyre::bail!("{}", image_ext.unwrap_err());
30    }
31}
32
33fn new_image_name(image: &DynamicImage, image_index: u16) -> Result<String> {
34    Ok(format!(
35        "{}.{}",
36        utils::num_to_str(image_index),
37        utils::new_image_ext(image)?
38    ))
39}
40
41fn save_image<T>(novel: &Novel, image_dir_path: T) -> Result<()>
42where
43    T: AsRef<Path>,
44{
45    let image_dir_path = image_dir_path.as_ref();
46    if !image_dir_path.exists() {
47        fs::create_dir_all(image_dir_path)?;
48    }
49
50    if novel.cover_image.is_some() {
51        let cover_image = novel.cover_image.as_ref().unwrap();
52        let image_ext = utils::new_image_ext(cover_image);
53
54        if image_ext.is_ok() {
55            let image_ext = image_ext.unwrap();
56            let image_path = image_dir_path.join(format!("cover.{}", image_ext));
57
58            if image_ext == "webp" {
59                novel_api::save_as_webp(cover_image, 75.0, image_path).unwrap_or_else(|err| {
60                    tracing::error!("Failed to save cover image: {err}");
61                });
62            } else {
63                cover_image.save(image_path).unwrap_or_else(|err| {
64                    tracing::error!("Failed to save image: {err}");
65                });
66            }
67        }
68    }
69
70    let mut images = Vec::new();
71    for volume in &novel.volumes {
72        for chapter in &volume.chapters {
73            if chapter.contents.is_some() {
74                for content in chapter.contents.as_ref().unwrap() {
75                    if let Content::Image(image) = content {
76                        images.push(image);
77                    }
78                }
79            }
80        }
81    }
82
83    thread::scope(|s| {
84        let mut image_index = 1;
85
86        for image in images {
87            let image_ext = utils::new_image_ext(image);
88
89            if image_ext.is_ok() {
90                let image_ext = image_ext.unwrap();
91                let image_name = format!("{}.{}", utils::num_to_str(image_index), image_ext);
92                image_index += 1;
93
94                let image_path = image_dir_path.join(image_name);
95
96                if image_ext == "webp" {
97                    s.spawn(|| {
98                        novel_api::save_as_webp(image, 75.0, image_path).unwrap_or_else(|err| {
99                            tracing::error!("Failed to save cover image: {err}");
100                        });
101                    });
102                } else {
103                    s.spawn(|| {
104                        image.save(image_path).unwrap_or_else(|err| {
105                            tracing::error!("Failed to save image: {err}");
106                        });
107                    });
108                }
109            }
110        }
111    });
112
113    Ok(())
114}