-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap-functions.scss
168 lines (136 loc) · 4.04 KB
/
map-functions.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//
/// @group Utilities
/// @access private
/// @author Hugo Giraudel
/// @link http://www.sitepoint.com/extra-map-functions-sass/
//
/// Fetch nested keys
/// @param {Map} $map - Map
/// @param {Arglist} $keys - Keys to fetch
/// @return {*}
@function map-deep-get($map, $keys...) {
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}
// Update a key deeply nested
/// @author Hugo Giraudel
/// @param {Map} $map - Map to update
/// @param {Arglist} $keys - Keys to access to value to update
/// @param {*} $value - New value (last member of `$keys`)
/// @return {Map} - Updated map
@function map-deep-set($map, $keys.../*, $value */) {
$map-list: ($map,);
$result: null;
@if length($keys) == 2 {
@return map-merge($map, (nth($keys, 1): nth($keys, -1)));
}
@for $i from 1 through length($keys) - 2 {
$map-list: append($map-list, map-get(nth($map-list, -1), nth($keys, $i)));
}
@for $i from length($map-list) through 1 {
$result: map-merge(nth($map-list, $i), (nth($keys, $i): if($i == length($map-list), nth($keys, -1), $result)));
}
@return $result;
}
// Compute the maximum depth of a map
/// @param {Map} $map
/// @return {Number} max depth of `$map`
@function map-depth($map) {
$level: 1;
@each $key, $value in $map {
@if type-of($value) == 'map' {
$level: max(map-depth($value) + 1, $level);
}
}
@return $level;
}
// Test if map got all `$keys` at first level
/// @access private
/// @author Hugo Giraudel
/// @param {Map} $map - Map
/// @param {Arglist} $keys - Keys to test
/// @return {Boolean}
@function map-has-keys($map, $keys...) {
@each $key in $keys {
@if not map-has-key($map, $key) {
@return false;
}
}
@return true;
}
// Test if map got all `$keys` nested with each others
/// @access private
/// @author Hugo Giraudel
/// @param {Map} $map - Map
/// @param {Arglist} $keys - Keys to test
/// @return {Boolean}
@function map-has-nested-keys($map, $keys...) {
@each $key in $keys {
@if not map-has-key($map, $key) {
@return false;
}
$map: map-get($map, $key);
}
@return true;
}
// An equivalent of `zip` function but for maps.
// Takes two lists, the first for keys, second for values.
/// @access private
/// @param {List} $keys - Keys for map
/// @param {List} $values - Values for map
/// @return {Map} Freshly created map
/// @link http://sass-lang.com/documentation/Sass/Script/Functions.html#zip-instance_method
@function map-zip($keys, $values) {
$l-keys: length($keys);
$l-values: length($values);
$min: min($l-keys, $l-values);
$map: ();
@if $l-keys != $l-values {
@warn '⚠️ There are #{$l-keys} key(s) for #{$l-values} value(s) in the map for `map-zip`. ' + 'Resulting map will only have #{$min} pairs.';
}
@if $min == 0 {
@return $map;
}
@for $i from 1 through $min {
$map: map-merge($map, (nth($keys, $i): nth($values, $i)));
}
@return $map;
}
// jQuery-style extend function
// About `map-merge()`:
// * only takes 2 arguments
// * is not recursive
/// @access private
/// @param {Map} $map - first map
/// @param {ArgList} $maps - other maps
/// @param {Boolean} $deep - recursive mode
/// @return {Map}
@function map-extend($map, $maps.../*, $deep */) {
$last: nth($maps, -1);
$deep: $last == true;
$max: if($deep, length($maps) - 1, length($maps));
// Loop through all maps in $maps...
@for $i from 1 through $max {
// Store current map
$current: nth($maps, $i);
// If not in deep mode, simply merge current map with map
@if not $deep {
$map: map-merge($map, $current);
}
@else {
// If in deep mode, loop through all tuples in current map
@each $key, $value in $current {
// If value is a nested map and same key from map is a nested map as well
@if type-of($value) == 'map' and type-of(map-get($map, $key)) == 'map' {
// Recursive extend
$value: map-extend(map-get($map, $key), $value, true);
}
// Merge current tuple with map
$map: map-merge($map, ($key: $value));
}
}
}
@return $map;
}