tailwind_rs_postcss/
source_map.rs1use crate::error::Result;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug)]
10pub struct SourceMapGenerator;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct SourceMap {
15 pub version: u32,
16 pub sources: Vec<String>,
17 pub names: Vec<String>,
18 pub mappings: String,
19 pub file: Option<String>,
20 pub source_root: Option<String>,
21 pub sources_content: Option<Vec<String>>,
22}
23
24#[derive(Debug, Clone)]
26pub struct SourceMapOptions {
27 pub inline: bool,
28 pub file: Option<String>,
29 pub source_root: Option<String>,
30 pub sources_content: bool,
31}
32
33impl SourceMapGenerator {
34 pub fn new() -> Self {
36 Self
37 }
38
39 pub fn generate(
41 &self,
42 input: &str,
43 output: &str,
44 options: &SourceMapOptions,
45 ) -> Result<SourceMap> {
46 let sources = if options.sources_content {
48 vec![input.to_string()]
49 } else {
50 vec![]
51 };
52
53 let sources_content = if options.sources_content {
54 Some(vec![input.to_string()])
55 } else {
56 None
57 };
58
59 let mappings = self.generate_mappings(input, output);
61
62 Ok(SourceMap {
63 version: 3,
64 sources,
65 names: Vec::new(),
66 mappings,
67 file: options.file.clone(),
68 source_root: options.source_root.clone(),
69 sources_content,
70 })
71 }
72
73 fn generate_mappings(&self, input: &str, output: &str) -> String {
75 let input_lines = input.lines().count();
78 let output_lines = output.lines().count();
79
80 if input_lines == output_lines {
81 format!("AAAA;{}", input_lines)
83 } else {
84 "AAAA".to_string()
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_source_map_generator() {
96 let generator = SourceMapGenerator::new();
97 let options = SourceMapOptions {
98 inline: false,
99 file: None,
100 source_root: None,
101 sources_content: true,
102 };
103
104 let result = generator.generate("input", "output", &options);
105 assert!(result.is_ok());
106 }
107}