rspack_style/interceptor/
less_interceptor.rs1use crate::util::file::path_resolve;
2use serde_json::Value;
3use std::collections::HashMap;
4use std::path::Path;
5use std::process::{Command, Stdio};
6use std::{env, fs};
7
8pub struct LessInterceptor;
9
10impl LessInterceptor {
11 fn copy_js_lib(target_dir: &str) {
16 let command = format!("rm -rf {}/**", target_dir);
18 let mut rm_task = Command::new("sh");
19 rm_task.arg("-c").arg(command);
20 rm_task.current_dir(target_dir).status().unwrap();
21 let js_lib_dir = format!("{}/**", path_resolve("js-lib"));
23 let command = format!("cp -rf {} {}", js_lib_dir, target_dir);
24 let mut cp_task = Command::new("sh");
25 cp_task.arg("-c").arg(command);
26 cp_task.current_dir(target_dir).status().unwrap();
27 }
28
29 fn filemanger() -> Result<String, String> {
34 let cwd = env::current_dir().unwrap();
35 let temp_rspack_style_dir = cwd.join(".rspack-style");
36 let js_main_file = temp_rspack_style_dir.join("dist/main.js");
37
38 return if temp_rspack_style_dir.exists() && temp_rspack_style_dir.is_dir() {
39 if js_main_file.exists() {
40 Ok(js_main_file.into_os_string().into_string().unwrap())
42 } else {
43 Self::copy_js_lib(temp_rspack_style_dir.to_str().unwrap());
45 Ok(js_main_file.into_os_string().into_string().unwrap())
46 }
47 } else if !temp_rspack_style_dir.exists() {
48 fs::create_dir_all(temp_rspack_style_dir.clone()).unwrap();
49 Self::copy_js_lib(temp_rspack_style_dir.to_str().unwrap());
50 Ok(js_main_file.into_os_string().into_string().unwrap())
51 } else {
52 Err(format!(
54 "rspack-style LessInterceptor filemanger call -> {} must be dir",
55 temp_rspack_style_dir
56 .into_os_string()
57 .into_string()
58 .unwrap()
59 ))
60 };
61 }
62
63 pub fn handle(filepath: &str, content: &str) -> Result<String, String> {
64 let path = Path::new(filepath);
65 if path.extension() == Some("less".to_string().as_ref()) {
66 let self_dir = Path::new(filepath).to_str().unwrap().to_string();
67 let cwd = path_resolve("");
68 let include_path = vec![
69 Value::String(self_dir),
70 Value::String(cwd.clone()),
71 Value::String("node_modules".to_string()),
72 ];
73 let mut option_map = HashMap::new();
74 option_map.insert("paths", Value::Array(include_path));
75 option_map.insert("filename", Value::String(filepath.to_string()));
76 let option_arg = serde_json::to_string(&option_map).unwrap();
77
78 let js_file = Self::filemanger()?;
79 let mut task = Command::new("node");
80 task.arg(js_file.as_str());
81 task.arg("--option");
82 task.arg(option_arg.as_str());
83 task.current_dir(cwd);
84 task.stdout(Stdio::piped());
85
86 let output = task
90 .output()
91 .unwrap_or_else(|_| panic!("{}->less.js callback is failed", filepath));
92 let status = output.status.code().unwrap();
93 let less_content = std::str::from_utf8(&*output.stdout).unwrap().to_string();
94 return if status > 0 {
95 Err(format!(
96 "parse less file ->{} \n has error in interceptor,\n ex is \n {}",
97 filepath, less_content
98 ))
99 } else {
100 Ok(less_content)
101 };
102 }
104 Ok(content.to_string())
105 }
106}