respect $module
argument to get-function
This commit is contained in:
parent
a03ad51b71
commit
a7325436ca
@ -1,7 +1,5 @@
|
|||||||
use super::{Builtin, GlobalFunctionMap, GLOBAL_FUNCTIONS};
|
use super::{Builtin, GlobalFunctionMap, GLOBAL_FUNCTIONS};
|
||||||
|
|
||||||
use codemap::Spanned;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
args::CallArgs,
|
args::CallArgs,
|
||||||
common::{Identifier, QuoteKind},
|
common::{Identifier, QuoteKind},
|
||||||
@ -166,7 +164,8 @@ pub(crate) fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassR
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if module.is_some() && css {
|
let func = match if let Some(module_name) = module {
|
||||||
|
if css {
|
||||||
return Err((
|
return Err((
|
||||||
"$css and $module may not both be passed at once.",
|
"$css and $module may not both be passed at once.",
|
||||||
args.span(),
|
args.span(),
|
||||||
@ -174,13 +173,13 @@ pub(crate) fn get_function(mut args: CallArgs, parser: &mut Parser<'_>) -> SassR
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let func = match parser.scopes.get_fn(
|
parser
|
||||||
Spanned {
|
.modules
|
||||||
node: name,
|
.get(module_name.into(), args.span())?
|
||||||
span: args.span(),
|
.get_fn(name)
|
||||||
},
|
} else {
|
||||||
parser.global_scope,
|
parser.scopes.get_fn(name, parser.global_scope)
|
||||||
) {
|
} {
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
None => match GLOBAL_FUNCTIONS.get(name.as_str()) {
|
None => match GLOBAL_FUNCTIONS.get(name.as_str()) {
|
||||||
Some(f) => SassFunction::Builtin(f.clone(), name),
|
Some(f) => SassFunction::Builtin(f.clone(), name),
|
||||||
|
@ -32,14 +32,7 @@ fn module_functions(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Map(
|
Ok(Value::Map(
|
||||||
parser
|
parser.modules.get(module.into(), args.span())?.functions(),
|
||||||
.modules
|
|
||||||
.get(&module)
|
|
||||||
.ok_or((
|
|
||||||
format!("There is no module with the namespace \"{}\".", module),
|
|
||||||
args.span(),
|
|
||||||
))?
|
|
||||||
.functions(),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,14 +51,7 @@ fn module_variables(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<V
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Map(
|
Ok(Value::Map(
|
||||||
parser
|
parser.modules.get(module.into(), args.span())?.variables(),
|
||||||
.modules
|
|
||||||
.get(&module)
|
|
||||||
.ok_or((
|
|
||||||
format!("There is no module with the namespace \"{}\".", module),
|
|
||||||
args.span(),
|
|
||||||
))?
|
|
||||||
.variables(),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use codemap::Spanned;
|
use codemap::{Span, Spanned};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
args::CallArgs,
|
args::CallArgs,
|
||||||
@ -26,6 +26,29 @@ mod string;
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct Module(pub Scope);
|
pub(crate) struct Module(pub Scope);
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub(crate) struct Modules(BTreeMap<Identifier, Module>);
|
||||||
|
|
||||||
|
impl Modules {
|
||||||
|
pub fn insert(&mut self, name: Identifier, module: Module) {
|
||||||
|
self.0.insert(name, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, name: Identifier, span: Span) -> SassResult<&Module> {
|
||||||
|
match self.0.get(&name) {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err((
|
||||||
|
format!(
|
||||||
|
"There is no module with the namespace \"{}\".",
|
||||||
|
name.as_str()
|
||||||
|
),
|
||||||
|
span,
|
||||||
|
)
|
||||||
|
.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn get_var(&self, name: Spanned<Identifier>) -> SassResult<&Value> {
|
pub fn get_var(&self, name: Spanned<Identifier>) -> SassResult<&Value> {
|
||||||
match self.0.vars.get(&name.node) {
|
match self.0.vars.get(&name.node) {
|
||||||
|
@ -81,7 +81,7 @@ grass input.scss
|
|||||||
)]
|
)]
|
||||||
#![cfg_attr(feature = "nightly", feature(track_caller))]
|
#![cfg_attr(feature = "nightly", feature(track_caller))]
|
||||||
#![cfg_attr(feature = "profiling", inline(never))]
|
#![cfg_attr(feature = "profiling", inline(never))]
|
||||||
use std::{collections::HashMap, fs, path::Path};
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
@ -95,6 +95,7 @@ use peekmore::PeekMore;
|
|||||||
pub use crate::error::{SassError as Error, SassResult as Result};
|
pub use crate::error::{SassError as Error, SassResult as Result};
|
||||||
pub(crate) use crate::token::Token;
|
pub(crate) use crate::token::Token;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builtin::modules::Modules,
|
||||||
lexer::Lexer,
|
lexer::Lexer,
|
||||||
output::Css,
|
output::Css,
|
||||||
parse::{
|
parse::{
|
||||||
@ -293,7 +294,7 @@ pub fn from_path(p: &str, options: &Options) -> Result<String> {
|
|||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
content_scopes: &mut Scopes::new(),
|
content_scopes: &mut Scopes::new(),
|
||||||
options,
|
options,
|
||||||
modules: &mut HashMap::new(),
|
modules: &mut Modules::default(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
|
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
|
||||||
@ -338,7 +339,7 @@ pub fn from_string(p: String, options: &Options) -> Result<String> {
|
|||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
content_scopes: &mut Scopes::new(),
|
content_scopes: &mut Scopes::new(),
|
||||||
options,
|
options,
|
||||||
modules: &mut HashMap::new(),
|
modules: &mut Modules::default(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
|
.map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
|
||||||
@ -374,7 +375,7 @@ pub fn from_string(p: String) -> std::result::Result<String, JsValue> {
|
|||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
content_scopes: &mut Scopes::new(),
|
content_scopes: &mut Scopes::new(),
|
||||||
options: &Options::default(),
|
options: &Options::default(),
|
||||||
modules: &mut HashMap::new(),
|
modules: &mut Modules::default(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e, true).to_string())?;
|
.map_err(|e| raw_to_parse_error(&map, *e, true).to_string())?;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashMap, convert::TryFrom, fs, path::Path, vec::IntoIter};
|
use std::{convert::TryFrom, fs, path::Path, vec::IntoIter};
|
||||||
|
|
||||||
use codemap::{CodeMap, Span, Spanned};
|
use codemap::{CodeMap, Span, Spanned};
|
||||||
use peekmore::{PeekMore, PeekMoreIterator};
|
use peekmore::{PeekMore, PeekMoreIterator};
|
||||||
@ -11,7 +11,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
builtin::modules::{
|
builtin::modules::{
|
||||||
declare_module_color, declare_module_list, declare_module_map, declare_module_math,
|
declare_module_color, declare_module_list, declare_module_map, declare_module_math,
|
||||||
declare_module_meta, declare_module_selector, declare_module_string, Module,
|
declare_module_meta, declare_module_selector, declare_module_string, Module, Modules,
|
||||||
},
|
},
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
lexer::Lexer,
|
lexer::Lexer,
|
||||||
@ -92,7 +92,7 @@ pub(crate) struct Parser<'a> {
|
|||||||
|
|
||||||
pub options: &'a Options<'a>,
|
pub options: &'a Options<'a>,
|
||||||
|
|
||||||
pub modules: &'a mut HashMap<String, Module>,
|
pub modules: &'a mut Modules,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
@ -262,7 +262,7 @@ impl<'a> Parser<'a> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.modules.insert(module_name, module);
|
self.modules.insert(module_name.into(), module);
|
||||||
}
|
}
|
||||||
Some(Token { kind: '/', .. }) => {
|
Some(Token { kind: '/', .. }) => {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
|
@ -261,14 +261,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
module_span = module_span.merge(var.span);
|
module_span = module_span.merge(var.span);
|
||||||
|
|
||||||
let value = self
|
let value = self.modules.get(module.into(), module_span)?.get_var(var)?;
|
||||||
.modules
|
|
||||||
.get(module)
|
|
||||||
.ok_or((
|
|
||||||
format!("There is no module with the namespace \"{}\".", module),
|
|
||||||
module_span,
|
|
||||||
))?
|
|
||||||
.get_var(var)?;
|
|
||||||
HigherIntermediateValue::Literal(value.clone())
|
HigherIntermediateValue::Literal(value.clone())
|
||||||
} else {
|
} else {
|
||||||
let fn_name = self
|
let fn_name = self
|
||||||
@ -277,11 +270,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let function = self
|
let function = self
|
||||||
.modules
|
.modules
|
||||||
.get(module)
|
.get(module.into(), module_span)?
|
||||||
.ok_or((
|
|
||||||
format!("There is no module with the namespace \"{}\".", module),
|
|
||||||
module_span,
|
|
||||||
))?
|
|
||||||
.get_fn(fn_name.node)
|
.get_fn(fn_name.node)
|
||||||
.ok_or(("Undefined function.", fn_name.span))?;
|
.ok_or(("Undefined function.", fn_name.span))?;
|
||||||
|
|
||||||
@ -341,13 +330,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let as_ident = Identifier::from(&s);
|
let as_ident = Identifier::from(&s);
|
||||||
let func = match self.scopes.get_fn(
|
let func = match self.scopes.get_fn(as_ident, self.global_scope) {
|
||||||
Spanned {
|
|
||||||
node: as_ident,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
self.global_scope,
|
|
||||||
) {
|
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
None => {
|
None => {
|
||||||
if let Some(f) = GLOBAL_FUNCTIONS.get(as_ident.as_str()) {
|
if let Some(f) = GLOBAL_FUNCTIONS.get(as_ident.as_str()) {
|
||||||
|
12
src/scope.rs
12
src/scope.rs
@ -230,17 +230,13 @@ impl Scopes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_fn<'a>(
|
pub fn get_fn<'a>(&'a self, name: Identifier, global_scope: &'a Scope) -> Option<SassFunction> {
|
||||||
&'a self,
|
|
||||||
name: Spanned<Identifier>,
|
|
||||||
global_scope: &'a Scope,
|
|
||||||
) -> Option<SassFunction> {
|
|
||||||
for scope in self.0.iter().rev() {
|
for scope in self.0.iter().rev() {
|
||||||
if scope.fn_exists(name.node) {
|
if scope.fn_exists(name) {
|
||||||
return scope.get_fn(name.node);
|
return scope.get_fn(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global_scope.get_fn(name.node)
|
global_scope.get_fn(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fn_exists(&self, name: Identifier, global_scope: &Scope) -> bool {
|
pub fn fn_exists(&self, name: Identifier, global_scope: &Scope) -> bool {
|
||||||
|
@ -121,3 +121,8 @@ test!(
|
|||||||
"a {\n color: call(call(get-function(get-function), darken), red, 10%);\n}\n",
|
"a {\n color: call(call(get-function(get-function), darken), red, 10%);\n}\n",
|
||||||
"a {\n color: #cc0000;\n}\n"
|
"a {\n color: #cc0000;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
get_function_of_module,
|
||||||
|
"@use 'sass:math';\na {\n color: call(get-function(cos, $module: math), 2);\n}\n",
|
||||||
|
"a {\n color: -0.4161468365;\n}\n"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user