1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct GeneratorConfig {
11 pub output_format: OutputFormat,
13 pub include_examples: bool,
15 pub validate_examples: bool,
17 pub include_type_info: bool,
19 pub include_cross_refs: bool,
21 pub max_hierarchy_depth: usize,
23 pub include_private: bool,
25 pub custom_styling: Option<String>,
27}
28
29impl GeneratorConfig {
30 pub fn new() -> Self {
32 Self {
33 output_format: OutputFormat::Json,
34 include_examples: true,
35 validate_examples: false, include_type_info: true,
37 include_cross_refs: true,
38 max_hierarchy_depth: 5,
39 include_private: false,
40 custom_styling: None,
41 }
42 }
43
44 pub fn with_output_format(mut self, format: OutputFormat) -> Self {
46 self.output_format = format;
47 self
48 }
49
50 pub fn with_validation(mut self, validate: bool) -> Self {
52 self.validate_examples = validate;
53 self
54 }
55
56 pub fn with_examples(mut self, include: bool) -> Self {
58 self.include_examples = include;
59 self
60 }
61
62 pub fn with_max_depth(mut self, depth: usize) -> Self {
64 self.max_hierarchy_depth = depth;
65 self
66 }
67
68 pub fn with_private_items(mut self, include: bool) -> Self {
70 self.include_private = include;
71 self
72 }
73
74 pub fn with_custom_styling(mut self, css: Option<String>) -> Self {
76 self.custom_styling = css;
77 self
78 }
79
80 pub fn with_type_info(mut self, include: bool) -> Self {
82 self.include_type_info = include;
83 self
84 }
85
86 pub fn with_cross_refs(mut self, include: bool) -> Self {
88 self.include_cross_refs = include;
89 self
90 }
91}
92
93impl Default for GeneratorConfig {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
101pub enum OutputFormat {
102 #[default]
104 Json,
105 Html,
107 Markdown,
109 Interactive,
111 OpenApi,
113}
114
115impl OutputFormat {
116 pub fn file_extension(&self) -> &'static str {
118 match self {
119 OutputFormat::Json => "json",
120 OutputFormat::Html => "html",
121 OutputFormat::Markdown => "md",
122 OutputFormat::Interactive => "html",
123 OutputFormat::OpenApi => "yaml",
124 }
125 }
126
127 pub fn mime_type(&self) -> &'static str {
129 match self {
130 OutputFormat::Json => "application/json",
131 OutputFormat::Html => "text/html",
132 OutputFormat::Markdown => "text/markdown",
133 OutputFormat::Interactive => "text/html",
134 OutputFormat::OpenApi => "application/x-yaml",
135 }
136 }
137
138 pub fn supports_interactive(&self) -> bool {
140 matches!(self, OutputFormat::Html | OutputFormat::Interactive)
141 }
142
143 pub fn supports_syntax_highlighting(&self) -> bool {
145 matches!(
146 self,
147 OutputFormat::Html | OutputFormat::Interactive | OutputFormat::Markdown
148 )
149 }
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct PlaygroundConfig {
155 pub wasm_enabled: bool,
157 pub real_time_execution: bool,
159 pub syntax_highlighting: bool,
161 pub auto_completion: bool,
163 pub error_highlighting: bool,
165 pub available_crates: Vec<String>,
167 pub example_count: usize,
169 pub trait_count: usize,
171 pub type_count: usize,
173}
174
175impl PlaygroundConfig {
176 pub fn new() -> Self {
178 Self {
179 wasm_enabled: true,
180 real_time_execution: true,
181 syntax_highlighting: true,
182 auto_completion: true,
183 error_highlighting: true,
184 available_crates: vec!["sklears-core".to_string()],
185 example_count: 0,
186 trait_count: 0,
187 type_count: 0,
188 }
189 }
190
191 pub fn with_wasm(mut self, enabled: bool) -> Self {
193 self.wasm_enabled = enabled;
194 self
195 }
196
197 pub fn with_real_time_execution(mut self, enabled: bool) -> Self {
199 self.real_time_execution = enabled;
200 self
201 }
202
203 pub fn with_syntax_highlighting(mut self, enabled: bool) -> Self {
205 self.syntax_highlighting = enabled;
206 self
207 }
208
209 pub fn with_auto_completion(mut self, enabled: bool) -> Self {
211 self.auto_completion = enabled;
212 self
213 }
214
215 pub fn with_error_highlighting(mut self, enabled: bool) -> Self {
217 self.error_highlighting = enabled;
218 self
219 }
220
221 pub fn with_available_crates(mut self, crates: Vec<String>) -> Self {
223 self.available_crates = crates;
224 self
225 }
226
227 pub fn with_stats(
229 mut self,
230 example_count: usize,
231 trait_count: usize,
232 type_count: usize,
233 ) -> Self {
234 self.example_count = example_count;
235 self.trait_count = trait_count;
236 self.type_count = type_count;
237 self
238 }
239}
240
241impl Default for PlaygroundConfig {
242 fn default() -> Self {
243 Self::new()
244 }
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct ValidationConfig {
250 pub compile_check: bool,
252 pub runtime_check: bool,
254 pub timeout_ms: u64,
256 pub max_memory: usize,
258 pub lint_check: bool,
260 pub extra_flags: Vec<String>,
262}
263
264impl ValidationConfig {
265 pub fn new() -> Self {
267 Self {
268 compile_check: true,
269 runtime_check: false,
270 timeout_ms: 5000,
271 max_memory: 1024 * 1024 * 50, lint_check: true,
273 extra_flags: Vec::new(),
274 }
275 }
276
277 pub fn with_compile_check(mut self, enabled: bool) -> Self {
279 self.compile_check = enabled;
280 self
281 }
282
283 pub fn with_runtime_check(mut self, enabled: bool) -> Self {
285 self.runtime_check = enabled;
286 self
287 }
288
289 pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
291 self.timeout_ms = timeout_ms;
292 self
293 }
294
295 pub fn with_max_memory(mut self, max_memory: usize) -> Self {
297 self.max_memory = max_memory;
298 self
299 }
300
301 pub fn with_lint_check(mut self, enabled: bool) -> Self {
303 self.lint_check = enabled;
304 self
305 }
306
307 pub fn with_extra_flags(mut self, flags: Vec<String>) -> Self {
309 self.extra_flags = flags;
310 self
311 }
312}
313
314impl Default for ValidationConfig {
315 fn default() -> Self {
316 Self::new()
317 }
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct ThemeConfig {
323 pub primary_color: String,
325 pub secondary_color: String,
327 pub background_color: String,
329 pub text_color: String,
331 pub code_background: String,
333 pub code_text_color: String,
335 pub font_family: String,
337 pub code_font_family: String,
339 pub dark_mode: bool,
341}
342
343impl ThemeConfig {
344 pub fn light_theme() -> Self {
346 Self {
347 primary_color: "#0066cc".to_string(),
348 secondary_color: "#ff6b35".to_string(),
349 background_color: "#ffffff".to_string(),
350 text_color: "#333333".to_string(),
351 code_background: "#f5f5f5".to_string(),
352 code_text_color: "#333333".to_string(),
353 font_family: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif".to_string(),
354 code_font_family: "'Monaco', 'Menlo', 'Ubuntu Mono', monospace".to_string(),
355 dark_mode: false,
356 }
357 }
358
359 pub fn dark_theme() -> Self {
361 Self {
362 primary_color: "#4da6ff".to_string(),
363 secondary_color: "#ff8c66".to_string(),
364 background_color: "#1e1e1e".to_string(),
365 text_color: "#d4d4d4".to_string(),
366 code_background: "#2d2d30".to_string(),
367 code_text_color: "#d4d4d4".to_string(),
368 font_family: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif".to_string(),
369 code_font_family: "'Monaco', 'Menlo', 'Ubuntu Mono', monospace".to_string(),
370 dark_mode: true,
371 }
372 }
373
374 pub fn to_css_variables(&self) -> String {
376 format!(
377 r#":root {{
378 --primary-color: {};
379 --secondary-color: {};
380 --background-color: {};
381 --text-color: {};
382 --code-background: {};
383 --code-text-color: {};
384 --font-family: {};
385 --code-font-family: {};
386}}"#,
387 self.primary_color,
388 self.secondary_color,
389 self.background_color,
390 self.text_color,
391 self.code_background,
392 self.code_text_color,
393 self.font_family,
394 self.code_font_family
395 )
396 }
397}
398
399impl Default for ThemeConfig {
400 fn default() -> Self {
401 Self::light_theme()
402 }
403}
404
405#[allow(non_snake_case)]
410#[cfg(test)]
411mod tests {
412 use super::*;
413
414 #[test]
415 fn test_generator_config_creation() {
416 let config = GeneratorConfig::new();
417 assert_eq!(config.output_format, OutputFormat::Json);
418 assert!(config.include_examples);
419 assert!(!config.validate_examples);
420 assert!(config.include_type_info);
421 assert!(config.include_cross_refs);
422 assert_eq!(config.max_hierarchy_depth, 5);
423 assert!(!config.include_private);
424 assert!(config.custom_styling.is_none());
425 }
426
427 #[test]
428 fn test_generator_config_builder() {
429 let config = GeneratorConfig::new()
430 .with_output_format(OutputFormat::Html)
431 .with_validation(true)
432 .with_examples(false)
433 .with_max_depth(10)
434 .with_private_items(true);
435
436 assert_eq!(config.output_format, OutputFormat::Html);
437 assert!(config.validate_examples);
438 assert!(!config.include_examples);
439 assert_eq!(config.max_hierarchy_depth, 10);
440 assert!(config.include_private);
441 }
442
443 #[test]
444 fn test_output_format_properties() {
445 assert_eq!(OutputFormat::Json.file_extension(), "json");
446 assert_eq!(OutputFormat::Html.file_extension(), "html");
447 assert_eq!(OutputFormat::Markdown.file_extension(), "md");
448 assert_eq!(OutputFormat::Interactive.file_extension(), "html");
449 assert_eq!(OutputFormat::OpenApi.file_extension(), "yaml");
450
451 assert_eq!(OutputFormat::Json.mime_type(), "application/json");
452 assert_eq!(OutputFormat::Html.mime_type(), "text/html");
453 assert_eq!(OutputFormat::Markdown.mime_type(), "text/markdown");
454
455 assert!(!OutputFormat::Json.supports_interactive());
456 assert!(OutputFormat::Html.supports_interactive());
457 assert!(OutputFormat::Interactive.supports_interactive());
458
459 assert!(!OutputFormat::Json.supports_syntax_highlighting());
460 assert!(OutputFormat::Html.supports_syntax_highlighting());
461 assert!(OutputFormat::Markdown.supports_syntax_highlighting());
462 }
463
464 #[test]
465 fn test_playground_config() {
466 let config = PlaygroundConfig::new()
467 .with_wasm(false)
468 .with_real_time_execution(false)
469 .with_available_crates(vec!["sklears-core".to_string(), "std".to_string()])
470 .with_stats(10, 5, 8);
471
472 assert!(!config.wasm_enabled);
473 assert!(!config.real_time_execution);
474 assert!(config.syntax_highlighting);
475 assert_eq!(config.available_crates.len(), 2);
476 assert_eq!(config.example_count, 10);
477 assert_eq!(config.trait_count, 5);
478 assert_eq!(config.type_count, 8);
479 }
480
481 #[test]
482 fn test_validation_config() {
483 let config = ValidationConfig::new()
484 .with_compile_check(false)
485 .with_runtime_check(true)
486 .with_timeout(10000)
487 .with_max_memory(1024 * 1024 * 100);
488
489 assert!(!config.compile_check);
490 assert!(config.runtime_check);
491 assert_eq!(config.timeout_ms, 10000);
492 assert_eq!(config.max_memory, 1024 * 1024 * 100);
493 assert!(config.lint_check);
494 }
495
496 #[test]
497 fn test_theme_config_light() {
498 let theme = ThemeConfig::light_theme();
499 assert_eq!(theme.primary_color, "#0066cc");
500 assert_eq!(theme.background_color, "#ffffff");
501 assert!(!theme.dark_mode);
502
503 let css = theme.to_css_variables();
504 assert!(css.contains("--primary-color: #0066cc"));
505 assert!(css.contains("--background-color: #ffffff"));
506 }
507
508 #[test]
509 fn test_theme_config_dark() {
510 let theme = ThemeConfig::dark_theme();
511 assert_eq!(theme.primary_color, "#4da6ff");
512 assert_eq!(theme.background_color, "#1e1e1e");
513 assert!(theme.dark_mode);
514
515 let css = theme.to_css_variables();
516 assert!(css.contains("--primary-color: #4da6ff"));
517 assert!(css.contains("--background-color: #1e1e1e"));
518 }
519
520 #[test]
521 fn test_config_serialization() {
522 let config = GeneratorConfig::new().with_output_format(OutputFormat::Html);
523 let serialized = serde_json::to_string(&config).unwrap();
524 let deserialized: GeneratorConfig = serde_json::from_str(&serialized).unwrap();
525
526 assert_eq!(config.output_format, deserialized.output_format);
527 assert_eq!(config.include_examples, deserialized.include_examples);
528 }
529
530 #[test]
531 fn test_default_implementations() {
532 let _: GeneratorConfig = Default::default();
533 let _: OutputFormat = Default::default();
534 let _: PlaygroundConfig = Default::default();
535 let _: ValidationConfig = Default::default();
536 let _: ThemeConfig = Default::default();
537 }
538}