nmd_core/utility/
image_utility.rs1use oxipng::Options;
2use crate::{codex::{modifier::ModifiersBucket, Codex}, compilable_text::{compilable_text_part::CompilableTextPart, CompilableText}, compilation::{compilable::Compilable, compilation_configuration::{compilation_configuration_overlay::CompilationConfigurationOverLay, CompilationConfiguration}, compilation_error::CompilationError, compilation_outcome::CompilationOutcome}, output_format::OutputFormat, resource::{image_resource::ImageResource, source::Source, ResourceError}};
3use super::{nmd_unique_identifier::NmdUniqueIdentifier, text_utility};
4
5
6pub fn set_image_base64_embed_src(image: &mut ImageResource, compression: bool) -> Result<(), ResourceError> {
7
8 let src = image.src().clone();
9
10 let src = src.try_into_bytes()?;
11
12 if let Source::Bytes { mut bytes } = src {
13
14 if compression {
15
16 let original_log_level = log::max_level();
17 log::set_max_level(log::LevelFilter::Warn);
18
19 let options = Options::max_compression();
20
21 let optimized_png = oxipng::optimize_from_memory(&bytes, &options);
22
23 log::set_max_level(original_log_level);
24
25 match optimized_png {
26 Ok(image) => bytes = image,
27 Err(err) => return Err(ResourceError::ElaborationError(format!("image compression error: {}", err)))
28 }
29
30 }
31
32 let src = Source::Bytes { bytes };
33
34 image.set_src(src.try_into_base64()?);
35
36 return Ok(())
37 }
38
39 unreachable!("'try_into_bytes' must return bytes type")
40}
41
42
43pub fn compile_image_resource_in_html(image: &ImageResource, img_classes: Vec<&str>, nuid: Option<&NmdUniqueIdentifier>, codex: &Codex, compilation_configuration: &CompilationConfiguration, compilation_configuration_overlay: CompilationConfigurationOverLay) -> Result<CompilationOutcome, CompilationError> {
44
45 let mut outcome = String::new();
46
47 let id_attr: String;
48
49 if let Some(id) = image.id() {
50 id_attr = format!(r#"id="{}""#, id.build_without_internal_sharp());
51 } else {
52 id_attr = String::new();
53 }
54
55 let styles: String;
56 let classes: String;
57
58 if let Some(style) = image.style() {
59
60 let (s, c) = text_utility::split_styles_and_classes(style);
61
62 styles = s.unwrap_or(String::new());
63 classes = c.unwrap_or(String::new());
64
65 } else {
66
67 styles = String::new();
68 classes = String::new();
69 }
70
71 outcome.push_str(&format!(r#"<figure class="figure {}" style="{}" {} {}>"#, classes, styles, id_attr, text_utility::html_nuid_tag_or_nothing(nuid)));
72
73 let src: String = match image.src() {
74 Source::Remote { url: _ } | Source::Local { path: _ } => image.src().to_string(),
75 Source::Base64String { base64 } => {
76 if image.mime_type().is_none() {
77
78 panic!("base64 image without mime type")
79 }
80
81 format!("data:{};base64,{}", image.mime_type().as_ref().unwrap(), base64)
82 },
83 Source::Bytes { bytes: _ } => {
84
85 let base64 = image.src().try_to_base64()?;
86
87 if image.mime_type().is_none() {
88
89 panic!("base64 image without mime type")
90 }
91
92 format!("data:{};base64,{}", image.mime_type().as_ref().unwrap(), base64)
93 },
94 };
95
96 outcome.push_str(&format!(r#"<img src="{}" class="{}" />"#, src, img_classes.join(" ")));
97
98
99 if let Some(caption) = image.caption() {
100
101 outcome.push_str(r#"<figcaption class="image-caption">"#);
102
103 let mut compilable_text = CompilableText::from(CompilableTextPart::new_compilable(caption.clone(), ModifiersBucket::None));
104
105 outcome.push_str(&compilable_text.compile(&OutputFormat::Html, codex, compilation_configuration, compilation_configuration_overlay.clone())?.content());
106
107 outcome.push_str(r#"</figcaption>"#);
108 }
109
110 outcome.push_str("</figure>");
111
112 Ok(CompilationOutcome::from(outcome))
113}