allow !global in mixins and functions

This commit is contained in:
ConnorSkees 2020-04-04 14:53:08 -04:00
parent dee4462cc7
commit ece0f5afde
3 changed files with 54 additions and 22 deletions

View File

@ -91,7 +91,7 @@ pub use crate::error::{SassError, SassResult};
use crate::format::PrettyPrinter; use crate::format::PrettyPrinter;
use crate::imports::import; use crate::imports::import;
use crate::lexer::Lexer; use crate::lexer::Lexer;
use crate::scope::{insert_global_var, Scope, GLOBAL_SCOPE}; use crate::scope::{insert_global_fn, insert_global_mixin, insert_global_var, Scope, GLOBAL_SCOPE};
use crate::selector::Selector; use crate::selector::Selector;
use crate::style::Style; use crate::style::Style;
pub(crate) use crate::token::Token; pub(crate) use crate::token::Token;
@ -284,7 +284,7 @@ impl<'a> StyleSheetParser<'a> {
match kind { match kind {
'a'..='z' | 'A'..='Z' | '_' | '-' 'a'..='z' | 'A'..='Z' | '_' | '-'
| '[' | '#' | ':' | '*' | '%' | '.' | '>' => rules | '[' | '#' | ':' | '*' | '%' | '.' | '>' => rules
.extend(self.eat_rules(&Selector::new(), &mut GLOBAL_SCOPE.with(|s| s.borrow().clone()))?), .extend(self.eat_rules(&Selector::new(), &mut Scope::new())?),
&'\t' | &'\n' | ' ' => { &'\t' | &'\n' | ' ' => {
self.lexer.next(); self.lexer.next();
continue; continue;
@ -303,7 +303,7 @@ impl<'a> StyleSheetParser<'a> {
return Err("expected \":\".".into()); return Err("expected \":\".".into());
} }
let VariableDecl { val, default, .. } = let VariableDecl { val, default, .. } =
eat_variable_value(&mut self.lexer, &GLOBAL_SCOPE.with(|s| s.borrow().clone()), &Selector::new())?; eat_variable_value(&mut self.lexer, &Scope::new(), &Selector::new())?;
GLOBAL_SCOPE.with(|s| { GLOBAL_SCOPE.with(|s| {
if !default || s.borrow().get_var(&name).is_err() { if !default || s.borrow().get_var(&name).is_err() {
match s.borrow_mut().insert_var(&name, val) { match s.borrow_mut().insert_var(&name, val) {
@ -336,7 +336,7 @@ impl<'a> StyleSheetParser<'a> {
match AtRuleKind::from(at_rule_kind.as_str()) { match AtRuleKind::from(at_rule_kind.as_str()) {
AtRuleKind::Include => rules.extend(eat_include( AtRuleKind::Include => rules.extend(eat_include(
&mut self.lexer, &mut self.lexer,
&GLOBAL_SCOPE.with(|s| s.borrow().clone()), &Scope::new(),
&Selector::new(), &Selector::new(),
)?), )?),
AtRuleKind::Import => { AtRuleKind::Import => {
@ -364,16 +364,12 @@ impl<'a> StyleSheetParser<'a> {
}); });
} }
v => { v => {
match AtRule::from_tokens(&v, Pos::new(), &mut self.lexer, &mut GLOBAL_SCOPE.with(|s| s.borrow().clone()), &Selector::new())? { match AtRule::from_tokens(&v, Pos::new(), &mut self.lexer, &mut Scope::new(), &Selector::new())? {
AtRule::Mixin(name, mixin) => { AtRule::Mixin(name, mixin) => {
GLOBAL_SCOPE.with(|s| { insert_global_mixin(&name, *mixin);
s.borrow_mut().insert_mixin(&name, *mixin);
});
} }
AtRule::Function(name, func) => { AtRule::Function(name, func) => {
GLOBAL_SCOPE.with(|s| { insert_global_fn(&name, *func);
s.borrow_mut().insert_fn(&name, *func);
});
} }
AtRule::Charset => continue, AtRule::Charset => continue,
AtRule::Error(pos, message) => self.error(pos, &message), AtRule::Error(pos, message) => self.error(pos, &message),

View File

@ -14,8 +14,12 @@ pub(crate) fn get_global_var(s: &str) -> SassResult<Value> {
}) })
} }
pub fn global_var_exists(v: &str) -> bool { pub(crate) fn global_var_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().var_exists(v)) GLOBAL_SCOPE.with(|scope| scope.borrow().vars().contains_key(v))
}
pub(crate) fn insert_global_var(s: &str, v: Value) -> SassResult<Option<Value>> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s, v))
} }
pub(crate) fn get_global_fn(s: &str) -> SassResult<Function> { pub(crate) fn get_global_fn(s: &str) -> SassResult<Function> {
@ -25,8 +29,27 @@ pub(crate) fn get_global_fn(s: &str) -> SassResult<Function> {
}) })
} }
pub(crate) fn insert_global_var(s: &str, v: Value) -> SassResult<Option<Value>> { pub(crate) fn global_fn_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s, v)) GLOBAL_SCOPE.with(|scope| scope.borrow().functions().contains_key(v))
}
pub(crate) fn insert_global_fn(s: &str, v: Function) -> Option<Function> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_fn(s, v))
}
pub(crate) fn get_global_mixin(s: &str) -> SassResult<Mixin> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().mixins().get(s) {
Some(v) => Ok(v.clone()),
None => Err("Undefined mixin.".into()),
})
}
pub(crate) fn global_mixin_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().mixins().contains_key(v))
}
pub(crate) fn insert_global_mixin(s: &str, v: Mixin) -> Option<Mixin> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_mixin(s, v))
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -54,6 +77,10 @@ impl Scope {
&self.functions &self.functions
} }
pub const fn mixins(&self) -> &HashMap<String, Mixin> {
&self.mixins
}
pub fn get_var(&self, v: &str) -> SassResult<Value> { pub fn get_var(&self, v: &str) -> SassResult<Value> {
let name = &v.replace('_', "-"); let name = &v.replace('_', "-");
match self.vars.get(name) { match self.vars.get(name) {
@ -67,13 +94,15 @@ impl Scope {
} }
pub fn var_exists(&self, v: &str) -> bool { pub fn var_exists(&self, v: &str) -> bool {
self.vars.contains_key(&v.replace('_', "-")) let name = &v.replace('_', "-");
self.vars.contains_key(name) || global_var_exists(name)
} }
pub fn get_mixin(&self, v: &str) -> SassResult<&Mixin> { pub fn get_mixin(&self, v: &str) -> SassResult<Mixin> {
match self.mixins.get(&v.replace('_', "-")) { let name = &v.replace('_', "-");
Some(v) => Ok(v), match self.mixins.get(name) {
None => Err("Undefined mixin.".into()), Some(v) => Ok(v.clone()),
None => get_global_mixin(name),
} }
} }
@ -82,7 +111,8 @@ impl Scope {
} }
pub fn mixin_exists(&self, v: &str) -> bool { pub fn mixin_exists(&self, v: &str) -> bool {
self.mixins.contains_key(&v.replace('_', "-")) let name = &v.replace('_', "-");
self.mixins.contains_key(name) || global_mixin_exists(name)
} }
pub fn get_fn(&self, v: &str) -> SassResult<Function> { pub fn get_fn(&self, v: &str) -> SassResult<Function> {
@ -98,7 +128,8 @@ impl Scope {
} }
pub fn fn_exists(&self, v: &str) -> bool { pub fn fn_exists(&self, v: &str) -> bool {
self.functions.contains_key(&v.replace('_', "-")) let name = &v.replace('_', "-");
self.functions.contains_key(name) || global_fn_exists(name)
} }
pub fn extend(&mut self, other: Scope) { pub fn extend(&mut self, other: Scope) {

View File

@ -18,3 +18,8 @@ test!(
"$foo: 42;\n\n.foo {\n content: $foo;\n $foo: 1337 !global;\n content: $foo;\n}\n\n.bar {\n content: $foo;\n}\n", "$foo: 42;\n\n.foo {\n content: $foo;\n $foo: 1337 !global;\n content: $foo;\n}\n\n.bar {\n content: $foo;\n}\n",
".foo {\n content: 42;\n content: 1337;\n}\n\n.bar {\n content: 1337;\n}\n" ".foo {\n content: 42;\n content: 1337;\n}\n\n.bar {\n content: 1337;\n}\n"
); );
test!(
global_in_mixin,
"$y: a;\n@mixin foo {\n $y: b !global;\n}\na {\n @include foo;\n color: $y;\n}\n",
"a {\n color: b;\n}\n"
);