-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce assoc-path and pluck
- Loading branch information
Showing
5 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
@use './internal/is'; | ||
@import 'assoc'; | ||
@import 'has'; | ||
@import 'slice'; | ||
|
||
/// Makes a shallow clone of an object, setting or overriding the nodes required | ||
/// to create the given path | ||
/// | ||
/// @group object | ||
/// @param {Array} path the path to set | ||
/// @param {*} val The new value | ||
/// @param {Object} obj The object to clone | ||
/// @return {Object} A new object equivalent to the original except along the specified path. | ||
/// | ||
/// @example scss - assoc-path | ||
/// | ||
/// $set-prop: assoc-path('a' 'b' 'c', 42, (a: (b: (c: 0)))); | ||
/// @debug $set-prop; //=> (a: (b: (c: 42))) | ||
|
||
@function assoc-path($path, $val, $obj) { | ||
@if length($path) == 0 { | ||
@return $val; | ||
} | ||
|
||
$idx: nth($path, 1); | ||
|
||
@if length($path) > 1 { | ||
$next-obj: if( | ||
is.map($obj) and has($idx, $obj), | ||
map-get($obj, $idx), | ||
() | ||
); | ||
$val: assoc-path(slice(2, length($path), $path), $val, $next-obj); | ||
} | ||
|
||
$result: (); | ||
|
||
@if is.number($idx) and is.list($obj) { | ||
@if length($obj) == 0 { | ||
$result: append($obj, $val); | ||
} @else { | ||
$result: set-nth($obj, $idx, $val); | ||
} | ||
} @else { | ||
$_obj: if(is.null($obj), (), $obj); | ||
$result: assoc($idx, $val, $_obj); | ||
} | ||
|
||
@return $result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@import 'prop'; | ||
@import 'map'; | ||
@import 'last'; | ||
|
||
/// Returns a new list by plucking the same named property from all objects in | ||
/// the supplied list. | ||
/// | ||
/// @group list | ||
/// @param {Number|String} key The key name to pluck from each object. | ||
/// @param {Array} arr The array to consider. | ||
/// @return {Array} The list of values for the given key. | ||
/// @see props | ||
/// | ||
/// @example scss - pluck | ||
/// | ||
/// $avenger-names: pluck('name', $avengers) | ||
/// @debug $avenger-names; //=> ('Black Widow' 'Captain America' 'Hawkeye' 'Hulk' 'Iron man' 'Thor') | ||
|
||
@function pluck($key, $arr) { | ||
@return map((prop, $key), $arr); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
@import 'true'; | ||
@import '../src/assoc-path'; | ||
@import '../src/path'; | ||
|
||
@include describe('assoc-path [function]') { | ||
@include it('overrides only what is necessary for the path') { | ||
$obj1: ( | ||
a: ( | ||
b: 1, | ||
c: 2, | ||
d: ( | ||
e: 3, | ||
), | ||
), | ||
f: ( | ||
g: ( | ||
h: 4, | ||
i: ( | ||
5, | ||
6, | ||
7, | ||
), | ||
j: ( | ||
k: 6, | ||
l: 7, | ||
), | ||
), | ||
), | ||
m: 8, | ||
); | ||
$obj2: assoc-path(('f', 'g', 'i', 2), 42, $obj1); | ||
@include assert-equal(path(f g i, $obj2), (5, 42, 7)); | ||
@include assert-equal(path(a, $obj2), path(a, $obj1)); | ||
@include assert-equal(path(m, $obj2), path(m, $obj1)); | ||
@include assert-equal(path(f g h, $obj2), path(f g h, $obj1)); | ||
@include assert-equal(path(f g j, $obj2), path(f g j, $obj1)); | ||
} | ||
|
||
@include it( | ||
'is the equivalent of clone and setPath if the property is not on the original' | ||
) { | ||
$obj1: ( | ||
a: 1, | ||
b: ( | ||
c: 2, | ||
d: 3, | ||
), | ||
e: 4, | ||
f: 5, | ||
); | ||
$obj2: assoc-path(('x', 1, 'y'), 42, $obj1); | ||
@include assert-equal( | ||
$obj2, | ||
( | ||
a: 1, | ||
b: ( | ||
c: 2, | ||
d: 3, | ||
), | ||
e: 4, | ||
f: 5, | ||
x: | ||
append( | ||
(), | ||
( | ||
y: 42, | ||
) | ||
), | ||
) | ||
); | ||
@include assert-equal(path(a, $obj2), path(a, $obj1)); | ||
@include assert-equal(path(b, $obj2), path(b, $obj1)); | ||
@include assert-equal(path(e, $obj2), path(e, $obj1)); | ||
@include assert-equal(path(f, $obj2), path(f, $obj1)); | ||
} | ||
|
||
@include it('empty path replaces the whole object') { | ||
@include assert-equal( | ||
assoc-path( | ||
(), | ||
3, | ||
( | ||
a: 1, | ||
b: 2, | ||
) | ||
), | ||
3 | ||
); | ||
} | ||
|
||
@include it('replaces `null` with a new object') { | ||
@include assert-equal( | ||
assoc-path( | ||
('foo', 'bar', 'baz'), | ||
42, | ||
( | ||
foo: null, | ||
) | ||
), | ||
( | ||
foo: ( | ||
bar: ( | ||
baz: 42, | ||
), | ||
), | ||
) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
@import 'true'; | ||
@import '../src/pluck'; | ||
|
||
@include describe('pluck [function]') { | ||
$the-avengers: ( | ||
( | ||
name: 'Black Widow', | ||
age: 34, | ||
), | ||
( | ||
name: 'Captain America', | ||
age: 100, | ||
), | ||
( | ||
name: 'Hawkeye', | ||
age: 47, | ||
), | ||
( | ||
name: 'Hulk', | ||
age: 49, | ||
), | ||
( | ||
name: 'Iron man', | ||
age: '48', | ||
), | ||
( | ||
name: 'Thor', | ||
age: 'unknown', | ||
) | ||
); | ||
|
||
@include it('should appropriate property over an array') { | ||
@include assert-equal( | ||
pluck('name', $the-avengers), | ||
('Black Widow' 'Captain America' 'Hawkeye' 'Hulk' 'Iron man' 'Thor') | ||
); | ||
} | ||
} |