html_to_markdown_rs/options/
preprocessing.rs1use crate::options::validation::normalize_token;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
12pub enum PreprocessingPreset {
13 Minimal,
15 #[default]
17 Standard,
18 Aggressive,
20}
21
22impl PreprocessingPreset {
23 #[must_use]
28 #[cfg_attr(alef, alef(skip))]
29 pub fn parse(value: &str) -> Self {
30 match normalize_token(value).as_str() {
31 "minimal" => Self::Minimal,
32 "aggressive" => Self::Aggressive,
33 _ => Self::Standard,
34 }
35 }
36}
37
38#[derive(Debug, Clone)]
40#[cfg_attr(
41 any(feature = "serde", feature = "metadata"),
42 derive(serde::Serialize, serde::Deserialize)
43)]
44#[cfg_attr(any(feature = "serde", feature = "metadata"), serde(default, deny_unknown_fields))]
45pub struct PreprocessingOptions {
46 pub enabled: bool,
48
49 pub preset: PreprocessingPreset,
51
52 pub remove_navigation: bool,
54
55 pub remove_forms: bool,
57}
58
59#[derive(Debug, Clone, Default)]
65#[cfg_attr(
66 any(feature = "serde", feature = "metadata"),
67 derive(serde::Serialize, serde::Deserialize)
68)]
69#[cfg_attr(any(feature = "serde", feature = "metadata"), serde(deny_unknown_fields))]
70pub struct PreprocessingOptionsUpdate {
71 pub enabled: Option<bool>,
73
74 pub preset: Option<PreprocessingPreset>,
76
77 pub remove_navigation: Option<bool>,
79
80 pub remove_forms: Option<bool>,
82}
83
84impl Default for PreprocessingOptions {
85 fn default() -> Self {
86 Self {
87 enabled: true,
88 preset: PreprocessingPreset::default(),
89 remove_navigation: true,
90 remove_forms: true,
91 }
92 }
93}
94
95impl PreprocessingOptions {
96 #[allow(clippy::needless_pass_by_value)]
105 #[cfg_attr(alef, alef(skip))]
106 pub const fn apply_update(&mut self, update: PreprocessingOptionsUpdate) {
107 if let Some(enabled) = update.enabled {
108 self.enabled = enabled;
109 }
110 if let Some(preset) = update.preset {
111 self.preset = preset;
112 }
113 if let Some(remove_navigation) = update.remove_navigation {
114 self.remove_navigation = remove_navigation;
115 }
116 if let Some(remove_forms) = update.remove_forms {
117 self.remove_forms = remove_forms;
118 }
119 }
120
121 #[must_use]
134 #[cfg_attr(alef, alef(skip))]
135 pub fn from_update(update: PreprocessingOptionsUpdate) -> Self {
136 let mut options = Self::default();
137 options.apply_update(update);
138 options
139 }
140}
141
142impl From<PreprocessingOptionsUpdate> for PreprocessingOptions {
143 fn from(update: PreprocessingOptionsUpdate) -> Self {
144 Self::from_update(update)
145 }
146}
147
148#[cfg(any(feature = "serde", feature = "metadata"))]
149mod serde_impls {
150 use super::PreprocessingPreset;
151 use serde::{Deserialize, Serializer};
152
153 impl<'de> Deserialize<'de> for PreprocessingPreset {
154 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155 where
156 D: serde::Deserializer<'de>,
157 {
158 let value = String::deserialize(deserializer)?;
159 Ok(Self::parse(&value))
160 }
161 }
162
163 impl serde::Serialize for PreprocessingPreset {
164 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165 where
166 S: Serializer,
167 {
168 let s = match self {
169 Self::Minimal => "minimal",
170 Self::Standard => "standard",
171 Self::Aggressive => "aggressive",
172 };
173 serializer.serialize_str(s)
174 }
175 }
176}
177
178#[cfg(all(test, any(feature = "serde", feature = "metadata")))]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_preprocessing_options_serde() {
184 let options = PreprocessingOptions {
185 enabled: true,
186 preset: PreprocessingPreset::Aggressive,
187 remove_navigation: false,
188 ..Default::default()
189 };
190
191 let json = serde_json::to_string(&options).expect("Failed to serialize");
193
194 let deserialized: PreprocessingOptions = serde_json::from_str(&json).expect("Failed to deserialize");
196
197 assert!(deserialized.enabled);
199 assert_eq!(deserialized.preset, PreprocessingPreset::Aggressive);
200 assert!(!deserialized.remove_navigation);
201 }
202}