2020-03-03 19:51:02 -05:00
|
|
|
use std::collections::HashMap;
|
2020-02-02 21:09:29 -05:00
|
|
|
|
2020-02-14 18:39:50 -05:00
|
|
|
use super::{Builtin, GLOBAL_FUNCTIONS};
|
2020-02-03 07:35:04 -05:00
|
|
|
use crate::common::QuoteKind;
|
2020-02-03 08:10:55 -05:00
|
|
|
use crate::units::Unit;
|
2020-02-02 22:33:04 -05:00
|
|
|
use crate::value::Value;
|
|
|
|
|
2020-03-03 19:51:02 -05:00
|
|
|
pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
2020-03-16 10:35:38 -04:00
|
|
|
f.insert(
|
|
|
|
"if".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 3);
|
|
|
|
if arg!(args, 0, "condition").is_true()? {
|
|
|
|
Ok(arg!(args, 1, "if-true"))
|
|
|
|
} else {
|
|
|
|
Ok(arg!(args, 2, "if-false"))
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"feature-exists".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
match arg!(args, 0, "feature").unquote().to_string().as_str() {
|
|
|
|
// A local variable will shadow a global variable unless
|
|
|
|
// `!global` is used.
|
|
|
|
"global-variable-shadowing" => Ok(Value::False),
|
|
|
|
// the @extend rule will affect selectors nested in pseudo-classes
|
|
|
|
// like :not()
|
|
|
|
"extend-selector-pseudoclass" => Ok(Value::False),
|
|
|
|
// Full support for unit arithmetic using units defined in the
|
|
|
|
// [Values and Units Level 3][] spec.
|
|
|
|
"units-level-3" => Ok(Value::False),
|
|
|
|
// The Sass `@error` directive is supported.
|
|
|
|
"at-error" => Ok(Value::True),
|
|
|
|
// The "Custom Properties Level 1" spec is supported. This means
|
|
|
|
// that custom properties are parsed statically, with only
|
|
|
|
// interpolation treated as SassScript.
|
|
|
|
"custom-property" => Ok(Value::False),
|
|
|
|
_ => Ok(Value::False),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"unit".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let unit = match arg!(args, 0, "number") {
|
|
|
|
Value::Dimension(_, u) => u.to_string(),
|
|
|
|
_ => String::new(),
|
|
|
|
};
|
|
|
|
Ok(Value::Ident(unit, QuoteKind::Double))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"type-of".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let value = arg!(args, 0, "value");
|
|
|
|
Ok(Value::Ident(value.kind()?.to_owned(), QuoteKind::None))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"unitless".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
match arg!(args, 0, "number") {
|
|
|
|
Value::Dimension(_, Unit::None) => Ok(Value::True),
|
|
|
|
Value::Dimension(_, _) => Ok(Value::False),
|
|
|
|
_ => Ok(Value::True),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"inspect".to_owned(),
|
|
|
|
Box::new(|args, _| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let value = arg!(args, 0, "value");
|
|
|
|
Ok(Value::Ident(value.to_string(), QuoteKind::None))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"variable-exists".to_owned(),
|
|
|
|
Box::new(|args, scope| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let value = arg!(args, 0, "name");
|
|
|
|
Ok(Value::bool(scope.var_exists(&value.to_string())))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"mixin-exists".to_owned(),
|
|
|
|
Box::new(|args, scope| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let value = arg!(args, 0, "name");
|
|
|
|
Ok(Value::bool(scope.mixin_exists(&value.to_string())))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert(
|
|
|
|
"function-exists".to_owned(),
|
|
|
|
Box::new(|args, scope| {
|
|
|
|
max_args!(args, 1);
|
|
|
|
let value = arg!(args, 0, "name");
|
|
|
|
let s = value.unquote().to_string();
|
|
|
|
Ok(Value::bool(
|
|
|
|
scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(&s),
|
|
|
|
))
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
f.insert("call".to_owned(), Box::new(|_args, _scope| {
|
2020-02-09 15:36:30 -05:00
|
|
|
todo!("builtin function `call()` is blocked on refactoring how call args are stored and parsed")
|
|
|
|
// let func = arg!(args, 0, "function").to_string();
|
|
|
|
// let func = match scope.get_fn(&func) {
|
|
|
|
// Ok(f) => f,
|
|
|
|
// Err(_) => match GLOBAL_FUNCTIONS.get(&func) {
|
|
|
|
// Some(f) => return f(&args, scope),
|
|
|
|
// None => todo!("called undefined function"),
|
|
|
|
// },
|
|
|
|
// };
|
|
|
|
// Some(func.clone().args(&args).call())
|
2020-03-16 10:35:38 -04:00
|
|
|
}));
|
2020-02-07 00:10:43 -05:00
|
|
|
}
|