Revert string interning
There existed issues related to multithreaded tests that are difficult to resolve. In the future interning may be reimplemented but in a more limited capacity. The motivation behind interning *values* was that it appeared checking for named colors was responsible for much of the time lost when parsing unquoted strings. If interning were to be reimplemented, it may make sense to limit it solely to identifiers and style properties.
This commit is contained in:
parent
3e5abf0587
commit
969726eb30
@ -49,7 +49,6 @@ rand = { version = "0.7.3", optional = true }
|
||||
codemap = "0.1.3"
|
||||
peekmore = "0.4.0"
|
||||
wasm-bindgen = { version = "0.2.60", optional = true }
|
||||
lasso = "0.2.2"
|
||||
|
||||
[features]
|
||||
default = ["commandline", "random"]
|
||||
|
@ -42,7 +42,7 @@ impl Each {
|
||||
if self.vars.len() == 1 {
|
||||
if this_iterator.len() == 1 {
|
||||
scope.insert_var(
|
||||
&self.vars[0].node,
|
||||
&self.vars[0],
|
||||
Spanned {
|
||||
node: this_iterator[0].clone(),
|
||||
span: self.vars[0].span,
|
||||
@ -50,7 +50,7 @@ impl Each {
|
||||
)?;
|
||||
} else {
|
||||
scope.insert_var(
|
||||
&self.vars[0].node,
|
||||
&self.vars[0],
|
||||
Spanned {
|
||||
node: Value::List(this_iterator, ListSeparator::Space, Brackets::None),
|
||||
span: self.vars[0].span,
|
||||
|
@ -6,7 +6,6 @@ use crate::args::CallArgs;
|
||||
use crate::color::Color;
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -108,10 +107,7 @@ fn inner_hsl(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -140,10 +136,7 @@ fn inner_hsl(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -174,10 +167,7 @@ fn inner_hsl(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -211,14 +201,14 @@ fn inner_hsl(
|
||||
}
|
||||
v if v.is_special_function() => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}({}, {}, {}, {})",
|
||||
name,
|
||||
hue,
|
||||
saturation,
|
||||
lightness,
|
||||
v.to_css_string(args.span())?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -368,10 +358,10 @@ fn saturate(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
|
||||
args.max_args(2)?;
|
||||
if args.len() == 1 {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"saturate({})",
|
||||
arg!(args, scope, super_selector, 0, "amount").to_css_string(args.span())?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -393,7 +383,7 @@ fn saturate(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
|
||||
Value::Color(c) => c,
|
||||
Value::Dimension(n, u) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("saturate({}{})", n, u)),
|
||||
format!("saturate({}{})", n, u),
|
||||
QuoteKind::None,
|
||||
))
|
||||
}
|
||||
@ -442,7 +432,7 @@ fn grayscale(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
Value::Color(c) => c,
|
||||
Value::Dimension(n, u) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("grayscale({}{})", n, u)),
|
||||
format!("grayscale({}{})", n, u),
|
||||
QuoteKind::None,
|
||||
))
|
||||
}
|
||||
@ -495,10 +485,9 @@ fn invert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassR
|
||||
};
|
||||
match arg!(args, scope, super_selector, 0, "color") {
|
||||
Value::Color(c) => Ok(Value::Color(Box::new(c.invert(weight)))),
|
||||
Value::Dimension(n, Unit::Percent) => Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("invert({}%)", n)),
|
||||
QuoteKind::None,
|
||||
)),
|
||||
Value::Dimension(n, Unit::Percent) => {
|
||||
Ok(Value::Ident(format!("invert({}%)", n), QuoteKind::None))
|
||||
}
|
||||
Value::Dimension(..) => Err((
|
||||
"Only one argument may be passed to the plain-CSS invert() function.",
|
||||
args.span(),
|
||||
|
@ -3,7 +3,6 @@ use super::{Builtin, GlobalFunctionMap};
|
||||
use crate::args::CallArgs;
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -27,7 +26,7 @@ fn opacity(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sass
|
||||
match arg!(args, scope, super_selector, 0, "color") {
|
||||
Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None)),
|
||||
Value::Dimension(num, unit) => Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("opacity({}{})", num, unit)),
|
||||
format!("opacity({}{})", num, unit),
|
||||
QuoteKind::None,
|
||||
)),
|
||||
v => Err((
|
||||
|
@ -6,7 +6,6 @@ use crate::args::CallArgs;
|
||||
use crate::color::Color;
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -47,13 +46,13 @@ fn inner_rgb(
|
||||
let green = channels.pop().unwrap();
|
||||
let red = channels.pop().unwrap();
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}({}, {}, {})",
|
||||
name,
|
||||
red.to_css_string(args.span())?,
|
||||
green.to_css_string(args.span())?,
|
||||
v.to_css_string(args.span())?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -81,10 +80,7 @@ fn inner_rgb(
|
||||
),
|
||||
None => format!("{}({} {})", name, v.to_css_string(args.span())?, blue),
|
||||
};
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
Some(v) => {
|
||||
return Err((
|
||||
@ -101,13 +97,13 @@ fn inner_rgb(
|
||||
Some(Value::Dimension(n, Unit::Percent)) => (n / Number::from(100)) * Number::from(255),
|
||||
Some(v) if v.is_special_function() => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}({}, {}, {})",
|
||||
name,
|
||||
v.to_css_string(args.span())?,
|
||||
green,
|
||||
blue
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -130,12 +126,12 @@ fn inner_rgb(
|
||||
v if v.is_special_function() => {
|
||||
let alpha = arg!(args, scope, super_selector, 1, "alpha");
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}({}, {})",
|
||||
name,
|
||||
v.to_css_string(args.span())?,
|
||||
alpha.to_css_string(args.span())?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -162,14 +158,14 @@ fn inner_rgb(
|
||||
}
|
||||
v if v.is_special_function() => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}({}, {}, {}, {})",
|
||||
name,
|
||||
color.red(),
|
||||
color.green(),
|
||||
color.blue(),
|
||||
v.to_css_string(args.span())?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
));
|
||||
}
|
||||
@ -214,10 +210,7 @@ fn inner_rgb(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -257,10 +250,7 @@ fn inner_rgb(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -299,10 +289,7 @@ fn inner_rgb(
|
||||
);
|
||||
}
|
||||
string.push(')');
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
@ -340,10 +327,7 @@ fn inner_rgb(
|
||||
blue,
|
||||
v.to_css_string(args.span())?
|
||||
);
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
));
|
||||
return Ok(Value::Ident(string, QuoteKind::None));
|
||||
}
|
||||
v => {
|
||||
return Err((
|
||||
|
@ -5,7 +5,6 @@ use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use crate::args::CallArgs;
|
||||
use crate::common::{Brackets, ListSeparator, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -73,10 +72,11 @@ fn list_separator(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(match arg!(args, scope, super_selector, 0, "list") {
|
||||
match arg!(args, scope, super_selector, 0, "list") {
|
||||
Value::List(_, sep, ..) => sep.name(),
|
||||
_ => ListSeparator::Space.name(),
|
||||
}),
|
||||
}
|
||||
.to_owned(),
|
||||
QuoteKind::None,
|
||||
))
|
||||
}
|
||||
@ -140,9 +140,9 @@ fn append(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassR
|
||||
scope,
|
||||
super_selector,
|
||||
2,
|
||||
"separator" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
|
||||
"separator" = Value::Ident("auto".to_owned(), QuoteKind::None)
|
||||
) {
|
||||
Value::Ident(s, ..) => match s.resolve_ref() {
|
||||
Value::Ident(s, ..) => match s.as_str() {
|
||||
"auto" => sep,
|
||||
"comma" => ListSeparator::Comma,
|
||||
"space" => ListSeparator::Space,
|
||||
@ -188,9 +188,9 @@ fn join(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
|
||||
scope,
|
||||
super_selector,
|
||||
2,
|
||||
"separator" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
|
||||
"separator" = Value::Ident("auto".to_owned(), QuoteKind::None)
|
||||
) {
|
||||
Value::Ident(s, ..) => match s.resolve_ref() {
|
||||
Value::Ident(s, ..) => match s.as_str() {
|
||||
"auto" => {
|
||||
if list1.is_empty() || (list1.len() == 1 && sep1 == ListSeparator::Space) {
|
||||
sep2
|
||||
@ -225,9 +225,9 @@ fn join(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
|
||||
scope,
|
||||
super_selector,
|
||||
3,
|
||||
"bracketed" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
|
||||
"bracketed" = Value::Ident("auto".to_owned(), QuoteKind::None)
|
||||
) {
|
||||
Value::Ident(s, ..) => match s.resolve_ref() {
|
||||
Value::Ident(s, ..) => match s.as_str() {
|
||||
"auto" => brackets,
|
||||
_ => Brackets::Bracketed,
|
||||
},
|
||||
|
@ -5,7 +5,6 @@ use codemap::Spanned;
|
||||
use crate::args::CallArgs;
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::global_var_exists;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
@ -28,7 +27,7 @@ fn feature_exists(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "feature") {
|
||||
Value::Ident(s, _) => Ok(match s.resolve_ref() {
|
||||
Value::Ident(s, _) => Ok(match s.as_str() {
|
||||
// A local variable will shadow a global variable unless
|
||||
// `!global` is used.
|
||||
"global-variable-shadowing" => Value::True,
|
||||
@ -72,17 +71,14 @@ fn unit(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
|
||||
.into())
|
||||
}
|
||||
};
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(unit),
|
||||
QuoteKind::Quoted,
|
||||
))
|
||||
Ok(Value::Ident(unit, QuoteKind::Quoted))
|
||||
}
|
||||
|
||||
fn type_of(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
let value = arg!(args, scope, super_selector, 0, "value");
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(value.kind(args.span())?),
|
||||
value.kind(args.span())?.to_owned(),
|
||||
QuoteKind::None,
|
||||
))
|
||||
}
|
||||
@ -99,9 +95,9 @@ fn unitless(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
|
||||
fn inspect(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(
|
||||
arg!(args, scope, super_selector, 0, "value").inspect(args.span())?,
|
||||
),
|
||||
arg!(args, scope, super_selector, 0, "value")
|
||||
.inspect(args.span())?
|
||||
.into(),
|
||||
QuoteKind::None,
|
||||
))
|
||||
}
|
||||
@ -113,7 +109,7 @@ fn variable_exists(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "name") {
|
||||
Value::Ident(s, _) => Ok(Value::bool(scope.var_exists(s))),
|
||||
Value::Ident(s, _) => Ok(Value::bool(scope.var_exists(&s))),
|
||||
v => Err((
|
||||
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
|
||||
args.span(),
|
||||
@ -129,7 +125,7 @@ fn global_variable_exists(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "name") {
|
||||
Value::Ident(s, _) => Ok(Value::bool(global_var_exists(s))),
|
||||
Value::Ident(s, _) => Ok(Value::bool(global_var_exists(&s))),
|
||||
v => Err((
|
||||
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
|
||||
args.span(),
|
||||
@ -141,7 +137,7 @@ fn global_variable_exists(
|
||||
fn mixin_exists(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
|
||||
args.max_args(2)?;
|
||||
match arg!(args, scope, super_selector, 0, "name") {
|
||||
Value::Ident(s, _) => Ok(Value::bool(scope.mixin_exists(s))),
|
||||
Value::Ident(s, _) => Ok(Value::bool(scope.mixin_exists(&s))),
|
||||
v => Err((
|
||||
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
|
||||
args.span(),
|
||||
@ -157,7 +153,9 @@ fn function_exists(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(2)?;
|
||||
match arg!(args, scope, super_selector, 0, "name") {
|
||||
Value::Ident(s, _) => Ok(Value::bool(scope.fn_exists(s))),
|
||||
Value::Ident(s, _) => Ok(Value::bool(
|
||||
scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(s.as_str()),
|
||||
)),
|
||||
v => Err((
|
||||
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
|
||||
args.span(),
|
||||
@ -203,12 +201,12 @@ fn get_function(mut args: CallArgs, scope: &Scope, super_selector: &Selector) ->
|
||||
}
|
||||
|
||||
let func = match scope.get_fn(Spanned {
|
||||
node: name,
|
||||
node: name.clone(),
|
||||
span: args.span(),
|
||||
}) {
|
||||
Ok(f) => SassFunction::UserDefined(Box::new(f), name.into()),
|
||||
Err(..) => match GLOBAL_FUNCTIONS.get(&name.resolve_ref()) {
|
||||
Some(f) => SassFunction::Builtin(f.clone(), name.into()),
|
||||
Ok(f) => SassFunction::UserDefined(Box::new(f), name),
|
||||
Err(..) => match GLOBAL_FUNCTIONS.get(name.as_str()) {
|
||||
Some(f) => SassFunction::Builtin(f.clone(), name),
|
||||
None => return Err((format!("Function not found: {}", name), args.span()).into()),
|
||||
},
|
||||
};
|
||||
|
@ -9,7 +9,6 @@ use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||
use crate::args::CallArgs;
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -22,10 +21,9 @@ fn to_upper_case(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "string") {
|
||||
Value::Ident(i, q) => {
|
||||
let mut i = i.resolve();
|
||||
Value::Ident(mut i, q) => {
|
||||
i.make_ascii_uppercase();
|
||||
Ok(Value::Ident(InternedString::get_or_intern(i), q))
|
||||
Ok(Value::Ident(i, q))
|
||||
}
|
||||
v => Err((
|
||||
format!(
|
||||
@ -45,10 +43,9 @@ fn to_lower_case(
|
||||
) -> SassResult<Value> {
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "string") {
|
||||
Value::Ident(i, q) => {
|
||||
let mut i = i.resolve();
|
||||
Value::Ident(mut i, q) => {
|
||||
i.make_ascii_lowercase();
|
||||
Ok(Value::Ident(InternedString::get_or_intern(i), q))
|
||||
Ok(Value::Ident(i, q))
|
||||
}
|
||||
v => Err((
|
||||
format!(
|
||||
@ -65,7 +62,7 @@ fn str_length(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
|
||||
args.max_args(1)?;
|
||||
match arg!(args, scope, super_selector, 0, "string") {
|
||||
Value::Ident(i, _) => Ok(Value::Dimension(
|
||||
Number::from(i.resolve().chars().count()),
|
||||
Number::from(i.chars().count()),
|
||||
Unit::None,
|
||||
)),
|
||||
v => Err((
|
||||
@ -124,7 +121,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
.into())
|
||||
}
|
||||
};
|
||||
let str_len = string.resolve().chars().count();
|
||||
let str_len = string.chars().count();
|
||||
let start = match arg!(args, scope, super_selector, 1, "start-at") {
|
||||
Value::Dimension(n, Unit::None) if n.is_decimal() => {
|
||||
return Err((format!("{} is not an int.", n), args.span()).into())
|
||||
@ -198,17 +195,14 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
}
|
||||
|
||||
if start > end || start > str_len {
|
||||
Ok(Value::Ident(InternedString::get_or_intern(""), quotes))
|
||||
Ok(Value::Ident(String::new(), quotes))
|
||||
} else {
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(
|
||||
string
|
||||
.resolve()
|
||||
.chars()
|
||||
.skip(start - 1)
|
||||
.take(end - start + 1)
|
||||
.collect::<String>(),
|
||||
),
|
||||
string
|
||||
.chars()
|
||||
.skip(start - 1)
|
||||
.take(end - start + 1)
|
||||
.collect(),
|
||||
quotes,
|
||||
))
|
||||
}
|
||||
@ -217,7 +211,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
|
||||
args.max_args(2)?;
|
||||
let s1 = match arg!(args, scope, super_selector, 0, "string") {
|
||||
Value::Ident(i, _) => i.resolve(),
|
||||
Value::Ident(i, _) => i,
|
||||
v => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -231,7 +225,7 @@ fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
};
|
||||
|
||||
let substr = match arg!(args, scope, super_selector, 1, "substring") {
|
||||
Value::Ident(i, _) => i.resolve(),
|
||||
Value::Ident(i, _) => i,
|
||||
v => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -253,7 +247,7 @@ fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
|
||||
fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
|
||||
args.max_args(3)?;
|
||||
let (s1, quotes) = match arg!(args, scope, super_selector, 0, "string") {
|
||||
Value::Ident(i, q) => (i.resolve().to_string(), q),
|
||||
Value::Ident(i, q) => (i, q),
|
||||
v => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -267,7 +261,7 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
|
||||
};
|
||||
|
||||
let substr = match arg!(args, scope, super_selector, 1, "insert") {
|
||||
Value::Ident(i, _) => i.resolve().to_string(),
|
||||
Value::Ident(i, _) => i,
|
||||
v => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -305,7 +299,7 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
|
||||
};
|
||||
|
||||
if s1.is_empty() {
|
||||
return Ok(Value::Ident(InternedString::get_or_intern(substr), quotes));
|
||||
return Ok(Value::Ident(substr, quotes));
|
||||
}
|
||||
|
||||
let len = s1.chars().count();
|
||||
@ -348,21 +342,18 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Value::Ident(InternedString::get_or_intern(string), quotes))
|
||||
Ok(Value::Ident(string, quotes))
|
||||
}
|
||||
|
||||
#[cfg(feature = "random")]
|
||||
fn unique_id(args: CallArgs, _: &Scope, _: &Selector) -> SassResult<Value> {
|
||||
args.max_args(0)?;
|
||||
let mut rng = thread_rng();
|
||||
let string: String = std::iter::repeat(())
|
||||
let string = std::iter::repeat(())
|
||||
.map(|()| rng.sample(Alphanumeric))
|
||||
.take(7)
|
||||
.collect();
|
||||
Ok(Value::Ident(
|
||||
InternedString::get_or_intern(string),
|
||||
QuoteKind::None,
|
||||
))
|
||||
Ok(Value::Ident(string, QuoteKind::None))
|
||||
}
|
||||
|
||||
pub(crate) fn declare(f: &mut GlobalFunctionMap) {
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use crate::interner::InternedString;
|
||||
use crate::value::Number;
|
||||
pub(crate) use name::NAMED_COLORS;
|
||||
|
||||
@ -469,14 +468,14 @@ impl Color {
|
||||
|
||||
/// Other color functions
|
||||
impl Color {
|
||||
pub fn to_ie_hex_str(&self) -> InternedString {
|
||||
InternedString::get_or_intern(format!(
|
||||
pub fn to_ie_hex_str(&self) -> String {
|
||||
format!(
|
||||
"#{:X}{:X}{:X}{:X}",
|
||||
(self.alpha() * Number::from(255)).round().to_integer(),
|
||||
self.red().to_integer(),
|
||||
self.green().to_integer(),
|
||||
self.blue().to_integer()
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,9 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::interner::InternedString;
|
||||
|
||||
pub(crate) struct NamedColorMap {
|
||||
name_to_rgba: HashMap<InternedString, [u8; 4]>,
|
||||
rgba_to_name: HashMap<[u8; 4], InternedString>,
|
||||
name_to_rgba: HashMap<&'static str, [u8; 4]>,
|
||||
rgba_to_name: HashMap<[u8; 4], &'static str>,
|
||||
}
|
||||
|
||||
impl NamedColorMap {
|
||||
@ -19,581 +17,161 @@ impl NamedColorMap {
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, name: InternedString, rgba: [u8; 4]) {
|
||||
pub fn insert(&mut self, name: &'static str, rgba: [u8; 4]) {
|
||||
self.name_to_rgba.insert(name, rgba);
|
||||
self.rgba_to_name.insert(rgba, name);
|
||||
}
|
||||
|
||||
pub fn get_by_name(&self, name: InternedString) -> Option<&[u8; 4]> {
|
||||
self.name_to_rgba.get(&name)
|
||||
pub fn get_by_name(&self, name: &str) -> Option<&[u8; 4]> {
|
||||
self.name_to_rgba.get(name)
|
||||
}
|
||||
|
||||
pub fn get_by_rgba(&self, rgba: [u8; 4]) -> Option<&InternedString> {
|
||||
pub fn get_by_rgba(&self, rgba: [u8; 4]) -> Option<&&str> {
|
||||
self.rgba_to_name.get(&rgba)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) static NAMED_COLORS: Lazy<NamedColorMap> = Lazy::new(|| {
|
||||
let mut m = NamedColorMap::with_capacity(150);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("aliceblue"),
|
||||
[0xF0, 0xF8, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("antiquewhite"),
|
||||
[0xFA, 0xEB, 0xD7, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("aqua"),
|
||||
[0x00, 0xFF, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("aquamarine"),
|
||||
[0x7F, 0xFF, 0xD4, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("azure"),
|
||||
[0xF0, 0xFF, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("beige"),
|
||||
[0xF5, 0xF5, 0xDC, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("bisque"),
|
||||
[0xFF, 0xE4, 0xC4, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("black"),
|
||||
[0x00, 0x00, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("blanchedalmond"),
|
||||
[0xFF, 0xEB, 0xCD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("blue"),
|
||||
[0x00, 0x00, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("blueviolet"),
|
||||
[0x8A, 0x2B, 0xE2, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("brown"),
|
||||
[0xA5, 0x2A, 0x2A, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("burlywood"),
|
||||
[0xDE, 0xB8, 0x87, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("cadetblue"),
|
||||
[0x5F, 0x9E, 0xA0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("chartreuse"),
|
||||
[0x7F, 0xFF, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("chocolate"),
|
||||
[0xD2, 0x69, 0x1E, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("coral"),
|
||||
[0xFF, 0x7F, 0x50, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("cornflowerblue"),
|
||||
[0x64, 0x95, 0xED, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("cornsilk"),
|
||||
[0xFF, 0xF8, 0xDC, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("crimson"),
|
||||
[0xDC, 0x14, 0x3C, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkblue"),
|
||||
[0x00, 0x00, 0x8B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkcyan"),
|
||||
[0x00, 0x8B, 0x8B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkgoldenrod"),
|
||||
[0xB8, 0x86, 0x0B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkgray"),
|
||||
[0xA9, 0xA9, 0xA9, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkgreen"),
|
||||
[0x00, 0x64, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkkhaki"),
|
||||
[0xBD, 0xB7, 0x6B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkmagenta"),
|
||||
[0x8B, 0x00, 0x8B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkolivegreen"),
|
||||
[0x55, 0x6B, 0x2F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkorange"),
|
||||
[0xFF, 0x8C, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkorchid"),
|
||||
[0x99, 0x32, 0xCC, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkred"),
|
||||
[0x8B, 0x00, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darksalmon"),
|
||||
[0xE9, 0x96, 0x7A, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkseagreen"),
|
||||
[0x8F, 0xBC, 0x8F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkslateblue"),
|
||||
[0x48, 0x3D, 0x8B, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkslategray"),
|
||||
[0x2F, 0x4F, 0x4F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkturquoise"),
|
||||
[0x00, 0xCE, 0xD1, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("darkviolet"),
|
||||
[0x94, 0x00, 0xD3, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("deeppink"),
|
||||
[0xFF, 0x14, 0x93, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("deepskyblue"),
|
||||
[0x00, 0xBF, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("dimgray"),
|
||||
[0x69, 0x69, 0x69, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("dodgerblue"),
|
||||
[0x1E, 0x90, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("firebrick"),
|
||||
[0xB2, 0x22, 0x22, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("floralwhite"),
|
||||
[0xFF, 0xFA, 0xF0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("forestgreen"),
|
||||
[0x22, 0x8B, 0x22, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("fuchsia"),
|
||||
[0xFF, 0x00, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("gainsboro"),
|
||||
[0xDC, 0xDC, 0xDC, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("ghostwhite"),
|
||||
[0xF8, 0xF8, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("gold"),
|
||||
[0xFF, 0xD7, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("goldenrod"),
|
||||
[0xDA, 0xA5, 0x20, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("gray"),
|
||||
[0x80, 0x80, 0x80, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("green"),
|
||||
[0x00, 0x80, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("greenyellow"),
|
||||
[0xAD, 0xFF, 0x2F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("honeydew"),
|
||||
[0xF0, 0xFF, 0xF0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("hotpink"),
|
||||
[0xFF, 0x69, 0xB4, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("indianred"),
|
||||
[0xCD, 0x5C, 0x5C, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("indigo"),
|
||||
[0x4B, 0x00, 0x82, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("ivory"),
|
||||
[0xFF, 0xFF, 0xF0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("khaki"),
|
||||
[0xF0, 0xE6, 0x8C, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lavender"),
|
||||
[0xE6, 0xE6, 0xFA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lavenderblush"),
|
||||
[0xFF, 0xF0, 0xF5, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lawngreen"),
|
||||
[0x7C, 0xFC, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lemonchiffon"),
|
||||
[0xFF, 0xFA, 0xCD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightblue"),
|
||||
[0xAD, 0xD8, 0xE6, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightcoral"),
|
||||
[0xF0, 0x80, 0x80, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightcyan"),
|
||||
[0xE0, 0xFF, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightgoldenrodyellow"),
|
||||
[0xFA, 0xFA, 0xD2, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightgray"),
|
||||
[0xD3, 0xD3, 0xD3, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightgreen"),
|
||||
[0x90, 0xEE, 0x90, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightpink"),
|
||||
[0xFF, 0xB6, 0xC1, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightsalmon"),
|
||||
[0xFF, 0xA0, 0x7A, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightseagreen"),
|
||||
[0x20, 0xB2, 0xAA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightskyblue"),
|
||||
[0x87, 0xCE, 0xFA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightslategray"),
|
||||
[0x77, 0x88, 0x99, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightsteelblue"),
|
||||
[0xB0, 0xC4, 0xDE, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lightyellow"),
|
||||
[0xFF, 0xFF, 0xE0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("lime"),
|
||||
[0x00, 0xFF, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("limegreen"),
|
||||
[0x32, 0xCD, 0x32, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("linen"),
|
||||
[0xFA, 0xF0, 0xE6, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("maroon"),
|
||||
[0x80, 0x00, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumaquamarine"),
|
||||
[0x66, 0xCD, 0xAA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumblue"),
|
||||
[0x00, 0x00, 0xCD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumorchid"),
|
||||
[0xBA, 0x55, 0xD3, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumpurple"),
|
||||
[0x93, 0x70, 0xDB, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumseagreen"),
|
||||
[0x3C, 0xB3, 0x71, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumslateblue"),
|
||||
[0x7B, 0x68, 0xEE, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumspringgreen"),
|
||||
[0x00, 0xFA, 0x9A, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumturquoise"),
|
||||
[0x48, 0xD1, 0xCC, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mediumvioletred"),
|
||||
[0xC7, 0x15, 0x85, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("midnightblue"),
|
||||
[0x19, 0x19, 0x70, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mintcream"),
|
||||
[0xF5, 0xFF, 0xFA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("mistyrose"),
|
||||
[0xFF, 0xE4, 0xE1, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("moccasin"),
|
||||
[0xFF, 0xE4, 0xB5, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("navajowhite"),
|
||||
[0xFF, 0xDE, 0xAD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("navy"),
|
||||
[0x00, 0x00, 0x80, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("oldlace"),
|
||||
[0xFD, 0xF5, 0xE6, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("olive"),
|
||||
[0x80, 0x80, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("olivedrab"),
|
||||
[0x6B, 0x8E, 0x23, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("orange"),
|
||||
[0xFF, 0xA5, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("orangered"),
|
||||
[0xFF, 0x45, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("orchid"),
|
||||
[0xDA, 0x70, 0xD6, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("palegoldenrod"),
|
||||
[0xEE, 0xE8, 0xAA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("palegreen"),
|
||||
[0x98, 0xFB, 0x98, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("paleturquoise"),
|
||||
[0xAF, 0xEE, 0xEE, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("palevioletred"),
|
||||
[0xDB, 0x70, 0x93, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("papayawhip"),
|
||||
[0xFF, 0xEF, 0xD5, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("peachpuff"),
|
||||
[0xFF, 0xDA, 0xB9, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("peru"),
|
||||
[0xCD, 0x85, 0x3F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("pink"),
|
||||
[0xFF, 0xC0, 0xCB, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("plum"),
|
||||
[0xDD, 0xA0, 0xDD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("powderblue"),
|
||||
[0xB0, 0xE0, 0xE6, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("purple"),
|
||||
[0x80, 0x00, 0x80, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("rebeccapurple"),
|
||||
[0x66, 0x33, 0x99, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("red"),
|
||||
[0xFF, 0x00, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("rosybrown"),
|
||||
[0xBC, 0x8F, 0x8F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("royalblue"),
|
||||
[0x41, 0x69, 0xE1, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("saddlebrown"),
|
||||
[0x8B, 0x45, 0x13, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("salmon"),
|
||||
[0xFA, 0x80, 0x72, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("sandybrown"),
|
||||
[0xF4, 0xA4, 0x60, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("seagreen"),
|
||||
[0x2E, 0x8B, 0x57, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("seashell"),
|
||||
[0xFF, 0xF5, 0xEE, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("sienna"),
|
||||
[0xA0, 0x52, 0x2D, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("silver"),
|
||||
[0xC0, 0xC0, 0xC0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("skyblue"),
|
||||
[0x87, 0xCE, 0xEB, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("slateblue"),
|
||||
[0x6A, 0x5A, 0xCD, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("slategray"),
|
||||
[0x70, 0x80, 0x90, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("snow"),
|
||||
[0xFF, 0xFA, 0xFA, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("springgreen"),
|
||||
[0x00, 0xFF, 0x7F, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("steelblue"),
|
||||
[0x46, 0x82, 0xB4, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("tan"),
|
||||
[0xD2, 0xB4, 0x8C, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("teal"),
|
||||
[0x00, 0x80, 0x80, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("thistle"),
|
||||
[0xD8, 0xBF, 0xD8, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("tomato"),
|
||||
[0xFF, 0x63, 0x47, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("turquoise"),
|
||||
[0x40, 0xE0, 0xD0, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("violet"),
|
||||
[0xEE, 0x82, 0xEE, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("wheat"),
|
||||
[0xF5, 0xDE, 0xB3, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("white"),
|
||||
[0xFF, 0xFF, 0xFF, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("whitesmoke"),
|
||||
[0xF5, 0xF5, 0xF5, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("yellow"),
|
||||
[0xFF, 0xFF, 0x00, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("yellowgreen"),
|
||||
[0x9A, 0xCD, 0x32, 0xFF],
|
||||
);
|
||||
m.insert(
|
||||
InternedString::get_or_intern("transparent"),
|
||||
[0x00, 0x00, 0x00, 0x00],
|
||||
);
|
||||
m.insert("aliceblue", [0xF0, 0xF8, 0xFF, 0xFF]);
|
||||
m.insert("antiquewhite", [0xFA, 0xEB, 0xD7, 0xFF]);
|
||||
m.insert("aqua", [0x00, 0xFF, 0xFF, 0xFF]);
|
||||
m.insert("aquamarine", [0x7F, 0xFF, 0xD4, 0xFF]);
|
||||
m.insert("azure", [0xF0, 0xFF, 0xFF, 0xFF]);
|
||||
m.insert("beige", [0xF5, 0xF5, 0xDC, 0xFF]);
|
||||
m.insert("bisque", [0xFF, 0xE4, 0xC4, 0xFF]);
|
||||
m.insert("black", [0x00, 0x00, 0x00, 0xFF]);
|
||||
m.insert("blanchedalmond", [0xFF, 0xEB, 0xCD, 0xFF]);
|
||||
m.insert("blue", [0x00, 0x00, 0xFF, 0xFF]);
|
||||
m.insert("blueviolet", [0x8A, 0x2B, 0xE2, 0xFF]);
|
||||
m.insert("brown", [0xA5, 0x2A, 0x2A, 0xFF]);
|
||||
m.insert("burlywood", [0xDE, 0xB8, 0x87, 0xFF]);
|
||||
m.insert("cadetblue", [0x5F, 0x9E, 0xA0, 0xFF]);
|
||||
m.insert("chartreuse", [0x7F, 0xFF, 0x00, 0xFF]);
|
||||
m.insert("chocolate", [0xD2, 0x69, 0x1E, 0xFF]);
|
||||
m.insert("coral", [0xFF, 0x7F, 0x50, 0xFF]);
|
||||
m.insert("cornflowerblue", [0x64, 0x95, 0xED, 0xFF]);
|
||||
m.insert("cornsilk", [0xFF, 0xF8, 0xDC, 0xFF]);
|
||||
m.insert("crimson", [0xDC, 0x14, 0x3C, 0xFF]);
|
||||
m.insert("darkblue", [0x00, 0x00, 0x8B, 0xFF]);
|
||||
m.insert("darkcyan", [0x00, 0x8B, 0x8B, 0xFF]);
|
||||
m.insert("darkgoldenrod", [0xB8, 0x86, 0x0B, 0xFF]);
|
||||
m.insert("darkgray", [0xA9, 0xA9, 0xA9, 0xFF]);
|
||||
m.insert("darkgreen", [0x00, 0x64, 0x00, 0xFF]);
|
||||
m.insert("darkkhaki", [0xBD, 0xB7, 0x6B, 0xFF]);
|
||||
m.insert("darkmagenta", [0x8B, 0x00, 0x8B, 0xFF]);
|
||||
m.insert("darkolivegreen", [0x55, 0x6B, 0x2F, 0xFF]);
|
||||
m.insert("darkorange", [0xFF, 0x8C, 0x00, 0xFF]);
|
||||
m.insert("darkorchid", [0x99, 0x32, 0xCC, 0xFF]);
|
||||
m.insert("darkred", [0x8B, 0x00, 0x00, 0xFF]);
|
||||
m.insert("darksalmon", [0xE9, 0x96, 0x7A, 0xFF]);
|
||||
m.insert("darkseagreen", [0x8F, 0xBC, 0x8F, 0xFF]);
|
||||
m.insert("darkslateblue", [0x48, 0x3D, 0x8B, 0xFF]);
|
||||
m.insert("darkslategray", [0x2F, 0x4F, 0x4F, 0xFF]);
|
||||
m.insert("darkturquoise", [0x00, 0xCE, 0xD1, 0xFF]);
|
||||
m.insert("darkviolet", [0x94, 0x00, 0xD3, 0xFF]);
|
||||
m.insert("deeppink", [0xFF, 0x14, 0x93, 0xFF]);
|
||||
m.insert("deepskyblue", [0x00, 0xBF, 0xFF, 0xFF]);
|
||||
m.insert("dimgray", [0x69, 0x69, 0x69, 0xFF]);
|
||||
m.insert("dodgerblue", [0x1E, 0x90, 0xFF, 0xFF]);
|
||||
m.insert("firebrick", [0xB2, 0x22, 0x22, 0xFF]);
|
||||
m.insert("floralwhite", [0xFF, 0xFA, 0xF0, 0xFF]);
|
||||
m.insert("forestgreen", [0x22, 0x8B, 0x22, 0xFF]);
|
||||
m.insert("fuchsia", [0xFF, 0x00, 0xFF, 0xFF]);
|
||||
m.insert("gainsboro", [0xDC, 0xDC, 0xDC, 0xFF]);
|
||||
m.insert("ghostwhite", [0xF8, 0xF8, 0xFF, 0xFF]);
|
||||
m.insert("gold", [0xFF, 0xD7, 0x00, 0xFF]);
|
||||
m.insert("goldenrod", [0xDA, 0xA5, 0x20, 0xFF]);
|
||||
m.insert("gray", [0x80, 0x80, 0x80, 0xFF]);
|
||||
m.insert("green", [0x00, 0x80, 0x00, 0xFF]);
|
||||
m.insert("greenyellow", [0xAD, 0xFF, 0x2F, 0xFF]);
|
||||
m.insert("honeydew", [0xF0, 0xFF, 0xF0, 0xFF]);
|
||||
m.insert("hotpink", [0xFF, 0x69, 0xB4, 0xFF]);
|
||||
m.insert("indianred", [0xCD, 0x5C, 0x5C, 0xFF]);
|
||||
m.insert("indigo", [0x4B, 0x00, 0x82, 0xFF]);
|
||||
m.insert("ivory", [0xFF, 0xFF, 0xF0, 0xFF]);
|
||||
m.insert("khaki", [0xF0, 0xE6, 0x8C, 0xFF]);
|
||||
m.insert("lavender", [0xE6, 0xE6, 0xFA, 0xFF]);
|
||||
m.insert("lavenderblush", [0xFF, 0xF0, 0xF5, 0xFF]);
|
||||
m.insert("lawngreen", [0x7C, 0xFC, 0x00, 0xFF]);
|
||||
m.insert("lemonchiffon", [0xFF, 0xFA, 0xCD, 0xFF]);
|
||||
m.insert("lightblue", [0xAD, 0xD8, 0xE6, 0xFF]);
|
||||
m.insert("lightcoral", [0xF0, 0x80, 0x80, 0xFF]);
|
||||
m.insert("lightcyan", [0xE0, 0xFF, 0xFF, 0xFF]);
|
||||
m.insert("lightgoldenrodyellow", [0xFA, 0xFA, 0xD2, 0xFF]);
|
||||
m.insert("lightgray", [0xD3, 0xD3, 0xD3, 0xFF]);
|
||||
m.insert("lightgreen", [0x90, 0xEE, 0x90, 0xFF]);
|
||||
m.insert("lightpink", [0xFF, 0xB6, 0xC1, 0xFF]);
|
||||
m.insert("lightsalmon", [0xFF, 0xA0, 0x7A, 0xFF]);
|
||||
m.insert("lightseagreen", [0x20, 0xB2, 0xAA, 0xFF]);
|
||||
m.insert("lightskyblue", [0x87, 0xCE, 0xFA, 0xFF]);
|
||||
m.insert("lightslategray", [0x77, 0x88, 0x99, 0xFF]);
|
||||
m.insert("lightsteelblue", [0xB0, 0xC4, 0xDE, 0xFF]);
|
||||
m.insert("lightyellow", [0xFF, 0xFF, 0xE0, 0xFF]);
|
||||
m.insert("lime", [0x00, 0xFF, 0x00, 0xFF]);
|
||||
m.insert("limegreen", [0x32, 0xCD, 0x32, 0xFF]);
|
||||
m.insert("linen", [0xFA, 0xF0, 0xE6, 0xFF]);
|
||||
m.insert("maroon", [0x80, 0x00, 0x00, 0xFF]);
|
||||
m.insert("mediumaquamarine", [0x66, 0xCD, 0xAA, 0xFF]);
|
||||
m.insert("mediumblue", [0x00, 0x00, 0xCD, 0xFF]);
|
||||
m.insert("mediumorchid", [0xBA, 0x55, 0xD3, 0xFF]);
|
||||
m.insert("mediumpurple", [0x93, 0x70, 0xDB, 0xFF]);
|
||||
m.insert("mediumseagreen", [0x3C, 0xB3, 0x71, 0xFF]);
|
||||
m.insert("mediumslateblue", [0x7B, 0x68, 0xEE, 0xFF]);
|
||||
m.insert("mediumspringgreen", [0x00, 0xFA, 0x9A, 0xFF]);
|
||||
m.insert("mediumturquoise", [0x48, 0xD1, 0xCC, 0xFF]);
|
||||
m.insert("mediumvioletred", [0xC7, 0x15, 0x85, 0xFF]);
|
||||
m.insert("midnightblue", [0x19, 0x19, 0x70, 0xFF]);
|
||||
m.insert("mintcream", [0xF5, 0xFF, 0xFA, 0xFF]);
|
||||
m.insert("mistyrose", [0xFF, 0xE4, 0xE1, 0xFF]);
|
||||
m.insert("moccasin", [0xFF, 0xE4, 0xB5, 0xFF]);
|
||||
m.insert("navajowhite", [0xFF, 0xDE, 0xAD, 0xFF]);
|
||||
m.insert("navy", [0x00, 0x00, 0x80, 0xFF]);
|
||||
m.insert("oldlace", [0xFD, 0xF5, 0xE6, 0xFF]);
|
||||
m.insert("olive", [0x80, 0x80, 0x00, 0xFF]);
|
||||
m.insert("olivedrab", [0x6B, 0x8E, 0x23, 0xFF]);
|
||||
m.insert("orange", [0xFF, 0xA5, 0x00, 0xFF]);
|
||||
m.insert("orangered", [0xFF, 0x45, 0x00, 0xFF]);
|
||||
m.insert("orchid", [0xDA, 0x70, 0xD6, 0xFF]);
|
||||
m.insert("palegoldenrod", [0xEE, 0xE8, 0xAA, 0xFF]);
|
||||
m.insert("palegreen", [0x98, 0xFB, 0x98, 0xFF]);
|
||||
m.insert("paleturquoise", [0xAF, 0xEE, 0xEE, 0xFF]);
|
||||
m.insert("palevioletred", [0xDB, 0x70, 0x93, 0xFF]);
|
||||
m.insert("papayawhip", [0xFF, 0xEF, 0xD5, 0xFF]);
|
||||
m.insert("peachpuff", [0xFF, 0xDA, 0xB9, 0xFF]);
|
||||
m.insert("peru", [0xCD, 0x85, 0x3F, 0xFF]);
|
||||
m.insert("pink", [0xFF, 0xC0, 0xCB, 0xFF]);
|
||||
m.insert("plum", [0xDD, 0xA0, 0xDD, 0xFF]);
|
||||
m.insert("powderblue", [0xB0, 0xE0, 0xE6, 0xFF]);
|
||||
m.insert("purple", [0x80, 0x00, 0x80, 0xFF]);
|
||||
m.insert("rebeccapurple", [0x66, 0x33, 0x99, 0xFF]);
|
||||
m.insert("red", [0xFF, 0x00, 0x00, 0xFF]);
|
||||
m.insert("rosybrown", [0xBC, 0x8F, 0x8F, 0xFF]);
|
||||
m.insert("royalblue", [0x41, 0x69, 0xE1, 0xFF]);
|
||||
m.insert("saddlebrown", [0x8B, 0x45, 0x13, 0xFF]);
|
||||
m.insert("salmon", [0xFA, 0x80, 0x72, 0xFF]);
|
||||
m.insert("sandybrown", [0xF4, 0xA4, 0x60, 0xFF]);
|
||||
m.insert("seagreen", [0x2E, 0x8B, 0x57, 0xFF]);
|
||||
m.insert("seashell", [0xFF, 0xF5, 0xEE, 0xFF]);
|
||||
m.insert("sienna", [0xA0, 0x52, 0x2D, 0xFF]);
|
||||
m.insert("silver", [0xC0, 0xC0, 0xC0, 0xFF]);
|
||||
m.insert("skyblue", [0x87, 0xCE, 0xEB, 0xFF]);
|
||||
m.insert("slateblue", [0x6A, 0x5A, 0xCD, 0xFF]);
|
||||
m.insert("slategray", [0x70, 0x80, 0x90, 0xFF]);
|
||||
m.insert("snow", [0xFF, 0xFA, 0xFA, 0xFF]);
|
||||
m.insert("springgreen", [0x00, 0xFF, 0x7F, 0xFF]);
|
||||
m.insert("steelblue", [0x46, 0x82, 0xB4, 0xFF]);
|
||||
m.insert("tan", [0xD2, 0xB4, 0x8C, 0xFF]);
|
||||
m.insert("teal", [0x00, 0x80, 0x80, 0xFF]);
|
||||
m.insert("thistle", [0xD8, 0xBF, 0xD8, 0xFF]);
|
||||
m.insert("tomato", [0xFF, 0x63, 0x47, 0xFF]);
|
||||
m.insert("turquoise", [0x40, 0xE0, 0xD0, 0xFF]);
|
||||
m.insert("violet", [0xEE, 0x82, 0xEE, 0xFF]);
|
||||
m.insert("wheat", [0xF5, 0xDE, 0xB3, 0xFF]);
|
||||
m.insert("white", [0xFF, 0xFF, 0xFF, 0xFF]);
|
||||
m.insert("whitesmoke", [0xF5, 0xF5, 0xF5, 0xFF]);
|
||||
m.insert("yellow", [0xFF, 0xFF, 0x00, 0xFF]);
|
||||
m.insert("yellowgreen", [0x9A, 0xCD, 0x32, 0xFF]);
|
||||
m.insert("transparent", [0x00, 0x00, 0x00, 0x00]);
|
||||
m
|
||||
});
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::interner::InternedString;
|
||||
use std::fmt::{self, Display, Write};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
@ -120,38 +119,3 @@ impl Display for QualifiedName {
|
||||
f.write_str(&self.ident)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Copy)]
|
||||
pub(crate) struct Identifier(InternedString);
|
||||
|
||||
impl Into<Identifier> for InternedString {
|
||||
fn into(self) -> Identifier {
|
||||
Identifier(InternedString::get_or_intern(
|
||||
self.resolve_ref().replace('_', "-"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Identifier {
|
||||
fn from(s: String) -> Identifier {
|
||||
Identifier(InternedString::get_or_intern(s.replace('_', "-")))
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Identifier> for &String {
|
||||
fn into(self) -> Identifier {
|
||||
Identifier(InternedString::get_or_intern(self.replace('_', "-")))
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Identifier> for &str {
|
||||
fn into(self) -> Identifier {
|
||||
Identifier(InternedString::get_or_intern(self.replace('_', "-")))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
use lasso::{Rodeo, Spur};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
thread_local!(static STRINGS: RefCell<Rodeo<Spur>> = RefCell::new(Rodeo::default()));
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct InternedString(Spur);
|
||||
|
||||
impl InternedString {
|
||||
pub fn get_or_intern<T: AsRef<str>>(s: T) -> Self {
|
||||
Self(STRINGS.with(|interner| interner.borrow_mut().get_or_intern(s)))
|
||||
}
|
||||
|
||||
pub fn resolve(self) -> String {
|
||||
STRINGS.with(|interner| interner.borrow().resolve(&self.0).to_string())
|
||||
}
|
||||
|
||||
pub fn is_empty(self) -> bool {
|
||||
self.resolve_ref() == ""
|
||||
}
|
||||
|
||||
pub fn resolve_ref<'a>(self) -> &'a str {
|
||||
unsafe {
|
||||
STRINGS.with(|interner| &(*(interner.as_ptr()).as_ref().unwrap().resolve(&self.0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for InternedString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
STRINGS.with(|interner| write!(f, "{}", interner.borrow().resolve(&self.0)))
|
||||
}
|
||||
}
|
10
src/lib.rs
10
src/lib.rs
@ -90,7 +90,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
|
||||
|
||||
use crate::atrule::{AtRule, AtRuleKind, Function, Mixin};
|
||||
pub use crate::error::{SassError, SassResult};
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::{insert_global_var, Scope};
|
||||
use crate::selector::Selector;
|
||||
use crate::style::Style;
|
||||
@ -110,7 +109,6 @@ mod color;
|
||||
mod common;
|
||||
mod error;
|
||||
mod imports;
|
||||
mod interner;
|
||||
mod lexer;
|
||||
mod output;
|
||||
mod scope;
|
||||
@ -200,7 +198,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
&mut values.into_iter().peekmore(),
|
||||
scope,
|
||||
super_selector,
|
||||
InternedString::get_or_intern(""),
|
||||
String::new(),
|
||||
tok.pos,
|
||||
)?;
|
||||
return Ok(Some(Spanned {
|
||||
@ -220,7 +218,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
devour_whitespace(toks);
|
||||
return Ok(Some(Spanned {
|
||||
node: Expr::Style(Box::new(Style {
|
||||
property: InternedString::get_or_intern(""),
|
||||
property: String::new(),
|
||||
value: Value::Null.span(span),
|
||||
})),
|
||||
span,
|
||||
@ -230,7 +228,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
&mut v,
|
||||
scope,
|
||||
super_selector,
|
||||
InternedString::get_or_intern(""),
|
||||
String::new(),
|
||||
span_before,
|
||||
)?;
|
||||
let value = Style::parse_value(&mut v, scope, super_selector)?;
|
||||
@ -257,7 +255,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
&mut v,
|
||||
scope,
|
||||
super_selector,
|
||||
InternedString::get_or_intern(""),
|
||||
String::new(),
|
||||
tok.pos,
|
||||
)?;
|
||||
let value = Style::parse_value(&mut v, scope, super_selector)?;
|
||||
|
114
src/scope.rs
114
src/scope.rs
@ -4,70 +4,66 @@ use std::collections::HashMap;
|
||||
use codemap::Spanned;
|
||||
|
||||
use crate::atrule::{Function, Mixin};
|
||||
use crate::common::Identifier;
|
||||
use crate::error::SassResult;
|
||||
use crate::value::Value;
|
||||
|
||||
thread_local!(pub(crate) static GLOBAL_SCOPE: RefCell<Scope> = RefCell::new(Scope::new()));
|
||||
|
||||
pub(crate) fn get_global_var<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Spanned<Value>> {
|
||||
GLOBAL_SCOPE.with(|scope| match scope.borrow().vars().get(&s.node.into()) {
|
||||
pub(crate) fn get_global_var(s: Spanned<String>) -> SassResult<Spanned<Value>> {
|
||||
GLOBAL_SCOPE.with(|scope| match scope.borrow().vars().get(&s.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(("Undefined variable.", s.span).into()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if a variable exists in the *global* scope
|
||||
pub(crate) fn global_var_exists<T: Into<Identifier>>(v: T) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow().vars().contains_key(&v.into()))
|
||||
pub(crate) fn global_var_exists(v: &str) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow().vars().contains_key(&v.replace('_', "-")))
|
||||
}
|
||||
|
||||
pub(crate) fn insert_global_var<T: Into<Identifier>>(
|
||||
s: T,
|
||||
v: Spanned<Value>,
|
||||
) -> SassResult<Option<Spanned<Value>>> {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s.into(), v))
|
||||
pub(crate) fn insert_global_var(s: &str, v: Spanned<Value>) -> SassResult<Option<Spanned<Value>>> {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s, v))
|
||||
}
|
||||
|
||||
pub(crate) fn get_global_fn<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Function> {
|
||||
GLOBAL_SCOPE.with(
|
||||
|scope| match scope.borrow().functions().get(&s.node.into()) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(("Undefined function.", s.span).into()),
|
||||
},
|
||||
)
|
||||
pub(crate) fn get_global_fn(s: Spanned<String>) -> SassResult<Function> {
|
||||
GLOBAL_SCOPE.with(|scope| match scope.borrow().functions().get(&s.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(("Undefined function.", s.span).into()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if a function exists in the *global* scope
|
||||
pub(crate) fn global_fn_exists<T: Into<Identifier>>(v: T) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow().functions().contains_key(&v.into()))
|
||||
pub(crate) fn global_fn_exists(v: &str) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| {
|
||||
scope
|
||||
.borrow()
|
||||
.functions()
|
||||
.contains_key(&v.replace('_', "-"))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn insert_global_fn<T: Into<Identifier>>(s: T, v: Function) -> Option<Function> {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_fn(s.into(), 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<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Mixin> {
|
||||
GLOBAL_SCOPE.with(|scope| match scope.borrow().mixins().get(&s.node.into()) {
|
||||
pub(crate) fn get_global_mixin(s: Spanned<String>) -> SassResult<Mixin> {
|
||||
GLOBAL_SCOPE.with(|scope| match scope.borrow().mixins().get(&s.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(("Undefined mixin.", s.span).into()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if a mixin exists in the *global* scope
|
||||
pub(crate) fn global_mixin_exists<T: Into<Identifier>>(v: T) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow().mixins().contains_key(&v.into()))
|
||||
pub(crate) fn global_mixin_exists(v: &str) -> bool {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow().mixins().contains_key(&v.replace('_', "-")))
|
||||
}
|
||||
|
||||
pub(crate) fn insert_global_mixin<T: Into<Identifier>>(s: T, v: Mixin) -> Option<Mixin> {
|
||||
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_mixin(s.into(), 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)]
|
||||
pub(crate) struct Scope {
|
||||
vars: HashMap<Identifier, Spanned<Value>>,
|
||||
mixins: HashMap<Identifier, Mixin>,
|
||||
functions: HashMap<Identifier, Function>,
|
||||
vars: HashMap<String, Spanned<Value>>,
|
||||
mixins: HashMap<String, Mixin>,
|
||||
functions: HashMap<String, Function>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
@ -80,72 +76,68 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn vars(&self) -> &HashMap<Identifier, Spanned<Value>> {
|
||||
pub const fn vars(&self) -> &HashMap<String, Spanned<Value>> {
|
||||
&self.vars
|
||||
}
|
||||
|
||||
pub const fn functions(&self) -> &HashMap<Identifier, Function> {
|
||||
pub const fn functions(&self) -> &HashMap<String, Function> {
|
||||
&self.functions
|
||||
}
|
||||
|
||||
pub const fn mixins(&self) -> &HashMap<Identifier, Mixin> {
|
||||
pub const fn mixins(&self) -> &HashMap<String, Mixin> {
|
||||
&self.mixins
|
||||
}
|
||||
|
||||
pub fn get_var<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Spanned<Value>> {
|
||||
let name = name.map_node(|n| n.into());
|
||||
pub fn get_var(&self, mut name: Spanned<String>) -> SassResult<Spanned<Value>> {
|
||||
name.node = name.node.replace('_', "-");
|
||||
match self.vars.get(&name.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => get_global_var(name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_var<T: Into<Identifier>>(
|
||||
&mut self,
|
||||
s: T,
|
||||
v: Spanned<Value>,
|
||||
) -> SassResult<Option<Spanned<Value>>> {
|
||||
pub fn insert_var(&mut self, s: &str, v: Spanned<Value>) -> SassResult<Option<Spanned<Value>>> {
|
||||
let Spanned { node, span } = v;
|
||||
Ok(self.vars.insert(s.into(), node.eval(span)?))
|
||||
Ok(self.vars.insert(s.replace('_', "-"), node.eval(span)?))
|
||||
}
|
||||
|
||||
pub fn var_exists<T: Into<Identifier>>(&self, v: T) -> bool {
|
||||
let name = v.into();
|
||||
self.vars.contains_key(&name) || global_var_exists(name)
|
||||
pub fn var_exists(&self, v: &str) -> bool {
|
||||
let name = &v.replace('_', "-");
|
||||
self.vars.contains_key(name) || global_var_exists(name)
|
||||
}
|
||||
|
||||
pub fn get_mixin<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Mixin> {
|
||||
let name = name.map_node(|n| n.into());
|
||||
pub fn get_mixin(&self, mut name: Spanned<String>) -> SassResult<Mixin> {
|
||||
name.node = name.node.replace('_', "-");
|
||||
match self.mixins.get(&name.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => get_global_mixin(name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_mixin<T: Into<Identifier>>(&mut self, s: T, v: Mixin) -> Option<Mixin> {
|
||||
self.mixins.insert(s.into(), v)
|
||||
pub fn insert_mixin(&mut self, s: &str, v: Mixin) -> Option<Mixin> {
|
||||
self.mixins.insert(s.replace('_', "-"), v)
|
||||
}
|
||||
|
||||
pub fn mixin_exists<T: Into<Identifier>>(&self, v: T) -> bool {
|
||||
let name = v.into();
|
||||
self.mixins.contains_key(&name) || global_mixin_exists(name)
|
||||
pub fn mixin_exists(&self, v: &str) -> bool {
|
||||
let name = &v.replace('_', "-");
|
||||
self.mixins.contains_key(name) || global_mixin_exists(name)
|
||||
}
|
||||
|
||||
pub fn get_fn<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Function> {
|
||||
let name = name.map_node(|n| n.into());
|
||||
pub fn get_fn(&self, mut name: Spanned<String>) -> SassResult<Function> {
|
||||
name.node = name.node.replace('_', "-");
|
||||
match self.functions.get(&name.node) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => get_global_fn(name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_fn<T: Into<Identifier>>(&mut self, s: T, v: Function) -> Option<Function> {
|
||||
self.functions.insert(s.into(), v)
|
||||
pub fn insert_fn(&mut self, s: &str, v: Function) -> Option<Function> {
|
||||
self.functions.insert(s.replace('_', "-"), v)
|
||||
}
|
||||
|
||||
pub fn fn_exists<T: Into<Identifier>>(&self, v: T) -> bool {
|
||||
let name = v.into();
|
||||
self.functions.contains_key(&name) || global_fn_exists(name)
|
||||
pub fn fn_exists(&self, v: &str) -> bool {
|
||||
let name = &v.replace('_', "-");
|
||||
self.functions.contains_key(name) || global_fn_exists(name)
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: Scope) {
|
||||
|
@ -7,7 +7,6 @@ use codemap::Span;
|
||||
use super::{Selector, SelectorKind};
|
||||
use crate::common::{QualifiedName, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::utils::{devour_whitespace, eat_ident, is_ident, parse_quoted_string};
|
||||
use crate::value::Value;
|
||||
@ -125,7 +124,7 @@ impl Attribute {
|
||||
q @ '\'' | q @ '"' => {
|
||||
toks.next();
|
||||
match parse_quoted_string(toks, scope, q, super_selector)?.node {
|
||||
Value::Ident(s, ..) => s.resolve().to_string(),
|
||||
Value::Ident(s, ..) => s,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -181,12 +180,9 @@ impl Display for Attribute {
|
||||
// or having special emitter for quoted strings?
|
||||
// (also avoids the clone because we can consume/modify self)
|
||||
f.write_str(
|
||||
&Value::Ident(
|
||||
InternedString::get_or_intern(self.value.clone()),
|
||||
QuoteKind::Quoted,
|
||||
)
|
||||
.to_css_string(self.span)
|
||||
.unwrap(),
|
||||
&Value::Ident(self.value.clone(), QuoteKind::Quoted)
|
||||
.to_css_string(self.span)
|
||||
.unwrap(),
|
||||
)?;
|
||||
// todo: this space is not emitted when `compressed` output
|
||||
if self.modifier.is_some() {
|
||||
|
@ -4,7 +4,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
|
||||
|
||||
use crate::common::{Brackets, ListSeparator, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::utils::{
|
||||
devour_whitespace, eat_comment, eat_ident_no_interpolation, parse_interpolation,
|
||||
@ -58,12 +57,7 @@ impl SelectorPart {
|
||||
Value::List(
|
||||
kinds
|
||||
.iter()
|
||||
.map(|s| {
|
||||
Value::Ident(
|
||||
InternedString::get_or_intern(s.to_string()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
})
|
||||
.map(|s| Value::Ident(s.to_string(), QuoteKind::None))
|
||||
.collect(),
|
||||
ListSeparator::Space,
|
||||
Brackets::None,
|
||||
|
27
src/style.rs
27
src/style.rs
@ -3,7 +3,6 @@ use peekmore::PeekMoreIterator;
|
||||
use codemap::{Span, Spanned};
|
||||
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::utils::{devour_whitespace, devour_whitespace_or_comment, eat_ident};
|
||||
@ -13,7 +12,7 @@ use crate::{Expr, Token};
|
||||
/// A style: `color: red`
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct Style {
|
||||
pub property: InternedString,
|
||||
pub property: String,
|
||||
pub value: Spanned<Value>,
|
||||
}
|
||||
|
||||
@ -22,9 +21,9 @@ impl Style {
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
scope: &Scope,
|
||||
super_selector: &Selector,
|
||||
super_property: InternedString,
|
||||
super_property: String,
|
||||
span_before: Span,
|
||||
) -> SassResult<InternedString> {
|
||||
) -> SassResult<String> {
|
||||
StyleParser::new(scope, super_selector).parse_property(toks, super_property, span_before)
|
||||
}
|
||||
|
||||
@ -58,7 +57,7 @@ impl Style {
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
scope: &Scope,
|
||||
super_selector: &Selector,
|
||||
super_property: InternedString,
|
||||
super_property: String,
|
||||
) -> SassResult<Expr> {
|
||||
StyleParser::new(scope, super_selector).eat_style_group(toks, super_property, scope)
|
||||
}
|
||||
@ -89,7 +88,7 @@ impl<'a> StyleParser<'a> {
|
||||
pub(crate) fn eat_style_group<I: Iterator<Item = Token>>(
|
||||
&self,
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
super_property: InternedString,
|
||||
super_property: String,
|
||||
scope: &Scope,
|
||||
) -> SassResult<Expr> {
|
||||
let mut styles = Vec::new();
|
||||
@ -100,7 +99,8 @@ impl<'a> StyleParser<'a> {
|
||||
let span_before = toks.next().unwrap().pos;
|
||||
devour_whitespace(toks);
|
||||
loop {
|
||||
let property = self.parse_property(toks, super_property, span_before)?;
|
||||
let property =
|
||||
self.parse_property(toks, super_property.clone(), span_before)?;
|
||||
if let Some(tok) = toks.peek() {
|
||||
if tok.kind == '{' {
|
||||
match self.eat_style_group(toks, property, scope)? {
|
||||
@ -133,7 +133,7 @@ impl<'a> StyleParser<'a> {
|
||||
}
|
||||
'{' => {
|
||||
styles.push(Style {
|
||||
property: property,
|
||||
property: property.clone(),
|
||||
value,
|
||||
});
|
||||
match self.eat_style_group(toks, property, scope)? {
|
||||
@ -170,7 +170,7 @@ impl<'a> StyleParser<'a> {
|
||||
}
|
||||
'{' => {
|
||||
let mut v = vec![Style {
|
||||
property: super_property,
|
||||
property: super_property.clone(),
|
||||
value,
|
||||
}];
|
||||
match self.eat_style_group(toks, super_property, scope)? {
|
||||
@ -195,9 +195,9 @@ impl<'a> StyleParser<'a> {
|
||||
pub(crate) fn parse_property<I: Iterator<Item = Token>>(
|
||||
&self,
|
||||
toks: &mut PeekMoreIterator<I>,
|
||||
super_property: InternedString,
|
||||
mut super_property: String,
|
||||
span_before: Span,
|
||||
) -> SassResult<InternedString> {
|
||||
) -> SassResult<String> {
|
||||
devour_whitespace(toks);
|
||||
let property = eat_ident(toks, self.scope, self.super_selector, span_before)?;
|
||||
devour_whitespace_or_comment(toks)?;
|
||||
@ -209,13 +209,12 @@ impl<'a> StyleParser<'a> {
|
||||
}
|
||||
|
||||
if super_property.is_empty() {
|
||||
Ok(InternedString::get_or_intern(property.node))
|
||||
Ok(property.node)
|
||||
} else {
|
||||
let mut super_property = super_property.resolve().to_string();
|
||||
super_property.reserve(1 + property.node.len());
|
||||
super_property.push('-');
|
||||
super_property.push_str(&property.node);
|
||||
Ok(InternedString::get_or_intern(super_property))
|
||||
Ok(super_property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::atrule::{eat_include, AtRule, AtRuleKind};
|
||||
use crate::common::Identifier;
|
||||
use crate::error::{SassError, SassResult};
|
||||
use crate::imports::import;
|
||||
use crate::lexer::Lexer;
|
||||
@ -165,9 +164,8 @@ impl<'a> StyleSheetParser<'a> {
|
||||
let mut rules: Vec<Spanned<Stmt>> = Vec::new();
|
||||
while let Some(Token { kind, .. }) = self.lexer.peek() {
|
||||
match kind {
|
||||
_ if is_selector_char(*kind) => {
|
||||
rules.extend(self.eat_rules(&Selector::new(), &mut Scope::new())?)
|
||||
}
|
||||
_ if is_selector_char(*kind) => rules
|
||||
.extend(self.eat_rules(&Selector::new(), &mut Scope::new())?),
|
||||
'\t' | '\n' | ' ' => {
|
||||
self.lexer.next();
|
||||
continue;
|
||||
@ -179,18 +177,15 @@ impl<'a> StyleSheetParser<'a> {
|
||||
|
||||
match self.lexer.peek() {
|
||||
Some(Token { kind: ':', .. }) => {
|
||||
self.lexer
|
||||
.take(name.node.chars().count() + whitespace + 1)
|
||||
self.lexer.take(name.node.chars().count() + whitespace + 1)
|
||||
.for_each(drop);
|
||||
devour_whitespace(self.lexer);
|
||||
|
||||
let name = name.map_node(|n| Identifier::from(n));
|
||||
|
||||
let VariableDecl { val, default, .. } =
|
||||
eat_variable_value(self.lexer, &Scope::new(), &Selector::new())?;
|
||||
eat_variable_value(self.lexer, &Scope::new(), &Selector::new())?;
|
||||
|
||||
if !(default && global_var_exists(name.node)) {
|
||||
insert_global_var(name.node, val)?;
|
||||
if !(default && global_var_exists(&name)) {
|
||||
insert_global_var(&name.node, val)?;
|
||||
}
|
||||
}
|
||||
Some(..) | None => return Err(("expected \":\".", name.span).into()),
|
||||
@ -207,15 +202,17 @@ impl<'a> StyleSheetParser<'a> {
|
||||
let comment = eat_comment(self.lexer, &Scope::new(), &Selector::new())?;
|
||||
rules.push(comment.map_node(Stmt::MultilineComment));
|
||||
}
|
||||
_ => return Err(("expected selector.", pos).into()),
|
||||
_ => return Err(("expected selector.", pos).into())
|
||||
}
|
||||
}
|
||||
'@' => {
|
||||
let span_before = self.lexer.next().unwrap().pos();
|
||||
let Spanned {
|
||||
node: at_rule_kind,
|
||||
span,
|
||||
} = eat_ident(self.lexer, &Scope::new(), &Selector::new(), span_before)?;
|
||||
let Spanned { node: at_rule_kind, span } = eat_ident(
|
||||
self.lexer,
|
||||
&Scope::new(),
|
||||
&Selector::new(),
|
||||
span_before
|
||||
)?;
|
||||
if at_rule_kind.is_empty() {
|
||||
return Err(("Expected identifier.", span).into());
|
||||
}
|
||||
@ -225,14 +222,14 @@ impl<'a> StyleSheetParser<'a> {
|
||||
&Scope::new(),
|
||||
&Selector::new(),
|
||||
None,
|
||||
span,
|
||||
span
|
||||
)?),
|
||||
AtRuleKind::Import => {
|
||||
devour_whitespace(self.lexer);
|
||||
let mut file_name = String::new();
|
||||
let next = match self.lexer.next() {
|
||||
Some(v) => v,
|
||||
None => todo!("expected input after @import"),
|
||||
None => todo!("expected input after @import")
|
||||
};
|
||||
match next.kind {
|
||||
q @ '"' | q @ '\'' => {
|
||||
@ -241,12 +238,8 @@ impl<'a> StyleSheetParser<'a> {
|
||||
self.lexer,
|
||||
&Scope::new(),
|
||||
q,
|
||||
&Selector::new(),
|
||||
)?
|
||||
.node
|
||||
.unquote()
|
||||
.to_css_string(span)?,
|
||||
);
|
||||
&Selector::new())?
|
||||
.node.unquote().to_css_string(span)?);
|
||||
}
|
||||
_ => return Err(("Expected string.", next.pos()).into()),
|
||||
}
|
||||
@ -258,22 +251,14 @@ impl<'a> StyleSheetParser<'a> {
|
||||
|
||||
devour_whitespace(self.lexer);
|
||||
|
||||
let (new_rules, new_scope) =
|
||||
import(self.path, file_name.as_ref(), &mut self.map)?;
|
||||
let (new_rules, new_scope) = import(self.path, file_name.as_ref(), &mut self.map)?;
|
||||
rules.extend(new_rules);
|
||||
GLOBAL_SCOPE.with(|s| {
|
||||
s.borrow_mut().extend(new_scope);
|
||||
});
|
||||
}
|
||||
v => {
|
||||
let rule = AtRule::from_tokens(
|
||||
v,
|
||||
span,
|
||||
self.lexer,
|
||||
&mut Scope::new(),
|
||||
&Selector::new(),
|
||||
None,
|
||||
)?;
|
||||
let rule = AtRule::from_tokens(v, span, self.lexer, &mut Scope::new(), &Selector::new(), None)?;
|
||||
match rule.node {
|
||||
AtRule::Mixin(name, mixin) => {
|
||||
insert_global_mixin(&name, *mixin);
|
||||
@ -289,36 +274,17 @@ impl<'a> StyleSheetParser<'a> {
|
||||
("This at-rule is not allowed here.", rule.span).into()
|
||||
)
|
||||
}
|
||||
AtRule::For(f) => rules.extend(f.ruleset_eval(
|
||||
&mut Scope::new(),
|
||||
&Selector::new(),
|
||||
None,
|
||||
)?),
|
||||
AtRule::While(w) => rules.extend(w.ruleset_eval(
|
||||
&mut Scope::new(),
|
||||
&Selector::new(),
|
||||
true,
|
||||
None,
|
||||
)?),
|
||||
AtRule::Each(e) => rules.extend(e.ruleset_eval(
|
||||
&mut Scope::new(),
|
||||
&Selector::new(),
|
||||
None,
|
||||
)?),
|
||||
AtRule::Include(s) => rules.extend(s),
|
||||
AtRule::Content => {
|
||||
return Err((
|
||||
"@content is only allowed within mixin declarations.",
|
||||
rule.span,
|
||||
)
|
||||
.into())
|
||||
AtRule::For(f) => rules.extend(f.ruleset_eval(&mut Scope::new(), &Selector::new(), None)?),
|
||||
AtRule::While(w) => rules.extend(w.ruleset_eval(&mut Scope::new(), &Selector::new(), true, None)?),
|
||||
AtRule::Each(e) => {
|
||||
rules.extend(e.ruleset_eval(&mut Scope::new(), &Selector::new(), None)?)
|
||||
}
|
||||
AtRule::Include(s) => rules.extend(s),
|
||||
AtRule::Content => return Err(
|
||||
("@content is only allowed within mixin declarations.", rule.span
|
||||
).into()),
|
||||
AtRule::If(i) => {
|
||||
rules.extend(i.eval(
|
||||
&mut Scope::new(),
|
||||
&Selector::new(),
|
||||
None,
|
||||
)?);
|
||||
rules.extend(i.eval(&mut Scope::new(), &Selector::new(), None)?);
|
||||
}
|
||||
AtRule::AtRoot(root_rules) => rules.extend(root_rules),
|
||||
AtRule::Unknown(..) => rules.push(rule.map_node(Stmt::AtRule)),
|
||||
@ -326,13 +292,11 @@ impl<'a> StyleSheetParser<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'&' => {
|
||||
return Err((
|
||||
"Top-level selectors may not contain the parent selector \"&\".",
|
||||
self.lexer.next().unwrap().pos(),
|
||||
return Err(
|
||||
("Top-level selectors may not contain the parent selector \"&\".", self.lexer.next().unwrap().pos()).into(),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
c if c.is_control() => {
|
||||
return Err(("expected selector.", self.lexer.next().unwrap().pos()).into());
|
||||
|
@ -6,7 +6,6 @@ use peekmore::PeekMoreIterator;
|
||||
|
||||
use crate::common::QuoteKind;
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::selector::Selector;
|
||||
use crate::value::Value;
|
||||
use crate::{Scope, Token};
|
||||
@ -214,7 +213,7 @@ pub(crate) fn eat_ident<I: Iterator<Item = Token>>(
|
||||
toks.next();
|
||||
text.push_str(
|
||||
&match parse_interpolation(toks, scope, super_selector)?.node {
|
||||
Value::Ident(s, ..) => s.resolve().to_string(),
|
||||
Value::Ident(s, ..) => s,
|
||||
v => v.to_css_string(span)?.into(),
|
||||
},
|
||||
);
|
||||
@ -292,7 +291,7 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
|
||||
toks.next();
|
||||
let interpolation = parse_interpolation(toks, scope, super_selector)?;
|
||||
s.push_str(&match interpolation.node {
|
||||
Value::Ident(s, ..) => s.resolve().to_string(),
|
||||
Value::Ident(s, ..) => s,
|
||||
v => v.to_css_string(interpolation.span)?.into(),
|
||||
});
|
||||
continue;
|
||||
@ -346,7 +345,7 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
|
||||
}
|
||||
}
|
||||
Ok(Spanned {
|
||||
node: Value::Ident(InternedString::get_or_intern(s), QuoteKind::Quoted),
|
||||
node: Value::Ident(s, QuoteKind::Quoted),
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ pub(crate) fn try_eat_url<I: Iterator<Item = Token>>(
|
||||
let (interpolation, count) = peek_interpolation(toks, scope, super_selector)?;
|
||||
peek_counter += count;
|
||||
buf.push_str(&match interpolation.node {
|
||||
Value::Ident(s, ..) => s.resolve().to_string(),
|
||||
Value::Ident(s, ..) => s,
|
||||
v => v.to_css_string(interpolation.span)?.into(),
|
||||
});
|
||||
} else {
|
||||
|
@ -6,7 +6,6 @@ use codemap::{Span, Spanned};
|
||||
use crate::color::Color;
|
||||
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::unit::Unit;
|
||||
use crate::utils::hex_char_for;
|
||||
|
||||
@ -34,7 +33,7 @@ pub(crate) enum Value {
|
||||
UnaryOp(Op, Box<Value>),
|
||||
BinaryOp(Box<Value>, Op, Box<Value>),
|
||||
Paren(Box<Value>),
|
||||
Ident(InternedString, QuoteKind),
|
||||
Ident(String, QuoteKind),
|
||||
Map(SassMap),
|
||||
ArgList(Vec<Spanned<Value>>),
|
||||
/// Returned by `get-function()`
|
||||
@ -168,7 +167,6 @@ impl Value {
|
||||
}
|
||||
Self::Paren(val) => val.to_css_string(span)?,
|
||||
Self::Ident(string, QuoteKind::None) => {
|
||||
let string = string.resolve();
|
||||
let mut after_newline = false;
|
||||
let mut buf = String::with_capacity(string.len());
|
||||
for c in string.chars() {
|
||||
@ -191,9 +189,8 @@ impl Value {
|
||||
Cow::Owned(buf)
|
||||
}
|
||||
Self::Ident(string, QuoteKind::Quoted) => {
|
||||
let string = string.resolve();
|
||||
let mut buf = String::with_capacity(string.len());
|
||||
visit_quoted_string(&mut buf, false, &string)?;
|
||||
visit_quoted_string(&mut buf, false, string)?;
|
||||
Cow::Owned(buf)
|
||||
}
|
||||
Self::True => Cow::Borrowed("true"),
|
||||
@ -252,7 +249,7 @@ impl Value {
|
||||
|
||||
pub fn is_special_function(&self) -> bool {
|
||||
match self {
|
||||
Self::Ident(s, QuoteKind::None) => is_special_function(s.resolve_ref()),
|
||||
Self::Ident(s, QuoteKind::None) => is_special_function(s),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
199
src/value/ops.rs
199
src/value/ops.rs
@ -4,7 +4,6 @@ use codemap::{Span, Spanned};
|
||||
|
||||
use crate::common::{Op, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
|
||||
use crate::value::Value;
|
||||
|
||||
@ -112,10 +111,7 @@ impl Value {
|
||||
pub fn unary_op_plus(self, span: Span) -> SassResult<Self> {
|
||||
Ok(match self.eval(span)?.node {
|
||||
v @ Value::Dimension(..) => v,
|
||||
v => Value::Ident(
|
||||
InternedString::get_or_intern(format!("+{}", v.to_css_string(span)?)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
v => Value::Ident(format!("+{}", v.to_css_string(span)?), QuoteKind::None),
|
||||
})
|
||||
}
|
||||
|
||||
@ -263,28 +259,22 @@ impl Value {
|
||||
Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(),
|
||||
Self::Important | Self::True | Self::False => match other {
|
||||
Self::Ident(s, QuoteKind::Quoted) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}", self.to_css_string(span)?, s)),
|
||||
format!("{}{}", self.to_css_string(span)?, s),
|
||||
QuoteKind::Quoted,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(self.to_css_string(span)?.into_owned()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(self.to_css_string(span)?.into(), QuoteKind::None),
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
Self::Null => match other {
|
||||
Self::Null => Self::Null,
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(dbg!(other.to_css_string(span)?).into_owned()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => Value::Ident(other.to_css_string(span)?.into(), QuoteKind::None),
|
||||
},
|
||||
Self::Dimension(num, unit) => match other {
|
||||
Self::Dimension(num2, unit2) => {
|
||||
@ -309,30 +299,14 @@ impl Value {
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}{}", num, unit, s)),
|
||||
q,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}", num, unit)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(s, q) => Value::Ident(format!("{}{}{}", num, unit, s), q),
|
||||
Self::Null => Value::Ident(format!("{}{}", num, unit), QuoteKind::None),
|
||||
Self::List(..) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}{}{}",
|
||||
num,
|
||||
unit,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
format!("{}{}{}", num, unit, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::True | Self::False => Self::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}{}{}",
|
||||
num,
|
||||
unit,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
format!("{}{}{}", num, unit, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => {
|
||||
@ -349,15 +323,10 @@ impl Value {
|
||||
}
|
||||
},
|
||||
Self::Color(c) => match other {
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(InternedString::get_or_intern(format!("{}{}", c, s)), q)
|
||||
}
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(c.to_string()),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(s, q) => Value::Ident(format!("{}{}", c, s), q),
|
||||
Self::Null => Value::Ident(c.to_string(), QuoteKind::None),
|
||||
Self::List(..) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}", c, other.to_css_string(span)?)),
|
||||
format!("{}{}", c, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => {
|
||||
@ -394,27 +363,18 @@ impl Value {
|
||||
}
|
||||
Self::UnaryOp(..) | Self::Paren(..) => self.eval(span)?.node.add(other, span)?,
|
||||
Self::Ident(text, quotes) => match other {
|
||||
Self::Ident(text2, ..) => Self::Ident(
|
||||
InternedString::get_or_intern(text.resolve() + text2.resolve_ref()),
|
||||
quotes,
|
||||
),
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(text.resolve() + &other.to_css_string(span)?),
|
||||
quotes,
|
||||
),
|
||||
Self::Ident(text2, ..) => Self::Ident(text + &text2, quotes),
|
||||
_ => Value::Ident(text + &other.to_css_string(span)?, quotes),
|
||||
},
|
||||
Self::List(..) => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}", self.to_css_string(span)?, s)),
|
||||
q,
|
||||
),
|
||||
Self::Ident(s, q) => Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q),
|
||||
Self::Paren(..) => (self.add(other.eval(span)?.node, span))?,
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
@ -452,34 +412,20 @@ impl Value {
|
||||
}
|
||||
}
|
||||
Self::List(..) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}{}-{}",
|
||||
num,
|
||||
unit,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
format!("{}{}-{}", num, unit, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(..) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}{}-{}",
|
||||
num,
|
||||
unit,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
format!("{}{}-{}", num, unit, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => todo!(),
|
||||
},
|
||||
Self::Color(c) => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}-{}{}{}", c, q, s, q)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}-", c)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(format!("{}-{}{}{}", c, q, s, q), QuoteKind::None)
|
||||
}
|
||||
Self::Null => Value::Ident(format!("{}-", c), QuoteKind::None),
|
||||
Self::Dimension(..) | Self::Color(..) => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -492,7 +438,7 @@ impl Value {
|
||||
.into())
|
||||
}
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}-{}", c, other.to_css_string(span)?)),
|
||||
format!("{}-{}", c, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
@ -518,54 +464,41 @@ impl Value {
|
||||
}
|
||||
Self::Paren(..) => self.eval(span)?.node.sub(other, span)?,
|
||||
Self::Ident(..) => Self::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}-{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::List(..) => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}-{}{}{}",
|
||||
self.to_css_string(span)?,
|
||||
q,
|
||||
s,
|
||||
q
|
||||
)),
|
||||
format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
|
||||
QuoteKind::None,
|
||||
),
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}-{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
_ => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}-{}{}{}",
|
||||
self.to_css_string(span)?,
|
||||
q,
|
||||
s,
|
||||
q
|
||||
)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}-", self.to_css_string(span)?)),
|
||||
format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => {
|
||||
Value::Ident(format!("{}-", self.to_css_string(span)?), QuoteKind::None)
|
||||
}
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}-{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
@ -671,24 +604,19 @@ impl Value {
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}/{}{}{}", num, unit, q, s, q)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(format!("{}{}/{}{}{}", num, unit, q, s, q), QuoteKind::None)
|
||||
}
|
||||
Self::BinaryOp(..) | Self::Paren(..) => {
|
||||
Self::Dimension(num, unit).div(other.eval(span)?.node, span)?
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
Self::Color(c) => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}/{}{}{}", c, q, s, q)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}/", c)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Ident(s, q) => {
|
||||
Value::Ident(format!("{}/{}{}{}", c, q, s, q), QuoteKind::None)
|
||||
}
|
||||
Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None),
|
||||
Self::Dimension(..) | Self::Color(..) => {
|
||||
return Err((
|
||||
format!(
|
||||
@ -701,7 +629,7 @@ impl Value {
|
||||
.into())
|
||||
}
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}/{}", c, other.to_css_string(span)?)),
|
||||
format!("{}/{}", c, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
@ -728,7 +656,7 @@ impl Value {
|
||||
Self::Paren(..) => self.eval(span)?.node.div(other, span)?,
|
||||
Self::Ident(s1, q1) => match other {
|
||||
Self::Ident(s2, q2) => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2)),
|
||||
format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Important
|
||||
@ -736,42 +664,26 @@ impl Value {
|
||||
| Self::False
|
||||
| Self::Dimension(..)
|
||||
| Self::Color(..) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}{}{}/{}",
|
||||
q1,
|
||||
s1,
|
||||
q1,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}{}{}/", q1, s1, q1)),
|
||||
format!("{}{}{}/{}", q1, s1, q1, other.to_css_string(span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(format!("{}{}{}/", q1, s1, q1), QuoteKind::None),
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => match other {
|
||||
Self::Ident(s, q) => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"{}/{}{}{}",
|
||||
self.to_css_string(span)?,
|
||||
q,
|
||||
s,
|
||||
q
|
||||
)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => Value::Ident(
|
||||
InternedString::get_or_intern(format!("{}/", self.to_css_string(span)?)),
|
||||
format!("{}/{}{}{}", self.to_css_string(span)?, q, s, q),
|
||||
QuoteKind::None,
|
||||
),
|
||||
Self::Null => {
|
||||
Value::Ident(format!("{}/", self.to_css_string(span)?), QuoteKind::None)
|
||||
}
|
||||
_ => Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
format!(
|
||||
"{}/{}",
|
||||
self.to_css_string(span)?,
|
||||
other.to_css_string(span)?
|
||||
)),
|
||||
),
|
||||
QuoteKind::None,
|
||||
),
|
||||
},
|
||||
@ -824,10 +736,7 @@ impl Value {
|
||||
pub fn neg(self, span: Span) -> SassResult<Self> {
|
||||
Ok(match self.eval(span)?.node {
|
||||
Value::Dimension(n, u) => Value::Dimension(-n, u),
|
||||
v => Value::Ident(
|
||||
InternedString::get_or_intern(format!("-{}", v.to_css_string(span)?)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
v => Value::Ident(format!("-{}", v.to_css_string(span)?), QuoteKind::None),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ use crate::builtin::GLOBAL_FUNCTIONS;
|
||||
use crate::color::{Color, NAMED_COLORS};
|
||||
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::interner::InternedString;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
use crate::unit::Unit;
|
||||
@ -59,10 +58,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
|
||||
span = span.merge(i.span);
|
||||
} else {
|
||||
return Ok(Spanned {
|
||||
node: Value::Ident(
|
||||
InternedString::get_or_intern(format!("#{}", i.node)),
|
||||
QuoteKind::None,
|
||||
),
|
||||
node: Value::Ident(format!("#{}", i.node), QuoteKind::None),
|
||||
span: i.span,
|
||||
});
|
||||
}
|
||||
@ -71,13 +67,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
|
||||
3 => {
|
||||
let v = match u16::from_str_radix(&s, 16) {
|
||||
Ok(a) => a,
|
||||
Err(_) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("#{}", s)),
|
||||
QuoteKind::None,
|
||||
)
|
||||
.span(span))
|
||||
}
|
||||
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
|
||||
};
|
||||
let red = (((v & 0xf00) >> 8) * 0x11) as u8;
|
||||
let green = (((v & 0x0f0) >> 4) * 0x11) as u8;
|
||||
@ -90,13 +80,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
|
||||
4 => {
|
||||
let v = match u16::from_str_radix(&s, 16) {
|
||||
Ok(a) => a,
|
||||
Err(_) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("#{}", s)),
|
||||
QuoteKind::None,
|
||||
)
|
||||
.span(span))
|
||||
}
|
||||
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
|
||||
};
|
||||
let red = (((v & 0xf000) >> 12) * 0x11) as u8;
|
||||
let green = (((v & 0x0f00) >> 8) * 0x11) as u8;
|
||||
@ -114,13 +98,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
|
||||
6 => {
|
||||
let v = match u32::from_str_radix(&s, 16) {
|
||||
Ok(a) => a,
|
||||
Err(_) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("#{}", s)),
|
||||
QuoteKind::None,
|
||||
)
|
||||
.span(span))
|
||||
}
|
||||
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
|
||||
};
|
||||
let red = ((v & 0x00ff_0000) >> 16) as u8;
|
||||
let green = ((v & 0x0000_ff00) >> 8) as u8;
|
||||
@ -133,13 +111,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
|
||||
8 => {
|
||||
let v = match u32::from_str_radix(&s, 16) {
|
||||
Ok(a) => a,
|
||||
Err(_) => {
|
||||
return Ok(Value::Ident(
|
||||
InternedString::get_or_intern(format!("#{}", s)),
|
||||
QuoteKind::None,
|
||||
)
|
||||
.span(span))
|
||||
}
|
||||
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
|
||||
};
|
||||
let red = ((v & 0xff00_0000) >> 24) as u8;
|
||||
let green = ((v & 0x00ff_0000) >> 16) as u8;
|
||||
@ -293,10 +265,7 @@ fn eat_op<I: Iterator<Item = Token>>(
|
||||
devour_whitespace(iter);
|
||||
space_separated.push(Spanned {
|
||||
node: Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"/{}",
|
||||
right.node.to_css_string(right.span)?
|
||||
)),
|
||||
format!("/{}", right.node.to_css_string(right.span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
span: op.span.merge(right.span),
|
||||
@ -340,13 +309,7 @@ fn eat_op<I: Iterator<Item = Token>>(
|
||||
devour_whitespace(iter);
|
||||
// special case when the value is literally "and" or "or"
|
||||
if iter.peek().is_none() {
|
||||
space_separated.push(
|
||||
Value::Ident(
|
||||
InternedString::get_or_intern(op.to_string()),
|
||||
QuoteKind::None,
|
||||
)
|
||||
.span(op.span),
|
||||
);
|
||||
space_separated.push(Value::Ident(op.to_string(), QuoteKind::None).span(op.span));
|
||||
} else if let Some(left) = space_separated.pop() {
|
||||
devour_whitespace(iter);
|
||||
let right = single_value(iter, scope, super_selector, left.span)?;
|
||||
@ -409,23 +372,30 @@ fn single_value<I: Iterator<Item = Token>>(
|
||||
let val = single_value(iter, scope, super_selector, span)?;
|
||||
Spanned {
|
||||
node: Value::Ident(
|
||||
InternedString::get_or_intern(format!(
|
||||
"/{}",
|
||||
val.node.to_css_string(val.span)?
|
||||
)),
|
||||
format!("/{}", val.node.to_css_string(val.span)?),
|
||||
QuoteKind::None,
|
||||
),
|
||||
span: next.span.merge(val.span),
|
||||
}
|
||||
}
|
||||
Op::And => Spanned {
|
||||
node: Value::Ident(InternedString::get_or_intern("and"), QuoteKind::None),
|
||||
span: next.span,
|
||||
},
|
||||
Op::Or => Spanned {
|
||||
node: Value::Ident(InternedString::get_or_intern("or"), QuoteKind::None),
|
||||
span: next.span,
|
||||
},
|
||||
Op::And => {
|
||||
Spanned {
|
||||
node: Value::Ident(
|
||||
"and".into(),
|
||||
QuoteKind::None,
|
||||
),
|
||||
span: next.span,
|
||||
}
|
||||
}
|
||||
Op::Or => {
|
||||
Spanned {
|
||||
node: Value::Ident(
|
||||
"or".into(),
|
||||
QuoteKind::None,
|
||||
),
|
||||
span: next.span,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(("Expected expression.", next.span).into());
|
||||
}
|
||||
@ -599,20 +569,15 @@ impl Value {
|
||||
) -> SassResult<Spanned<IntermediateValue>> {
|
||||
let Spanned { node: mut s, span } = eat_ident(toks, scope, super_selector, span_before)?;
|
||||
|
||||
let lower = dbg!(InternedString::get_or_intern(s.to_ascii_lowercase()));
|
||||
let lower = s.to_ascii_lowercase();
|
||||
|
||||
if lower.resolve_ref() == "progid"
|
||||
&& toks.peek().is_some()
|
||||
&& toks.peek().unwrap().kind == ':'
|
||||
{
|
||||
s = "progid:".to_string();
|
||||
if lower == "progid" && toks.peek().is_some() && toks.peek().unwrap().kind == ':' {
|
||||
s = lower;
|
||||
toks.next();
|
||||
s.push(':');
|
||||
s.push_str(&eat_progid(toks, scope, super_selector)?);
|
||||
return Ok(Spanned {
|
||||
node: IntermediateValue::Value(Value::Ident(
|
||||
InternedString::get_or_intern(s),
|
||||
QuoteKind::None,
|
||||
)),
|
||||
node: IntermediateValue::Value(Value::Ident(s, QuoteKind::None)),
|
||||
span,
|
||||
});
|
||||
}
|
||||
@ -634,9 +599,9 @@ impl Value {
|
||||
.span(span))
|
||||
}
|
||||
None => {
|
||||
match lower.resolve_ref() {
|
||||
match lower.as_str() {
|
||||
"calc" | "element" | "expression" => {
|
||||
s = lower.resolve().to_string();
|
||||
s = lower;
|
||||
eat_calc_args(toks, scope, super_selector, &mut s)?;
|
||||
}
|
||||
// "min" => {}
|
||||
@ -651,11 +616,9 @@ impl Value {
|
||||
&eat_call_args(toks)?.to_css_string(scope, super_selector)?,
|
||||
),
|
||||
}
|
||||
return Ok(IntermediateValue::Value(Value::Ident(
|
||||
InternedString::get_or_intern(s),
|
||||
QuoteKind::None,
|
||||
))
|
||||
.span(span));
|
||||
return Ok(
|
||||
IntermediateValue::Value(Value::Ident(s, QuoteKind::None)).span(span)
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -667,24 +630,21 @@ impl Value {
|
||||
.span(span));
|
||||
}
|
||||
|
||||
if let Some(c) = NAMED_COLORS.get_by_name(lower) {
|
||||
if let Some(c) = NAMED_COLORS.get_by_name(&lower.as_str()) {
|
||||
return Ok(IntermediateValue::Value(Value::Color(Box::new(Color::new(
|
||||
c[0], c[1], c[2], c[3], s,
|
||||
))))
|
||||
.span(span));
|
||||
}
|
||||
|
||||
Ok(match dbg!(lower.resolve_ref()) {
|
||||
Ok(match lower.as_str() {
|
||||
"true" => IntermediateValue::Value(Value::True),
|
||||
"false" => IntermediateValue::Value(Value::False),
|
||||
"null" => IntermediateValue::Value(Value::Null),
|
||||
"not" => IntermediateValue::Op(Op::Not),
|
||||
"and" => IntermediateValue::Op(Op::And),
|
||||
"or" => IntermediateValue::Op(Op::Or),
|
||||
_ => IntermediateValue::Value(Value::Ident(
|
||||
InternedString::get_or_intern(s),
|
||||
QuoteKind::None,
|
||||
)),
|
||||
_ => IntermediateValue::Value(Value::Ident(s, QuoteKind::None)),
|
||||
}
|
||||
.span(span))
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ use std::fmt;
|
||||
use crate::args::CallArgs;
|
||||
use crate::atrule::Function;
|
||||
use crate::builtin::Builtin;
|
||||
use crate::common::Identifier;
|
||||
use crate::error::SassResult;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
@ -28,15 +27,15 @@ use crate::value::Value;
|
||||
/// for use in the builtin function `inspect()`
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum SassFunction {
|
||||
Builtin(Builtin, Identifier),
|
||||
UserDefined(Box<Function>, Identifier),
|
||||
Builtin(Builtin, String),
|
||||
UserDefined(Box<Function>, String),
|
||||
}
|
||||
|
||||
impl SassFunction {
|
||||
/// Get the name of the function referenced
|
||||
///
|
||||
/// Used mainly in debugging and `inspect()`
|
||||
pub fn name(&self) -> &Identifier {
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Self::Builtin(_, name) => name,
|
||||
Self::UserDefined(_, name) => name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user