1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use std::ffi; use std::path; #[cfg(feature = "sass")] use sass_rs; use super::files; use crate::error::*; #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub enum SassOutputStyle { Nested, Expanded, Compact, Compressed, } impl Default for SassOutputStyle { fn default() -> Self { SassOutputStyle::Nested } } #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] #[serde(deny_unknown_fields, default)] pub struct SassBuilder { pub import_dir: Option<String>, pub style: SassOutputStyle, } impl SassBuilder { pub fn new() -> Self { Default::default() } pub fn build(self) -> SassCompiler { let Self { import_dir, style } = self; SassCompiler { import_dir, style } } } #[derive(Debug, PartialEq)] pub struct SassCompiler { import_dir: Option<String>, style: SassOutputStyle, } impl Default for SassCompiler { fn default() -> Self { SassBuilder::default().build() } } impl SassCompiler { pub fn compile_file<S: AsRef<path::Path>, D: AsRef<path::Path>, F: AsRef<path::Path>>( &self, source: S, dest: D, file_path: F, ) -> Result<()> { self.compile_sass_internal(source.as_ref(), dest.as_ref(), file_path.as_ref()) } #[cfg(feature = "sass")] fn compile_sass_internal( &self, source: &path::Path, dest: &path::Path, file_path: &path::Path, ) -> Result<()> { let mut sass_opts = sass_rs::Options::default(); sass_opts.include_paths = self.import_dir.iter().cloned().collect(); sass_opts.output_style = match self.style { SassOutputStyle::Nested => sass_rs::OutputStyle::Nested, SassOutputStyle::Expanded => sass_rs::OutputStyle::Expanded, SassOutputStyle::Compact => sass_rs::OutputStyle::Compact, SassOutputStyle::Compressed => sass_rs::OutputStyle::Compressed, }; let content = sass_rs::compile_file(file_path, sass_opts).map_err(failure::err_msg)?; let rel_src = file_path .strip_prefix(source) .expect("file was found under the root"); let mut dest_file = dest.join(rel_src); dest_file.set_extension("css"); files::write_document_file(content, dest_file) } #[cfg(not(feature = "sass"))] fn compile_sass_internal( &self, source: &path::Path, dest: &path::Path, file_path: &path::Path, ) -> Result<()> { let rel_src = file_path .strip_prefix(source) .expect("file was found under the root"); let dest_file = dest.join(rel_src); files::copy_file(file_path, &dest_file) } } pub fn is_sass_file(file_path: &path::Path) -> bool { file_path.extension() == Some(ffi::OsStr::new("scss")) || file_path.extension() == Some(ffi::OsStr::new("sass")) }