support arg to map-merge
This commit is contained in:
parent
150ba14b74
commit
2ff3524ac2
@ -1,3 +1,5 @@
|
||||
use std::mem;
|
||||
|
||||
use super::{Builtin, GlobalFunctionMap};
|
||||
|
||||
use crate::{
|
||||
@ -87,7 +89,12 @@ pub(crate) fn map_values(mut args: CallArgs, parser: &mut Parser<'_>) -> SassRes
|
||||
}
|
||||
|
||||
pub(crate) fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
|
||||
args.max_args(2)?;
|
||||
if args.len() == 1 {
|
||||
return Err(("Expected $args to contain a key.", args.span()).into());
|
||||
}
|
||||
|
||||
let last_position = args.len().saturating_sub(1);
|
||||
|
||||
let mut map1 = match args.get_err(0, "map1")? {
|
||||
Value::Map(m) => m,
|
||||
Value::List(v, ..) if v.is_empty() => SassMap::new(),
|
||||
@ -100,7 +107,8 @@ pub(crate) fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResu
|
||||
.into())
|
||||
}
|
||||
};
|
||||
let map2 = match args.get_err(1, "map2")? {
|
||||
|
||||
let mut map2 = match args.get_err(last_position, "map2")? {
|
||||
Value::Map(m) => m,
|
||||
Value::List(v, ..) if v.is_empty() => SassMap::new(),
|
||||
Value::ArgList(v) if v.is_empty() => SassMap::new(),
|
||||
@ -112,7 +120,28 @@ pub(crate) fn map_merge(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResu
|
||||
.into())
|
||||
}
|
||||
};
|
||||
map1.merge(map2);
|
||||
|
||||
let mut keys = args.get_variadic()?;
|
||||
|
||||
if keys.is_empty() {
|
||||
map1.merge(map2);
|
||||
} else {
|
||||
while let Some(key) = keys.pop() {
|
||||
let mut new_map = SassMap::new();
|
||||
new_map.insert(key.node, Value::Map(mem::take(&mut map2)));
|
||||
map2 = new_map;
|
||||
}
|
||||
|
||||
for (key, value) in map2 {
|
||||
// if they are two maps sharing a key, merge the keys
|
||||
if let (Some(Value::Map(map1)), Value::Map(map2)) = (map1.get_mut(&key), &value) {
|
||||
map1.merge(map2.clone());
|
||||
} else {
|
||||
map1.insert(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Map(map1))
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ grass input.scss
|
||||
// it is sometimes useful to break up `impl`s
|
||||
clippy::multiple_inherent_impl,
|
||||
// filter isn't fallible
|
||||
clippy::filter_map,
|
||||
clippy::manual_filter_map,
|
||||
clippy::else_if_without_else,
|
||||
clippy::new_ret_no_self,
|
||||
renamed_and_removed_lints,
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
value::Value,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct SassMap(Vec<(Value, Value)>);
|
||||
|
||||
impl PartialEq for SassMap {
|
||||
@ -51,6 +51,16 @@ impl SassMap {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: &Value) -> Option<&mut Value> {
|
||||
for (k, v) in &mut self.0 {
|
||||
if k == key {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: &Value) {
|
||||
self.0.retain(|(ref k, ..)| k.not_equals(key));
|
||||
}
|
||||
|
25
tests/map.rs
25
tests/map.rs
@ -95,6 +95,31 @@ test!(
|
||||
"a {\n color: inspect(map-merge((c: d, e: f), (c: 1, e: 2)));\n}\n",
|
||||
"a {\n color: (c: 1, e: 2);\n}\n"
|
||||
);
|
||||
test!(
|
||||
map_merge_nested_empty,
|
||||
"a {b: inspect(map-merge((c: ()), c, ()))}",
|
||||
"a {\n b: (c: ());\n}\n"
|
||||
);
|
||||
test!(
|
||||
map_merge_nested_overlapping_keys,
|
||||
"a {b: inspect(map-merge((c: (d: e, f: g, h: i)), c, (j: 1, f: 2, k: 3)))}",
|
||||
"a {\n b: (c: (d: e, f: 2, h: i, j: 1, k: 3));\n}\n"
|
||||
);
|
||||
test!(
|
||||
map_merge_nested_intermediate_is_not_map,
|
||||
"a {b: inspect(map-merge((c: 1), c, d, (e: f)))}",
|
||||
"a {\n b: (c: (d: (e: f)));\n}\n"
|
||||
);
|
||||
test!(
|
||||
map_merge_nested_leaf_is_not_map,
|
||||
"a {b: inspect(map-merge((c: 1), c, (d: e)))}",
|
||||
"a {\n b: (c: (d: e));\n}\n"
|
||||
);
|
||||
test!(
|
||||
map_merge_nested_multiple_keys,
|
||||
"a {b: inspect(map-merge((c: (d: (e: (f: (g: h))))), c, d, e, f, (g: 1)))}",
|
||||
"a {\n b: (c: (d: (e: (f: (g: 1)))));\n}\n"
|
||||
);
|
||||
error!(
|
||||
map_merge_map1_non_map,
|
||||
"a {\n color: map-merge(foo, (a: b));\n}\n", "Error: $map1: foo is not a map."
|
||||
|
Loading…
x
Reference in New Issue
Block a user