initial implementation of selector-replace

This commit is contained in:
ConnorSkees 2020-06-07 14:23:15 -04:00
parent e0ab71f73e
commit e76903cb47
3 changed files with 66 additions and 9 deletions

View File

@ -177,7 +177,28 @@ fn selector_replace(
super_selector: &Selector, super_selector: &Selector,
) -> SassResult<Value> { ) -> SassResult<Value> {
args.max_args(3)?; args.max_args(3)?;
todo!("built-in fn selector-replace") let selector = arg!(args, scope, super_selector, 0, "selector").to_selector(
args.span(),
scope,
super_selector,
"selector",
false,
)?;
let target = arg!(args, scope, super_selector, 1, "original").to_selector(
args.span(),
scope,
super_selector,
"original",
false,
)?;
let source = arg!(args, scope, super_selector, 2, "replacement").to_selector(
args.span(),
scope,
super_selector,
"replacement",
false,
)?;
Ok(Extender::replace(selector.0, source.0, target.0).to_sass_list())
} }
fn selector_unify( fn selector_unify(

View File

@ -189,9 +189,8 @@ impl Extender {
if i != 0 { if i != 0 {
extended = list.components[0..i].to_vec(); extended = list.components[0..i].to_vec();
} }
extended.extend(result.into_iter());
} }
extended.extend(result.into_iter());
} else { } else {
if !extended.is_empty() { if !extended.is_empty() {
extended.push(complex); extended.push(complex);
@ -275,8 +274,6 @@ impl Extender {
return None; return None;
} }
// dbg!(&extended_not_expanded);
let mut first = true; let mut first = true;
let mut originals: Vec<ComplexSelector> = Vec::new(); let mut originals: Vec<ComplexSelector> = Vec::new();
@ -359,7 +356,7 @@ impl Extender {
// If `self.mode` isn't `ExtendMode::Normal` and we didn't use all the targets in // If `self.mode` isn't `ExtendMode::Normal` and we didn't use all the targets in
// `extensions`, extension fails for `compound`. // `extensions`, extension fails for `compound`.
if targets_used.len() != extensions.len() { if targets_used.len() > 0 && targets_used.len() != extensions.len() {
return None; return None;
} }
@ -443,7 +440,7 @@ impl Extender {
to_unify.push_back(state.extender.components.clone()); to_unify.push_back(state.extender.components.clone());
} }
} }
if originals.is_empty() { if !originals.is_empty() {
to_unify.push_front(vec![ComplexSelectorComponent::Compound( to_unify.push_front(vec![ComplexSelectorComponent::Compound(
CompoundSelector { CompoundSelector {
components: originals, components: originals,
@ -473,8 +470,6 @@ impl Extender {
}) })
.collect(); .collect();
dbg!(&unified_paths);
Some( Some(
unified_paths unified_paths
.into_iter() .into_iter()
@ -631,6 +626,7 @@ impl Extender {
} }
}) })
.collect(); .collect();
// Older browsers support `:not`, but only with a single complex selector. // Older browsers support `:not`, but only with a single complex selector.
// In order to support those browsers, we break up the contents of a `:not` // In order to support those browsers, we break up the contents of a `:not`
// unless it originally contained a selector list. // unless it originally contained a selector list.

40
tests/selector-replace.rs Normal file
View File

@ -0,0 +1,40 @@
#![cfg(test)]
#[macro_use]
mod macros;
test!(
simple,
"a {\n color: selector-replace(\"c\", \"c\", \"d\");\n}\n",
"a {\n color: d;\n}\n"
);
test!(
compound,
"a {\n color: selector-replace(\"c.d\", \"c\", \"e\");\n}\n",
"a {\n color: e.d;\n}\n"
);
test!(
complex,
"a {\n color: selector-replace(\"c d\", \"d\", \"e f\");\n}\n",
"a {\n color: c e f, e c f;\n}\n"
);
test!(
psuedo_matches,
"a {\n color: selector-replace(\":matches(c)\", \"c\", \"d\");\n}\n",
"a {\n color: :matches(d);\n}\n"
);
test!(
psuedo_not,
"a {\n color: selector-replace(\":not(c)\", \"c\", \"d\");\n}\n",
"a {\n color: :not(d);\n}\n"
);
test!(
no_op,
"a {\n color: selector-replace(\"c\", \"d\", \"e\");\n}\n",
"a {\n color: c;\n}\n"
);
test!(
partial_no_op,
"a {\n color: selector-replace(\"c, d\", \"d\", \"e\");\n}\n",
"a {\n color: c, e;\n}\n"
);