respect $with
argument to load-css
This commit is contained in:
parent
0254517095
commit
cacf605af8
@ -1,3 +1,5 @@
|
|||||||
|
use codemap::Spanned;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
args::CallArgs,
|
args::CallArgs,
|
||||||
builtin::{
|
builtin::{
|
||||||
@ -5,7 +7,7 @@ use crate::{
|
|||||||
call, content_exists, feature_exists, function_exists, get_function,
|
call, content_exists, feature_exists, function_exists, get_function,
|
||||||
global_variable_exists, inspect, keywords, mixin_exists, type_of, variable_exists,
|
global_variable_exists, inspect, keywords, mixin_exists, type_of, variable_exists,
|
||||||
},
|
},
|
||||||
modules::Module,
|
modules::{Module, ModuleConfig},
|
||||||
},
|
},
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
parse::{Parser, Stmt},
|
parse::{Parser, Stmt},
|
||||||
@ -15,13 +17,15 @@ use crate::{
|
|||||||
fn load_css(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Vec<Stmt>> {
|
fn load_css(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Vec<Stmt>> {
|
||||||
args.max_args(2)?;
|
args.max_args(2)?;
|
||||||
|
|
||||||
|
let span = args.span();
|
||||||
|
|
||||||
// todo: https://github.com/sass/dart-sass/issues/1054
|
// todo: https://github.com/sass/dart-sass/issues/1054
|
||||||
let url = match args.get_err(0, "module")? {
|
let url = match args.get_err(0, "module")? {
|
||||||
Value::String(s, ..) => s,
|
Value::String(s, ..) => s,
|
||||||
v => {
|
v => {
|
||||||
return Err((
|
return Err((
|
||||||
format!("$module: {} is not a string.", v.inspect(args.span())?),
|
format!("$module: {} is not a string.", v.inspect(span)?),
|
||||||
args.span(),
|
span,
|
||||||
)
|
)
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
@ -30,19 +34,39 @@ fn load_css(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Vec<Stmt>
|
|||||||
let with = match args.default_arg(1, "with", Value::Null)? {
|
let with = match args.default_arg(1, "with", Value::Null)? {
|
||||||
Value::Map(map) => Some(map),
|
Value::Map(map) => Some(map),
|
||||||
Value::Null => None,
|
Value::Null => None,
|
||||||
v => {
|
v => return Err((format!("$with: {} is not a map.", v.inspect(span)?), span).into()),
|
||||||
return Err((
|
|
||||||
format!("$with: {} is not a map.", v.inspect(args.span())?),
|
|
||||||
args.span(),
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(..) = with {
|
// todo: tests for `with`
|
||||||
todo!("`$with` to `load-css` not yet implemented")
|
if let Some(with) = with {
|
||||||
|
let mut config = ModuleConfig::default();
|
||||||
|
|
||||||
|
for (key, value) in with {
|
||||||
|
let key = match key {
|
||||||
|
Value::String(s, ..) => s,
|
||||||
|
v => {
|
||||||
|
return Err((
|
||||||
|
format!("$with key: {} is not a string.", v.inspect(span)?),
|
||||||
|
span,
|
||||||
|
)
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
config.insert(
|
||||||
|
Spanned {
|
||||||
|
node: key.into(),
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
value.span(span),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, stmts) = parser.load_module(&url, &mut config)?;
|
||||||
|
|
||||||
|
Ok(stmts)
|
||||||
} else {
|
} else {
|
||||||
parser.parse_single_import(&url, args.span())
|
parser.parse_single_import(&url, span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
src/parse/mod.rs
114
src/parse/mod.rs
@ -208,6 +208,66 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_module(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
config: &mut ModuleConfig,
|
||||||
|
) -> SassResult<(Module, Vec<Stmt>)> {
|
||||||
|
Ok(match name {
|
||||||
|
"sass:color" => (declare_module_color(), Vec::new()),
|
||||||
|
"sass:list" => (declare_module_list(), Vec::new()),
|
||||||
|
"sass:map" => (declare_module_map(), Vec::new()),
|
||||||
|
"sass:math" => (declare_module_math(), Vec::new()),
|
||||||
|
"sass:meta" => (declare_module_meta(), Vec::new()),
|
||||||
|
"sass:selector" => (declare_module_selector(), Vec::new()),
|
||||||
|
"sass:string" => (declare_module_string(), Vec::new()),
|
||||||
|
_ => {
|
||||||
|
if let Some(import) = self.find_import(name.as_ref()) {
|
||||||
|
let mut global_scope = Scope::new();
|
||||||
|
|
||||||
|
let file = self
|
||||||
|
.map
|
||||||
|
.add_file(name.to_owned(), String::from_utf8(fs::read(&import)?)?);
|
||||||
|
|
||||||
|
let stmts = Parser {
|
||||||
|
toks: &mut Lexer::new(&file)
|
||||||
|
.collect::<Vec<Token>>()
|
||||||
|
.into_iter()
|
||||||
|
.peekmore(),
|
||||||
|
map: self.map,
|
||||||
|
path: &import,
|
||||||
|
scopes: self.scopes,
|
||||||
|
global_scope: &mut 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,
|
||||||
|
options: self.options,
|
||||||
|
modules: self.modules,
|
||||||
|
module_config: config,
|
||||||
|
}
|
||||||
|
.parse()?;
|
||||||
|
|
||||||
|
if !config.is_empty() {
|
||||||
|
return Err((
|
||||||
|
"This variable was not declared with !default in the @used module.",
|
||||||
|
self.span_before,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
(Module::new_from_scope(global_scope), stmts)
|
||||||
|
} else {
|
||||||
|
return Err(("Can't find stylesheet to import.", self.span_before).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns any multiline comments that may have been found
|
/// Returns any multiline comments that may have been found
|
||||||
/// while loading modules
|
/// while loading modules
|
||||||
#[allow(clippy::eval_order_dependence)]
|
#[allow(clippy::eval_order_dependence)]
|
||||||
@ -260,58 +320,10 @@ impl<'a> Parser<'a> {
|
|||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
self.expect_char(';')?;
|
self.expect_char(';')?;
|
||||||
|
|
||||||
let module = match module_name.as_ref() {
|
let (module, mut stmts) =
|
||||||
"sass:color" => declare_module_color(),
|
self.load_module(module_name.as_ref(), &mut config)?;
|
||||||
"sass:list" => declare_module_list(),
|
|
||||||
"sass:map" => declare_module_map(),
|
|
||||||
"sass:math" => declare_module_math(),
|
|
||||||
"sass:meta" => declare_module_meta(),
|
|
||||||
"sass:selector" => declare_module_selector(),
|
|
||||||
"sass:string" => declare_module_string(),
|
|
||||||
_ => {
|
|
||||||
if let Some(import) = self.find_import(module_name.as_ref().as_ref()) {
|
|
||||||
let mut global_scope = Scope::new();
|
|
||||||
|
|
||||||
let file = self.map.add_file(
|
comments.append(&mut stmts);
|
||||||
module_name.clone().into_owned(),
|
|
||||||
String::from_utf8(fs::read(&import)?)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
comments.append(
|
|
||||||
&mut Parser {
|
|
||||||
toks: &mut Lexer::new(&file)
|
|
||||||
.collect::<Vec<Token>>()
|
|
||||||
.into_iter()
|
|
||||||
.peekmore(),
|
|
||||||
map: self.map,
|
|
||||||
path: &import,
|
|
||||||
scopes: self.scopes,
|
|
||||||
global_scope: &mut 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,
|
|
||||||
options: self.options,
|
|
||||||
modules: self.modules,
|
|
||||||
module_config: &mut config,
|
|
||||||
}
|
|
||||||
.parse()?,
|
|
||||||
);
|
|
||||||
|
|
||||||
if !config.is_empty() {
|
|
||||||
return Err(("This variable was not declared with !default in the @used module.", span).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Module::new_from_scope(global_scope)
|
|
||||||
} else {
|
|
||||||
return Err(("Can't find stylesheet to import.", span).into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// if the config isn't empty here, that means
|
// if the config isn't empty here, that means
|
||||||
// variables were passed to a builtin module
|
// variables were passed to a builtin module
|
||||||
|
Loading…
x
Reference in New Issue
Block a user