From ec5ab053309d11d714f7efd17d6de8b8b6074af2 Mon Sep 17 00:00:00 2001 From: Joe Ling - uni laptop Date: Mon, 13 Jul 2020 18:18:25 +0100 Subject: [PATCH] added find_import to import and renamed lib method to from_paths --- src/lib.rs | 46 +++---------- src/main.rs | 6 +- src/parse/import.rs | 161 ++++++++++++++++++++------------------------ 3 files changed, 85 insertions(+), 128 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c47281b..b65735e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,13 @@ fn raw_to_parse_error(map: &CodeMap, err: Error) -> Box { #[cfg_attr(not(feature = "profiling"), inline)] #[cfg(not(feature = "wasm"))] pub fn from_path(p: &str) -> Result { + from_paths(p, &Vec::new()) +} + +#[cfg_attr(feature = "profiling", inline(never))] +#[cfg_attr(not(feature = "profiling"), inline)] +#[cfg(not(feature = "wasm"))] +pub fn from_paths(p: &str, loadpaths: &[&Path]) -> Result { let mut map = CodeMap::new(); let file = map.add_file(p.into(), String::from_utf8(fs::read(p)?)?); let empty_span = file.span.subspan(0, 0); @@ -161,7 +168,7 @@ pub fn from_path(p: &str) -> Result { at_root_has_selector: false, extender: &mut Extender::new(empty_span), content_scopes: &mut Scopes::new(), - load_paths: &Vec::new(), + load_paths: loadpaths, } .parse() .map_err(|e| raw_to_parse_error(&map, *e))?; @@ -171,7 +178,6 @@ pub fn from_path(p: &str) -> Result { .pretty_print(&map) .map_err(|e| raw_to_parse_error(&map, *e)) } - /// Compile CSS from a string /// /// ``` @@ -249,39 +255,3 @@ pub fn from_string(p: String) -> std::result::Result { .pretty_print(&map) .map_err(|e| raw_to_parse_error(&map, *e).to_string())?) } - -#[cfg_attr(feature = "profiling", inline(never))] -#[cfg_attr(not(feature = "profiling"), inline)] -#[cfg(not(feature = "wasm"))] -pub fn from_path_with_load_paths(p: &str, loadpaths: &[&Path]) -> Result { - let mut map = CodeMap::new(); - let file = map.add_file(p.into(), String::from_utf8(fs::read(p)?)?); - let empty_span = file.span.subspan(0, 0); - - let stmts = Parser { - toks: &mut Lexer::new(&file) - .collect::>() - .into_iter() - .peekmore(), - map: &mut map, - path: p.as_ref(), - scopes: &mut Scopes::new(), - global_scope: &mut Scope::new(), - super_selectors: &mut NeverEmptyVec::new(Selector::new(empty_span)), - span_before: empty_span, - content: &mut Vec::new(), - flags: ContextFlags::empty(), - at_root: true, - at_root_has_selector: false, - extender: &mut Extender::new(empty_span), - content_scopes: &mut Scopes::new(), - load_paths: loadpaths, - } - .parse() - .map_err(|e| raw_to_parse_error(&map, *e))?; - - Css::from_stmts(stmts, false) - .map_err(|e| raw_to_parse_error(&map, *e))? - .pretty_print(&map) - .map_err(|e| raw_to_parse_error(&map, *e)) -} diff --git a/src/main.rs b/src/main.rs index ec04045..6ebece7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::{ use clap::{arg_enum, App, AppSettings, Arg}; #[cfg(not(feature = "wasm"))] -use grass::from_path_with_load_paths; +use grass::from_paths; arg_enum! { #[derive(PartialEq, Debug)] @@ -193,7 +193,7 @@ fn main() -> std::io::Result<()> { if let Some(path) = matches.value_of("OUTPUT") { let mut buf = BufWriter::new(File::open(path).unwrap_or(File::create(path)?)); buf.write_all( - from_path_with_load_paths(name, &vals) + from_paths(name, &vals) .unwrap_or_else(|e| { eprintln!("{}", e); std::process::exit(1) @@ -203,7 +203,7 @@ fn main() -> std::io::Result<()> { } else { let mut stdout = BufWriter::new(stdout()); stdout.write_all( - from_path_with_load_paths(name, &vals) + from_paths(name, &vals) .unwrap_or_else(|e| { eprintln!("{}", e); std::process::exit(1) diff --git a/src/parse/import.rs b/src/parse/import.rs index 3641550..83816ef 100644 --- a/src/parse/import.rs +++ b/src/parse/import.rs @@ -7,6 +7,56 @@ use crate::{common::QuoteKind, error::SassResult, lexer::Lexer, value::Value, To use super::{Parser, Stmt}; +/// Searches the current directory of the file then searches in load paths directories +/// if the import has not yet been found. +/// [https://sass-lang.com/documentation/at-rules/import#finding-the-file](finding a file) +/// [https://sass-lang.com/documentation/at-rules/import#load-paths](load path) +fn find_import(file_path: &PathBuf, name: &OsStr, load_paths: &[&Path]) -> Option { + let paths = [ + file_path.with_file_name(name).with_extension("scss"), + file_path + .with_file_name(format!("_{}", name.to_str().unwrap())) + .with_extension("scss"), + file_path.clone(), + file_path.join("index.scss"), + file_path.join("_index.scss"), + ]; + + for name in &paths { + if name.is_file() { + return Some(name.to_path_buf()); + } + } + + for path in load_paths { + let paths: Vec = if path.is_dir() { + vec![ + path.join(format!("{}.scss", name.to_str().unwrap())), + path.join(format!("_{}.scss", name.to_str().unwrap())), + path.join("index.scss"), + path.join("_index.scss"), + ] + } else { + vec![ + path.to_path_buf(), + path.with_file_name(name).with_extension("scss"), + path.with_file_name(format!("_{}", name.to_str().unwrap())) + .with_extension("scss"), + path.join("index.scss"), + path.join("_index.scss"), + ] + }; + + for name in paths { + if name.is_file() { + return Some(name); + } + } + } + + None +} + impl<'a> Parser<'a> { pub(super) fn import(&mut self) -> SassResult> { self.whitespace(); @@ -57,95 +107,32 @@ impl<'a> Parser<'a> { let name = path_buf.file_name().unwrap_or_else(|| OsStr::new("..")); - let paths = [ - path_buf.with_file_name(name).with_extension("scss"), - path_buf - .with_file_name(format!("_{}", name.to_str().unwrap())) - .with_extension("scss"), - path_buf.clone(), - path_buf.join("index.scss"), - path_buf.join("_index.scss"), - ]; + if let Some(name) = find_import(&path_buf, name, self.load_paths) { + let file = self.map.add_file( + name.to_string_lossy().into(), + String::from_utf8(fs::read(&name)?)?, + ); - for name in &paths { - if name.is_file() { - let file = self.map.add_file( - name.to_string_lossy().into(), - String::from_utf8(fs::read(name)?)?, - ); - - return Parser { - toks: &mut Lexer::new(&file) - .collect::>() - .into_iter() - .peekmore(), - map: self.map, - path: name.as_ref(), - scopes: self.scopes, - global_scope: self.global_scope, - super_selectors: self.super_selectors, - span_before: file.span.subspan(0, 0), - content: self.content, - flags: self.flags, - at_root: self.at_root, - at_root_has_selector: self.at_root_has_selector, - extender: self.extender, - content_scopes: self.content_scopes, - load_paths: self.load_paths, - } - .parse(); - } - } - - for path in self.load_paths { - let paths: Vec = if path.is_dir() { - vec![ - path.join(format!("{}.scss", name.to_str().unwrap())), - path.join(format!("_{}.scss", name.to_str().unwrap())), - path.join("index.scss"), - path.join("_index.scss"), - ] - } else { - vec![ - path.to_path_buf(), - path.with_file_name(name).with_extension("scss"), - path.with_file_name(format!("_{}", name.to_str().unwrap())) - .with_extension("scss"), - path.join("index.scss"), - path.join("_index.scss"), - ] - }; - - for name in &paths { - if name.is_file() { - println!("found file: {:?}", name); - let file = self.map.add_file( - name.to_string_lossy().into(), - String::from_utf8(fs::read(name)?)?, - ); - - return Parser { - toks: &mut Lexer::new(&file) - .collect::>() - .into_iter() - .peekmore(), - map: self.map, - path: name.as_ref(), - scopes: self.scopes, - global_scope: self.global_scope, - super_selectors: self.super_selectors, - span_before: file.span.subspan(0, 0), - content: self.content, - flags: self.flags, - at_root: self.at_root, - at_root_has_selector: self.at_root_has_selector, - extender: self.extender, - content_scopes: self.content_scopes, - load_paths: self.load_paths, - } - .parse(); - } + return Parser { + toks: &mut Lexer::new(&file) + .collect::>() + .into_iter() + .peekmore(), + map: self.map, + path: &name, + scopes: self.scopes, + global_scope: self.global_scope, + super_selectors: self.super_selectors, + span_before: file.span.subspan(0, 0), + content: self.content, + flags: self.flags, + at_root: self.at_root, + at_root_has_selector: self.at_root_has_selector, + extender: self.extender, + content_scopes: self.content_scopes, + load_paths: self.load_paths, } + .parse(); } Err(("Can't find stylesheet to import.", span).into())