aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.stylelintrc.json2
-rw-r--r--package.json4
-rw-r--r--src/_contexts.scss217
-rw-r--r--src/_easing.scss206
-rw-r--r--src/_functions.scss320
-rw-r--r--src/_gradients.scss643
-rw-r--r--src/_harmony.scss65
-rw-r--r--src/_props.scss202
-rw-r--r--src/_responsive.scss391
-rw-r--r--src/bem/_block.scss222
-rw-r--r--src/bem/_debug.scss15
-rw-r--r--src/bem/_element.scss483
-rw-r--r--src/bem/_functions.scss27
-rw-r--r--src/bem/_modifier.scss227
-rw-r--r--src/bem/_multi.scss102
-rw-r--r--src/bem/_state.scss84
-rw-r--r--src/bem/_suffix.scss95
-rw-r--r--src/bem/_theme.scss57
-rw-r--r--src/bem/_validators.scss137
-rw-r--r--src/bem/_vars.scss28
-rw-r--r--test/_bem.scss32
-rw-r--r--test/_contexts.scss90
-rw-r--r--test/_functions.scss84
-rw-r--r--test/_gradients.scss392
-rw-r--r--test/_harmony.scss386
-rw-r--r--test/_props.scss489
-rw-r--r--test/_responsive.scss12
-rw-r--r--test/bem/_at-theme.scss80
-rw-r--r--test/bem/_block.scss139
-rw-r--r--test/bem/_composed-of.scss237
-rw-r--r--test/bem/_element.scss792
-rw-r--r--test/bem/_examples.scss352
-rw-r--r--test/bem/_modifier.scss1066
-rw-r--r--test/bem/_multi.scss948
-rw-r--r--test/bem/_next-twin-element.scss248
-rw-r--r--test/bem/_related-element.scss752
-rw-r--r--test/bem/_state.scss280
-rw-r--r--test/bem/_suffix.scss146
-rw-r--r--test/test.scss2
39 files changed, 5013 insertions, 5041 deletions
diff --git a/.stylelintrc.json b/.stylelintrc.json
index ad8225f..fa2128b 100644
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@ -1,7 +1,7 @@
1{ 1{
2 "extends": "stylelint-config-sass-guidelines", 2 "extends": "stylelint-config-sass-guidelines",
3 "rules": { 3 "rules": {
4 "@stylistic/indentation": 4, 4 "@stylistic/indentation": "tab",
5 "@stylistic/number-leading-zero": "never", 5 "@stylistic/number-leading-zero": "never",
6 "@stylistic/declaration-colon-space-after": null, 6 "@stylistic/declaration-colon-space-after": null,
7 "max-nesting-depth": 9, 7 "max-nesting-depth": 9,
diff --git a/package.json b/package.json
index da3fcc5..810a15f 100644
--- a/package.json
+++ b/package.json
@@ -35,8 +35,8 @@
35 }, 35 },
36 "scripts": { 36 "scripts": {
37 "prepublishOnly": "npm run test", 37 "prepublishOnly": "npm run test",
38 "lint": "stylelint \"src/**/*.scss\"", 38 "lint": "stylelint \"{src,test}/**/*.scss\"",
39 "fix": "stylelint \"src/**/*.scss\" --fix", 39 "fix": "stylelint \"{src,test}/**/*.scss\" --fix",
40 "livelint": "nodemon --watch src --watch test -e scss -x 'echo \"BEGIN LINT\" && npm run lint && echo \"END LINT\"'", 40 "livelint": "nodemon --watch src --watch test -e scss -x 'echo \"BEGIN LINT\" && npm run lint && echo \"END LINT\"'",
41 "doc": "sassdoc src", 41 "doc": "sassdoc src",
42 "test": "mocha test/test.js" 42 "test": "mocha test/test.js"
diff --git a/src/_contexts.scss b/src/_contexts.scss
index 7ffbb4e..ed376a2 100644
--- a/src/_contexts.scss
+++ b/src/_contexts.scss
@@ -15,6 +15,9 @@
15/// @access public 15/// @access public
16//// 16////
17 17
18@use 'sass:list';
19@use 'sass:map';
20@use 'sass:meta';
18@use './functions'; 21@use './functions';
19 22
20/// 23///
@@ -34,7 +37,7 @@ $stacks: ();
34/// @throw If context stack already exists 37/// @throw If context stack already exists
35/// 38///
36@mixin create($stack-id) { 39@mixin create($stack-id) {
37 $noop: create($stack-id); 40 $noop: create($stack-id);
38} 41}
39 42
40/// 43///
@@ -43,13 +46,13 @@ $stacks: ();
43/// @param {string} $stack-id - ID of context stack 46/// @param {string} $stack-id - ID of context stack
44/// 47///
45@function create($stack-id) { 48@function create($stack-id) {
46 @if map-has-key($stacks, $stack-id) { 49 @if map.has-key($stacks, $stack-id) {
47 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 50 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
48 } 51 }
49 52
50 $stacks: map-merge($stacks, ($stack-id: ())) !global; 53 $stacks: map.merge($stacks, ($stack-id: ())) !global;
51 54
52 @return null; 55 @return null;
53} 56}
54 57
55/// 58///
@@ -58,7 +61,7 @@ $stacks: ();
58/// @param {string} $stack-id - ID of context stack 61/// @param {string} $stack-id - ID of context stack
59/// 62///
60@mixin clear($stack-id) { 63@mixin clear($stack-id) {
61 $noop: clear($stack-id); 64 $noop: clear($stack-id);
62} 65}
63 66
64/// 67///
@@ -67,14 +70,14 @@ $stacks: ();
67/// @param {string} $stack-id - ID of context stack 70/// @param {string} $stack-id - ID of context stack
68/// 71///
69@function clear($stack-id) { 72@function clear($stack-id) {
70 @if not map-has-key($stacks, $stack-id) { 73 @if not map.has-key($stacks, $stack-id) {
71 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 74 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
72 } 75 }
73 76
74 $context-stack: (); 77 $context-stack: ();
75 $stacks: map-merge($stacks, ($stack-id: $context-stack)) !global; 78 $stacks: map.merge($stacks, ($stack-id: $context-stack)) !global;
76 79
77 @return null; 80 @return null;
78} 81}
79 82
80/// 83///
@@ -83,7 +86,7 @@ $stacks: ();
83/// @param {string} $stack-id - ID of context stack 86/// @param {string} $stack-id - ID of context stack
84/// 87///
85@mixin delete($stack-id) { 88@mixin delete($stack-id) {
86 $noop: delete($stack-id); 89 $noop: delete($stack-id);
87} 90}
88 91
89/// 92///
@@ -92,13 +95,13 @@ $stacks: ();
92/// @param {string} $stack-id - ID of context stack 95/// @param {string} $stack-id - ID of context stack
93/// 96///
94@function delete($stack-id) { 97@function delete($stack-id) {
95 @if not map-has-key($stacks, $stack-id) { 98 @if not map.has-key($stacks, $stack-id) {
96 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 99 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
97 } 100 }
98 101
99 $stacks: map-remove($stacks, $stack-id) !global; 102 $stacks: map.remove($stacks, $stack-id) !global;
100 103
101 @return null; 104 @return null;
102} 105}
103 106
104/// 107///
@@ -109,7 +112,7 @@ $stacks: ();
109/// @param {any} $data [()] - Data that belongs to the context 112/// @param {any} $data [()] - Data that belongs to the context
110/// 113///
111@mixin push($stack-id, $id, $data: ()) { 114@mixin push($stack-id, $id, $data: ()) {
112 $noop: push($stack-id, $id, $data); 115 $noop: push($stack-id, $id, $data);
113} 116}
114 117
115/// 118///
@@ -122,16 +125,16 @@ $stacks: ();
122/// @return {list} A list with two items: 1 = context id, 2 = context data 125/// @return {list} A list with two items: 1 = context id, 2 = context data
123/// 126///
124@function push($stack-id, $id, $data: ()) { 127@function push($stack-id, $id, $data: ()) {
125 @if not map-has-key($stacks, $stack-id) { 128 @if not map.has-key($stacks, $stack-id) {
126 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 129 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
127 } 130 }
128 131
129 $context: $id $data; 132 $context: $id $data;
130 $context-stack: map-get($stacks, $stack-id); 133 $context-stack: map.get($stacks, $stack-id);
131 $context-stack: append($context-stack, $context); 134 $context-stack: list.append($context-stack, $context);
132 $stacks: map-merge($stacks, ($stack-id: $context-stack)) !global; 135 $stacks: map.merge($stacks, ($stack-id: $context-stack)) !global;
133 136
134 @return $context; 137 @return $context;
135} 138}
136 139
137/// 140///
@@ -142,7 +145,7 @@ $stacks: ();
142/// @throw If context stack doesn't exist 145/// @throw If context stack doesn't exist
143/// 146///
144@mixin pop($stack-id) { 147@mixin pop($stack-id) {
145 $noop: pop($stack-id); 148 $noop: pop($stack-id);
146} 149}
147 150
148/// 151///
@@ -153,27 +156,27 @@ $stacks: ();
153/// @return {list} A list with two items: 1 = context id, 2 = context data 156/// @return {list} A list with two items: 1 = context id, 2 = context data
154/// 157///
155@function pop($stack-id) { 158@function pop($stack-id) {
156 @if not map-has-key($stacks, $stack-id) { 159 @if not map.has-key($stacks, $stack-id) {
157 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 160 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
158 } 161 }
159 162
160 $context-stack: map-get($stacks, $stack-id); 163 $context-stack: map.get($stacks, $stack-id);
161 164
162 @if length($context-stack) == 0 { 165 @if list.length($context-stack) == 0 {
163 @error 'Context stack "#{inspect($stack-id)}" is already empty.'; 166 @error 'Context stack "#{inspect($stack-id)}" is already empty.';
164 } 167 }
165 168
166 $popped-context: nth($context-stack, -1); 169 $popped-context: list.nth($context-stack, -1);
167 170
168 @if length($context-stack) == 1 { 171 @if list.length($context-stack) == 1 {
169 $context-stack: (); 172 $context-stack: ();
170 } @else { 173 } @else {
171 $context-stack: functions.list-slice($context-stack, 1, length($context-stack) - 1); 174 $context-stack: functions.list-slice($context-stack, 1, list.length($context-stack) - 1);
172 } 175 }
173 176
174 $stacks: map-merge($stacks, ($stack-id: $context-stack)) !global; 177 $stacks: map.merge($stacks, ($stack-id: $context-stack)) !global;
175 178
176 @return $popped-context; 179 @return $popped-context;
177} 180}
178 181
179/// 182///
@@ -186,15 +189,15 @@ $stacks: ();
186/// @throw If assertion fails 189/// @throw If assertion fails
187/// 190///
188@function assert-stack-must-contain($stack-id, $context-ids, $check-head-only: false) { 191@function assert-stack-must-contain($stack-id, $context-ids, $check-head-only: false) {
189 @if not contains($stack-id, $context-ids, $check-head-only) { 192 @if not contains($stack-id, $context-ids, $check-head-only) {
190 @error 'Must be called inside of contexts "#{inspect($context-ids)}".'; 193 @error 'Must be called inside of contexts "#{inspect($context-ids)}".';
191 } 194 }
192 195
193 @return null; 196 @return null;
194} 197}
195 198
196@mixin assert-stack-must-contain($stack-id, $context-ids, $check-head-only: false) { 199@mixin assert-stack-must-contain($stack-id, $context-ids, $check-head-only: false) {
197 $noop: assert-stack-must-contain($stack-id, $context-ids, $check-head-only); 200 $noop: assert-stack-must-contain($stack-id, $context-ids, $check-head-only);
198} 201}
199 202
200/// 203///
@@ -207,15 +210,15 @@ $stacks: ();
207/// @throw If assertion fails 210/// @throw If assertion fails
208/// 211///
209@function assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only: false) { 212@function assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only: false) {
210 @if contains($stack-id, $context-ids, $check-head-only) { 213 @if contains($stack-id, $context-ids, $check-head-only) {
211 @error 'Must not be called inside of contexts "#{inspect($context-ids)}".'; 214 @error 'Must not be called inside of contexts "#{inspect($context-ids)}".';
212 } 215 }
213 216
214 @return null; 217 @return null;
215} 218}
216 219
217@mixin assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only: false) { 220@mixin assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only: false) {
218 $noop: assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only); 221 $noop: assert-stack-must-not-contain($stack-id, $context-ids, $check-head-only);
219} 222}
220 223
221/// 224///
@@ -228,29 +231,29 @@ $stacks: ();
228/// @return {bool} `true` if the context stack contains one of the context IDs, otherwise `false` 231/// @return {bool} `true` if the context stack contains one of the context IDs, otherwise `false`
229/// 232///
230@function contains($stack-id, $context-ids, $check-head-only: false) { 233@function contains($stack-id, $context-ids, $check-head-only: false) {
231 @if not map-has-key($stacks, $stack-id) { 234 @if not map.has-key($stacks, $stack-id) {
232 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 235 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
233 } 236 }
234 237
235 $context-stack: map-get($stacks, $stack-id); 238 $context-stack: map.get($stacks, $stack-id);
236 239
237 @if length($context-stack) == 0 { 240 @if list.length($context-stack) == 0 {
238 @return false; 241 @return false;
239 } 242 }
240 243
241 $end-idx: if($check-head-only, length($context-stack), 1); 244 $end-idx: if($check-head-only, list.length($context-stack), 1);
242 245
243 @for $i from length($context-stack) through $end-idx { 246 @for $i from list.length($context-stack) through $end-idx {
244 $context: nth($context-stack, $i); 247 $context: list.nth($context-stack, $i);
245 248
246 @each $chk-context in $context-ids { 249 @each $chk-context in $context-ids {
247 @if nth($context, 1) == $chk-context { 250 @if list.nth($context, 1) == $chk-context {
248 @return true; 251 @return true;
249 } 252 }
250 } 253 }
251 } 254 }
252 255
253 @return false; 256 @return false;
254} 257}
255 258
256/// 259///
@@ -262,15 +265,15 @@ $stacks: ();
262/// @throw If assertion fails 265/// @throw If assertion fails
263/// 266///
264@function assert-stack-count($stack-id, $max-count) { 267@function assert-stack-count($stack-id, $max-count) {
265 @if count($stack-id) > $max-count { 268 @if count($stack-id) > $max-count {
266 @error 'Maximum context count "#{inspect($max-count)}" exceeded.'; 269 @error 'Maximum context count "#{inspect($max-count)}" exceeded.';
267 } 270 }
268 271
269 @return null; 272 @return null;
270} 273}
271 274
272@mixin assert-stack-count($stack-id, $max-count) { 275@mixin assert-stack-count($stack-id, $max-count) {
273 $noop: assert-stack-count($stack-id, $max-count); 276 $noop: assert-stack-count($stack-id, $max-count);
274} 277}
275 278
276/// 279///
@@ -281,13 +284,13 @@ $stacks: ();
281/// @return {number} The number of contexts 284/// @return {number} The number of contexts
282/// 285///
283@function count($stack-id) { 286@function count($stack-id) {
284 @if not map-has-key($stacks, $stack-id) { 287 @if not map.has-key($stacks, $stack-id) {
285 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 288 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
286 } 289 }
287 290
288 $context-stack: map-get($stacks, $stack-id); 291 $context-stack: map.get($stacks, $stack-id);
289 292
290 @return length($context-stack); 293 @return list.length($context-stack);
291} 294}
292 295
293/// 296///
@@ -299,37 +302,37 @@ $stacks: ();
299/// @return {list} Null if no match was found, otherwise a list with two items: 1. context ID, 2. context data. 302/// @return {list} Null if no match was found, otherwise a list with two items: 1. context ID, 2. context data.
300/// 303///
301@function get($stack-id, $type-or-level: null) { 304@function get($stack-id, $type-or-level: null) {
302 @if not map-has-key($stacks, $stack-id) { 305 @if not map.has-key($stacks, $stack-id) {
303 @error 'Context stack "#{inspect($stack-id)}" does not exist.'; 306 @error 'Context stack "#{inspect($stack-id)}" does not exist.';
304 } 307 }
305 308
306 $context-stack: map-get($stacks, $stack-id); 309 $context-stack: map.get($stacks, $stack-id);
307 310
308 @if length($context-stack) == 0 { 311 @if list.length($context-stack) == 0 {
309 @return null; 312 @return null;
310 } 313 }
311 314
312 @if type-of($type-or-level) == number { 315 @if meta.type-of($type-or-level) == number {
313 $context: nth($context-stack, -$type-or-level); 316 $context: list.nth($context-stack, -$type-or-level);
314 317
315 @return $context; 318 @return $context;
316 } @else { 319 } @else {
317 @for $i from -1 through -(length($context-stack)) { 320 @for $i from -1 through -(list.length($context-stack)) {
318 $context: nth($context-stack, $i); 321 $context: list.nth($context-stack, $i);
319 322
320 @if type-of($type-or-level) == list { 323 @if meta.type-of($type-or-level) == list {
321 @for $j from 1 through length($type-or-level) { 324 @for $j from 1 through list.length($type-or-level) {
322 $ctx: nth($type-or-level, $j); 325 $ctx: list.nth($type-or-level, $j);
323 326
324 @if nth($context, 1) == $ctx { 327 @if list.nth($context, 1) == $ctx {
325 @return $context; 328 @return $context;
326 } 329 }
327 } 330 }
328 } @else if nth($context, 1) == $type-or-level { 331 } @else if list.nth($context, 1) == $type-or-level {
329 @return $context; 332 @return $context;
330 } 333 }
331 } 334 }
332 } 335 }
333 336
334 @return null; 337 @return null;
335} 338}
diff --git a/src/_easing.scss b/src/_easing.scss
index 6d66ea7..939eda2 100644
--- a/src/_easing.scss
+++ b/src/_easing.scss
@@ -55,62 +55,62 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
55/// @return {number} 55/// @return {number}
56/// 56///
57@function cubic-bezier($x1, $y1, $x2, $y2, $x) { 57@function cubic-bezier($x1, $y1, $x2, $y2, $x) {
58 // 58 //
59 // Cover simple cases 59 // Cover simple cases
60 // 60 //
61 61
62 @if ($x1 == $y1) and ($x2 == $y2) { 62 @if ($x1 == $y1) and ($x2 == $y2) {
63 @return $x; 63 @return $x;
64 } 64 }
65 @if $x == 0 { 65 @if $x == 0 {
66 @return 0; 66 @return 0;
67 } 67 }
68 @if $x == 1 { 68 @if $x == 1 {
69 @return 1; 69 @return 1;
70 } 70 }
71 71
72 // 72 //
73 // Generate samples 73 // Generate samples
74 // 74 //
75 75
76 $sample-pool-key: $x1 + '_' + $x2; 76 $sample-pool-key: $x1 + '_' + $x2;
77 77
78 @if not map.has-key($cubic-bezier-sample-pool, $sample-pool-key) { 78 @if not map.has-key($cubic-bezier-sample-pool, $sample-pool-key) {
79 $samples: (); 79 $samples: ();
80 80
81 @for $i from 0 through $cubic-bezier-sample-pool-size { 81 @for $i from 0 through $cubic-bezier-sample-pool-size {
82 $samples: list.append($samples, cubic-bezier-func($x1, $x2, math.div($i, $cubic-bezier-sample-pool-size))); 82 $samples: list.append($samples, cubic-bezier-func($x1, $x2, math.div($i, $cubic-bezier-sample-pool-size)));
83 } 83 }
84 84
85 $cubic-bezier-sample-pool: map.merge($cubic-bezier-sample-pool, ($sample-pool-key: $samples)) !global; 85 $cubic-bezier-sample-pool: map.merge($cubic-bezier-sample-pool, ($sample-pool-key: $samples)) !global;
86 } 86 }
87 87
88 // 88 //
89 // Calculate cubic bezier 89 // Calculate cubic bezier
90 // 90 //
91 91
92 @return cubic-bezier-func($y1, $y2, cubic-bezier-t-for-x($x1, $x2, $x)); 92 @return cubic-bezier-func($y1, $y2, cubic-bezier-t-for-x($x1, $x2, $x));
93} 93}
94 94
95/// 95///
96/// @access private 96/// @access private
97/// 97///
98@function cubic-bezier-func-a($p1, $p2) { 98@function cubic-bezier-func-a($p1, $p2) {
99 @return 1 - 3 * $p2 + 3 * $p1; 99 @return 1 - 3 * $p2 + 3 * $p1;
100} 100}
101 101
102/// 102///
103/// @access private 103/// @access private
104/// 104///
105@function cubic-bezier-func-b($p1, $p2) { 105@function cubic-bezier-func-b($p1, $p2) {
106 @return 3 * $p2 - 6 * $p1; 106 @return 3 * $p2 - 6 * $p1;
107} 107}
108 108
109/// 109///
110/// @access private 110/// @access private
111/// 111///
112@function cubic-bezier-func-c($p1) { 112@function cubic-bezier-func-c($p1) {
113 @return 3 * $p1; 113 @return 3 * $p1;
114} 114}
115 115
116/// 116///
@@ -119,7 +119,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
119/// @access private 119/// @access private
120/// 120///
121@function cubic-bezier-func($p1, $p2, $t) { 121@function cubic-bezier-func($p1, $p2, $t) {
122 @return ((cubic-bezier-func-a($p1, $p2) * $t + cubic-bezier-func-b($p1, $p2)) * $t + cubic-bezier-func-c($p1)) * $t; 122 @return ((cubic-bezier-func-a($p1, $p2) * $t + cubic-bezier-func-b($p1, $p2)) * $t + cubic-bezier-func-c($p1)) * $t;
123} 123}
124 124
125/// 125///
@@ -128,7 +128,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
128/// @access private 128/// @access private
129/// 129///
130@function cubic-bezier-func-slope($p1, $p2, $t) { 130@function cubic-bezier-func-slope($p1, $p2, $t) {
131 @return 3 * cubic-bezier-func-a($p1, $p2) * $t * $t + 2 * cubic-bezier-func-b($p1, $p2) * $t + cubic-bezier-func-c($p1); 131 @return 3 * cubic-bezier-func-a($p1, $p2) * $t * $t + 2 * cubic-bezier-func-b($p1, $p2) * $t + cubic-bezier-func-c($p1);
132} 132}
133 133
134/// 134///
@@ -137,18 +137,18 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
137/// @access private 137/// @access private
138/// 138///
139@function cubic-bezier-newton-raphson($x1, $x2, $x, $t) { 139@function cubic-bezier-newton-raphson($x1, $x2, $x, $t) {
140 @for $i from 1 through $cubic-bezier-newton-iters { 140 @for $i from 1 through $cubic-bezier-newton-iters {
141 $cur-slope: cubic-bezier-func-slope($x1, $x2, $t); 141 $cur-slope: cubic-bezier-func-slope($x1, $x2, $t);
142 142
143 @if $cur-slope == 0 { 143 @if $cur-slope == 0 {
144 @return $t; 144 @return $t;
145 } 145 }
146 146
147 $cur-x: cubic-bezier-func($x1, $x2, $t) - $x; 147 $cur-x: cubic-bezier-func($x1, $x2, $t) - $x;
148 $t: $t - math.div($cur-x, $cur-slope); 148 $t: $t - math.div($cur-x, $cur-slope);
149 } 149 }
150 150
151 @return $t; 151 @return $t;
152} 152}
153 153
154/// 154///
@@ -157,26 +157,26 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
157/// @access private 157/// @access private
158/// 158///
159@function cubic-bezier-binary-subdivide($x1, $x2, $x, $a, $b) { 159@function cubic-bezier-binary-subdivide($x1, $x2, $x, $a, $b) {
160 $cur-x: 0; 160 $cur-x: 0;
161 $cur-t: 0; 161 $cur-t: 0;
162 $i: 0; 162 $i: 0;
163 163
164 @while $i < $cubic-bezier-subdiv-max-iters { 164 @while $i < $cubic-bezier-subdiv-max-iters {
165 $cur-t: $a + ($b - $a) / 2; 165 $cur-t: $a + ($b - $a) / 2;
166 $cur-x: cubic-bezier-func($x1, $x2, $cur-t) - $x; 166 $cur-x: cubic-bezier-func($x1, $x2, $cur-t) - $x;
167 167
168 @if $cur-x > 0 { 168 @if $cur-x > 0 {
169 $b: $cur-t; 169 $b: $cur-t;
170 } @else { 170 } @else {
171 $a: $cur-t; 171 $a: $cur-t;
172 } 172 }
173 173
174 @if math.abs($cur-x) < $cubic-bezier-subdiv-precision { 174 @if math.abs($cur-x) < $cubic-bezier-subdiv-precision {
175 @return $cur-t; 175 @return $cur-t;
176 } 176 }
177 } 177 }
178 178
179 @return $cur-t; 179 @return $cur-t;
180} 180}
181 181
182/// 182///
@@ -185,30 +185,30 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
185/// @access private 185/// @access private
186/// 186///
187@function cubic-bezier-t-for-x($x1, $x2, $x) { 187@function cubic-bezier-t-for-x($x1, $x2, $x) {
188 $sample-pool-key: $x1 + '_' + $x2; 188 $sample-pool-key: $x1 + '_' + $x2;
189 $samples: map.get($cubic-bezier-sample-pool, $sample-pool-key); 189 $samples: map.get($cubic-bezier-sample-pool, $sample-pool-key);
190 190
191 $intv-start: 0; 191 $intv-start: 0;
192 $cur-sample: 1; 192 $cur-sample: 1;
193 $last-sample: $cubic-bezier-sample-pool-size; 193 $last-sample: $cubic-bezier-sample-pool-size;
194 194
195 @while ($cur-sample != $last-sample) and (list.nth($samples, $cur-sample) <= $x) { 195 @while ($cur-sample != $last-sample) and (list.nth($samples, $cur-sample) <= $x) {
196 $intv-start: $intv-start + math.div(1, $cubic-bezier-sample-pool-size); 196 $intv-start: $intv-start + math.div(1, $cubic-bezier-sample-pool-size);
197 $cur-sample: $cur-sample + 1; 197 $cur-sample: $cur-sample + 1;
198 } 198 }
199 $cur-sample: $cur-sample - 1; 199 $cur-sample: $cur-sample - 1;
200 200
201 $dist: math.div($x - list.nth($samples, $cur-sample), list.nth($samples, $cur-sample + 1) - list.nth($samples, $cur-sample)); 201 $dist: math.div($x - list.nth($samples, $cur-sample), list.nth($samples, $cur-sample + 1) - list.nth($samples, $cur-sample));
202 $guess-t: $intv-start + math.div($dist, $cubic-bezier-sample-pool-size); 202 $guess-t: $intv-start + math.div($dist, $cubic-bezier-sample-pool-size);
203 203
204 $init-slope: cubic-bezier-func-slope($x1, $x2, $guess-t); 204 $init-slope: cubic-bezier-func-slope($x1, $x2, $guess-t);
205 @if $init-slope >= $cubic-bezier-newton-min-slope { 205 @if $init-slope >= $cubic-bezier-newton-min-slope {
206 @return cubic-bezier-newton-raphson($x1, $x2, $x, $guess-t); 206 @return cubic-bezier-newton-raphson($x1, $x2, $x, $guess-t);
207 } @else if $init-slope == 0 { 207 } @else if $init-slope == 0 {
208 @return $guess-t; 208 @return $guess-t;
209 } @else { 209 } @else {
210 @return cubic-bezier-binary-subdivide($x1, $x2, $x, $intv-start, $intv-start + 1 / $cubic-bezier-sample-pool-size); 210 @return cubic-bezier-binary-subdivide($x1, $x2, $x, $intv-start, $intv-start + 1 / $cubic-bezier-sample-pool-size);
211 } 211 }
212} 212}
213 213
214/// 214///
@@ -219,7 +219,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
219/// @return {number} 219/// @return {number}
220/// 220///
221@function linear($x) { 221@function linear($x) {
222 @return $x; 222 @return $x;
223} 223}
224 224
225/// 225///
@@ -230,7 +230,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
230/// @return {number} 230/// @return {number}
231/// 231///
232@function ease($x) { 232@function ease($x) {
233 @return cubic-bezier(.25, .1, .25, 1, $x); 233 @return cubic-bezier(.25, .1, .25, 1, $x);
234} 234}
235 235
236/// 236///
@@ -241,7 +241,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
241/// @return {number} 241/// @return {number}
242/// 242///
243@function ease-in($x) { 243@function ease-in($x) {
244 @return cubic-bezier(.42, 0, 1, 1, $x); 244 @return cubic-bezier(.42, 0, 1, 1, $x);
245} 245}
246 246
247/// 247///
@@ -252,7 +252,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
252/// @return {number} 252/// @return {number}
253/// 253///
254@function ease-out($x) { 254@function ease-out($x) {
255 @return cubic-bezier(0, 0, .58, 1, $x); 255 @return cubic-bezier(0, 0, .58, 1, $x);
256} 256}
257 257
258/// 258///
@@ -263,7 +263,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
263/// @return {number} 263/// @return {number}
264/// 264///
265@function ease-in-out($x) { 265@function ease-in-out($x) {
266 @return cubic-bezier(.42, 0, .58, 1, $x); 266 @return cubic-bezier(.42, 0, .58, 1, $x);
267} 267}
268 268
269/// 269///
@@ -274,7 +274,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
274/// @return {number} 274/// @return {number}
275/// 275///
276@function ease-in-sine($x) { 276@function ease-in-sine($x) {
277 @return cubic-bezier(.47, 0, .745, .715, $x); 277 @return cubic-bezier(.47, 0, .745, .715, $x);
278} 278}
279 279
280/// 280///
@@ -285,7 +285,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
285/// @return {number} 285/// @return {number}
286/// 286///
287@function ease-out-sine($x) { 287@function ease-out-sine($x) {
288 @return cubic-bezier(.39, .575, .565, 1, $x); 288 @return cubic-bezier(.39, .575, .565, 1, $x);
289} 289}
290 290
291/// 291///
@@ -296,7 +296,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
296/// @return {number} 296/// @return {number}
297/// 297///
298@function ease-in-out-sine($x) { 298@function ease-in-out-sine($x) {
299 @return cubic-bezier(.445, .05, .55, .95, $x); 299 @return cubic-bezier(.445, .05, .55, .95, $x);
300} 300}
301 301
302/// 302///
@@ -307,7 +307,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
307/// @return {number} 307/// @return {number}
308/// 308///
309@function ease-in-quad($x) { 309@function ease-in-quad($x) {
310 @return cubic-bezier(.55, .085, .68, .53, $x); 310 @return cubic-bezier(.55, .085, .68, .53, $x);
311} 311}
312 312
313/// 313///
@@ -318,7 +318,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
318/// @return {number} 318/// @return {number}
319/// 319///
320@function ease-out-quad($x) { 320@function ease-out-quad($x) {
321 @return cubic-bezier(.25, .46, .45, .94, $x); 321 @return cubic-bezier(.25, .46, .45, .94, $x);
322} 322}
323 323
324/// 324///
@@ -329,7 +329,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
329/// @return {number} 329/// @return {number}
330/// 330///
331@function ease-in-out-quad($x) { 331@function ease-in-out-quad($x) {
332 @return cubic-bezier(.455, .03, .515, .955, $x); 332 @return cubic-bezier(.455, .03, .515, .955, $x);
333} 333}
334 334
335/// 335///
@@ -340,7 +340,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
340/// @return {number} 340/// @return {number}
341/// 341///
342@function ease-in-cubic($x) { 342@function ease-in-cubic($x) {
343 @return cubic-bezier(.55, .055, .675, .19, $x); 343 @return cubic-bezier(.55, .055, .675, .19, $x);
344} 344}
345 345
346/// 346///
@@ -351,7 +351,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
351/// @return {number} 351/// @return {number}
352/// 352///
353@function ease-out-cubic($x) { 353@function ease-out-cubic($x) {
354 @return cubic-bezier(.215, .61, .355, 1, $x); 354 @return cubic-bezier(.215, .61, .355, 1, $x);
355} 355}
356 356
357/// 357///
@@ -362,7 +362,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
362/// @return {number} 362/// @return {number}
363/// 363///
364@function ease-in-out-cubic($x) { 364@function ease-in-out-cubic($x) {
365 @return cubic-bezier(.645, .045, .355, 1, $x); 365 @return cubic-bezier(.645, .045, .355, 1, $x);
366} 366}
367 367
368/// 368///
@@ -373,7 +373,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
373/// @return {number} 373/// @return {number}
374/// 374///
375@function ease-in-quart($x) { 375@function ease-in-quart($x) {
376 @return cubic-bezier(.895, .03, .685, .22, $x); 376 @return cubic-bezier(.895, .03, .685, .22, $x);
377} 377}
378 378
379/// 379///
@@ -384,7 +384,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
384/// @return {number} 384/// @return {number}
385/// 385///
386@function ease-out-quart($x) { 386@function ease-out-quart($x) {
387 @return cubic-bezier(.165, .84, .44, 1, $x); 387 @return cubic-bezier(.165, .84, .44, 1, $x);
388} 388}
389 389
390/// 390///
@@ -395,7 +395,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
395/// @return {number} 395/// @return {number}
396/// 396///
397@function ease-in-out-quart($x) { 397@function ease-in-out-quart($x) {
398 @return cubic-bezier(.77, 0, .175, 1, $x); 398 @return cubic-bezier(.77, 0, .175, 1, $x);
399} 399}
400 400
401/// 401///
@@ -406,7 +406,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
406/// @return {number} 406/// @return {number}
407/// 407///
408@function ease-in-quint($x) { 408@function ease-in-quint($x) {
409 @return cubic-bezier(.755, .05, .855, .06, $x); 409 @return cubic-bezier(.755, .05, .855, .06, $x);
410} 410}
411 411
412/// 412///
@@ -417,7 +417,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
417/// @return {number} 417/// @return {number}
418/// 418///
419@function ease-out-quint($x) { 419@function ease-out-quint($x) {
420 @return cubic-bezier(.23, 1, .32, 1, $x); 420 @return cubic-bezier(.23, 1, .32, 1, $x);
421} 421}
422 422
423/// 423///
@@ -428,7 +428,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
428/// @return {number} 428/// @return {number}
429/// 429///
430@function ease-in-out-quint($x) { 430@function ease-in-out-quint($x) {
431 @return cubic-bezier(.86, 0, .07, 1, $x); 431 @return cubic-bezier(.86, 0, .07, 1, $x);
432} 432}
433 433
434/// 434///
@@ -439,7 +439,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
439/// @return {number} 439/// @return {number}
440/// 440///
441@function ease-in-expo($x) { 441@function ease-in-expo($x) {
442 @return cubic-bezier(.95, .05, .795, .035, $x); 442 @return cubic-bezier(.95, .05, .795, .035, $x);
443} 443}
444 444
445/// 445///
@@ -450,7 +450,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
450/// @return {number} 450/// @return {number}
451/// 451///
452@function ease-out-expo($x) { 452@function ease-out-expo($x) {
453 @return cubic-bezier(.19, 1, .22, 1, $x); 453 @return cubic-bezier(.19, 1, .22, 1, $x);
454} 454}
455 455
456/// 456///
@@ -461,7 +461,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
461/// @return {number} 461/// @return {number}
462/// 462///
463@function ease-in-out-expo($x) { 463@function ease-in-out-expo($x) {
464 @return cubic-bezier(1, 0, 0, 1, $x); 464 @return cubic-bezier(1, 0, 0, 1, $x);
465} 465}
466 466
467/// 467///
@@ -472,7 +472,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
472/// @return {number} 472/// @return {number}
473/// 473///
474@function ease-in-circ($x) { 474@function ease-in-circ($x) {
475 @return cubic-bezier(.6, .04, .98, .335, $x); 475 @return cubic-bezier(.6, .04, .98, .335, $x);
476} 476}
477 477
478/// 478///
@@ -483,7 +483,7 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
483/// @return {number} 483/// @return {number}
484/// 484///
485@function ease-out-circ($x) { 485@function ease-out-circ($x) {
486 @return cubic-bezier(.075, .82, .165, 1, $x); 486 @return cubic-bezier(.075, .82, .165, 1, $x);
487} 487}
488 488
489/// 489///
@@ -494,5 +494,5 @@ $cubic-bezier-subdiv-max-iters: 10 !default;
494/// @return {number} 494/// @return {number}
495/// 495///
496@function ease-in-out-circ($x) { 496@function ease-in-out-circ($x) {
497 @return cubic-bezier(.785, .135, .15, .86, $x); 497 @return cubic-bezier(.785, .135, .15, .86, $x);
498} 498}
diff --git a/src/_functions.scss b/src/_functions.scss
index 0d139b4..74cc1b5 100644
--- a/src/_functions.scss
+++ b/src/_functions.scss
@@ -19,21 +19,21 @@
19$numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9); 19$numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9);
20 20
21$units: ( 21$units: (
22 'px': 1px, 22 'px': 1px,
23 'cm': 1cm, 23 'cm': 1cm,
24 'mm': 1mm, 24 'mm': 1mm,
25 '%': 1%, 25 '%': 1%,
26 'ch': 1ch, 26 'ch': 1ch,
27 'pc': 1pc, 27 'pc': 1pc,
28 'in': 1in, 28 'in': 1in,
29 'em': 1em, 29 'em': 1em,
30 'rem': 1rem, 30 'rem': 1rem,
31 'pt': 1pt, 31 'pt': 1pt,
32 'ex': 1ex, 32 'ex': 1ex,
33 'vw': 1vw, 33 'vw': 1vw,
34 'vh': 1vh, 34 'vh': 1vh,
35 'vmin': 1vmin, 35 'vmin': 1vmin,
36 'vmax': 1vmax 36 'vmax': 1vmax
37); 37);
38 38
39/// 39///
@@ -46,13 +46,13 @@ $units: (
46/// @return {string} A string with all instances of $search replaced with $replace 46/// @return {string} A string with all instances of $search replaced with $replace
47/// 47///
48@function str-replace($string, $search, $replace) { 48@function str-replace($string, $search, $replace) {
49 $index: string.index($string, $search); 49 $index: string.index($string, $search);
50 50
51 @if $index { 51 @if $index {
52 @return string.slice($string, 1, $index - 1) + $replace + str-replace(string.slice($string, $index + string.length($search)), $search, $replace); 52 @return string.slice($string, 1, $index - 1) + $replace + str-replace(string.slice($string, $index + string.length($search)), $search, $replace);
53 } 53 }
54 54
55 @return $string; 55 @return $string;
56} 56}
57 57
58/// 58///
@@ -64,17 +64,17 @@ $units: (
64/// @return {string} 64/// @return {string}
65/// 65///
66@function str-implode($list, $glue: '') { 66@function str-implode($list, $glue: '') {
67 $result: ''; 67 $result: '';
68 68
69 @each $item in $list { 69 @each $item in $list {
70 $result: $result + if(list.length($item) > 1, str-implode($item, $glue), $item); 70 $result: $result + if(list.length($item) > 1, str-implode($item, $glue), $item);
71 71
72 @if $item != list.nth($list, list.length($list)) { 72 @if $item != list.nth($list, list.length($list)) {
73 $result: $result + $glue; 73 $result: $result + $glue;
74 } 74 }
75 } 75 }
76 76
77 @return $result; 77 @return $result;
78} 78}
79 79
80/// 80///
@@ -87,17 +87,17 @@ $units: (
87/// @return {list} A slice of the list 87/// @return {list} A slice of the list
88/// 88///
89@function list-slice($list, $start: 1, $end: list.length($list)) { 89@function list-slice($list, $start: 1, $end: list.length($list)) {
90 $result: (); 90 $result: ();
91 91
92 @if $end >= $start { 92 @if $end >= $start {
93 @for $i from $start through $end { 93 @for $i from $start through $end {
94 @if $i != 0 { 94 @if $i != 0 {
95 $result: list.append($result, list.nth($list, $i), list.separator($list)); 95 $result: list.append($result, list.nth($list, $i), list.separator($list));
96 } 96 }
97 } 97 }
98 } 98 }
99 99
100 @return $result; 100 @return $result;
101} 101}
102 102
103/// 103///
@@ -109,15 +109,15 @@ $units: (
109/// @return {list} A list with $value at the beginning, followed by the other items 109/// @return {list} A list with $value at the beginning, followed by the other items
110/// 110///
111@function list-prepend($list, $value) { 111@function list-prepend($list, $value) {
112 $result: list.append((), $value, list.separator($list)); 112 $result: list.append((), $value, list.separator($list));
113 113
114 @if list.length($list) > 0 { 114 @if list.length($list) > 0 {
115 @for $i from 1 through list.length($list) { 115 @for $i from 1 through list.length($list) {
116 $result: list.append($result, list.nth($list, $i), list.separator($list)); 116 $result: list.append($result, list.nth($list, $i), list.separator($list));
117 } 117 }
118 } 118 }
119 119
120 @return $result; 120 @return $result;
121} 121}
122 122
123/// 123///
@@ -128,15 +128,15 @@ $units: (
128/// @return {list} Teh reversed list 128/// @return {list} Teh reversed list
129/// 129///
130@function list-reverse($list) { 130@function list-reverse($list) {
131 @if list.length($list) == 0 { 131 @if list.length($list) == 0 {
132 @return $list; 132 @return $list;
133 } 133 }
134 134
135 $result: (); 135 $result: ();
136 @for $i from list.length($list) * -1 through -1 { 136 @for $i from list.length($list) * -1 through -1 {
137 $result: list.append($result, list.nth($list, math.abs($i))); 137 $result: list.append($result, list.nth($list, math.abs($i)));
138 } 138 }
139 @return $result; 139 @return $result;
140} 140}
141 141
142/// 142///
@@ -150,51 +150,51 @@ $units: (
150/// @return {list} Sorted list 150/// @return {list} Sorted list
151/// 151///
152@function quicksort($l, $left: 1, $right: list.length($l)) { 152@function quicksort($l, $left: 1, $right: list.length($l)) {
153 @if $left < $right { 153 @if $left < $right {
154 $pvr: quicksort-partition($l, $left, $right); 154 $pvr: quicksort-partition($l, $left, $right);
155 $pivot: list.nth($pvr, 1); 155 $pivot: list.nth($pvr, 1);
156 $l: list.nth($pvr, 2); 156 $l: list.nth($pvr, 2);
157 $l: quicksort($l, $left, $pivot); 157 $l: quicksort($l, $left, $pivot);
158 $l: quicksort($l, $pivot + 1, $right); 158 $l: quicksort($l, $pivot + 1, $right);
159 } 159 }
160 160
161 @return $l; 161 @return $l;
162} 162}
163 163
164/// 164///
165/// @access private 165/// @access private
166/// 166///
167@function quicksort-partition($l, $left, $right) { 167@function quicksort-partition($l, $left, $right) {
168 $start: true; 168 $start: true;
169 $i: $left; 169 $i: $left;
170 $j: $right - 1; 170 $j: $right - 1;
171 $pivot: list.nth($l, $right); 171 $pivot: list.nth($l, $right);
172 172
173 @while ($i < $j) or $start { 173 @while ($i < $j) or $start {
174 @while (list.nth($l, $i) < $pivot) and ($i < $right - 1) { 174 @while (list.nth($l, $i) < $pivot) and ($i < $right - 1) {
175 $i: $i + 1; 175 $i: $i + 1;
176 } 176 }
177 177
178 @while (list.nth($l, $j)>= $pivot) and ($j > $left) { 178 @while (list.nth($l, $j)>= $pivot) and ($j > $left) {
179 $j: $j - 1; 179 $j: $j - 1;
180 } 180 }
181 181
182 @if $i < $j { 182 @if $i < $j {
183 $i-val: list.nth($l, $i); 183 $i-val: list.nth($l, $i);
184 $l: list.set-nth($l, $i, list.nth($l, $j)); 184 $l: list.set-nth($l, $i, list.nth($l, $j));
185 $l: list.set-nth($l, $j, $i-val); 185 $l: list.set-nth($l, $j, $i-val);
186 } 186 }
187 187
188 $start: false; 188 $start: false;
189 } 189 }
190 190
191 @if list.nth($l, $i) > $pivot { 191 @if list.nth($l, $i) > $pivot {
192 $i-val: list.nth($l, $i); 192 $i-val: list.nth($l, $i);
193 $l: list.set-nth($l, $i, list.nth($l, $right)); 193 $l: list.set-nth($l, $i, list.nth($l, $right));
194 $l: list.set-nth($l, $right, $i-val); 194 $l: list.set-nth($l, $right, $i-val);
195 } 195 }
196 196
197 @return $i $l; 197 @return $i $l;
198} 198}
199 199
200/// 200///
@@ -208,10 +208,10 @@ $units: (
208/// @return {any} Either the value assigned to $key or $default 208/// @return {any} Either the value assigned to $key or $default
209/// 209///
210@function map-get-default($map, $key, $keys...) { 210@function map-get-default($map, $key, $keys...) {
211 $default: list.nth($keys, list.length($keys)); 211 $default: list.nth($keys, list.length($keys));
212 $keys: list-slice($keys, 1, list.length($keys) - 1); 212 $keys: list-slice($keys, 1, list.length($keys) - 1);
213 213
214 @return if(map.has-key($map, $key, $keys...), map.get($map, $key, $keys...), $default); 214 @return if(map.has-key($map, $key, $keys...), map.get($map, $key, $keys...), $default);
215} 215}
216 216
217/// 217///
@@ -222,29 +222,29 @@ $units: (
222/// @return {string} 222/// @return {string}
223/// 223///
224@function map-print($map) { 224@function map-print($map) {
225 $output: ''; 225 $output: '';
226 226
227 @each $key, $value in $map { 227 @each $key, $value in $map {
228 $value-str: ''; 228 $value-str: '';
229 229
230 @if meta.type-of($value) == map { 230 @if meta.type-of($value) == map {
231 $value-str: '[ ' + map-print($value) + ' ]'; 231 $value-str: '[ ' + map-print($value) + ' ]';
232 } @else if meta.type-of($value) == list { 232 } @else if meta.type-of($value) == list {
233 $value-str: '[ ' + str-implode($value, ', ') + ' ]'; 233 $value-str: '[ ' + str-implode($value, ', ') + ' ]';
234 } @else if meta.type-of($value) == string { 234 } @else if meta.type-of($value) == string {
235 $value-str: '\'' + $value + '\''; 235 $value-str: '\'' + $value + '\'';
236 } @else { 236 } @else {
237 $value-str: $value; 237 $value-str: $value;
238 } 238 }
239 239
240 @if $output == '' { 240 @if $output == '' {
241 $output: $key + ': ' + $value-str; 241 $output: $key + ': ' + $value-str;
242 } @else { 242 } @else {
243 $output: $output + ', ' + $key + ': ' + $value-str; 243 $output: $output + ', ' + $key + ': ' + $value-str;
244 } 244 }
245 } 245 }
246 246
247 @return $output; 247 @return $output;
248} 248}
249 249
250/// 250///
@@ -256,35 +256,35 @@ $units: (
256/// @return {bool} `true` if the selector matches at least one suffix, otherwise `false`. 256/// @return {bool} `true` if the selector matches at least one suffix, otherwise `false`.
257/// 257///
258@function selector-suffix-match($selector, $suffixes) { 258@function selector-suffix-match($selector, $suffixes) {
259 $match: true; 259 $match: true;
260 260
261 @each $sel in $selector { 261 @each $sel in $selector {
262 @if $match { 262 @if $match {
263 $sel-match: false; 263 $sel-match: false;
264 264
265 @each $suffix in $suffixes { 265 @each $suffix in $suffixes {
266 @if not $sel-match { 266 @if not $sel-match {
267 $suf-match: true; 267 $suf-match: true;
268 268
269 @for $i from 1 through list.length($suffix) { 269 @for $i from 1 through list.length($suffix) {
270 @if $suf-match and (list.nth($sel, -$i) != list.nth($suffix, -$i)) { 270 @if $suf-match and (list.nth($sel, -$i) != list.nth($suffix, -$i)) {
271 $suf-match: false; 271 $suf-match: false;
272 } 272 }
273 } 273 }
274 274
275 @if $suf-match { 275 @if $suf-match {
276 $sel-match: true; 276 $sel-match: true;
277 } 277 }
278 } 278 }
279 } 279 }
280 280
281 @if not $sel-match { 281 @if not $sel-match {
282 $match: false; 282 $match: false;
283 } 283 }
284 } 284 }
285 } 285 }
286 286
287 @return $match; 287 @return $match;
288} 288}
289 289
290/// 290///
@@ -295,7 +295,7 @@ $units: (
295/// @return {number} Unit-less variable 295/// @return {number} Unit-less variable
296/// 296///
297@function strip-unit($n) { 297@function strip-unit($n) {
298 @return math.div($n, $n * 0 + 1); 298 @return math.div($n, $n * 0 + 1);
299} 299}
300 300
301/// 301///
@@ -307,7 +307,7 @@ $units: (
307/// @return {number} Pixel value converted to rem 307/// @return {number} Pixel value converted to rem
308/// 308///
309@function px-to-rem($size, $base: vars.$root-size) { 309@function px-to-rem($size, $base: vars.$root-size) {
310 @return math.div($size, $base) * 1rem; 310 @return math.div($size, $base) * 1rem;
311} 311}
312 312
313/// 313///
@@ -318,35 +318,35 @@ $units: (
318/// @return {number} 318/// @return {number}
319/// 319///
320@function to-number($value) { 320@function to-number($value) {
321 @if meta.type-of($value) == 'number' { 321 @if meta.type-of($value) == 'number' {
322 @return $value; 322 @return $value;
323 } 323 }
324 @if meta.type-of($value) != 'string' { 324 @if meta.type-of($value) != 'string' {
325 @error 'Value for `to-number` should be a number or a string.'; 325 @error 'Value for `to-number` should be a number or a string.';
326 } 326 }
327 327
328 $result: 0; 328 $result: 0;
329 $digits: 0; 329 $digits: 0;
330 $minus: string.slice($value, 1, 1) == '-'; 330 $minus: string.slice($value, 1, 1) == '-';
331 331
332 @for $i from if($minus, 2, 1) through string.length($value) { 332 @for $i from if($minus, 2, 1) through string.length($value) {
333 $character: string.slice($value, $i, $i); 333 $character: string.slice($value, $i, $i);
334 334
335 @if not list.index(map.keys($numbers), $character) and $character != '.' { 335 @if not list.index(map.keys($numbers), $character) and $character != '.' {
336 @return to-length(if($minus, -$result, $result), string.slice($value, $i)); 336 @return to-length(if($minus, -$result, $result), string.slice($value, $i));
337 } 337 }
338 338
339 @if $character == '.' { 339 @if $character == '.' {
340 $digits: 1; 340 $digits: 1;
341 } @else if $digits == 0 { 341 } @else if $digits == 0 {
342 $result: $result * 10 + map.get($numbers, $character); 342 $result: $result * 10 + map.get($numbers, $character);
343 } @else { 343 } @else {
344 $digits: $digits * 10; 344 $digits: $digits * 10;
345 $result: $result + math.div(map.get($numbers, $character), $digits); 345 $result: $result + math.div(map.get($numbers, $character), $digits);
346 } 346 }
347 } 347 }
348 348
349 @return if($minus, -$result, $result); 349 @return if($minus, -$result, $result);
350} 350}
351 351
352/// 352///
@@ -358,11 +358,11 @@ $units: (
358/// @return {number} $value expressed in $unit 358/// @return {number} $value expressed in $unit
359/// 359///
360@function to-length($value, $unit) { 360@function to-length($value, $unit) {
361 @if not list.index(map.keys($units), $unit) { 361 @if not list.index(map.keys($units), $unit) {
362 @error 'Invalid unit `#{$unit}`.'; 362 @error 'Invalid unit `#{$unit}`.';
363 } 363 }
364 364
365 @return $value * map.get($units, $unit); 365 @return $value * map.get($units, $unit);
366} 366}
367 367
368/// 368///
@@ -371,5 +371,5 @@ $units: (
371/// @content 371/// @content
372/// 372///
373@mixin execute { 373@mixin execute {
374 @content; 374 @content;
375} 375}
diff --git a/src/_gradients.scss b/src/_gradients.scss
index 6575482..345a9f1 100644
--- a/src/_gradients.scss
+++ b/src/_gradients.scss
@@ -15,8 +15,11 @@
15/// @access public 15/// @access public
16//// 16////
17 17
18@use 'sass:color';
19@use 'sass:list';
18@use 'sass:math'; 20@use 'sass:math';
19@use 'sass:meta'; 21@use 'sass:meta';
22@use 'sass:string';
20@use './functions'; 23@use './functions';
21@use './easing'; 24@use './easing';
22 25
@@ -135,144 +138,136 @@ $easing-gradient-steps: 10 !default;
135/// } 138/// }
136/// 139///
137@function easing-gradient($type, $dir, $stop, $stops...) { 140@function easing-gradient($type, $dir, $stop, $stops...) {
138 $pos-template: null; 141 $pos-template: null;
139 $stops: functions.list-prepend($stops, $stop); 142 $stops: functions.list-prepend($stops, $stop);
140 143
141 $last-positioned-stop: 1; 144 $last-positioned-stop: 1;
142 $generated-stops: (); 145 $generated-stops: ();
143 146
144 // 147 //
145 // Generate gradient 148 // Generate gradient
146 // 149 //
147 150
148 @for $i from 1 through length($stops) { 151 @for $i from 1 through list.length($stops) {
149 $stop: nth($stops, $i); 152 $stop: list.nth($stops, $i);
150 153
151 @if $i == 1 { 154 @if $i == 1 {
152 @if not easing-gradient-is-color-stop($stop) { 155 @if not easing-gradient-is-color-stop($stop) {
153 @error 'The first color stop argument must be a color stop.'; 156 @error 'The first color stop argument must be a color stop.';
154 } 157 }
155 158
156 @if type-of($stop) == color { 159 @if meta.type-of($stop) == color {
157 // 160 //
158 // The first color stop is unpositioned. The default position for the first 161 // The first color stop is unpositioned. The default position for the first
159 // color stop is 0, which is explicitly added for easier calculations. 162 // color stop is 0, which is explicitly added for easier calculations.
160 // 163 //
161 164
162 $stop: $stop 0; 165 $stop: $stop 0;
163 $stops: set-nth($stops, $i, $stop); 166 $stops: list.set-nth($stops, $i, $stop);
164 } 167 }
165 168
166 $generated-stops: append($generated-stops, functions.str-implode($stop, ' ')); 169 $generated-stops: list.append($generated-stops, functions.str-implode($stop, ' '));
167 } @else if easing-gradient-is-positioned-color-stop($stop) or ($i == length($stops)) { 170 } @else if easing-gradient-is-positioned-color-stop($stop) or ($i == list.length($stops)) {
168 @if not easing-gradient-is-color-stop($stop) { 171 @if not easing-gradient-is-color-stop($stop) {
169 @error 'The last color stop argument must be a color stop.'; 172 @error 'The last color stop argument must be a color stop.';
170 } 173 }
171 174
172 // 175 //
173 // Either the current stops list item is a positioned color stop, or the end of 176 // Either the current stops list item is a positioned color stop, or the end of
174 // the stops list has been reached. 177 // the stops list has been reached.
175 // 178 //
176 179
177 @if (type-of($stop) == color) and ($i == length($stops)) { 180 @if (meta.type-of($stop) == color) and ($i == list.length($stops)) {
178 // 181 //
179 // The current stop is an unpositioned color stop, which means this is the end 182 // The current stop is an unpositioned color stop, which means this is the end
180 // of the stops list. The default position for the last color stop is 100%, which 183 // of the stops list. The default position for the last color stop is 100%, which
181 // is explicitly added for easier calculations. 184 // is explicitly added for easier calculations.
182 // 185 //
183 186
184 $stop: $stop 100%; 187 $stop: $stop 100%;
185 $stops: set-nth($stops, $i, $stop); 188 $stops: list.set-nth($stops, $i, $stop);
186 } 189 }
187 190
188 // 191 //
189 // Now the current color stop is guaranteed to be a positioned color stop. 192 // Now the current color stop is guaranteed to be a positioned color stop.
190 // 193 //
191 194
192 @if $i > $last-positioned-stop + 1 { 195 @if $i > $last-positioned-stop + 1 {
193 // 196 //
194 // There is at least one stops list item (unpositioned color stop or easing function) 197 // There is at least one stops list item (unpositioned color stop or easing function)
195 // between the last positioned color stop and the current stops list item. Interpolate 198 // between the last positioned color stop and the current stops list item. Interpolate
196 // the positions of all stops list items that are color stops. 199 // the positions of all stops list items that are color stops.
197 // 200 //
198 201
199 $interpolated-stops: easing-gradient-interpolate-stop-positions( 202 $interpolated-stops: easing-gradient-interpolate-stop-positions(list.nth($stops, $last-positioned-stop),
200 nth($stops, $last-positioned-stop), 203 functions.list-slice($stops, $last-positioned-stop + 1, $i - 1),
201 functions.list-slice($stops, $last-positioned-stop + 1, $i - 1), 204 $stop);
202 $stop
203 );
204 205
205 $new-stops: join( 206 $new-stops: list.join(functions.list-slice($stops, 1, $last-positioned-stop),
206 functions.list-slice($stops, 1, $last-positioned-stop), 207 $interpolated-stops);
207 $interpolated-stops 208 $new-stops: list.join($new-stops,
208 ); 209 functions.list-slice($stops, $i));
209 $new-stops: join( 210 $stops: $new-stops;
210 $new-stops, 211 }
211 functions.list-slice($stops, $i)
212 );
213 $stops: $new-stops;
214 }
215 212
216 // 213 //
217 // Now all color stops between this one and the last positioned one have 214 // Now all color stops between this one and the last positioned one have
218 // interpolated positions. 215 // interpolated positions.
219 // Next task is to perform an easing transition between all color stops that 216 // Next task is to perform an easing transition between all color stops that
220 // have an easing function specified. The rest can be left alone since the 217 // have an easing function specified. The rest can be left alone since the
221 // browser will automatically apply a linear transition between them. 218 // browser will automatically apply a linear transition between them.
222 // 219 //
223 220
224 $j: $last-positioned-stop + 1; 221 $j: $last-positioned-stop + 1;
225 @while $j <= $i { 222 @while $j <= $i {
226 $easing: null; 223 $easing: null;
227 $prev-stop: nth($stops, $j - 1); 224 $prev-stop: list.nth($stops, $j - 1);
228 $next-stop: nth($stops, $j); 225 $next-stop: list.nth($stops, $j);
229 226
230 @if not easing-gradient-is-color-stop($next-stop) { 227 @if not easing-gradient-is-color-stop($next-stop) {
231 $j: $j + 1; 228 $j: $j + 1;
232 229
233 $easing: $next-stop; 230 $easing: $next-stop;
234 $next-stop: nth($stops, $j); 231 $next-stop: list.nth($stops, $j);
235 232
236 @if not easing-gradient-is-color-stop($next-stop) { 233 @if not easing-gradient-is-color-stop($next-stop) {
237 @error 'There can be at most one interpolation hint between to color stops.'; 234 @error 'There can be at most one interpolation hint between to color stops.';
238 } 235 }
239 } 236 }
240 237
241 @if $easing != null { 238 @if $easing != null {
242 @if type-of($easing) == number { 239 @if meta.type-of($easing) == number {
243 @error 'Midpoint shifts are not supported.'; 240 @error 'Midpoint shifts are not supported.';
244 } 241 }
245 242
246 $easing-func: null; 243 $easing-func: null;
247 $easing-args: (); 244 $easing-args: ();
248 245
249 @if type-of($easing) == list { 246 @if meta.type-of($easing) == list {
250 $easing-args: functions.list-slice($easing, 2); 247 $easing-args: functions.list-slice($easing, 2);
251 $easing: nth($easing, 1); 248 $easing: list.nth($easing, 1);
252 } 249 }
253 250
254 $generated-stops: join( 251 $generated-stops: list.join($generated-stops,
255 $generated-stops, 252 easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args));
256 easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args) 253 } @else {
257 ); 254 $generated-stops: list.append($generated-stops, functions.str-implode($next-stop, ' '));
258 } @else { 255 }
259 $generated-stops: append($generated-stops, functions.str-implode($next-stop, ' '));
260 }
261 256
262 $j: $j + 1; 257 $j: $j + 1;
263 } 258 }
264 259
265 $last-positioned-stop: $i; 260 $last-positioned-stop: $i;
266 } 261 }
267 } 262 }
268 263
269 @if $type == 'linear' { 264 @if $type == 'linear' {
270 @return linear-gradient($dir, unquote(functions.str-implode($generated-stops, ', '))); 265 @return linear-gradient($dir, string.unquote(functions.str-implode($generated-stops, ', ')));
271 } @else if $type == 'radial' { 266 } @else if $type == 'radial' {
272 @return radial-gradient($dir, unquote(functions.str-implode($generated-stops, ', '))); 267 @return radial-gradient($dir, string.unquote(functions.str-implode($generated-stops, ', ')));
273 } @else { 268 } @else {
274 @error 'Invalid gradient type: #{inspect($type)}.'; 269 @error 'Invalid gradient type: #{inspect($type)}.';
275 } 270 }
276} 271}
277 272
278/// 273///
@@ -281,7 +276,7 @@ $easing-gradient-steps: 10 !default;
281/// @see {function} easing-gradient 276/// @see {function} easing-gradient
282/// 277///
283@function easing-linear-gradient($dir, $stop, $stops...) { 278@function easing-linear-gradient($dir, $stop, $stops...) {
284 @return easing-gradient('linear', $dir, $stop, $stops...); 279 @return easing-gradient('linear', $dir, $stop, $stops...);
285} 280}
286 281
287/// 282///
@@ -290,7 +285,7 @@ $easing-gradient-steps: 10 !default;
290/// @see {function} easing-gradient 285/// @see {function} easing-gradient
291/// 286///
292@function easing-radial-gradient($dir, $stop, $stops...) { 287@function easing-radial-gradient($dir, $stop, $stops...) {
293 @return easing-gradient('radial', $dir, $stop, $stops...); 288 @return easing-gradient('radial', $dir, $stop, $stops...);
294} 289}
295 290
296/// 291///
@@ -299,24 +294,24 @@ $easing-gradient-steps: 10 !default;
299/// @access private 294/// @access private
300/// 295///
301@function easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args: ()) { 296@function easing-gradient-ease-stops($prev-stop, $next-stop, $easing, $easing-args: ()) {
302 @if $easing == 'steps' { 297 @if $easing == 'steps' {
303 $steps: null; 298 $steps: null;
304 $jump: null; 299 $jump: null;
305 300
306 @if length($easing-args) > 1 { 301 @if list.length($easing-args) > 1 {
307 $steps: nth($easing-args, 1); 302 $steps: list.nth($easing-args, 1);
308 $jump: nth($easing-args, 2); 303 $jump: list.nth($easing-args, 2);
309 } @else { 304 } @else {
310 $steps: nth($easing-args, 1); 305 $steps: list.nth($easing-args, 1);
311 $jump: jump-end; 306 $jump: jump-end;
312 } 307 }
313 308
314 @return easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump); 309 @return easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump);
315 } @else { 310 } @else {
316 $easing-func: get-function($easing, $module: easing); 311 $easing-func: meta.get-function($easing, $module: easing);
317 312
318 @return easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args); 313 @return easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args);
319 } 314 }
320} 315}
321 316
322/// 317///
@@ -325,74 +320,74 @@ $easing-gradient-steps: 10 !default;
325/// @access private 320/// @access private
326/// 321///
327@function easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args: ()) { 322@function easing-gradient-bezier-stops($prev-stop, $next-stop, $easing-func, $easing-args: ()) {
328 $prev-stop-color: nth($prev-stop, 1); 323 $prev-stop-color: list.nth($prev-stop, 1);
329 $prev-stop-pos: nth($prev-stop, 2); 324 $prev-stop-pos: list.nth($prev-stop, 2);
330 $next-stop-color: nth($next-stop, 1); 325 $next-stop-color: list.nth($next-stop, 1);
331 $next-stop-pos: nth($next-stop, 2); 326 $next-stop-pos: list.nth($next-stop, 2);
332 327
333 $stops: (); 328 $stops: ();
334 329
335 @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { 330 @if ((meta.type-of($prev-stop-pos) == number) and (meta.type-of($next-stop-pos) == number) and (math.unit($prev-stop-pos) == math.unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) {
336 // 331 //
337 // The transition color stop positions can be statically calculated. 332 // The transition color stop positions can be statically calculated.
338 // 333 //
339 334
340 $distance: $next-stop-pos - $prev-stop-pos; 335 $distance: $next-stop-pos - $prev-stop-pos;
341 336
342 @for $i from 1 through $easing-gradient-steps { 337 @for $i from 1 through $easing-gradient-steps {
343 $perc: math.div($i, $easing-gradient-steps); 338 $perc: math.div($i, $easing-gradient-steps);
344 339
345 $color: null; 340 $color: null;
346 $pos: $prev-stop-pos + $perc * $distance; 341 $pos: $prev-stop-pos + $perc * $distance;
347 @if $perc == 1 { 342 @if $perc == 1 {
348 $color: $next-stop-color; 343 $color: $next-stop-color;
349 } @else { 344 } @else {
350 $color: mix($next-stop-color, $prev-stop-color, call($easing-func, append($easing-args, $perc)...) * 100%); 345 $color: color.mix($next-stop-color, $prev-stop-color, meta.call($easing-func, list.append($easing-args, $perc)...) * 100%);
351 } 346 }
352 347
353 $stops: append($stops, $color + ' ' + $pos); 348 $stops: list.append($stops, $color + ' ' + $pos);
354 } 349 }
355 } @else { 350 } @else {
356 // 351 //
357 // The transition color stop positions have to be dynamically calculated with the calc() function. 352 // The transition color stop positions have to be dynamically calculated with the calc() function.
358 // 353 //
359 354
360 @if type-of($prev-stop-pos) != number { 355 @if meta.type-of($prev-stop-pos) != number {
361 // must be calc() 356 // must be calc()
362 @if type-of($prev-stop-pos) != calculation { 357 @if meta.type-of($prev-stop-pos) != calculation {
363 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; 358 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}';
364 } 359 }
365 360
366 $prev-stop-pos: meta.calc-args($prev-stop-pos); 361 $prev-stop-pos: meta.calc-args($prev-stop-pos);
367 } 362 }
368 363
369 @if type-of($next-stop-pos) != number { 364 @if meta.type-of($next-stop-pos) != number {
370 // must be calc() 365 // must be calc()
371 @if type-of($next-stop-pos) != calculation { 366 @if meta.type-of($next-stop-pos) != calculation {
372 @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; 367 @error 'Invalid color stop position: #{inspect($next-stop-pos)}';
373 } 368 }
374 369
375 $next-stop-pos: meta.calc-args($next-stop-pos); 370 $next-stop-pos: meta.calc-args($next-stop-pos);
376 } 371 }
377 372
378 @for $i from 1 through $easing-gradient-steps { 373 @for $i from 1 through $easing-gradient-steps {
379 $perc: math.div($i, $easing-gradient-steps); 374 $perc: math.div($i, $easing-gradient-steps);
380 375
381 $color: null; 376 $color: null;
382 $pos: null; 377 $pos: null;
383 @if $perc == 1 { 378 @if $perc == 1 {
384 $color: $next-stop-color; 379 $color: $next-stop-color;
385 $pos: calc(#{$next-stop-pos}); 380 $pos: calc(#{$next-stop-pos});
386 } @else { 381 } @else {
387 $color: mix($next-stop-color, $prev-stop-color, call($easing-func, append($easing-args, $perc)...) * 100%); 382 $color: color.mix($next-stop-color, $prev-stop-color, meta.call($easing-func, list.append($easing-args, $perc)...) * 100%);
388 $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc}); 383 $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc});
389 } 384 }
390 385
391 $stops: append($stops, $color + ' ' + $pos); 386 $stops: list.append($stops, $color + ' ' + $pos);
392 } 387 }
393 } 388 }
394 389
395 @return $stops; 390 @return $stops;
396} 391}
397 392
398/// 393///
@@ -401,110 +396,110 @@ $easing-gradient-steps: 10 !default;
401/// @access private 396/// @access private
402/// 397///
403@function easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump: jump-end) { 398@function easing-gradient-steps-stops($prev-stop, $next-stop, $steps, $jump: jump-end) {
404 $prev-stop-color: nth($prev-stop, 1); 399 $prev-stop-color: list.nth($prev-stop, 1);
405 $prev-stop-pos: nth($prev-stop, 2); 400 $prev-stop-pos: list.nth($prev-stop, 2);
406 $next-stop-color: nth($next-stop, 1); 401 $next-stop-color: list.nth($next-stop, 1);
407 $next-stop-pos: nth($next-stop, 2); 402 $next-stop-pos: list.nth($next-stop, 2);
408 403
409 $stops: (); 404 $stops: ();
410 405
411 @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { 406 @if ((meta.type-of($prev-stop-pos) == number) and (meta.type-of($next-stop-pos) == number) and (math.unit($prev-stop-pos) == math.unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) {
412 // 407 //
413 // The transition color stop positions can be statically calculated. 408 // The transition color stop positions can be statically calculated.
414 // 409 //
415 410
416 $distance: $next-stop-pos - $prev-stop-pos; 411 $distance: $next-stop-pos - $prev-stop-pos;
417 412
418 @for $i from 1 through $steps { 413 @for $i from 1 through $steps {
419 $x1: math.div($i - 1, $steps); 414 $xx1: math.div($i - 1, $steps);
420 $x2: math.div($i, $steps); 415 $xx2: math.div($i, $steps);
421 $y: null; 416 $y: null;
422 417
423 @if $jump == jump-start { 418 @if $jump == jump-start {
424 $y: math.div($i, $steps); 419 $y: math.div($i, $steps);
425 } @else if $jump == jump-end { 420 } @else if $jump == jump-end {
426 $y: math.div($i - 1, $steps); 421 $y: math.div($i - 1, $steps);
427 } @else if $jump == jump-both { 422 } @else if $jump == jump-both {
428 $y: math.div($i, $steps + 1); 423 $y: math.div($i, $steps + 1);
429 } @else if $jump == jump-none { 424 } @else if $jump == jump-none {
430 $y: math.div($i - 1, $steps - 1); 425 $y: math.div($i - 1, $steps - 1);
431 } @else { 426 } @else {
432 @error 'Invalid $jump: #{inspect($jump)}'; 427 @error 'Invalid $jump: #{inspect($jump)}';
433 } 428 }
434 429
435 $color: null; 430 $color: null;
436 $pos1: if($x1 == 0, $prev-stop-pos, $prev-stop-pos + $x1 * $distance); 431 $pos1: if($xx1 == 0, $prev-stop-pos, $prev-stop-pos + $xx1 * $distance);
437 $pos2: if($x2 == 1, $next-stop-pos, $prev-stop-pos + $x2 * $distance); 432 $pos2: if($xx2 == 1, $next-stop-pos, $prev-stop-pos + $xx2 * $distance);
438 433
439 @if $y == 0 { 434 @if $y == 0 {
440 $color: $prev-stop-color; 435 $color: $prev-stop-color;
441 } @else if $y == 1 { 436 } @else if $y == 1 {
442 $color: $next-stop-color; 437 $color: $next-stop-color;
443 } @else { 438 } @else {
444 $color: mix($next-stop-color, $prev-stop-color, $y * 100%); 439 $color: color.mix($next-stop-color, $prev-stop-color, $y * 100%);
445 } 440 }
446 441
447 $stops: append($stops, $color + ' ' + $pos1); 442 $stops: list.append($stops, $color + ' ' + $pos1);
448 $stops: append($stops, $color + ' ' + $pos2); 443 $stops: list.append($stops, $color + ' ' + $pos2);
449 } 444 }
450 } @else { 445 } @else {
451 // 446 //
452 // The transition color stop positions have to be dynamically calculated with the calc() function. 447 // The transition color stop positions have to be dynamically calculated with the calc() function.
453 // 448 //
454 449
455 @if type-of($prev-stop-pos) != number { 450 @if meta.type-of($prev-stop-pos) != number {
456 // must be calc() 451 // must be calc()
457 @if type-of($prev-stop-pos) != calculation { 452 @if meta.type-of($prev-stop-pos) != calculation {
458 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; 453 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}';
459 } 454 }
460 455
461 $prev-stop-pos: meta.calc-args($prev-stop-pos); 456 $prev-stop-pos: meta.calc-args($prev-stop-pos);
462 } 457 }
463 458
464 @if type-of($next-stop-pos) != number { 459 @if meta.type-of($next-stop-pos) != number {
465 // must be calc() 460 // must be calc()
466 @if type-of($next-stop-pos) != calculation { 461 @if meta.type-of($next-stop-pos) != calculation {
467 @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; 462 @error 'Invalid color stop position: #{inspect($next-stop-pos)}';
468 } 463 }
469 464
470 $next-stop-pos: meta.calc-args($next-stop-pos); 465 $next-stop-pos: meta.calc-args($next-stop-pos);
471 } 466 }
472 467
473 @for $i from 1 through $steps { 468 @for $i from 1 through $steps {
474 $x1: math.div($i - 1, $steps); 469 $xx1: math.div($i - 1, $steps);
475 $x2: math.div($i, $steps); 470 $xx2: math.div($i, $steps);
476 $y: null; 471 $y: null;
477 472
478 @if $jump == jump-start { 473 @if $jump == jump-start {
479 $y: math.div($i, $steps); 474 $y: math.div($i, $steps);
480 } @else if $jump == jump-end { 475 } @else if $jump == jump-end {
481 $y: math.div($i - 1, $steps); 476 $y: math.div($i - 1, $steps);
482 } @else if $jump == jump-both { 477 } @else if $jump == jump-both {
483 $y: math.div($i, $steps + 1); 478 $y: math.div($i, $steps + 1);
484 } @else if $jump == jump-none { 479 } @else if $jump == jump-none {
485 $y: math.div($i - 1, $steps - 1); 480 $y: math.div($i - 1, $steps - 1);
486 } @else { 481 } @else {
487 @error 'Invalid $jump: #{inspect($jump)}'; 482 @error 'Invalid $jump: #{inspect($jump)}';
488 } 483 }
489 484
490 $color: null; 485 $color: null;
491 $pos1: if($x1 == 0, $prev-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$x1})); 486 $pos1: if($xx1 == 0, $prev-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$xx1}));
492 $pos2: if($x2 == 1, $next-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$x2})); 487 $pos2: if($xx2 == 1, $next-stop-pos, calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$xx2}));
493 488
494 @if $y == 0 { 489 @if $y == 0 {
495 $color: $prev-stop-color; 490 $color: $prev-stop-color;
496 } @else if $y == 1 { 491 } @else if $y == 1 {
497 $color: $next-stop-color; 492 $color: $next-stop-color;
498 } @else { 493 } @else {
499 $color: mix($next-stop-color, $prev-stop-color, $y * 100%); 494 $color: color.mix($next-stop-color, $prev-stop-color, $y * 100%);
500 } 495 }
501 496
502 $stops: append($stops, $color + ' ' + $pos1); 497 $stops: list.append($stops, $color + ' ' + $pos1);
503 $stops: append($stops, $color + ' ' + $pos2); 498 $stops: list.append($stops, $color + ' ' + $pos2);
504 } 499 }
505 } 500 }
506 501
507 @return $stops; 502 @return $stops;
508} 503}
509 504
510/// 505///
@@ -513,72 +508,72 @@ $easing-gradient-steps: 10 !default;
513/// @access private 508/// @access private
514/// 509///
515@function easing-gradient-interpolate-stop-positions($prev-stop, $stops, $next-stop) { 510@function easing-gradient-interpolate-stop-positions($prev-stop, $stops, $next-stop) {
516 $prev-stop-pos: nth($prev-stop, 2); 511 $prev-stop-pos: list.nth($prev-stop, 2);
517 $next-stop-pos: nth($next-stop, 2); 512 $next-stop-pos: list.nth($next-stop, 2);
518 513
519 $stops-num: 0; 514 $stops-num: 0;
520 @for $i from 1 through length($stops) { 515 @for $i from 1 through list.length($stops) {
521 $stop: nth($stops, $i); 516 $stop: list.nth($stops, $i);
522 @if easing-gradient-is-color-stop($stop) { 517 @if easing-gradient-is-color-stop($stop) {
523 $stops-num: $stops-num + 1; 518 $stops-num: $stops-num + 1;
524 } 519 }
525 } 520 }
526 521
527 $i: 1; 522 $i: 1;
528 $cur-stop-num: 1; 523 $cur-stop-num: 1;
529 524
530 @if ((type-of($prev-stop-pos) == number) and (type-of($next-stop-pos) == number) and (unit($prev-stop-pos) == unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) { 525 @if ((meta.type-of($prev-stop-pos) == number) and (meta.type-of($next-stop-pos) == number) and (math.unit($prev-stop-pos) == math.unit($next-stop-pos))) or ($prev-stop-pos == 0) or ($next-stop-pos == 0) {
531 // 526 //
532 // The color stop positions can be statically calculated. 527 // The color stop positions can be statically calculated.
533 // 528 //
534 529
535 $distance: $next-stop-pos - $prev-stop-pos; 530 $distance: $next-stop-pos - $prev-stop-pos;
536 531
537 @for $i from 1 through length($stops) { 532 @for $i from 1 through list.length($stops) {
538 $stop: nth($stops, $i); 533 $stop: list.nth($stops, $i);
539 @if easing-gradient-is-color-stop($stop) { 534 @if easing-gradient-is-color-stop($stop) {
540 $pos: $prev-stop-pos + math.div($distance, $stops-num + 1) * $cur-stop-num; 535 $pos: $prev-stop-pos + math.div($distance, $stops-num + 1) * $cur-stop-num;
541 $stops: set-nth($stops, $i, $stop $pos); 536 $stops: list.set-nth($stops, $i, $stop $pos);
542 537
543 $cur-stop-num: $cur-stop-num + 1; 538 $cur-stop-num: $cur-stop-num + 1;
544 } 539 }
545 } 540 }
546 } @else { 541 } @else {
547 // 542 //
548 // The color stop positions have to be dynamically calculated with the calc() function. 543 // The color stop positions have to be dynamically calculated with the calc() function.
549 // 544 //
550 545
551 @if type-of($prev-stop-pos) != number { 546 @if meta.type-of($prev-stop-pos) != number {
552 // must be calc() 547 // must be calc()
553 @if type-of($prev-stop-pos) != calculation { 548 @if meta.type-of($prev-stop-pos) != calculation {
554 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}'; 549 @error 'Invalid color stop position: #{inspect($prev-stop-pos)}';
555 } 550 }
556 551
557 $prev-stop-pos: meta.calc-args($prev-stop-pos); 552 $prev-stop-pos: meta.calc-args($prev-stop-pos);
558 } 553 }
559 554
560 @if type-of($next-stop-pos) != number { 555 @if meta.type-of($next-stop-pos) != number {
561 // must be calc() 556 // must be calc()
562 @if type-of($next-stop-pos) != calculation { 557 @if meta.type-of($next-stop-pos) != calculation {
563 @error 'Invalid color stop position: #{inspect($next-stop-pos)}'; 558 @error 'Invalid color stop position: #{inspect($next-stop-pos)}';
564 } 559 }
565 560
566 $next-stop-pos: meta.calc-args($next-stop-pos); 561 $next-stop-pos: meta.calc-args($next-stop-pos);
567 } 562 }
568 563
569 @for $i from 1 through length($stops) { 564 @for $i from 1 through list.length($stops) {
570 $stop: nth($stops, $i); 565 $stop: list.nth($stops, $i);
571 @if easing-gradient-is-color-stop($stop) { 566 @if easing-gradient-is-color-stop($stop) {
572 $perc: math.div($cur-stop-num, $stops-num + 1); 567 $perc: math.div($cur-stop-num, $stops-num + 1);
573 $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc}); 568 $pos: calc(#{$prev-stop-pos} + (#{$next-stop-pos} - #{$prev-stop-pos}) * #{$perc});
574 $stops: set-nth($stops, $i, $stop $pos); 569 $stops: list.set-nth($stops, $i, $stop $pos);
575 570
576 $cur-stop-num: $cur-stop-num + 1; 571 $cur-stop-num: $cur-stop-num + 1;
577 } 572 }
578 } 573 }
579 } 574 }
580 575
581 @return $stops; 576 @return $stops;
582} 577}
583 578
584/// 579///
@@ -587,7 +582,7 @@ $easing-gradient-steps: 10 !default;
587/// @access private 582/// @access private
588/// 583///
589@function easing-gradient-is-color-stop($input) { 584@function easing-gradient-is-color-stop($input) {
590 @return (type-of($input) == color) or easing-gradient-is-positioned-color-stop($input); 585 @return (meta.type-of($input) == color) or easing-gradient-is-positioned-color-stop($input);
591} 586}
592 587
593/// 588///
@@ -596,5 +591,5 @@ $easing-gradient-steps: 10 !default;
596/// @access private 591/// @access private
597/// 592///
598@function easing-gradient-is-positioned-color-stop($input) { 593@function easing-gradient-is-positioned-color-stop($input) {
599 @return (type-of($input) == list) and (type-of(nth($input, 1)) == color); 594 @return (meta.type-of($input) == list) and (meta.type-of(list.nth($input, 1)) == color);
600} 595}
diff --git a/src/_harmony.scss b/src/_harmony.scss
index aaab726..c0cb772 100644
--- a/src/_harmony.scss
+++ b/src/_harmony.scss
@@ -8,7 +8,10 @@
8/// @access public 8/// @access public
9//// 9////
10 10
11@use 'sass:list';
12@use 'sass:map';
11@use 'sass:math'; 13@use 'sass:math';
14@use 'sass:meta';
12@use './functions'; 15@use './functions';
13@use './responsive'; 16@use './responsive';
14 17
@@ -26,35 +29,35 @@
26/// @return {number} 29/// @return {number}
27/// 30///
28@function modular-scale($times, $base, $ratio) { 31@function modular-scale($times, $base, $ratio) {
29 @if type-of($base) == number { 32 @if meta.type-of($base) == number {
30 @return $base * math.pow($ratio, $times); 33 @return $base * math.pow($ratio, $times);
31 } 34 }
32 35
33 $main-base: nth($base, 1); 36 $main-base: list.nth($base, 1);
34 $norm-bases: (); 37 $norm-bases: ();
35 38
36 @each $b in functions.list-slice($base, 2) { 39 @each $b in functions.list-slice($base, 2) {
37 @if $b > $main-base { 40 @if $b > $main-base {
38 @while $b > $main-base { 41 @while $b > $main-base {
39 $b: math.div($b, $ratio); 42 $b: math.div($b, $ratio);
40 } 43 }
41 $b: $b * $ratio; 44 $b: $b * $ratio;
42 } @else if $b < $main-base { 45 } @else if $b < $main-base {
43 @while $b < $main-base { 46 @while $b < $main-base {
44 $b: $b * $ratio; 47 $b: $b * $ratio;
45 } 48 }
46 } 49 }
47 50
48 $norm-bases: append($norm-bases, $b); 51 $norm-bases: list.append($norm-bases, $b);
49 } 52 }
50 53
51 $all-bases: append($norm-bases, $main-base); 54 $all-bases: list.append($norm-bases, $main-base);
52 $all-bases: functions.quicksort($all-bases); 55 $all-bases: functions.quicksort($all-bases);
53 56
54 $base-index: $times % length($all-bases) + 1; 57 $base-index: $times % list.length($all-bases) + 1;
55 $exp: math.floor(math.div($times, length($all-bases))); 58 $exp: math.floor(math.div($times, list.length($all-bases)));
56 59
57 @return nth($all-bases, $base-index) * math.pow($ratio, $exp); 60 @return list.nth($all-bases, $base-index) * math.pow($ratio, $exp);
58} 61}
59 62
60/// 63///
@@ -86,15 +89,13 @@
86/// } 89/// }
87/// 90///
88@mixin responsive-modular-scale($props, $times, $responsive-map, $fluid: true) { 91@mixin responsive-modular-scale($props, $times, $responsive-map, $fluid: true) {
89 $new-map: (); 92 $new-map: ();
90 93
91 @each $key, $value in $responsive-map { 94 @each $key, $value in $responsive-map {
92 $new-map: map-merge( 95 $new-map: map.merge($new-map, (
93 $new-map, ( 96 $key: modular-scale($times, $value...)
94 $key: modular-scale($times, $value...) 97 ));
95 ) 98 }
96 );
97 }
98 99
99 @include responsive.property($props, $new-map, $fluid); 100 @include responsive.property($props, $new-map, $fluid);
100} 101}
diff --git a/src/_props.scss b/src/_props.scss
index 300fc28..17e9de7 100644
--- a/src/_props.scss
+++ b/src/_props.scss
@@ -3,137 +3,137 @@
3@use 'sass:meta'; 3@use 'sass:meta';
4 4
5@function is-prop-ref($value) { 5@function is-prop-ref($value) {
6 @if meta.type-of($value) != 'list' { 6 @if meta.type-of($value) != 'list' {
7 @return false; 7 @return false;
8 } 8 }
9 @if list.length($value) != 4 { 9 @if list.length($value) != 4 {
10 @return false; 10 @return false;
11 } 11 }
12 @if list.nth($value, 1) != 'prop-ref' { 12 @if list.nth($value, 1) != 'prop-ref' {
13 @return false; 13 @return false;
14 } 14 }
15 @return true; 15 @return true;
16} 16}
17 17
18@function def($name, $value: (), $metadata: ()) { 18@function def($name, $value: (), $metadata: ()) {
19 @return ('prop-ref' $name $value $metadata); 19 @return ('prop-ref' $name $value $metadata);
20} 20}
21 21
22@function merge($ref, $value) { 22@function merge($ref, $value) {
23 @if not is-prop-ref($ref) { 23 @if not is-prop-ref($ref) {
24 @return $ref; 24 @return $ref;
25 } 25 }
26 26
27 $v: list.nth($ref, 3); 27 $v: list.nth($ref, 3);
28 $ref: list.set-nth($ref, 3, map.deep-merge($v, $value)); 28 $ref: list.set-nth($ref, 3, map.deep-merge($v, $value));
29 @return $ref; 29 @return $ref;
30} 30}
31 31
32@function get-deep($name, $value, $key: null, $keys...) { 32@function get-deep($name, $value, $key: null, $keys...) {
33 @if is-prop-ref($value) { 33 @if is-prop-ref($value) {
34 @return get($value, $key, $keys); 34 @return get($value, $key, $keys);
35 } 35 }
36 @if meta.type-of($value) == 'map' and $key != null { 36 @if meta.type-of($value) == 'map' and $key != null {
37 @if meta.type-of($key) != 'string' { 37 @if meta.type-of($key) != 'string' {
38 @error 'Expected string, got #{$key}'; 38 @error 'Expected string, got #{$key}';
39 } 39 }
40 @return get-deep(#{$name}#{$key}, map.get($value, $key), $keys...); 40 @return get-deep(#{$name}#{$key}, map.get($value, $key), $keys...);
41 } 41 }
42 @return $name $value; 42 @return $name $value;
43} 43}
44 44
45@function map-to-vars($name, $map) { 45@function map-to-vars($name, $map) {
46 @if meta.type-of($map) != 'map' { 46 @if meta.type-of($map) != 'map' {
47 @if meta.type-of($name) != 'string' { 47 @if meta.type-of($name) != 'string' {
48 @error 'Expected variable name, got #{$name} instead'; 48 @error 'Expected variable name, got #{$name} instead';
49 } 49 }
50 @return var($name); 50 @return var($name);
51 } 51 }
52 52
53 $out: (); 53 $out: ();
54 54
55 @each $key, $value in $map { 55 @each $key, $value in $map {
56 $out: map.set($out, $key, map-to-vars(#{$name}#{$key}, $value)); 56 $out: map.set($out, $key, map-to-vars(#{$name}#{$key}, $value));
57 } 57 }
58 58
59 @return $out; 59 @return $out;
60} 60}
61 61
62@function get($ref, $key: null, $keys...) { 62@function get($ref, $key: null, $keys...) {
63 @if not is-prop-ref($ref) { 63 @if not is-prop-ref($ref) {
64 @return $ref; 64 @return $ref;
65 } 65 }
66 66
67 $name: list.nth($ref, 2); 67 $name: list.nth($ref, 2);
68 $value: get(list.nth($ref, 3)); 68 $value: get(list.nth($ref, 3));
69 69
70 @if meta.type-of($value) == 'map' { 70 @if meta.type-of($value) == 'map' {
71 $res: get-deep($name, $value, $key, $keys...); 71 $res: get-deep($name, $value, $key, $keys...);
72 $name: list.nth($res, 1); 72 $name: list.nth($res, 1);
73 $value: list.nth($res, 2); 73 $value: list.nth($res, 2);
74 } @else if meta.type-of($value) == 'list' { 74 } @else if meta.type-of($value) == 'list' {
75 $i: 1; 75 $i: 1;
76 @each $item in $value { 76 @each $item in $value {
77 $value: list.set-nth($value, $i, get($item)); 77 $value: list.set-nth($value, $i, get($item));
78 $i: $i + 1; 78 $i: $i + 1;
79 } 79 }
80 } 80 }
81 81
82 @return map-to-vars($name, $value); 82 @return map-to-vars($name, $value);
83} 83}
84 84
85@mixin materialize-helper($name, $value) { 85@mixin materialize-helper($name, $value) {
86 @if meta.type-of($value) == 'map' { 86 @if meta.type-of($value) == 'map' {
87 @each $key, $value in $value { 87 @each $key, $value in $value {
88 @include materialize-helper(#{$name}#{$key}, $value); 88 @include materialize-helper(#{$name}#{$key}, $value);
89 } 89 }
90 } @else { 90 } @else {
91 #{$name}: #{$value}; 91 #{$name}: #{$value};
92 } 92 }
93} 93}
94 94
95@mixin materialize($ref, $match-meta: ()) { 95@mixin materialize($ref, $match-meta: ()) {
96 @if is-prop-ref($ref) { 96 @if is-prop-ref($ref) {
97 $name: list.nth($ref, 2); 97 $name: list.nth($ref, 2);
98 $value: get(list.nth($ref, 3)); 98 $value: get(list.nth($ref, 3));
99 $meta: get(list.nth($ref, 4)); 99 $meta: get(list.nth($ref, 4));
100 100
101 $match: true; 101 $match: true;
102 @if meta.type-of($match-meta) == 'list' { 102 @if meta.type-of($match-meta) == 'list' {
103 @each $item in $match-meta { 103 @each $item in $match-meta {
104 $match: $match and list.index($meta, $item) != null; 104 $match: $match and list.index($meta, $item) != null;
105 } 105 }
106 } @else if $match-meta == null and list.length($meta) == 0 { 106 } @else if $match-meta == null and list.length($meta) == 0 {
107 $match: true; 107 $match: true;
108 } @else { 108 } @else {
109 $match: list.index($meta, $match-meta) != null; 109 $match: list.index($meta, $match-meta) != null;
110 } 110 }
111 111
112 @if $match { 112 @if $match {
113 @include materialize-helper($name, $value); 113 @include materialize-helper($name, $value);
114 } 114 }
115 } @else if meta.type-of($ref) == 'list' { 115 } @else if meta.type-of($ref) == 'list' {
116 @each $r in $ref { 116 @each $r in $ref {
117 @if is-prop-ref($r) { 117 @if is-prop-ref($r) {
118 $name: list.nth($r, 2); 118 $name: list.nth($r, 2);
119 $value: get(list.nth($r, 3)); 119 $value: get(list.nth($r, 3));
120 $meta: get(list.nth($r, 4)); 120 $meta: get(list.nth($r, 4));
121 121
122 $match: true; 122 $match: true;
123 @if meta.type-of($match-meta) == 'list' { 123 @if meta.type-of($match-meta) == 'list' {
124 @each $item in $match-meta { 124 @each $item in $match-meta {
125 $match: $match and list.index($meta, $item) != null; 125 $match: $match and list.index($meta, $item) != null;
126 } 126 }
127 } @else if $match-meta == null and list.length($meta) == 0 { 127 } @else if $match-meta == null and list.length($meta) == 0 {
128 $match: true; 128 $match: true;
129 } @else { 129 } @else {
130 $match: list.index($meta, $match-meta) != null; 130 $match: list.index($meta, $match-meta) != null;
131 } 131 }
132 132
133 @if $match { 133 @if $match {
134 @include materialize-helper($name, $value); 134 @include materialize-helper($name, $value);
135 } 135 }
136 } 136 }
137 } 137 }
138 } 138 }
139} 139}
diff --git a/src/_responsive.scss b/src/_responsive.scss
index 4d98638..f613a6d 100644
--- a/src/_responsive.scss
+++ b/src/_responsive.scss
@@ -17,6 +17,11 @@
17/// @access public 17/// @access public
18//// 18////
19 19
20@use 'sass:list';
21@use 'sass:map';
22@use 'sass:math';
23@use 'sass:meta';
24@use 'sass:string';
20@use './functions'; 25@use './functions';
21@use './contexts'; 26@use './contexts';
22 27
@@ -99,15 +104,15 @@ $named-viewports: () !default;
99/// } 104/// }
100/// 105///
101@mixin property($props, $responsive-map, $fluid: true, $vertical: false) { 106@mixin property($props, $responsive-map, $fluid: true, $vertical: false) {
102 @include env(map-keys($responsive-map), $fluid, $vertical) { 107 @include env(map.keys($responsive-map), $fluid, $vertical) {
103 @if type-of($props) == list { 108 @if meta.type-of($props) == list {
104 @each $prop in $props { 109 @each $prop in $props {
105 #{$prop}: set(map-values($responsive-map)); 110 #{$prop}: set(map.values($responsive-map));
106 } 111 }
107 } @else { 112 } @else {
108 #{$props}: set(map-values($responsive-map)); 113 #{$props}: set(map.values($responsive-map));
109 } 114 }
110 } 115 }
111} 116}
112 117
113/// 118///
@@ -150,153 +155,153 @@ $named-viewports: () !default;
150/// } 155/// }
151/// 156///
152@mixin env($viewports, $fluid: true, $vertical: false) { 157@mixin env($viewports, $fluid: true, $vertical: false) {
153 @if length($viewports) <= 1 { 158 @if list.length($viewports) <= 1 {
154 @error '$viewports must contain at least two viewports.'; 159 @error '$viewports must contain at least two viewports.';
155 } 160 }
156 161
157 $new-viewports: (); 162 $new-viewports: ();
158 163
159 @each $viewport in $viewports { 164 @each $viewport in $viewports {
160 @if map-has-key($named-viewports, $viewport) { 165 @if map.has-key($named-viewports, $viewport) {
161 $viewport: map-get($named-viewports, $viewport); 166 $viewport: map.get($named-viewports, $viewport);
162 } 167 }
163 168
164 @if (type-of($viewport) != number) or unitless($viewport) { 169 @if (meta.type-of($viewport) != number) or math.is-unitless($viewport) {
165 @error '$viewports contains invalid viewports.'; 170 @error '$viewports contains invalid viewports.';
166 } 171 }
167 172
168 $new-viewports: append($new-viewports, $viewport); 173 $new-viewports: list.append($new-viewports, $viewport);
169 } 174 }
170 175
171 $viewports: functions.quicksort($new-viewports); 176 $viewports: functions.quicksort($new-viewports);
172 177
173 @if $new-viewports != $viewports { 178 @if $new-viewports != $viewports {
174 @error '$viewports was not sorted in ascending order.'; 179 @error '$viewports was not sorted in ascending order.';
175 } 180 }
176 181
177 @if $fluid { 182 @if $fluid {
178 $first-vp: nth($viewports, 1); 183 $first-vp: list.nth($viewports, 1);
179 $last-vp: nth($viewports, length($viewports)); 184 $last-vp: list.nth($viewports, list.length($viewports));
180 185
181 @include contexts.push($context-id, 'env', ( 186 @include contexts.push($context-id, 'env', (
182 'viewports': $viewports, 187 'viewports': $viewports,
183 'mode': set, 188 'mode': set,
184 'index': 1, 189 'index': 1,
185 'fluid': $fluid, 190 'fluid': $fluid,
186 'vertical': $vertical, 191 'vertical': $vertical,
187 )); 192 ));
188 193
189 @content; 194 @content;
190 195
191 @include contexts.pop($context-id); 196 @include contexts.pop($context-id);
192 197
193 @for $i from 1 to length($viewports) { 198 @for $i from 1 to list.length($viewports) {
194 $prev-vp: nth($viewports, $i); 199 $prev-vp: list.nth($viewports, $i);
195 $next-vp: nth($viewports, $i + 1); 200 $next-vp: list.nth($viewports, $i + 1);
196 201
197 @if not $vertical { 202 @if not $vertical {
198 @media (min-width: $prev-vp) and (max-width: $next-vp) { 203 @media (min-width: $prev-vp) and (max-width: $next-vp) {
199 @include contexts.push($context-id, 'env', ( 204 @include contexts.push($context-id, 'env', (
200 'viewports': $viewports, 205 'viewports': $viewports,
201 'mode': transition, 206 'mode': transition,
202 'index': $i, 207 'index': $i,
203 'fluid': $fluid, 208 'fluid': $fluid,
204 'vertical': $vertical, 209 'vertical': $vertical,
205 )); 210 ));
206 211
207 @content; 212 @content;
208 213
209 @include contexts.pop($context-id); 214 @include contexts.pop($context-id);
210 } 215 }
211 } @else { 216 } @else {
212 @media (min-height: $prev-vp) and (max-height: $next-vp) { 217 @media (min-height: $prev-vp) and (max-height: $next-vp) {
213 @include contexts.push($context-id, 'env', ( 218 @include contexts.push($context-id, 'env', (
214 'viewports': $viewports, 219 'viewports': $viewports,
215 'mode': transition, 220 'mode': transition,
216 'index': $i, 221 'index': $i,
217 'fluid': $fluid, 222 'fluid': $fluid,
218 'vertical': $vertical, 223 'vertical': $vertical,
219 )); 224 ));
220 225
221 @content; 226 @content;
222 227
223 @include contexts.pop($context-id); 228 @include contexts.pop($context-id);
224 } 229 }
225 } 230 }
226 } 231 }
227 232
228 @if not $vertical { 233 @if not $vertical {
229 @media (min-width: $last-vp) { 234 @media (min-width: $last-vp) {
230 @include contexts.push($context-id, 'env', ( 235 @include contexts.push($context-id, 'env', (
231 'viewports': $viewports, 236 'viewports': $viewports,
232 'mode': set, 237 'mode': set,
233 'index': length($viewports), 238 'index': list.length($viewports),
234 'fluid': $fluid, 239 'fluid': $fluid,
235 'vertical': $vertical, 240 'vertical': $vertical,
236 )); 241 ));
237 242
238 @content; 243 @content;
239 244
240 @include contexts.pop($context-id); 245 @include contexts.pop($context-id);
241 } 246 }
242 } @else { 247 } @else {
243 @media (min-height: $last-vp) { 248 @media (min-height: $last-vp) {
244 @include contexts.push($context-id, 'env', ( 249 @include contexts.push($context-id, 'env', (
245 'viewports': $viewports, 250 'viewports': $viewports,
246 'mode': set, 251 'mode': set,
247 'index': length($viewports), 252 'index': list.length($viewports),
248 'fluid': $fluid, 253 'fluid': $fluid,
249 'vertical': $vertical, 254 'vertical': $vertical,
250 )); 255 ));
251 256
252 @content; 257 @content;
253 258
254 @include contexts.pop($context-id); 259 @include contexts.pop($context-id);
255 } 260 }
256 } 261 }
257 } @else { 262 } @else {
258 @include contexts.push($context-id, 'env', ( 263 @include contexts.push($context-id, 'env', (
259 'viewports': $viewports, 264 'viewports': $viewports,
260 'mode': set, 265 'mode': set,
261 'index': 1, 266 'index': 1,
262 'fluid': $fluid, 267 'fluid': $fluid,
263 'vertical': $vertical, 268 'vertical': $vertical,
264 )); 269 ));
265 270
266 @content; 271 @content;
267 272
268 @include contexts.pop($context-id); 273 @include contexts.pop($context-id);
269 274
270 @for $i from 2 through length($viewports) { 275 @for $i from 2 through list.length($viewports) {
271 $vp: nth($viewports, $i); 276 $vp: list.nth($viewports, $i);
272 277
273 @if not $vertical { 278 @if not $vertical {
274 @media (min-width: $vp) { 279 @media (min-width: $vp) {
275 @include contexts.push($context-id, 'env', ( 280 @include contexts.push($context-id, 'env', (
276 'viewports': $viewports, 281 'viewports': $viewports,
277 'mode': set, 282 'mode': set,
278 'index': $i 283 'index': $i
279 )); 284 ));
280 285
281 @content; 286 @content;
282 287
283 @include contexts.pop($context-id); 288 @include contexts.pop($context-id);
284 } 289 }
285 } @else { 290 } @else {
286 @media (min-height: $vp) { 291 @media (min-height: $vp) {
287 @include contexts.push($context-id, 'env', ( 292 @include contexts.push($context-id, 'env', (
288 'viewports': $viewports, 293 'viewports': $viewports,
289 'mode': set, 294 'mode': set,
290 'index': $i 295 'index': $i
291 )); 296 ));
292 297
293 @content; 298 @content;
294 299
295 @include contexts.pop($context-id); 300 @include contexts.pop($context-id);
296 } 301 }
297 } 302 }
298 } 303 }
299 } 304 }
300} 305}
301 306
302/// 307///
@@ -307,29 +312,29 @@ $named-viewports: () !default;
307/// @return {number|string} 312/// @return {number|string}
308/// 313///
309@function set($values, $without-calc: false) { 314@function set($values, $without-calc: false) {
310 $noop: contexts.assert-stack-must-contain($context-id, 'env'); 315 $noop: contexts.assert-stack-must-contain($context-id, 'env');
311 316
312 $data: nth(contexts.get($context-id, 'env'), 2); 317 $data: list.nth(contexts.get($context-id, 'env'), 2);
313 $viewports: map-get($data, 'viewports'); 318 $viewports: map.get($data, 'viewports');
314 $mode: map-get($data, 'mode'); 319 $mode: map.get($data, 'mode');
315 $fluid: map-get($data, 'fluid'); 320 $fluid: map.get($data, 'fluid');
316 $vertical: map-get($data, 'vertical'); 321 $vertical: map.get($data, 'vertical');
317 322
318 @if length($values) != length($viewports) { 323 @if list.length($values) != list.length($viewports) {
319 @error '$values must contain the same number of items as the responsive environment\'s $viewports.'; 324 @error '$values must contain the same number of items as the responsive environment\'s $viewports.';
320 } 325 }
321 326
322 @if $mode == set { 327 @if $mode == set {
323 @return nth($values, map-get($data, 'index')); 328 @return list.nth($values, map.get($data, 'index'));
324 } @else { 329 } @else {
325 $index: map-get($data, 'index'); 330 $index: map.get($data, 'index');
326 $prev-vp: nth($viewports, $index); 331 $prev-vp: list.nth($viewports, $index);
327 $next-vp: nth($viewports, $index + 1); 332 $next-vp: list.nth($viewports, $index + 1);
328 $prev-value: nth($values, $index); 333 $prev-value: list.nth($values, $index);
329 $next-value: nth($values, $index + 1); 334 $next-value: list.nth($values, $index + 1);
330 335
331 @return fluid-calc($prev-value, $next-value, $prev-vp, $next-vp, $vertical, $without-calc); 336 @return fluid-calc($prev-value, $next-value, $prev-vp, $next-vp, $vertical, $without-calc);
332 } 337 }
333} 338}
334 339
335/// 340///
@@ -345,62 +350,62 @@ $named-viewports: () !default;
345/// @access private 350/// @access private
346/// 351///
347@function fluid-calc($min-value, $max-value, $min-viewport, $max-viewport, $vertical: false, $without-calc: false) { 352@function fluid-calc($min-value, $max-value, $min-viewport, $max-viewport, $vertical: false, $without-calc: false) {
348 $value-unit: unit($min-value); 353 $value-unit: math.unit($min-value);
349 $max-value-unit: unit($max-value); 354 $max-value-unit: math.unit($max-value);
350 $viewport-unit: unit($min-viewport); 355 $viewport-unit: math.unit($min-viewport);
351 $max-viewport-unit: unit($max-viewport); 356 $max-viewport-unit: math.unit($max-viewport);
352 357
353 @if $min-value == 0 { 358 @if $min-value == 0 {
354 $value-unit: $max-value-unit; 359 $value-unit: $max-value-unit;
355 } 360 }
356 @if $max-value == 0 { 361 @if $max-value == 0 {
357 $max-value-unit: $value-unit; 362 $max-value-unit: $value-unit;
358 } 363 }
359 @if $min-viewport == 0 { 364 @if $min-viewport == 0 {
360 $viewport-unit: $max-viewport-unit; 365 $viewport-unit: $max-viewport-unit;
361 } 366 }
362 @if $max-viewport == 0 { 367 @if $max-viewport == 0 {
363 $max-viewport-unit: $viewport-unit; 368 $max-viewport-unit: $viewport-unit;
364 } 369 }
365 370
366 @if ($value-unit != $max-value-unit) or ($viewport-unit != $max-viewport-unit) { 371 @if ($value-unit != $max-value-unit) or ($viewport-unit != $max-viewport-unit) {
367 @error 'Units of $min-value and $max-value, $min-viewport and $max-viewport must match.'; 372 @error 'Units of $min-value and $max-value, $min-viewport and $max-viewport must match.';
368 } 373 }
369 374
370 @if ($value-unit == rem) and ($viewport-unit == px) { 375 @if ($value-unit == rem) and ($viewport-unit == px) {
371 $min-viewport: functions.px-to-rem($min-viewport); 376 $min-viewport: functions.px-to-rem($min-viewport);
372 $max-viewport: functions.px-to-rem($max-viewport); 377 $max-viewport: functions.px-to-rem($max-viewport);
373 $viewport-unit: rem; 378 $viewport-unit: rem;
374 } @else if ($value-unit == px) and ($viewport-unit == rem) { 379 } @else if ($value-unit == px) and ($viewport-unit == rem) {
375 $min-value: functions.px-to-rem($min-value); 380 $min-value: functions.px-to-rem($min-value);
376 $max-value: functions.px-to-rem($max-value); 381 $max-value: functions.px-to-rem($max-value);
377 $value-unit: rem; 382 $value-unit: rem;
378 } 383 }
379 384
380 @if $value-unit != $viewport-unit { 385 @if $value-unit != $viewport-unit {
381 @error 'This combination of units is not supported.'; 386 @error 'This combination of units is not supported.';
382 } 387 }
383 388
384 $value-diff: functions.strip-unit($max-value - $min-value); 389 $value-diff: functions.strip-unit($max-value - $min-value);
385 $viewport-diff: functions.strip-unit($max-viewport - $min-viewport); 390 $viewport-diff: functions.strip-unit($max-viewport - $min-viewport);
386 391
387 $calc: ''; 392 $calc: '';
388 393
389 @if $min-value != 0 { 394 @if $min-value != 0 {
390 $calc: '#{$min-value} + '; 395 $calc: '#{$min-value} + ';
391 } 396 }
392 397
393 @if not $vertical { 398 @if not $vertical {
394 $calc: unquote('#{$calc}#{$value-diff} * (100vw - #{$min-viewport}) / #{$viewport-diff}'); 399 $calc: string.unquote('#{$calc}#{$value-diff} * (100vw - #{$min-viewport}) / #{$viewport-diff}');
395 } @else { 400 } @else {
396 $calc: unquote('#{$calc}#{$value-diff} * (100vh - #{$min-viewport}) / #{$viewport-diff}'); 401 $calc: string.unquote('#{$calc}#{$value-diff} * (100vh - #{$min-viewport}) / #{$viewport-diff}');
397 } 402 }
398 403
399 @if $without-calc { 404 @if $without-calc {
400 @return $calc; 405 @return $calc;
401 } @else { 406 } @else {
402 @return calc(#{$calc}); 407 @return calc(#{$calc});
403 } 408 }
404} 409}
405 410
406@include contexts.create($context-id); 411@include contexts.create($context-id);
diff --git a/src/bem/_block.scss b/src/bem/_block.scss
index cfa9f33..a4b2a47 100644
--- a/src/bem/_block.scss
+++ b/src/bem/_block.scss
@@ -4,6 +4,10 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:meta';
10@use 'sass:selector';
7@use './validators'; 11@use './validators';
8@use './vars'; 12@use './vars';
9@use './functions' as bemfunctions; 13@use './functions' as bemfunctions;
@@ -37,34 +41,34 @@
37/// } 41/// }
38/// 42///
39@mixin block($name, $type: null) { 43@mixin block($name, $type: null) {
40 $result: block($name, $type); 44 $result: block($name, $type);
41 $selector: nth($result, 1); 45 $selector: list.nth($result, 1);
42 $context: nth($result, 2); 46 $context: list.nth($result, 2);
43 47
44 @include validators.validate( 48 @include validators.validate(
45 'block', 49 'block',
46 (name: $name, type: $type), 50 (name: $name, type: $type),
47 $selector, 51 $selector,
48 $context 52 $context
49 ); 53 );
50 54
51 @if $type != null { 55 @if $type != null {
52 vars.$blocks: append(vars.$blocks, $name + '_' + $type); 56 vars.$blocks: list.append(vars.$blocks, $name + '_' + $type);
53 } @else { 57 } @else {
54 vars.$blocks: append(vars.$blocks, $name); 58 vars.$blocks: list.append(vars.$blocks, $name);
55 } 59 }
56 60
57 @include contexts.push(vars.$context-id, $context...); 61 @include contexts.push(vars.$context-id, $context...);
58 @at-root #{$selector} { 62 @at-root #{$selector} {
59 @if $type != null { 63 @if $type != null {
60 @layer #{$type} { 64 @layer #{$type} {
61 @content; 65 @content;
62 } 66 }
63 } @else { 67 } @else {
64 @content; 68 @content;
65 } 69 }
66 } 70 }
67 @include contexts.pop(vars.$context-id); 71 @include contexts.pop(vars.$context-id);
68} 72}
69 73
70/// 74///
@@ -75,47 +79,47 @@
75/// @see {mixin} block 79/// @see {mixin} block
76/// 80///
77@function block($name, $type: null) { 81@function block($name, $type: null) {
78 // 82 //
79 // Possible outcomes: 83 // Possible outcomes:
80 // - ({b,e,m,s}) block 84 // - ({b,e,m,s}) block
81 // 85 //
82 86
83 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 87 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
84 88
85 $selector: null; 89 $selector: null;
86 $base-selector: null; 90 $base-selector: null;
87 91
88 @if $type != null { 92 @if $type != null {
89 $namespace: map-get(vars.$namespaces, $type); 93 $namespace: map.get(vars.$namespaces, $type);
90 94
91 @if not $namespace { 95 @if not $namespace {
92 @error '"#{$type}" is not a valid type.'; 96 @error '"#{$type}" is not a valid type.';
93 } 97 }
94 98
95 $base-selector: selector-parse('.' + $namespace + '-' + $name); 99 $base-selector: selector.parse('.' + $namespace + '-' + $name);
96 100
97 @if $type != 'theme' or & { 101 @if $type != 'theme' or & {
98 $selector: $base-selector; 102 $selector: $base-selector;
99 } @else if not & { 103 } @else if not & {
100 $selector: bemfunctions.theme-selector($name); 104 $selector: bemfunctions.theme-selector($name);
101 } 105 }
102 } @else { 106 } @else {
103 $base-selector: selector-parse('.' + $name); 107 $base-selector: selector.parse('.' + $name);
104 $selector: $base-selector; 108 $selector: $base-selector;
105 } 109 }
106 110
107 @if & { 111 @if & {
108 $selector: selector-nest(&, $selector); 112 $selector: selector.nest(&, $selector);
109 } 113 }
110 114
111 $context: 'block', ( 115 $context: 'block', (
112 'name': $name, 116 'name': $name,
113 'type': $type, 117 'type': $type,
114 'selector': $selector, 118 'selector': $selector,
115 'base-selector': $base-selector 119 'base-selector': $base-selector
116 ); 120 );
117 121
118 @return $selector $context; 122 @return $selector $context;
119} 123}
120 124
121/// 125///
@@ -126,9 +130,9 @@
126/// @content 130/// @content
127/// 131///
128@mixin object($name) { 132@mixin object($name) {
129 @include block($name, 'object') { 133 @include block($name, 'object') {
130 @content; 134 @content;
131 } 135 }
132} 136}
133 137
134/// 138///
@@ -139,7 +143,7 @@
139/// @see {mixin} object 143/// @see {mixin} object
140/// 144///
141@function object($name) { 145@function object($name) {
142 @return block($name, 'object'); 146 @return block($name, 'object');
143} 147}
144 148
145/// 149///
@@ -150,9 +154,9 @@
150/// @content 154/// @content
151/// 155///
152@mixin component($name) { 156@mixin component($name) {
153 @include block($name, 'component') { 157 @include block($name, 'component') {
154 @content; 158 @content;
155 } 159 }
156} 160}
157 161
158/// 162///
@@ -163,7 +167,7 @@
163/// @see {mixin} component 167/// @see {mixin} component
164/// 168///
165@function component($name) { 169@function component($name) {
166 @return block($name, 'component'); 170 @return block($name, 'component');
167} 171}
168 172
169/// 173///
@@ -174,9 +178,9 @@
174/// @content 178/// @content
175/// 179///
176@mixin layout($name) { 180@mixin layout($name) {
177 @include block($name, 'layout') { 181 @include block($name, 'layout') {
178 @content; 182 @content;
179 } 183 }
180} 184}
181 185
182/// 186///
@@ -187,7 +191,7 @@
187/// @see {mixin} layout 191/// @see {mixin} layout
188/// 192///
189@function layout($name) { 193@function layout($name) {
190 @return block($name, 'layout'); 194 @return block($name, 'layout');
191} 195}
192 196
193/// 197///
@@ -198,9 +202,9 @@
198/// @content 202/// @content
199/// 203///
200@mixin utility($name) { 204@mixin utility($name) {
201 @include block($name, 'utility') { 205 @include block($name, 'utility') {
202 @content; 206 @content;
203 } 207 }
204} 208}
205 209
206/// 210///
@@ -211,7 +215,7 @@
211/// @see {mixin} utility 215/// @see {mixin} utility
212/// 216///
213@function utility($name) { 217@function utility($name) {
214 @return block($name, 'utility'); 218 @return block($name, 'utility');
215} 219}
216 220
217/// 221///
@@ -222,9 +226,9 @@
222/// @content 226/// @content
223/// 227///
224@mixin scope($name) { 228@mixin scope($name) {
225 @include block($name, 'scope') { 229 @include block($name, 'scope') {
226 @content; 230 @content;
227 } 231 }
228} 232}
229 233
230/// 234///
@@ -235,7 +239,7 @@
235/// @see {mixin} scope 239/// @see {mixin} scope
236/// 240///
237@function scope($name) { 241@function scope($name) {
238 @return block($name, 'scope'); 242 @return block($name, 'scope');
239} 243}
240 244
241/// 245///
@@ -246,9 +250,9 @@
246/// @content 250/// @content
247/// 251///
248@mixin theme($name) { 252@mixin theme($name) {
249 @include block($name, 'theme') { 253 @include block($name, 'theme') {
250 @content; 254 @content;
251 } 255 }
252} 256}
253 257
254/// 258///
@@ -259,7 +263,7 @@
259/// @see {mixin} theme 263/// @see {mixin} theme
260/// 264///
261@function theme($name) { 265@function theme($name) {
262 @return block($name, 'theme'); 266 @return block($name, 'theme');
263} 267}
264 268
265/// 269///
@@ -270,9 +274,9 @@
270/// @content 274/// @content
271/// 275///
272@mixin js($name) { 276@mixin js($name) {
273 @include block($name, 'js') { 277 @include block($name, 'js') {
274 @content; 278 @content;
275 } 279 }
276} 280}
277 281
278/// 282///
@@ -283,7 +287,7 @@
283/// @see {mixin} js 287/// @see {mixin} js
284/// 288///
285@function js($name) { 289@function js($name) {
286 @return block($name, 'js'); 290 @return block($name, 'js');
287} 291}
288 292
289/// 293///
@@ -294,9 +298,9 @@
294/// @content 298/// @content
295/// 299///
296@mixin qa($name) { 300@mixin qa($name) {
297 @include block($name, 'qa') { 301 @include block($name, 'qa') {
298 @content; 302 @content;
299 } 303 }
300} 304}
301 305
302/// 306///
@@ -307,7 +311,7 @@
307/// @see {mixin} qa 311/// @see {mixin} qa
308/// 312///
309@function qa($name) { 313@function qa($name) {
310 @return block($name, 'qa'); 314 @return block($name, 'qa');
311} 315}
312 316
313/// 317///
@@ -318,9 +322,9 @@
318/// @content 322/// @content
319/// 323///
320@mixin hack($name) { 324@mixin hack($name) {
321 @include block($name, 'hack') { 325 @include block($name, 'hack') {
322 @content; 326 @content;
323 } 327 }
324} 328}
325 329
326/// 330///
@@ -331,7 +335,7 @@
331/// @see {mixin} hack 335/// @see {mixin} hack
332/// 336///
333@function hack($name) { 337@function hack($name) {
334 @return block($name, 'hack'); 338 @return block($name, 'hack');
335} 339}
336 340
337/// 341///
@@ -383,22 +387,22 @@
383/// // Compilation will fail because c-someBlock is defined after c-anotherBlock__elem 387/// // Compilation will fail because c-someBlock is defined after c-anotherBlock__elem
384/// 388///
385@mixin composed-of($block, $blocks...) { 389@mixin composed-of($block, $blocks...) {
386 @each $block in functions.list-prepend($blocks, $block) { 390 @each $block in functions.list-prepend($blocks, $block) {
387 @if type-of($block) == string { 391 @if meta.type-of($block) == string {
388 @if not index(vars.$blocks, $block) { 392 @if not list.index(vars.$blocks, $block) {
389 @error 'Block "#{$block}" does not exist.'; 393 @error 'Block "#{$block}" does not exist.';
390 } 394 }
391 } @else { 395 } @else {
392 $name: nth($block, 1); 396 $name: list.nth($block, 1);
393 $type: nth($block, 2); 397 $type: list.nth($block, 2);
394 398
395 @if not map-get(vars.$namespaces, $type) { 399 @if not map.get(vars.$namespaces, $type) {
396 @error '"#{$type}" is not a valid type.'; 400 @error '"#{$type}" is not a valid type.';
397 } 401 }
398 402
399 @if not index(vars.$blocks, $name + '_' + $type) { 403 @if not list.index(vars.$blocks, $name + '_' + $type) {
400 @error 'Block "#{$name}" does not exist.'; 404 @error 'Block "#{$name}" does not exist.';
401 } 405 }
402 } 406 }
403 } 407 }
404} 408}
diff --git a/src/bem/_debug.scss b/src/bem/_debug.scss
index 8ea0f05..b1f20a7 100644
--- a/src/bem/_debug.scss
+++ b/src/bem/_debug.scss
@@ -4,15 +4,16 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:map';
7@use './vars'; 8@use './vars';
8 9
9@if vars.$debug { 10@if vars.$debug {
10 @each $type, $color in vars.$debug-colors { 11 @each $type, $color in vars.$debug-colors {
11 $namespace: map-get(vars.$namespaces, $type); 12 $namespace: map.get(vars.$namespaces, $type);
12 13
13 [class^='#{$namespace}-'], 14 [class^='#{$namespace}-'],
14 [class*=' #{$namespace}-'] { 15 [class*=' #{$namespace}-'] {
15 outline: 5px solid $color; 16 outline: 5px solid $color;
16 } 17 }
17 } 18 }
18} 19}
diff --git a/src/bem/_element.scss b/src/bem/_element.scss
index 64862b0..9f108fe 100644
--- a/src/bem/_element.scss
+++ b/src/bem/_element.scss
@@ -4,6 +4,11 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:meta';
10@use 'sass:selector';
11@use 'sass:string';
7@use './validators'; 12@use './validators';
8@use './vars'; 13@use './vars';
9@use '../functions'; 14@use '../functions';
@@ -92,22 +97,22 @@
92/// } 97/// }
93/// 98///
94@mixin elem($name, $names...) { 99@mixin elem($name, $names...) {
95 $result: elem($name, $names...); 100 $result: elem($name, $names...);
96 $selector: nth($result, 1); 101 $selector: list.nth($result, 1);
97 $context: nth($result, 2); 102 $context: list.nth($result, 2);
98 103
99 @include validators.validate( 104 @include validators.validate(
100 'element', 105 'element',
101 (name: $name, names: $names), 106 (name: $name, names: $names),
102 $selector, 107 $selector,
103 $context 108 $context
104 ); 109 );
105 110
106 @include contexts.push(vars.$context-id, $context...); 111 @include contexts.push(vars.$context-id, $context...);
107 @at-root #{$selector} { 112 @at-root #{$selector} {
108 @content; 113 @content;
109 } 114 }
110 @include contexts.pop(vars.$context-id); 115 @include contexts.pop(vars.$context-id);
111} 116}
112 117
113/// 118///
@@ -118,99 +123,93 @@
118/// @see {mixin} element 123/// @see {mixin} element
119/// 124///
120@function elem($name, $names...) { 125@function elem($name, $names...) {
121 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 126 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
122 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block'); 127 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block');
123 128
124 $parent-context: contexts.get(vars.$context-id, 'block' 'element'); 129 $parent-context: contexts.get(vars.$context-id, 'block' 'element');
125 130
126 $selector: (); 131 $selector: ();
127 $parts-data: (); 132 $parts-data: ();
128 133
129 @if nth($parent-context, 1) == 'element' { 134 @if list.nth($parent-context, 1) == 'element' {
130 @if vars.$element-nesting-policy == 'disallow' { 135 @if vars.$element-nesting-policy == 'disallow' {
131 @error 'Element nesting is forbidden.'; 136 @error 'Element nesting is forbidden.';
132 } 137 }
133 138
134 @if vars.$element-nesting-policy == 'append' { 139 @if vars.$element-nesting-policy == 'append' {
135 $element-selector: map-get(nth($parent-context, 2), 'selector'); 140 $element-selector: map.get(list.nth($parent-context, 2), 'selector');
136 141
137 @if not functions.selector-suffix-match(&, $element-selector) { 142 @if not functions.selector-suffix-match(&, $element-selector) {
138 @error 'A nested element must be an immediate children of the parent element.'; 143 @error 'A nested element must be an immediate children of the parent element.';
139 } 144 }
140 145
141 // 146 //
142 // Possible outcomes: 147 // Possible outcomes:
143 // - {e}__element 148 // - {e}__element
144 // - [manual selector] {e}__element 149 // - [manual selector] {e}__element
145 // 150 //
146 151
147 @each $name in join($name, $names) { 152 @each $name in list.join($name, $names) {
148 $sel: selector-append(&, vars.$element-separator + $name); 153 $sel: selector.append(&, vars.$element-separator + $name);
149 $selector: join($selector, $sel, comma); 154 $selector: list.join($selector, $sel, comma);
150 $parts-data: append( 155 $parts-data: list.append($parts-data, (
151 $parts-data, ( 156 'name': $name,
152 'name': $name, 157 'selector': $sel
153 'selector': $sel 158 ));
154 ) 159 }
155 ); 160 }
156 }
157 }
158 161
159 $parent-context: contexts.get(vars.$context-id, 'block'); 162 $parent-context: contexts.get(vars.$context-id, 'block');
160 } 163 }
161 164
162 @if length($selector) == 0 { 165 @if list.length($selector) == 0 {
163 $parent-selector: map-get(nth($parent-context, 2), 'selector'); 166 $parent-selector: map.get(list.nth($parent-context, 2), 'selector');
164 167
165 @if functions.selector-suffix-match(&, $parent-selector) { 168 @if functions.selector-suffix-match(&, $parent-selector) {
166 // 169 //
167 // Possible outcomes: 170 // Possible outcomes:
168 // - {b}__element 171 // - {b}__element
169 // - [manual selector] {b}__element 172 // - [manual selector] {b}__element
170 // 173 //
171 174
172 @each $name in join($name, $names) { 175 @each $name in list.join($name, $names) {
173 $sel: selector-append(&, vars.$element-separator + $name); 176 $sel: selector.append(&, vars.$element-separator + $name);
174 $selector: join($selector, $sel, comma); 177 $selector: list.join($selector, $sel, comma);
175 $parts-data: append( 178 $parts-data: list.append($parts-data, (
176 $parts-data, ( 179 'name': $name,
177 'name': $name, 180 'selector': $sel
178 'selector': $sel 181 ));
179 ) 182 }
180 ); 183 } @else {
181 } 184 //
182 } @else { 185 // Possible outcomes:
183 // 186 // - {b} [manual selector] {b}__element
184 // Possible outcomes: 187 // - {e,m,s} ([manual selector]) {b}__element
185 // - {b} [manual selector] {b}__element 188 //
186 // - {e,m,s} ([manual selector]) {b}__element
187 //
188 189
189 @if nth($parent-context, 1) != 'block' { 190 @if list.nth($parent-context, 1) != 'block' {
190 $parent-context: contexts.get(vars.$context-id, 'block'); 191 $parent-context: contexts.get(vars.$context-id, 'block');
191 } 192 }
192 193
193 $block-base-selector: map-get(nth($parent-context, 2), 'base-selector'); 194 $block-base-selector: map.get(list.nth($parent-context, 2), 'base-selector');
194 195
195 @each $name in join($name, $names) { 196 @each $name in list.join($name, $names) {
196 $sel: selector-nest(&, selector-append($block-base-selector, vars.$element-separator + $name)); 197 $sel: selector.nest(&, selector.append($block-base-selector, vars.$element-separator + $name));
197 $selector: join($selector, $sel, comma); 198 $selector: list.join($selector, $sel, comma);
198 $parts-data: append( 199 $parts-data: list.append($parts-data, (
199 $parts-data, ( 200 'name': $name,
200 'name': $name, 201 'selector': $sel
201 'selector': $sel 202 ));
202 ) 203 }
203 ); 204 }
204 } 205 }
205 }
206 }
207 206
208 $context: 'element', ( 207 $context: 'element', (
209 'parts': $parts-data, 208 'parts': $parts-data,
210 'selector': $selector 209 'selector': $selector
211 ); 210 );
212 211
213 @return $selector $context; 212 @return $selector $context;
214} 213}
215 214
216/// 215///
@@ -291,22 +290,22 @@
291/// } 290/// }
292/// 291///
293@mixin related-elem($sign, $name, $names...) { 292@mixin related-elem($sign, $name, $names...) {
294 $result: related-elem($sign, $name, $names...); 293 $result: related-elem($sign, $name, $names...);
295 $selector: nth($result, 1); 294 $selector: list.nth($result, 1);
296 $context: nth($result, 2); 295 $context: list.nth($result, 2);
297 296
298 @include validators.validate( 297 @include validators.validate(
299 'related-element', 298 'related-element',
300 (sign: $sign, name: $name, names: $names), 299 (sign: $sign, name: $name, names: $names),
301 $selector, 300 $selector,
302 $context 301 $context
303 ); 302 );
304 303
305 @include contexts.push(vars.$context-id, $context...); 304 @include contexts.push(vars.$context-id, $context...);
306 @at-root #{$selector} { 305 @at-root #{$selector} {
307 @content; 306 @content;
308 } 307 }
309 @include contexts.pop(vars.$context-id); 308 @include contexts.pop(vars.$context-id);
310} 309}
311 310
312/// 311///
@@ -318,44 +317,42 @@
318/// @see {mixin} related-element 317/// @see {mixin} related-element
319/// 318///
320@function related-elem($sign, $name, $names...) { 319@function related-elem($sign, $name, $names...) {
321 // 320 //
322 // Generating this selector is simple: Take the latest block context, use it 321 // Generating this selector is simple: Take the latest block context, use it
323 // to generate the element part, and insert it at the end of the current selector. 322 // to generate the element part, and insert it at the end of the current selector.
324 // Possible outcomes: 323 // Possible outcomes:
325 // - {e} ({m,s}) ([manual selector]) + {e} 324 // - {e} ({m,s}) ([manual selector]) + {e}
326 // - {e} ({m,s}) ([manual selector]) ~ {e} 325 // - {e} ({m,s}) ([manual selector]) ~ {e}
327 // 326 //
328 327
329 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 328 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
330 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'element'); 329 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'element');
331 330
332 @if $sign != '+' and $sign != '~' { 331 @if $sign != '+' and $sign != '~' {
333 @error 'Invalid relationship sign #{inspect($sign)}.'; 332 @error 'Invalid relationship sign #{inspect($sign)}.';
334 } 333 }
335 334
336 $block-context: contexts.get(vars.$context-id, 'block'); 335 $block-context: contexts.get(vars.$context-id, 'block');
337 $block-base-selector: map-get(nth($block-context, 2), 'base-selector'); 336 $block-base-selector: map.get(list.nth($block-context, 2), 'base-selector');
338 337
339 $selector: (); 338 $selector: ();
340 $parts-data: (); 339 $parts-data: ();
341 340
342 @each $name in join($name, $names) { 341 @each $name in list.join($name, $names) {
343 $sel: selector-nest(&, $sign, selector-append($block-base-selector, vars.$element-separator + $name)); 342 $sel: selector.nest(&, $sign, selector.append($block-base-selector, vars.$element-separator + $name));
344 $selector: join($selector, $sel, comma); 343 $selector: list.join($selector, $sel, comma);
345 $parts-data: append( 344 $parts-data: list.append($parts-data, (
346 $parts-data, ( 345 'name': $name,
347 'name': $name, 346 'selector': $sel
348 'selector': $sel 347 ));
349 ) 348 }
350 );
351 }
352 349
353 $context: 'element', ( 350 $context: 'element', (
354 'parts': $parts-data, 351 'parts': $parts-data,
355 'selector': $selector 352 'selector': $selector
356 ); 353 );
357 354
358 @return $selector $context; 355 @return $selector $context;
359} 356}
360 357
361/// 358///
@@ -369,9 +366,9 @@
369/// @content 366/// @content
370/// 367///
371@mixin sibling-elem($name, $names...) { 368@mixin sibling-elem($name, $names...) {
372 @include related-elem('~', $name, $names...) { 369 @include related-elem('~', $name, $names...) {
373 @content; 370 @content;
374 } 371 }
375} 372}
376 373
377/// 374///
@@ -383,7 +380,7 @@
383/// @see {mixin} sibling-element 380/// @see {mixin} sibling-element
384/// 381///
385@function sibling-elem($name, $names...) { 382@function sibling-elem($name, $names...) {
386 @return related-elem('~', $name, $names...); 383 @return related-elem('~', $name, $names...);
387} 384}
388 385
389/// 386///
@@ -397,9 +394,9 @@
397/// @content 394/// @content
398/// 395///
399@mixin next-elem($name, $names...) { 396@mixin next-elem($name, $names...) {
400 @include related-elem('+', $name, $names...) { 397 @include related-elem('+', $name, $names...) {
401 @content; 398 @content;
402 } 399 }
403} 400}
404 401
405/// 402///
@@ -411,7 +408,7 @@
411/// @see {mixin} next-element 408/// @see {mixin} next-element
412/// 409///
413@function next-elem($name, $names...) { 410@function next-elem($name, $names...) {
414 @return related-elem('+', $name, $names...); 411 @return related-elem('+', $name, $names...);
415} 412}
416 413
417/// 414///
@@ -467,22 +464,22 @@
467/// } 464/// }
468/// 465///
469@mixin related-twin-elem($sign) { 466@mixin related-twin-elem($sign) {
470 $result: related-twin-elem($sign); 467 $result: related-twin-elem($sign);
471 $selector: nth($result, 1); 468 $selector: list.nth($result, 1);
472 $context: nth($result, 2); 469 $context: list.nth($result, 2);
473 470
474 @include validators.validate( 471 @include validators.validate(
475 'next-twin-elem', 472 'next-twin-elem',
476 (), 473 (),
477 $selector, 474 $selector,
478 $context 475 $context
479 ); 476 );
480 477
481 @include contexts.push(vars.$context-id, $context...); 478 @include contexts.push(vars.$context-id, $context...);
482 @at-root #{$selector} { 479 @at-root #{$selector} {
483 @content; 480 @content;
484 } 481 }
485 @include contexts.pop(vars.$context-id); 482 @include contexts.pop(vars.$context-id);
486} 483}
487 484
488/// 485///
@@ -494,96 +491,94 @@
494/// @see {mixin} next-twin-elem 491/// @see {mixin} next-twin-elem
495/// 492///
496@function related-twin-elem($sign) { 493@function related-twin-elem($sign) {
497 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 494 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
498 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'element'); 495 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'element');
499 496
500 $element-context: contexts.get(vars.$context-id, 'element'); 497 $element-context: contexts.get(vars.$context-id, 'element');
501 $element-selector: map-get(nth($element-context, 2), 'selector'); 498 $element-selector: map.get(list.nth($element-context, 2), 'selector');
502 499
503 $block-context: contexts.get(vars.$context-id, 'block'); 500 $block-context: contexts.get(vars.$context-id, 'block');
504 $block-base-selector: map-get(nth($block-context, 2), 'base-selector'); 501 $block-base-selector: map.get(list.nth($block-context, 2), 'base-selector');
505 502
506 $selector: (); 503 $selector: ();
507 $parts-data: (); 504 $parts-data: ();
508 505
509 // 506 //
510 // To determine the twin for each element, iterate the sub-selectors from the current selector 507 // To determine the twin for each element, iterate the sub-selectors from the current selector
511 // and check if it contains the currently inspected element. This has to be done with string 508 // and check if it contains the currently inspected element. This has to be done with string
512 // comparison since none of Sass selector functions is of use here. 509 // comparison since none of Sass selector functions is of use here.
513 // Finally, the current twin will be appended to the extracted sub-selector as a successor 510 // Finally, the current twin will be appended to the extracted sub-selector as a successor
514 // element. 511 // element.
515 // 512 //
516 @each $part-data in map-get(nth($element-context, 2), 'parts') { 513 @each $part-data in map.get(list.nth($element-context, 2), 'parts') {
517 $part-selector: map-get($part-data, 'selector'); 514 $part-selector: map.get($part-data, 'selector');
518 $part-name: map-get($part-data, 'name'); 515 $part-name: map.get($part-data, 'name');
519 516
520 $sel: (); 517 $sel: ();
521 @if functions.selector-suffix-match(&, $element-selector) { 518 @if functions.selector-suffix-match(&, $element-selector) {
522 // 519 //
523 // This mixin is included in the selector the last element mixin created. 520 // This mixin is included in the selector the last element mixin created.
524 // Possible outcomes: 521 // Possible outcomes:
525 // - {e} + {e} 522 // - {e} + {e}
526 // - [manual selector] {e} + {e} 523 // - [manual selector] {e} + {e}
527 // 524 //
528 525
529 @each $s in & { 526 @each $s in & {
530 @each $ps in $part-selector { 527 @each $ps in $part-selector {
531 @if nth($s, -1) == nth($ps, -1) { 528 @if list.nth($s, -1) == list.nth($ps, -1) {
532 $sel-ent: selector-nest($s, $sign, selector-append($block-base-selector, vars.$element-separator + $part-name)); 529 $sel-ent: selector.nest($s, $sign, selector.append($block-base-selector, vars.$element-separator + $part-name));
533 $sel: join($sel, $sel-ent, comma); 530 $sel: list.join($sel, $sel-ent, comma);
534 } 531 }
535 } 532 }
536 } 533 }
537 } @else { 534 } @else {
538 // 535 //
539 // This mixin is NOT included in the selector the last element mixin created. 536 // This mixin is NOT included in the selector the last element mixin created.
540 // Possible outcomes: 537 // Possible outcomes:
541 // - {e} {m,s} + {e} 538 // - {e} {m,s} + {e}
542 // - {e} [manual selector] + {e} 539 // - {e} [manual selector] + {e}
543 // - {e} {m,s} [manual selector] + {e} 540 // - {e} {m,s} [manual selector] + {e}
544 // 541 //
545 542
546 @each $s in & { 543 @each $s in & {
547 @each $ps in $part-selector { 544 @each $ps in $part-selector {
548 @if str-index(inspect($s), inspect($ps)) { 545 @if string.index(meta.inspect($s), meta.inspect($ps)) {
549 $char-index: str-length(inspect($ps)) + 1; 546 $char-index: string.length(meta.inspect($ps)) + 1;
550 $match: index(' ' ':' ',', str-slice(inspect($s), $char-index, $char-index)) != null; 547 $match: list.index(' ' ':' ',', string.slice(meta.inspect($s), $char-index, $char-index)) != null;
551 548
552 @if not $match { 549 @if not $match {
553 @each $separator in vars.$element-separator vars.$modifier-separator vars.$suffix-separator { 550 @each $separator in vars.$element-separator vars.$modifier-separator vars.$suffix-separator {
554 @if str-slice(inspect($s), $char-index, $char-index + str-length($separator) - 1) == $separator { 551 @if string.slice(meta.inspect($s), $char-index, $char-index + string.length($separator) - 1) == $separator {
555 $match: true; 552 $match: true;
556 } 553 }
557 } 554 }
558 } 555 }
559 556
560 @if $match { 557 @if $match {
561 $sel-ent: selector-nest($s, '+', selector-append($block-base-selector, vars.$element-separator + $part-name)); 558 $sel-ent: selector.nest($s, '+', selector.append($block-base-selector, vars.$element-separator + $part-name));
562 $sel: join($sel, $sel-ent, comma); 559 $sel: list.join($sel, $sel-ent, comma);
563 } 560 }
564 } 561 }
565 } 562 }
566 } 563 }
567 } 564 }
568 @if length($sel) != length($part-selector) { 565 @if list.length($sel) != list.length($part-selector) {
569 @error 'Could not generate twin element selector.'; 566 @error 'Could not generate twin element selector.';
570 } 567 }
571 568
572 $selector: join($selector, $sel, comma); 569 $selector: list.join($selector, $sel, comma);
573 $parts-data: append( 570 $parts-data: list.append($parts-data, (
574 $parts-data, ( 571 'name': $part-name,
575 'name': $part-name, 572 'selector': $sel
576 'selector': $sel 573 ));
577 ) 574 }
578 );
579 }
580 575
581 $context: 'element', ( 576 $context: 'element', (
582 'parts': $parts-data, 577 'parts': $parts-data,
583 'selector': $selector 578 'selector': $selector
584 ); 579 );
585 580
586 @return $selector $context; 581 @return $selector $context;
587} 582}
588 583
589/// 584///
@@ -594,9 +589,9 @@
594/// @content 589/// @content
595/// 590///
596@mixin sibling-twin-element { 591@mixin sibling-twin-element {
597 @include related-twin-elem('~') { 592 @include related-twin-elem('~') {
598 @content; 593 @content;
599 } 594 }
600} 595}
601 596
602/// 597///
@@ -608,7 +603,7 @@
608/// @see {mixin} sibling-twin-element 603/// @see {mixin} sibling-twin-element
609/// 604///
610@function sibling-twin-elem() { 605@function sibling-twin-elem() {
611 @return related-twin-elem('~'); 606 @return related-twin-elem('~');
612} 607}
613 608
614/// 609///
@@ -619,9 +614,9 @@
619/// @content 614/// @content
620/// 615///
621@mixin next-twin-elem { 616@mixin next-twin-elem {
622 @include related-twin-elem('+') { 617 @include related-twin-elem('+') {
623 @content; 618 @content;
624 } 619 }
625} 620}
626 621
627/// 622///
@@ -633,5 +628,5 @@
633/// @see {mixin} next-twin-elem 628/// @see {mixin} next-twin-elem
634/// 629///
635@function next-twin-elem() { 630@function next-twin-elem() {
636 @return related-twin-elem('+'); 631 @return related-twin-elem('+');
637} 632}
diff --git a/src/bem/_functions.scss b/src/bem/_functions.scss
index b7bd5ec..7f52b93 100644
--- a/src/bem/_functions.scss
+++ b/src/bem/_functions.scss
@@ -4,25 +4,28 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:selector';
7@use './vars'; 10@use './vars';
8 11
9/// 12///
10/// @access private 13/// @access private
11/// 14///
12@function theme-selector($name, $names...) { 15@function theme-selector($name, $names...) {
13 $namespace: map-get(vars.$namespaces, 'theme'); 16 $namespace: map.get(vars.$namespaces, 'theme');
14 $selector: null; 17 $selector: null;
15 18
16 @each $name in join($name, $names) { 19 @each $name in list.join($name, $names) {
17 $sel: '.' + $namespace + '-' + $name; 20 $sel: '.' + $namespace + '-' + $name;
18 21
19 @if $selector == null { 22 @if $selector == null {
20 $selector: join(selector-parse($sel), selector-parse('[class*=\' t-\'] ' + $sel), comma); 23 $selector: list.join(selector.parse($sel), selector.parse('[class*=\' t-\'] ' + $sel), comma);
21 $selector: join($selector, selector-parse('[class^=\'t-\'] ' + $sel), comma); 24 $selector: list.join($selector, selector.parse('[class^=\'t-\'] ' + $sel), comma);
22 } @else { 25 } @else {
23 $selector: selector-nest($selector, $sel); 26 $selector: selector.nest($selector, $sel);
24 } 27 }
25 } 28 }
26 29
27 @return $selector; 30 @return $selector;
28} 31}
diff --git a/src/bem/_modifier.scss b/src/bem/_modifier.scss
index 07267fe..10e2826 100644
--- a/src/bem/_modifier.scss
+++ b/src/bem/_modifier.scss
@@ -4,6 +4,11 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:meta';
10@use 'sass:selector';
11@use 'sass:string';
7@use './validators'; 12@use './validators';
8@use './vars'; 13@use './vars';
9@use '../functions'; 14@use '../functions';
@@ -111,22 +116,22 @@
111/// } 116/// }
112/// 117///
113@mixin modifier($name, $names...) { 118@mixin modifier($name, $names...) {
114 $result: modifier($name, $names...); 119 $result: modifier($name, $names...);
115 $selector: nth($result, 1); 120 $selector: list.nth($result, 1);
116 $context: nth($result, 2); 121 $context: list.nth($result, 2);
117 122
118 @include validators.validate( 123 @include validators.validate(
119 'modifier', 124 'modifier',
120 (name: $name, names: $names), 125 (name: $name, names: $names),
121 $selector, 126 $selector,
122 $context 127 $context
123 ); 128 );
124 129
125 @include contexts.push(vars.$context-id, $context...); 130 @include contexts.push(vars.$context-id, $context...);
126 @at-root #{$selector} { 131 @at-root #{$selector} {
127 @content; 132 @content;
128 } 133 }
129 @include contexts.pop(vars.$context-id); 134 @include contexts.pop(vars.$context-id);
130} 135}
131 136
132/// 137///
@@ -137,121 +142,115 @@
137/// @see {mixin} modifier 142/// @see {mixin} modifier
138/// 143///
139@function modifier($name, $names...) { 144@function modifier($name, $names...) {
140 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 145 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
141 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block'); 146 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block');
142 147
143 $parent-context: contexts.get(vars.$context-id, 'block' 'element' 'modifier' 'suffix' 'state'); 148 $parent-context: contexts.get(vars.$context-id, 'block' 'element' 'modifier' 'suffix' 'state');
144 $parent-selector: map-get(nth($parent-context, 2), 'selector'); 149 $parent-selector: map.get(list.nth($parent-context, 2), 'selector');
145 $selector: (); 150 $selector: ();
146 $parts-data: (); 151 $parts-data: ();
147 152
148 @if not functions.selector-suffix-match(&, $parent-selector) { 153 @if not functions.selector-suffix-match(&, $parent-selector) {
149 // 154 //
150 // The current selector doesn't match the parent selector. 155 // The current selector doesn't match the parent selector.
151 // The user manually added a selector between parent context and this modifier call. 156 // The user manually added a selector between parent context and this modifier call.
152 // This case is forbidden because any outcome semantically wouldn't make sense: 157 // This case is forbidden because any outcome semantically wouldn't make sense:
153 // - {b,e,m,s} [manual selector] {b,e,m,s}--modifier 158 // - {b,e,m,s} [manual selector] {b,e,m,s}--modifier
154 // - {b,e,m,s}--modifier [manual selector] 159 // - {b,e,m,s}--modifier [manual selector]
155 // The first case would make the modifier behave like an element. 160 // The first case would make the modifier behave like an element.
156 // The second case is unintuitive, the code would be more clear by nesting the manual 161 // The second case is unintuitive, the code would be more clear by nesting the manual
157 // selector in the modifier instead. 162 // selector in the modifier instead.
158 // 163 //
159 164
160 @error 'A modifier must be an immediate child of the parent context'; 165 @error 'A modifier must be an immediate child of the parent context';
161 } 166 }
162 167
163 @each $name in functions.list-prepend($names, $name) { 168 @each $name in functions.list-prepend($names, $name) {
164 $extend: false; 169 $extend: false;
165 @if type-of($name) == list { 170 @if meta.type-of($name) == list {
166 $extend: nth($name, 2); 171 $extend: list.nth($name, 2);
167 $name: nth($name, 1); 172 $name: list.nth($name, 1);
168 } 173 }
169 174
170 @if index('block' 'element', nth($parent-context, 1)) or $extend == true { 175 @if list.index('block' 'element', list.nth($parent-context, 1)) or $extend == true {
171 // 176 //
172 // Either the parent context is block or element, or a modifier or suffix 177 // Either the parent context is block or element, or a modifier or suffix
173 // is to be extended. The modifier part can simply be appended. 178 // is to be extended. The modifier part can simply be appended.
174 // Possible outcomes: 179 // Possible outcomes:
175 // - {b,e,m,s}--modifier 180 // - {b,e,m,s}--modifier
176 // 181 //
177 182
178 $sel: selector-append(&, vars.$modifier-separator + $name); 183 $sel: selector.append(&, vars.$modifier-separator + $name);
179 $selector: join($selector, $sel, comma); 184 $selector: list.join($selector, $sel, comma);
180 $parts-data: append( 185 $parts-data: list.append($parts-data, (
181 $parts-data, ( 186 'name': $name,
182 'name': $name, 187 'selector': $sel
183 'selector': $sel 188 ));
184 ) 189 } @else {
185 ); 190 //
186 } @else { 191 // Parent context is modifier, suffix or state and $extend is false.
187 // 192 //
188 // Parent context is modifier, suffix or state and $extend is false.
189 //
190 193
191 $be-context: contexts.get(vars.$context-id, 'block' 'element'); 194 $be-context: contexts.get(vars.$context-id, 'block' 'element');
192 195
193 @if nth($be-context, 1) == 'element' { 196 @if list.nth($be-context, 1) == 'element' {
194 // 197 //
195 // Latest context is element. Since element contexts can consist of multiple single 198 // Latest context is element. Since element contexts can consist of multiple single
196 // elements, inspect all elements and append its selector with the suffix "--$name". 199 // elements, inspect all elements and append its selector with the suffix "--$name".
197 // This has to be done with string comparison since none of Sass selector functions 200 // This has to be done with string comparison since none of Sass selector functions
198 // is of use here. 201 // is of use here.
199 // Possible outcomes: 202 // Possible outcomes:
200 // - {m,s}.{e}--modifier 203 // - {m,s}.{e}--modifier
201 // 204 //
202 205
203 $nsel: (); 206 $nsel: ();
204 207
205 @each $elem-part-data in map-get(nth($be-context, 2), 'parts') { 208 @each $elem-part-data in map.get(list.nth($be-context, 2), 'parts') {
206 $elem-part-selector: map-get($elem-part-data, 'selector'); 209 $elem-part-selector: map.get($elem-part-data, 'selector');
207 210
208 $sel: (); 211 $sel: ();
209 @each $s in & { 212 @each $s in & {
210 @each $ps in $elem-part-selector { 213 @each $ps in $elem-part-selector {
211 @if str-index(inspect($s), inspect($ps) + vars.$modifier-separator) or str-index(inspect($s), inspect($ps) + vars.$suffix-separator) { 214 @if string.index(meta.inspect($s), meta.inspect($ps) + vars.$modifier-separator) or string.index(meta.inspect($s), meta.inspect($ps) + vars.$suffix-separator) {
212 $sel: join($sel, selector-unify($s, selector-append($ps, vars.$modifier-separator + $name)), comma); 215 $sel: list.join($sel, selector.unify($s, selector.append($ps, vars.$modifier-separator + $name)), comma);
213 } 216 }
214 } 217 }
215 } 218 }
216 @if length($sel) == 0 { 219 @if list.length($sel) == 0 {
217 @error 'Could not generate modifier selector.'; 220 @error 'Could not generate modifier selector.';
218 } 221 }
219 222
220 $nsel: join($nsel, $sel, comma); 223 $nsel: list.join($nsel, $sel, comma);
221 } 224 }
222 225
223 $selector: join($selector, $nsel, comma); 226 $selector: list.join($selector, $nsel, comma);
224 $parts-data: append( 227 $parts-data: list.append($parts-data, (
225 $parts-data, ( 228 'name': $name,
226 'name': $name, 229 'selector': $nsel
227 'selector': $nsel 230 ));
228 ) 231 } @else {
229 ); 232 //
230 } @else { 233 // Latest context is block. Just append the modifier part.
231 // 234 // Possible outcomes:
232 // Latest context is block. Just append the modifier part. 235 // - {m,s}.{b}--modifier
233 // Possible outcomes: 236 //
234 // - {m,s}.{b}--modifier
235 //
236 237
237 $block-base-selector: map-get(nth($be-context, 2), 'base-selector'); 238 $block-base-selector: map.get(list.nth($be-context, 2), 'base-selector');
238 239
239 $sel: selector-append(&, $block-base-selector, vars.$modifier-separator + $name); 240 $sel: selector.append(&, $block-base-selector, vars.$modifier-separator + $name);
240 $selector: join($selector, $sel, comma); 241 $selector: list.join($selector, $sel, comma);
241 $parts-data: append( 242 $parts-data: list.append($parts-data, (
242 $parts-data, ( 243 'name': $name,
243 'name': $name, 244 'selector': $sel
244 'selector': $sel 245 ));
245 ) 246 }
246 ); 247 }
247 } 248 }
248 }
249 }
250 249
251 $context: 'modifier', ( 250 $context: 'modifier', (
252 'parts': $parts-data, 251 'parts': $parts-data,
253 'selector': $selector 252 'selector': $selector
254 ); 253 );
255 254
256 @return $selector $context; 255 @return $selector $context;
257} 256}
diff --git a/src/bem/_multi.scss b/src/bem/_multi.scss
index 1de5cdc..c0beeeb 100644
--- a/src/bem/_multi.scss
+++ b/src/bem/_multi.scss
@@ -4,6 +4,10 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:meta';
9@use 'sass:selector';
10@use 'sass:string';
7@use '../functions'; 11@use '../functions';
8@use '../contexts'; 12@use '../contexts';
9@use './block'; 13@use './block';
@@ -81,67 +85,67 @@
81/// } 85/// }
82/// 86///
83@mixin multi($first, $others...) { 87@mixin multi($first, $others...) {
84 @include contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 88 @include contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
85 89
86 @each $entity in functions.list-prepend($others, $first) { 90 @each $entity in functions.list-prepend($others, $first) {
87 $is-manual-selector: false; 91 $is-manual-selector: false;
88 92
89 @if type-of($entity) == string { 93 @if meta.type-of($entity) == string {
90 @if find-bem-function($entity) == null { 94 @if find-bem-function($entity) == null {
91 $is-manual-selector: true; 95 $is-manual-selector: true;
92 } 96 }
93 } 97 }
94 98
95 @if $is-manual-selector { 99 @if $is-manual-selector {
96 $sel: if(&, selector-nest(&, $entity), selector-parse($entity)); 100 $sel: if(&, selector.nest(&, $entity), selector.parse($entity));
97 101
98 @at-root #{$sel} { 102 @at-root #{$sel} {
99 @content; 103 @content;
100 } 104 }
101 } @else { 105 } @else {
102 $entity-func-id: null; 106 $entity-func-id: null;
103 107
104 @if type-of($entity) == list { 108 @if meta.type-of($entity) == list {
105 $entity-func-id: nth($entity, 1); 109 $entity-func-id: list.nth($entity, 1);
106 $entity: functions.list-slice($entity, 2); 110 $entity: functions.list-slice($entity, 2);
107 } @else { 111 } @else {
108 $entity-func-id: $entity; 112 $entity-func-id: $entity;
109 $entity: (); 113 $entity: ();
110 } 114 }
111 115
112 @if str-slice($entity-func-id, str-length($entity-func-id)) == ':' { 116 @if string.slice($entity-func-id, string.length($entity-func-id)) == ':' {
113 $entity-func-id: unquote(str-slice($entity-func-id, 1, str-length($entity-func-id) - 1)); 117 $entity-func-id: string.unquote(string.slice($entity-func-id, 1, string.length($entity-func-id) - 1));
114 } 118 }
115 119
116 $sel-func: find-bem-function($entity-func-id); 120 $sel-func: find-bem-function($entity-func-id);
117 121
118 @if $sel-func == null { 122 @if $sel-func == null {
119 @error 'Function "#{inspect($entity-func-id)}" was not found.'; 123 @error 'Function "#{inspect($entity-func-id)}" was not found.';
120 } 124 }
121 125
122 $entity-result: call($sel-func, $entity...); 126 $entity-result: meta.call($sel-func, $entity...);
123 $entity-result-selector: nth($entity-result, 1); 127 $entity-result-selector: list.nth($entity-result, 1);
124 $entity-result-context: nth($entity-result, 2); 128 $entity-result-context: list.nth($entity-result, 2);
125 129
126 @if $entity-result-context != null { 130 @if $entity-result-context != null {
127 @include contexts.push(vars.$context-id, $entity-result-context...); 131 @include contexts.push(vars.$context-id, $entity-result-context...);
128 } 132 }
129 @at-root #{$entity-result-selector} { 133 @at-root #{$entity-result-selector} {
130 @content; 134 @content;
131 } 135 }
132 @if $entity-result-context != null { 136 @if $entity-result-context != null {
133 @include contexts.pop(vars.$context-id); 137 @include contexts.pop(vars.$context-id);
134 } 138 }
135 } 139 }
136 } 140 }
137} 141}
138 142
139@function find-bem-function($name) { 143@function find-bem-function($name) {
140 @each $module in (block element modifier state suffix theme) { 144 @each $module in (block element modifier state suffix theme) {
141 @if function-exists($name, $module) { 145 @if meta.function-exists($name, $module) {
142 @return get-function($name, $module: $module); 146 @return meta.get-function($name, $module: $module);
143 } 147 }
144 } 148 }
145 149
146 @return null; 150 @return null;
147} 151}
diff --git a/src/bem/_state.scss b/src/bem/_state.scss
index 41bacee..bd0efb1 100644
--- a/src/bem/_state.scss
+++ b/src/bem/_state.scss
@@ -4,6 +4,8 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:selector';
7@use './validators'; 9@use './validators';
8@use './vars'; 10@use './vars';
9@use '../contexts'; 11@use '../contexts';
@@ -56,22 +58,22 @@
56/// } 58/// }
57/// 59///
58@mixin state($prefix, $state, $states...) { 60@mixin state($prefix, $state, $states...) {
59 $result: state($prefix, $state, $states...); 61 $result: state($prefix, $state, $states...);
60 $selector: nth($result, 1); 62 $selector: list.nth($result, 1);
61 $context: nth($result, 2); 63 $context: list.nth($result, 2);
62 64
63 @include validators.validate( 65 @include validators.validate(
64 'state', 66 'state',
65 (prefix: $prefix, state: $state, states: $states), 67 (prefix: $prefix, state: $state, states: $states),
66 $selector, 68 $selector,
67 $context 69 $context
68 ); 70 );
69 71
70 @include contexts.push(vars.$context-id, $context...); 72 @include contexts.push(vars.$context-id, $context...);
71 @at-root #{$selector} { 73 @at-root #{$selector} {
72 @content; 74 @content;
73 } 75 }
74 @include contexts.pop(vars.$context-id); 76 @include contexts.pop(vars.$context-id);
75} 77}
76 78
77/// 79///
@@ -82,29 +84,27 @@
82/// @see {mixin} has 84/// @see {mixin} has
83/// 85///
84@function state($prefix, $state, $states...) { 86@function state($prefix, $state, $states...) {
85 $selector: (); 87 $selector: ();
86 $parts-data: (); 88 $parts-data: ();
87 89
88 @each $state in join($state, $states) { 90 @each $state in list.join($state, $states) {
89 $sel: selector-parse('.#{$prefix}-#{$state}'); 91 $sel: selector.parse('.#{$prefix}-#{$state}');
90 @if & { 92 @if & {
91 $sel: selector-append(&, $sel); 93 $sel: selector.append(&, $sel);
92 } 94 }
93 $selector: join($selector, $sel, comma); 95 $selector: list.join($selector, $sel, comma);
94 $parts-data: append( 96 $parts-data: list.append($parts-data, (
95 $parts-data, ( 97 'name': $state,
96 'name': $state, 98 'selector': $sel
97 'selector': $sel 99 ));
98 ) 100 }
99 );
100 }
101 101
102 $context: 'state', ( 102 $context: 'state', (
103 'parts': $parts-data, 103 'parts': $parts-data,
104 'selector': $selector 104 'selector': $selector
105 ); 105 );
106 106
107 @return $selector $context; 107 @return $selector $context;
108} 108}
109 109
110/// 110///
@@ -113,9 +113,9 @@
113/// It's a shorthand for state('is', $state, $states...). 113/// It's a shorthand for state('is', $state, $states...).
114/// 114///
115@mixin is($state, $states...) { 115@mixin is($state, $states...) {
116 @include state('is', $state, $states...) { 116 @include state('is', $state, $states...) {
117 @content; 117 @content;
118 } 118 }
119} 119}
120 120
121/// 121///
@@ -126,7 +126,7 @@
126/// @see {mixin} is 126/// @see {mixin} is
127/// 127///
128@function is($state, $states...) { 128@function is($state, $states...) {
129 @return state('is', $state, $states...); 129 @return state('is', $state, $states...);
130} 130}
131 131
132/// 132///
@@ -135,9 +135,9 @@
135/// It's a shorthand for state('has', $state, $states...). 135/// It's a shorthand for state('has', $state, $states...).
136/// 136///
137@mixin has($state, $states...) { 137@mixin has($state, $states...) {
138 @include state('has', $state, $states...) { 138 @include state('has', $state, $states...) {
139 @content; 139 @content;
140 } 140 }
141} 141}
142 142
143/// 143///
@@ -148,5 +148,5 @@
148/// @see {mixin} has 148/// @see {mixin} has
149/// 149///
150@function has($state, $states...) { 150@function has($state, $states...) {
151 @return state('has', $state, $states...); 151 @return state('has', $state, $states...);
152} 152}
diff --git a/src/bem/_suffix.scss b/src/bem/_suffix.scss
index 2ddb54d..93e4066 100644
--- a/src/bem/_suffix.scss
+++ b/src/bem/_suffix.scss
@@ -4,6 +4,9 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:selector';
7@use './validators'; 10@use './validators';
8@use './vars'; 11@use './vars';
9@use '../functions'; 12@use '../functions';
@@ -54,22 +57,22 @@
54/// } 57/// }
55/// 58///
56@mixin suffix($name) { 59@mixin suffix($name) {
57 $result: suffix($name); 60 $result: suffix($name);
58 $selector: nth($result, 1); 61 $selector: list.nth($result, 1);
59 $context: nth($result, 2); 62 $context: list.nth($result, 2);
60 63
61 @include validators.validate( 64 @include validators.validate(
62 'suffix', 65 'suffix',
63 (name: $name), 66 (name: $name),
64 $selector, 67 $selector,
65 $context 68 $context
66 ); 69 );
67 70
68 @include contexts.push(vars.$context-id, $context...); 71 @include contexts.push(vars.$context-id, $context...);
69 @at-root #{$selector} { 72 @at-root #{$selector} {
70 @content; 73 @content;
71 } 74 }
72 @include contexts.pop(vars.$context-id); 75 @include contexts.pop(vars.$context-id);
73} 76}
74 77
75/// 78///
@@ -80,44 +83,44 @@
80/// @see {mixin} suffix 83/// @see {mixin} suffix
81/// 84///
82@function suffix($name) { 85@function suffix($name) {
83 // 86 //
84 // Suffixes can be used on block, element and modifier. 87 // Suffixes can be used on block, element and modifier.
85 // 88 //
86 89
87 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth); 90 $noop: contexts.assert-stack-count(vars.$context-id, vars.$max-depth);
88 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block'); 91 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block');
89 $noop: contexts.assert-stack-must-not-contain(vars.$context-id, 'suffix'); 92 $noop: contexts.assert-stack-must-not-contain(vars.$context-id, 'suffix');
90 93
91 $parent-context: contexts.get(vars.$context-id, 'block' 'element' 'modifier'); 94 $parent-context: contexts.get(vars.$context-id, 'block' 'element' 'modifier');
92 $parent-selector: map-get(nth($parent-context, 2), 'selector'); 95 $parent-selector: map.get(list.nth($parent-context, 2), 'selector');
93 96
94 @if not functions.selector-suffix-match(&, $parent-selector) { 97 @if not functions.selector-suffix-match(&, $parent-selector) {
95 // 98 //
96 // The current selector doesn't match the parent selector. 99 // The current selector doesn't match the parent selector.
97 // The user manually added a selector between parent context and this suffix call. 100 // The user manually added a selector between parent context and this suffix call.
98 // This case is forbidden because any outcome semantically wouldn't make sense: 101 // This case is forbidden because any outcome semantically wouldn't make sense:
99 // - {b,e,m} [manual selector] {b,e,m}@suffix 102 // - {b,e,m} [manual selector] {b,e,m}@suffix
100 // - {b,e,m}@suffix [manual selector] 103 // - {b,e,m}@suffix [manual selector]
101 // The first case would make the modifier behave like an element. 104 // The first case would make the modifier behave like an element.
102 // The second case is unintuitive, the code would be more clear by nesting the manual 105 // The second case is unintuitive, the code would be more clear by nesting the manual
103 // selector in the suffix instead. 106 // selector in the suffix instead.
104 // 107 //
105 108
106 @error 'A suffix must be an immediate child of the parent context'; 109 @error 'A suffix must be an immediate child of the parent context';
107 } 110 }
108 111
109 // 112 //
110 // The suffix part can simply be appended. 113 // The suffix part can simply be appended.
111 // Possible outcomes: 114 // Possible outcomes:
112 // - {b,e,m}@suffix 115 // - {b,e,m}@suffix
113 // 116 //
114 117
115 $selector: selector-append(&, vars.$suffix-separator + $name); 118 $selector: selector.append(&, vars.$suffix-separator + $name);
116 119
117 $context: 'suffix', ( 120 $context: 'suffix', (
118 'name': $name, 121 'name': $name,
119 'selector': $selector 122 'selector': $selector
120 ); 123 );
121 124
122 @return $selector $context; 125 @return $selector $context;
123} 126}
diff --git a/src/bem/_theme.scss b/src/bem/_theme.scss
index ff1ba49..535cc81 100644
--- a/src/bem/_theme.scss
+++ b/src/bem/_theme.scss
@@ -4,6 +4,9 @@
4/// @access public 4/// @access public
5//// 5////
6 6
7@use 'sass:list';
8@use 'sass:map';
9@use 'sass:selector';
7@use './functions'; 10@use './functions';
8@use './validators'; 11@use './validators';
9@use './vars'; 12@use './vars';
@@ -18,22 +21,22 @@
18/// @content 21/// @content
19/// 22///
20@mixin at-theme($name, $names...) { 23@mixin at-theme($name, $names...) {
21 $result: at-theme($name, $names...); 24 $result: at-theme($name, $names...);
22 $selector: nth($result, 1); 25 $selector: list.nth($result, 1);
23 $context: nth($result, 2); 26 $context: list.nth($result, 2);
24 27
25 @include validators.validate( 28 @include validators.validate(
26 'at-theme', 29 'at-theme',
27 (name: $name, names: $names), 30 (name: $name, names: $names),
28 $selector, 31 $selector,
29 $context 32 $context
30 ); 33 );
31 34
32 @include contexts.push(vars.$context-id, $context...); 35 @include contexts.push(vars.$context-id, $context...);
33 @at-root #{$selector} { 36 @at-root #{$selector} {
34 @content; 37 @content;
35 } 38 }
36 @include contexts.pop(vars.$context-id); 39 @include contexts.pop(vars.$context-id);
37} 40}
38 41
39/// 42///
@@ -45,22 +48,22 @@
45/// @see {mixin} at-theme 48/// @see {mixin} at-theme
46/// 49///
47@function at-theme($name, $names...) { 50@function at-theme($name, $names...) {
48 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block'); 51 $noop: contexts.assert-stack-must-contain(vars.$context-id, 'block');
49 52
50 $parent-context: contexts.get(vars.$context-id, 'block'); 53 $parent-context: contexts.get(vars.$context-id, 'block');
51 $parent-selector: map-get(nth($parent-context, 2), 'selector'); 54 $parent-selector: map.get(list.nth($parent-context, 2), 'selector');
52 55
53 //@if not functions.selector-suffix-match(&, $parent-selector) { 56 //@if not functions.selector-suffix-match(&, $parent-selector) {
54 // @error 'An at-theme rule must be an immediate child of a block'; 57 // @error 'An at-theme rule must be an immediate child of a block';
55 //} 58 //}
56 59
57 $selector: functions.theme-selector($name, $names...); 60 $selector: functions.theme-selector($name, $names...);
58 $selector: selector-nest($selector, &); 61 $selector: selector.nest($selector, &);
59 62
60 $context: 'at-theme', ( 63 $context: 'at-theme', (
61 'name': join($name, $names), 64 'name': list.join($name, $names),
62 'selector': $selector 65 'selector': $selector
63 ); 66 );
64 67
65 @return $selector $context; 68 @return $selector $context;
66} 69}
diff --git a/src/bem/_validators.scss b/src/bem/_validators.scss
index 042e15e..bc3c9b7 100644
--- a/src/bem/_validators.scss
+++ b/src/bem/_validators.scss
@@ -16,6 +16,9 @@
16/// @access public 16/// @access public
17//// 17////
18 18
19@use 'sass:list';
20@use 'sass:map';
21@use 'sass:meta';
19@use './vars'; 22@use './vars';
20@use '../functions'; 23@use '../functions';
21@use '../contexts'; 24@use '../contexts';
@@ -46,7 +49,7 @@ $validators: ();
46/// @param {string} $func-names - Other function names. 49/// @param {string} $func-names - Other function names.
47/// 50///
48@mixin add($func-name, $func-names...) { 51@mixin add($func-name, $func-names...) {
49 $noop: add($func-name, $func-names...); 52 $noop: add($func-name, $func-names...);
50} 53}
51 54
52/// 55///
@@ -55,11 +58,11 @@ $validators: ();
55/// @see {mixin} add 58/// @see {mixin} add
56/// 59///
57@function add($func-name, $func-names...) { 60@function add($func-name, $func-names...) {
58 @each $fn-name in join($func-name, $func-names) { 61 @each $fn-name in list.join($func-name, $func-names) {
59 $fn: get-function($fn-name); 62 $fn: meta.get-function($fn-name);
60 $validators: map-merge($validators, ($fn-name: $fn)); 63 $validators: map.merge($validators, ($fn-name: $fn));
61 } 64 }
62 @return null; 65 @return null;
63} 66}
64 67
65/// 68///
@@ -69,7 +72,7 @@ $validators: ();
69/// @param {string} $func-names - Other function names. 72/// @param {string} $func-names - Other function names.
70/// 73///
71@mixin remove($func-name, $func-names...) { 74@mixin remove($func-name, $func-names...) {
72 $noop: remove($func-name, $func-names...); 75 $noop: remove($func-name, $func-names...);
73} 76}
74 77
75/// 78///
@@ -78,20 +81,20 @@ $validators: ();
78/// @see {mixin} remove 81/// @see {mixin} remove
79/// 82///
80@function remove($func-name, $func-names...) { 83@function remove($func-name, $func-names...) {
81 $validators: map-remove($validators, $func-name, $func-names...); 84 $validators: map.remove($validators, $func-name, $func-names...);
82 @return null; 85 @return null;
83} 86}
84 87
85/// 88///
86/// @access private 89/// @access private
87/// 90///
88@mixin validate($type, $args, $selector, $context) { 91@mixin validate($type, $args, $selector, $context) {
89 @each $id, $fn in $validators { 92 @each $id, $fn in $validators {
90 $result: call($fn, $type, $args, $selector, $context); 93 $result: meta.call($fn, $type, $args, $selector, $context);
91 @if not nth($result, 1) { 94 @if not list.nth($result, 1) {
92 @error 'A BEM validator rejected this mixin usage due to the following reason: #{nth($result, 2)}'; 95 @error 'A BEM validator rejected this mixin usage due to the following reason: #{nth($result, 2)}';
93 } 96 }
94 } 97 }
95} 98}
96 99
97// 100//
@@ -105,76 +108,76 @@ $validators: ();
105/// namespace used. 108/// namespace used.
106/// 109///
107@function enforce-namespace-order($type, $args, $selector, $context) { 110@function enforce-namespace-order($type, $args, $selector, $context) {
108 @if not global-variable-exists(namespace-order, vars) { 111 @if not meta.global-variable-exists(namespace-order, vars) {
109 vars.$namespace-order: map-keys(vars.$namespaces); 112 vars.$namespace-order: map.keys(vars.$namespaces);
110 } 113 }
111 @if not global-variable-exists(cur-namespace-index, vars) { 114 @if not meta.global-variable-exists(cur-namespace-index, vars) {
112 vars.$cur-namespace-index: 1; 115 vars.$cur-namespace-index: 1;
113 } 116 }
114 117
115 @if $type == 'block' { 118 @if $type == 'block' {
116 $block-type: map-get($args, 'type'); 119 $block-type: map.get($args, 'type');
117 120
118 @if $block-type != null { 121 @if $block-type != null {
119 $ns-index: index(vars.$namespace-order, $block-type); 122 $ns-index: list.index(vars.$namespace-order, $block-type);
120 123
121 @if $ns-index != null { 124 @if $ns-index != null {
122 @if $ns-index < vars.$cur-namespace-index { 125 @if $ns-index < vars.$cur-namespace-index {
123 @return false 'Namespace "#{$block-type}" comes before current namespace #{nth(vars.$namespace-order, vars.$cur-namespace-index)}'; 126 @return false 'Namespace "#{$block-type}" comes before current namespace #{nth(vars.$namespace-order, vars.$cur-namespace-index)}';
124 } 127 }
125 128
126 vars.$cur-namespace-index: $ns-index; 129 vars.$cur-namespace-index: $ns-index;
127 } 130 }
128 } 131 }
129 } 132 }
130 133
131 @return true ''; 134 @return true '';
132} 135}
133 136
134/// 137///
135/// A validator that makes all BEM entities immutable. 138/// A validator that makes all BEM entities immutable.
136/// 139///
137@function immutable-entities($type, $args, $selector, $context) { 140@function immutable-entities($type, $args, $selector, $context) {
138 @if not global-variable-exists(generated-selectors, vars) { 141 @if not meta.global-variable-exists(generated-selectors, vars) {
139 vars.$generated-selectors: (); 142 vars.$generated-selectors: ();
140 } 143 }
141 144
142 $block-name: null; 145 $block-name: null;
143 $block-type: null; 146 $block-type: null;
144 $block-id: null; 147 $block-id: null;
145 148
146 @if $type == 'block' { 149 @if $type == 'block' {
147 $block-name: map-get($args, 'name'); 150 $block-name: map.get($args, 'name');
148 $block-type: map-get($args, 'type'); 151 $block-type: map.get($args, 'type');
149 } @else { 152 } @else {
150 $block-context: contexts.get(vars.$context-id, 'block'); 153 $block-context: contexts.get(vars.$context-id, 'block');
151 $block-name: map-get(nth($block-context, 2), 'name'); 154 $block-name: map.get(list.nth($block-context, 2), 'name');
152 $block-type: map-get(nth($block-context, 2), 'type'); 155 $block-type: map.get(list.nth($block-context, 2), 'type');
153 } 156 }
154 157
155 @if $block-type != null { 158 @if $block-type != null {
156 $block-id: $block-name + '_' + $block-type; 159 $block-id: $block-name + '_' + $block-type;
157 } @else { 160 } @else {
158 $block-id: $block-name; 161 $block-id: $block-name;
159 } 162 }
160 163
161 @if $type == 'block' { 164 @if $type == 'block' {
162 @if map-has-key(vars.$generated-selectors, $block-id) { 165 @if map.has-key(vars.$generated-selectors, $block-id) {
163 @return false 'Entity "#{$type}" with arguments [ #{functions.map-print($args)} ] was already defined.'; 166 @return false 'Entity "#{$type}" with arguments [ #{functions.map-print($args)} ] was already defined.';
164 } 167 }
165 168
166 vars.$generated-selectors: map-merge(vars.$generated-selectors, ($block-id: ())); 169 vars.$generated-selectors: map.merge(vars.$generated-selectors, ($block-id: ()));
167 } @else { 170 } @else {
168 $selectors: map-get(vars.$generated-selectors, $block-id); 171 $selectors: map.get(vars.$generated-selectors, $block-id);
169 172
170 @if index($selectors, $selector) { 173 @if list.index($selectors, $selector) {
171 @return false 'Entity "#{$type}" with arguments [ #{functions.map-print($args)} ] was already defined.'; 174 @return false 'Entity "#{$type}" with arguments [ #{functions.map-print($args)} ] was already defined.';
172 } 175 }
173 176
174 $selectors: append($selectors, $selector); 177 $selectors: list.append($selectors, $selector);
175 178
176 vars.$generated-selectors: map-merge(vars.$generated-selectors, ($block-id: $selectors)); 179 vars.$generated-selectors: map.merge(vars.$generated-selectors, ($block-id: $selectors));
177 } 180 }
178 181
179 @return true ''; 182 @return true '';
180} 183}
diff --git a/src/bem/_vars.scss b/src/bem/_vars.scss
index 3d0f92a..823bf0a 100644
--- a/src/bem/_vars.scss
+++ b/src/bem/_vars.scss
@@ -41,15 +41,15 @@ $suffix-separator: '\\@' !default;
41/// @type map 41/// @type map
42/// 42///
43$namespaces: ( 43$namespaces: (
44 object: 'o', 44 object: 'o',
45 component: 'c', 45 component: 'c',
46 layout: 'l', 46 layout: 'l',
47 scope: 's', 47 scope: 's',
48 theme: 't', 48 theme: 't',
49 utility: 'u', 49 utility: 'u',
50 js: 'js', 50 js: 'js',
51 qa: 'qa', 51 qa: 'qa',
52 hack: '_' 52 hack: '_'
53) !default; 53) !default;
54 54
55/// 55///
@@ -100,9 +100,9 @@ $debug: false !default;
100/// @type map 100/// @type map
101/// 101///
102$debug-colors: ( 102$debug-colors: (
103 object: #ffa500, 103 object: #ffa500,
104 component: #00f, 104 component: #00f,
105 layout: #ff0, 105 layout: #ff0,
106 utility: #008000, 106 utility: #008000,
107 hack: #f00 107 hack: #f00
108) !default; 108) !default;
diff --git a/test/_bem.scss b/test/_bem.scss
index b7bd6b4..48a5ee9 100644
--- a/test/_bem.scss
+++ b/test/_bem.scss
@@ -1,21 +1,21 @@
1@use 'true' as *; 1@use 'true' as *;
2 2
3@include describe('bem') { 3@include describe('bem') {
4 // 4 //
5 // The following unit tests only test the BEM mixins. 5 // The following unit tests only test the BEM mixins.
6 // Since they are wrappers for the BEM functions, the latter are 6 // Since they are wrappers for the BEM functions, the latter are
7 // automatically covered. 7 // automatically covered.
8 // 8 //
9 9
10 @import 'bem/block'; 10 @import 'bem/block';
11 @import 'bem/composed-of'; 11 @import 'bem/composed-of';
12 @import 'bem/at-theme'; 12 @import 'bem/at-theme';
13 @import 'bem/element'; 13 @import 'bem/element';
14 @import 'bem/related-element'; 14 @import 'bem/related-element';
15 @import 'bem/next-twin-element'; 15 @import 'bem/next-twin-element';
16 @import 'bem/modifier'; 16 @import 'bem/modifier';
17 @import 'bem/suffix'; 17 @import 'bem/suffix';
18 @import 'bem/state'; 18 @import 'bem/state';
19 @import 'bem/multi'; 19 @import 'bem/multi';
20 @import 'bem/examples'; 20 @import 'bem/examples';
21} 21}
diff --git a/test/_contexts.scss b/test/_contexts.scss
index 510f79b..fc49186 100644
--- a/test/_contexts.scss
+++ b/test/_contexts.scss
@@ -2,67 +2,67 @@
2@use '../src/contexts'; 2@use '../src/contexts';
3 3
4@include describe('contexts') { 4@include describe('contexts') {
5 @include it('Creating / deleting context stacks') { 5 @include it('Creating / deleting context stacks') {
6 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created'); 6 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created');
7 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted'); 7 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted');
8 } 8 }
9 9
10 @include it('Adding / removing contexts') { 10 @include it('Adding / removing contexts') {
11 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created'); 11 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created');
12 12
13 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed'); 13 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed');
14 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed'); 14 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed');
15 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed'); 15 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed');
16 16
17 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped'); 17 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped');
18 @include assert-equal(contexts.pop('test'), 'another' 'text', 'Check if context 2 was popped'); 18 @include assert-equal(contexts.pop('test'), 'another' 'text', 'Check if context 2 was popped');
19 @include assert-equal(contexts.pop('test'), 'ctx' 1234, 'Check if context 1 was popped'); 19 @include assert-equal(contexts.pop('test'), 'ctx' 1234, 'Check if context 1 was popped');
20 20
21 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted'); 21 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted');
22 } 22 }
23 23
24 @include it('Clearing / counting context stacks') { 24 @include it('Clearing / counting context stacks') {
25 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created'); 25 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created');
26 26
27 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed'); 27 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed');
28 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed'); 28 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed');
29 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed'); 29 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed');
30 30
31 @include assert-equal(contexts.count('test'), 3, 'Check if context stack contains 3 contexts'); 31 @include assert-equal(contexts.count('test'), 3, 'Check if context stack contains 3 contexts');
32 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped'); 32 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped');
33 @include assert-equal(contexts.count('test'), 2, 'Check if context stack contains 2 contexts'); 33 @include assert-equal(contexts.count('test'), 2, 'Check if context stack contains 2 contexts');
34 @include assert-equal(contexts.clear('test'), null, 'Check if context stack was cleared'); 34 @include assert-equal(contexts.clear('test'), null, 'Check if context stack was cleared');
35 @include assert-equal(contexts.count('test'), 0, 'Check if context stack contains no contexts'); 35 @include assert-equal(contexts.count('test'), 0, 'Check if context stack contains no contexts');
36 36
37 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted'); 37 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted');
38 } 38 }
39 39
40 @include it('Retrieving contexts') { 40 @include it('Retrieving contexts') {
41 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created'); 41 @include assert-equal(contexts.create('test'), null, 'Check if context stack was created');
42 42
43 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed'); 43 @include assert-equal(contexts.push('test', 'ctx', 1234), 'ctx' 1234, 'Check if context 1 was pushed');
44 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed'); 44 @include assert-equal(contexts.push('test', 'another', 'text'), 'another' 'text', 'Check if context 2 was pushed');
45 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed'); 45 @include assert-equal(contexts.push('test', 'ctx', 56), 'ctx' 56, 'Check if context 3 was pushed');
46 46
47 @include assert-equal(contexts.get('test', 1), 'ctx' 56, 'Check if context at position 1 is context 3'); 47 @include assert-equal(contexts.get('test', 1), 'ctx' 56, 'Check if context at position 1 is context 3');
48 @include assert-equal(contexts.get('test', 'ctx'), 'ctx' 56, 'Check if latest context with id "ctx" is context 3'); 48 @include assert-equal(contexts.get('test', 'ctx'), 'ctx' 56, 'Check if latest context with id "ctx" is context 3');
49 @include assert-equal(contexts.get('test', 2), 'another' 'text', 'Check if latest context with id "another" is context 2'); 49 @include assert-equal(contexts.get('test', 2), 'another' 'text', 'Check if latest context with id "another" is context 2');
50 50
51 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped'); 51 @include assert-equal(contexts.pop('test'), 'ctx' 56, 'Check if context 3 was popped');
52 52
53 @include assert-equal(contexts.get('test', 1), 'another' 'text', 'Check if context at position 1 is context 2'); 53 @include assert-equal(contexts.get('test', 1), 'another' 'text', 'Check if context at position 1 is context 2');
54 @include assert-equal(contexts.get('test', -1), 'ctx' 1234, 'Check if latest context with id "ctx" is context 1'); 54 @include assert-equal(contexts.get('test', -1), 'ctx' 1234, 'Check if latest context with id "ctx" is context 1');
55 55
56 @include assert-equal(contexts.push('test', 'more', 'string'), 'more' 'string', 'Check if context 4 was pushed'); 56 @include assert-equal(contexts.push('test', 'more', 'string'), 'more' 'string', 'Check if context 4 was pushed');
57 57
58 @include assert-equal(contexts.get('test', 1), 'more' 'string', 'Check if context at position 1 is context 4'); 58 @include assert-equal(contexts.get('test', 1), 'more' 'string', 'Check if context at position 1 is context 4');
59 @include assert-equal(contexts.get('test', 'more'), 'more' 'string', 'Check if latest context with id "more" is context 4'); 59 @include assert-equal(contexts.get('test', 'more'), 'more' 'string', 'Check if latest context with id "more" is context 4');
60 60
61 @include assert-equal(contexts.pop('test'), 'more' 'string', 'Check if context 4 was popped'); 61 @include assert-equal(contexts.pop('test'), 'more' 'string', 'Check if context 4 was popped');
62 @include assert-equal(contexts.pop('test'), 'another' 'text', 'Check if context 2 was popped'); 62 @include assert-equal(contexts.pop('test'), 'another' 'text', 'Check if context 2 was popped');
63 63
64 @include assert-equal(contexts.get('test', 1), contexts.get('test', -1), 'Check if first and last context are context 1'); 64 @include assert-equal(contexts.get('test', 1), contexts.get('test', -1), 'Check if first and last context are context 1');
65 65
66 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted'); 66 @include assert-equal(contexts.delete('test'), null, 'Check if context stack was deleted');
67 } 67 }
68} 68}
diff --git a/test/_functions.scss b/test/_functions.scss
index 07561ef..4d545db 100644
--- a/test/_functions.scss
+++ b/test/_functions.scss
@@ -2,56 +2,56 @@
2@use '../src/functions'; 2@use '../src/functions';
3 3
4@include describe('functions') { 4@include describe('functions') {
5 @include it('str-replace') { 5 @include it('str-replace') {
6 $str: 'Hello world!'; 6 $str: 'Hello world!';
7 7
8 @include assert-equal(functions.str-replace($str, 'world', 'neighbor'), 'Hello neighbor!', 'Replace "world" with "neighbor"'); 8 @include assert-equal(functions.str-replace($str, 'world', 'neighbor'), 'Hello neighbor!', 'Replace "world" with "neighbor"');
9 @include assert-equal(functions.str-replace($str, 'neighbor', 'moon'), 'Hello world!', 'Replace "neighbor" with "moon"'); 9 @include assert-equal(functions.str-replace($str, 'neighbor', 'moon'), 'Hello world!', 'Replace "neighbor" with "moon"');
10 @include assert-equal(functions.str-replace($str, 'Hello', 'Bye'), 'Bye world!', 'Replace "Hello" with "Bye"'); 10 @include assert-equal(functions.str-replace($str, 'Hello', 'Bye'), 'Bye world!', 'Replace "Hello" with "Bye"');
11 } 11 }
12 12
13 @include it('list-slice') { 13 @include it('list-slice') {
14 $list: 'this' 'is' 'a' 'list'; 14 $list: 'this' 'is' 'a' 'list';
15 15
16 @include assert-equal(functions.list-slice($list, 2), 'is' 'a' 'list', 'Discard first item'); 16 @include assert-equal(functions.list-slice($list, 2), 'is' 'a' 'list', 'Discard first item');
17 @include assert-equal(functions.list-slice($list, 1, 3), 'this' 'is' 'a', 'Keep first 3 items'); 17 @include assert-equal(functions.list-slice($list, 1, 3), 'this' 'is' 'a', 'Keep first 3 items');
18 @include assert-equal(functions.list-slice($list, 2, 3), 'is' 'a', 'Extract list from index 2 to 3'); 18 @include assert-equal(functions.list-slice($list, 2, 3), 'is' 'a', 'Extract list from index 2 to 3');
19 @include assert-equal(functions.list-slice($list, -1, -1), join((), 'list'), 'Keep last item'); 19 @include assert-equal(functions.list-slice($list, -1, -1), join((), 'list'), 'Keep last item');
20 @include assert-equal(functions.list-slice($list, -1, 1), 'list' 'this', 'Extract first and last item'); 20 @include assert-equal(functions.list-slice($list, -1, 1), 'list' 'this', 'Extract first and last item');
21 } 21 }
22 22
23 @include it('list-prepend') { 23 @include it('list-prepend') {
24 $list: 'this' 'is' 'a' 'list'; 24 $list: 'this' 'is' 'a' 'list';
25 25
26 @include assert-equal(functions.list-prepend($list, 'and'), 'and' 'this' 'is' 'a' 'list', 'Prepend "and"'); 26 @include assert-equal(functions.list-prepend($list, 'and'), 'and' 'this' 'is' 'a' 'list', 'Prepend "and"');
27 @include assert-equal(functions.list-prepend($list, 2), 2 'this' 'is' 'a' 'list', 'Prepend 2'); 27 @include assert-equal(functions.list-prepend($list, 2), 2 'this' 'is' 'a' 'list', 'Prepend 2');
28 } 28 }
29 29
30 @include it('quicksort') { 30 @include it('quicksort') {
31 @include assert-equal(functions.quicksort(1 2 3 4 5), 1 2 3 4 5, 'Already sorted list of 5 items'); 31 @include assert-equal(functions.quicksort(1 2 3 4 5), 1 2 3 4 5, 'Already sorted list of 5 items');
32 @include assert-equal(functions.quicksort(1 3 2), 1 2 3, 'Random list of 3 items'); 32 @include assert-equal(functions.quicksort(1 3 2), 1 2 3, 'Random list of 3 items');
33 @include assert-equal(functions.quicksort(6 3 7 3 8 1 4), 1 3 3 4 6 7 8, 'Random list of 7 items, one duplicate'); 33 @include assert-equal(functions.quicksort(6 3 7 3 8 1 4), 1 3 3 4 6 7 8, 'Random list of 7 items, one duplicate');
34 @include assert-equal(functions.quicksort(1 1 1 1), 1 1 1 1, 'List of 4 identical items'); 34 @include assert-equal(functions.quicksort(1 1 1 1), 1 1 1 1, 'List of 4 identical items');
35 } 35 }
36 36
37 @include it('map-get-default') { 37 @include it('map-get-default') {
38 $map: ('key': 'value', 'another': 'item'); 38 $map: ('key': 'value', 'another': 'item');
39 39
40 @include assert-equal(functions.map-get-default($map, 'another', 0), map-get($map, 'another'), 'Get existing value'); 40 @include assert-equal(functions.map-get-default($map, 'another', 0), map-get($map, 'another'), 'Get existing value');
41 @include assert-equal(functions.map-get-default($map, 'index', 'nothing'), 'nothing', 'Get missing value'); 41 @include assert-equal(functions.map-get-default($map, 'index', 'nothing'), 'nothing', 'Get missing value');
42 } 42 }
43 43
44 @include it('strip-unit') { 44 @include it('strip-unit') {
45 @include assert-true(unitless(functions.strip-unit(1em)), 'Remove unit from 1em'); 45 @include assert-true(unitless(functions.strip-unit(1em)), 'Remove unit from 1em');
46 @include assert-true(unitless(functions.strip-unit(2rem)), 'Remove unit from 2rem'); 46 @include assert-true(unitless(functions.strip-unit(2rem)), 'Remove unit from 2rem');
47 @include assert-true(unitless(functions.strip-unit(3px)), 'Remove unit from 3px'); 47 @include assert-true(unitless(functions.strip-unit(3px)), 'Remove unit from 3px');
48 @include assert-true(unitless(functions.strip-unit(4)), 'Remove unit from 4'); 48 @include assert-true(unitless(functions.strip-unit(4)), 'Remove unit from 4');
49 @include assert-true(unitless(functions.strip-unit(5pt)), 'Remove unit from 5pt'); 49 @include assert-true(unitless(functions.strip-unit(5pt)), 'Remove unit from 5pt');
50 } 50 }
51 51
52 @include it('px-to-rem') { 52 @include it('px-to-rem') {
53 @include assert-equal(functions.px-to-rem(16px, 16px), 1rem, 'Convert 16px'); 53 @include assert-equal(functions.px-to-rem(16px, 16px), 1rem, 'Convert 16px');
54 @include assert-equal(functions.px-to-rem(32px, 16px), 2rem, 'Convert 16px'); 54 @include assert-equal(functions.px-to-rem(32px, 16px), 2rem, 'Convert 16px');
55 @include assert-equal(functions.px-to-rem(8px, 16px), 0.5rem, 'Convert 16px'); 55 @include assert-equal(functions.px-to-rem(8px, 16px), .5rem, 'Convert 16px');
56 } 56 }
57} 57}
diff --git a/test/_gradients.scss b/test/_gradients.scss
index c11439c..db5fda7 100644
--- a/test/_gradients.scss
+++ b/test/_gradients.scss
@@ -5,264 +5,220 @@
5@use '../src/gradients'; 5@use '../src/gradients';
6 6
7@include describe('gradients') { 7@include describe('gradients') {
8 @include it('easing-gradient') { 8 @include it('easing-gradient') {
9 $gradient1: gradients.easing-gradient( 9 $gradient1: gradients.easing-gradient(linear,
10 linear, 10 to right,
11 to right, 11 #000,
12 #000, 12 ease-in-quad,
13 ease-in-quad, 13 transparent);
14 transparent
15 );
16 14
17 $expected1: linear-gradient( 15 $expected1: linear-gradient(to right,
18 to right, 16 #000 0,
19 #000 0, 17 mix(transparent, #000, easing.ease-in-quad(.25) * 100%) 25%,
20 mix(transparent, #000, easing.ease-in-quad(0.25) * 100%) 25%, 18 mix(transparent, #000, easing.ease-in-quad(.5) * 100%) 50%,
21 mix(transparent, #000, easing.ease-in-quad(0.5) * 100%) 50%, 19 mix(transparent, #000, easing.ease-in-quad(.75) * 100%) 75%,
22 mix(transparent, #000, easing.ease-in-quad(0.75) * 100%) 75%, 20 transparent 100%);
23 transparent 100%
24 );
25 21
26 @include assert-equal($gradient1, $expected1, 'Simple linear gradient'); 22 @include assert-equal($gradient1, $expected1, 'Simple linear gradient');
27 23
28 // --------------------------------------------------------------------------- 24 // ---------------------------------------------------------------------------
29 25
30 $gradient2: gradients.easing-gradient( 26 $gradient2: gradients.easing-gradient(radial,
31 radial, 27 1em 2em at 50% 60%,
32 1em 2em at 50% 60%, 28 #000,
33 #000, 29 ease-out-cubic,
34 ease-out-cubic, 30 transparent);
35 transparent
36 );
37 31
38 $expected2: radial-gradient( 32 $expected2: radial-gradient(1em 2em at 50% 60%,
39 1em 2em at 50% 60%, 33 #000 0,
40 #000 0, 34 mix(transparent, #000, easing.ease-out-cubic(.25) * 100%) 25%,
41 mix(transparent, #000, easing.ease-out-cubic(0.25) * 100%) 25%, 35 mix(transparent, #000, easing.ease-out-cubic(.5) * 100%) 50%,
42 mix(transparent, #000, easing.ease-out-cubic(0.5) * 100%) 50%, 36 mix(transparent, #000, easing.ease-out-cubic(.75) * 100%) 75%,
43 mix(transparent, #000, easing.ease-out-cubic(0.75) * 100%) 75%, 37 transparent 100%);
44 transparent 100%
45 );
46 38
47 @include assert-equal($gradient2, $expected2, 'Simple radial gradient'); 39 @include assert-equal($gradient2, $expected2, 'Simple radial gradient');
48 40
49 // --------------------------------------------------------------------------- 41 // ---------------------------------------------------------------------------
50 42
51 $gradient3: gradients.easing-gradient( 43 $gradient3: gradients.easing-gradient(linear,
52 linear, 44 to right,
53 to right, 45 #000 2em,
54 #000 2em, 46 ease-in-quad,
55 ease-in-quad, 47 transparent 10em);
56 transparent 10em
57 );
58 48
59 $expected3: linear-gradient( 49 $expected3: linear-gradient(to right,
60 to right, 50 #000 2em,
61 #000 2em, 51 mix(transparent, #000, easing.ease-in-quad(.25) * 100%) 4em,
62 mix(transparent, #000, easing.ease-in-quad(0.25) * 100%) 4em, 52 mix(transparent, #000, easing.ease-in-quad(.5) * 100%) 6em,
63 mix(transparent, #000, easing.ease-in-quad(0.5) * 100%) 6em, 53 mix(transparent, #000, easing.ease-in-quad(.75) * 100%) 8em,
64 mix(transparent, #000, easing.ease-in-quad(0.75) * 100%) 8em, 54 transparent 10em);
65 transparent 10em
66 );
67 55
68 @include assert-equal($gradient3, $expected3, 'Linear gradient with positioned color stops'); 56 @include assert-equal($gradient3, $expected3, 'Linear gradient with positioned color stops');
69 57
70 // --------------------------------------------------------------------------- 58 // ---------------------------------------------------------------------------
71 59
72 $gradient4: gradients.easing-gradient( 60 $gradient4: gradients.easing-gradient(linear,
73 linear, 61 to right,
74 to right, 62 #000 20%,
75 #000 20%, 63 ease-in-quad,
76 ease-in-quad, 64 transparent calc(20% + 10em));
77 transparent calc(20% + 10em)
78 );
79 65
80 $expected4: linear-gradient( 66 $expected4: linear-gradient(to right,
81 to right, 67 #000 20%,
82 #000 20%, 68 mix(transparent, #000, easing.ease-in-quad(.25) * 100%) calc(20% + (20% + 10em - 20%) * .25),
83 mix(transparent, #000, easing.ease-in-quad(0.25) * 100%) calc(20% + (20% + 10em - 20%) * 0.25), 69 mix(transparent, #000, easing.ease-in-quad(.5) * 100%) calc(20% + (20% + 10em - 20%) * .5),
84 mix(transparent, #000, easing.ease-in-quad(0.5) * 100%) calc(20% + (20% + 10em - 20%) * 0.5), 70 mix(transparent, #000, easing.ease-in-quad(.75) * 100%) calc(20% + (20% + 10em - 20%) * .75),
85 mix(transparent, #000, easing.ease-in-quad(0.75) * 100%) calc(20% + (20% + 10em - 20%) * 0.75), 71 transparent calc(20% + 10em));
86 transparent calc(20% + 10em)
87 );
88 72
89 @include assert-equal($gradient4, $expected4, 'More advanced linear gradient with positioned color stops'); 73 @include assert-equal($gradient4, $expected4, 'More advanced linear gradient with positioned color stops');
90 74
91 // --------------------------------------------------------------------------- 75 // ---------------------------------------------------------------------------
92 76
93 $gradient5: gradients.easing-gradient( 77 $gradient5: gradients.easing-gradient(linear,
94 linear, 78 to right,
95 to right, 79 #000 2em,
96 #000 2em, 80 #f00 7em,
97 #f00 7em, 81 ease-in-quad,
98 ease-in-quad, 82 transparent 10em);
99 transparent 10em
100 );
101 83
102 $expected5: linear-gradient( 84 $expected5: linear-gradient(to right,
103 to right, 85 #000 2em,
104 #000 2em, 86 #f00 7em,
105 #f00 7em, 87 mix(transparent, #f00, easing.ease-in-quad(.25) * 100%) 7em + 3em * .25,
106 mix(transparent, #f00, easing.ease-in-quad(0.25) * 100%) 7em + 3em * 0.25, 88 mix(transparent, #f00, easing.ease-in-quad(.5) * 100%) 7em + 3em * .5,
107 mix(transparent, #f00, easing.ease-in-quad(0.5) * 100%) 7em + 3em * 0.5, 89 mix(transparent, #f00, easing.ease-in-quad(.75) * 100%) 7em + 3em * .75,
108 mix(transparent, #f00, easing.ease-in-quad(0.75) * 100%) 7em + 3em * 0.75, 90 transparent 10em);
109 transparent 10em
110 );
111 91
112 @include assert-equal($gradient5, $expected5, 'Linear gradient with 3 positioned color stops, 1 easing transitions'); 92 @include assert-equal($gradient5, $expected5, 'Linear gradient with 3 positioned color stops, 1 easing transitions');
113 93
114 // --------------------------------------------------------------------------- 94 // ---------------------------------------------------------------------------
115 95
116 $gradient6: gradients.easing-gradient( 96 $gradient6: gradients.easing-gradient(linear,
117 linear, 97 to right,
118 to right, 98 #000 2em,
119 #000 2em, 99 ease-in-quad,
120 ease-in-quad, 100 #f00 7em,
121 #f00 7em, 101 ease-in-quad,
122 ease-in-quad, 102 transparent 10em);
123 transparent 10em
124 );
125 103
126 $expected6: linear-gradient( 104 $expected6: linear-gradient(to right,
127 to right, 105 #000 2em,
128 #000 2em, 106 mix(#f00, #000, easing.ease-in-quad(.25) * 100%) 2em + 5em * .25,
129 mix(#f00, #000, easing.ease-in-quad(0.25) * 100%) 2em + 5em * 0.25, 107 mix(#f00, #000, easing.ease-in-quad(.5) * 100%) 2em + 5em * .5,
130 mix(#f00, #000, easing.ease-in-quad(0.5) * 100%) 2em + 5em * 0.5, 108 mix(#f00, #000, easing.ease-in-quad(.75) * 100%) 2em + 5em * .75,
131 mix(#f00, #000, easing.ease-in-quad(0.75) * 100%) 2em + 5em * 0.75, 109 #f00 7em,
132 #f00 7em, 110 mix(transparent, #f00, easing.ease-in-quad(.25) * 100%) 7em + 3em * .25,
133 mix(transparent, #f00, easing.ease-in-quad(0.25) * 100%) 7em + 3em * 0.25, 111 mix(transparent, #f00, easing.ease-in-quad(.5) * 100%) 7em + 3em * .5,
134 mix(transparent, #f00, easing.ease-in-quad(0.5) * 100%) 7em + 3em * 0.5, 112 mix(transparent, #f00, easing.ease-in-quad(.75) * 100%) 7em + 3em * .75,
135 mix(transparent, #f00, easing.ease-in-quad(0.75) * 100%) 7em + 3em * 0.75, 113 transparent 10em);
136 transparent 10em
137 );
138 114
139 @include assert-equal($gradient6, $expected6, 'Linear gradient with 3 positioned color stops, 2 easing transitions'); 115 @include assert-equal($gradient6, $expected6, 'Linear gradient with 3 positioned color stops, 2 easing transitions');
140 116
141 // --------------------------------------------------------------------------- 117 // ---------------------------------------------------------------------------
142 118
143 $gradient7: gradients.easing-gradient( 119 $gradient7: gradients.easing-gradient(linear,
144 linear, 120 to right,
145 to right, 121 #000 2em,
146 #000 2em, 122 ease-in-quad,
147 ease-in-quad, 123 #f00,
148 #f00, 124 ease-in-quad,
149 ease-in-quad, 125 transparent 10em);
150 transparent 10em
151 );
152 126
153 $expected7: linear-gradient( 127 $expected7: linear-gradient(to right,
154 to right, 128 #000 2em,
155 #000 2em, 129 mix(#f00, #000, easing.ease-in-quad(.25) * 100%) 2em + 4em * .25,
156 mix(#f00, #000, easing.ease-in-quad(0.25) * 100%) 2em + 4em * 0.25, 130 mix(#f00, #000, easing.ease-in-quad(.5) * 100%) 2em + 4em * .5,
157 mix(#f00, #000, easing.ease-in-quad(0.5) * 100%) 2em + 4em * 0.5, 131 mix(#f00, #000, easing.ease-in-quad(.75) * 100%) 2em + 4em * .75,
158 mix(#f00, #000, easing.ease-in-quad(0.75) * 100%) 2em + 4em * 0.75, 132 #f00 6em,
159 #f00 6em, 133 mix(transparent, #f00, easing.ease-in-quad(.25) * 100%) 6em + 4em * .25,
160 mix(transparent, #f00, easing.ease-in-quad(0.25) * 100%) 6em + 4em * 0.25, 134 mix(transparent, #f00, easing.ease-in-quad(.5) * 100%) 6em + 4em * .5,
161 mix(transparent, #f00, easing.ease-in-quad(0.5) * 100%) 6em + 4em * 0.5, 135 mix(transparent, #f00, easing.ease-in-quad(.75) * 100%) 6em + 4em * .75,
162 mix(transparent, #f00, easing.ease-in-quad(0.75) * 100%) 6em + 4em * 0.75, 136 transparent 10em);
163 transparent 10em
164 );
165 137
166 @include assert-equal($gradient7, $expected7, 'Linear gradient with 2 / 3 positioned color stops, 2 easing transitions'); 138 @include assert-equal($gradient7, $expected7, 'Linear gradient with 2 / 3 positioned color stops, 2 easing transitions');
167 139
168 // --------------------------------------------------------------------------- 140 // ---------------------------------------------------------------------------
169 141
170 $gradient8: gradients.easing-gradient( 142 $gradient8: gradients.easing-gradient(linear,
171 linear, 143 to right,
172 to right, 144 #000,
173 #000, 145 ease-in-quad,
174 ease-in-quad, 146 #f00,
175 #f00, 147 ease-in-quad,
176 ease-in-quad, 148 transparent);
177 transparent
178 );
179 149
180 $expected8: linear-gradient( 150 $expected8: linear-gradient(to right,
181 to right, 151 #000 0,
182 #000 0, 152 mix(#f00, #000, easing.ease-in-quad(.25) * 100%) 50% * .25,
183 mix(#f00, #000, easing.ease-in-quad(0.25) * 100%) 50% * 0.25, 153 mix(#f00, #000, easing.ease-in-quad(.5) * 100%) 50% * .5,
184 mix(#f00, #000, easing.ease-in-quad(0.5) * 100%) 50% * 0.5, 154 mix(#f00, #000, easing.ease-in-quad(.75) * 100%) 50% * .75,
185 mix(#f00, #000, easing.ease-in-quad(0.75) * 100%) 50% * 0.75, 155 #f00 50%,
186 #f00 50%, 156 mix(transparent, #f00, easing.ease-in-quad(.25) * 100%) 50% + 50% * .25,
187 mix(transparent, #f00, easing.ease-in-quad(0.25) * 100%) 50% + 50% * 0.25, 157 mix(transparent, #f00, easing.ease-in-quad(.5) * 100%) 50% + 50% * .5,
188 mix(transparent, #f00, easing.ease-in-quad(0.5) * 100%) 50% + 50% * 0.5, 158 mix(transparent, #f00, easing.ease-in-quad(.75) * 100%) 50% + 50% * .75,
189 mix(transparent, #f00, easing.ease-in-quad(0.75) * 100%) 50% + 50% * 0.75, 159 transparent 100%);
190 transparent 100%
191 );
192 160
193 @include assert-equal($gradient8, $expected8, 'Linear gradient with 0 / 3 positioned color stops, 2 easing transitions'); 161 @include assert-equal($gradient8, $expected8, 'Linear gradient with 0 / 3 positioned color stops, 2 easing transitions');
194 162
195 // --------------------------------------------------------------------------- 163 // ---------------------------------------------------------------------------
196 164
197 $gradient9: gradients.easing-gradient( 165 $gradient9: gradients.easing-gradient(linear,
198 linear, 166 to right,
199 to right, 167 #000,
200 #000, 168 ease-in-quad,
201 ease-in-quad, 169 #f00,
202 #f00, 170 ease-in-quad,
203 ease-in-quad, 171 transparent 20em);
204 transparent 20em
205 );
206 172
207 $expected9: linear-gradient( 173 $expected9: linear-gradient(to right,
208 to right, 174 #000 0,
209 #000 0, 175 mix(#f00, #000, easing.ease-in-quad(.25) * 100%) 10em * .25,
210 mix(#f00, #000, easing.ease-in-quad(0.25) * 100%) 10em * 0.25, 176 mix(#f00, #000, easing.ease-in-quad(.5) * 100%) 10em * .5,
211 mix(#f00, #000, easing.ease-in-quad(0.5) * 100%) 10em * 0.5, 177 mix(#f00, #000, easing.ease-in-quad(.75) * 100%) 10em * .75,
212 mix(#f00, #000, easing.ease-in-quad(0.75) * 100%) 10em * 0.75, 178 #f00 10em,
213 #f00 10em, 179 mix(transparent, #f00, easing.ease-in-quad(.25) * 100%) 10em + 10em * .25,
214 mix(transparent, #f00, easing.ease-in-quad(0.25) * 100%) 10em + 10em * 0.25, 180 mix(transparent, #f00, easing.ease-in-quad(.5) * 100%) 10em + 10em * .5,
215 mix(transparent, #f00, easing.ease-in-quad(0.5) * 100%) 10em + 10em * 0.5, 181 mix(transparent, #f00, easing.ease-in-quad(.75) * 100%) 10em + 10em * .75,
216 mix(transparent, #f00, easing.ease-in-quad(0.75) * 100%) 10em + 10em * 0.75, 182 transparent 20em);
217 transparent 20em
218 );
219 183
220 @include assert-equal($gradient9, $expected9, 'Linear gradient with 1 / 3 positioned color stops, 2 easing transitions'); 184 @include assert-equal($gradient9, $expected9, 'Linear gradient with 1 / 3 positioned color stops, 2 easing transitions');
221 185
222 // --------------------------------------------------------------------------- 186 // ---------------------------------------------------------------------------
223 187
224 $gradient10: gradients.easing-gradient( 188 $gradient10: gradients.easing-gradient(linear,
225 linear, 189 to right,
226 to right, 190 #000,
227 #000, 191 cubic-bezier .47 0 .745 .715,
228 cubic-bezier 0.47 0 0.745 0.715, 192 transparent);
229 transparent
230 );
231 193
232 $expected10: linear-gradient( 194 $expected10: linear-gradient(to right,
233 to right, 195 #000 0,
234 #000 0, 196 mix(transparent, #000, easing.cubic-bezier(.47, 0, .745, .715, .25) * 100%) 25%,
235 mix(transparent, #000, easing.cubic-bezier(0.47, 0, 0.745, 0.715, 0.25) * 100%) 25%, 197 mix(transparent, #000, easing.cubic-bezier(.47, 0, .745, .715, .5) * 100%) 50%,
236 mix(transparent, #000, easing.cubic-bezier(0.47, 0, 0.745, 0.715, 0.5) * 100%) 50%, 198 mix(transparent, #000, easing.cubic-bezier(.47, 0, .745, .715, .75) * 100%) 75%,
237 mix(transparent, #000, easing.cubic-bezier(0.47, 0, 0.745, 0.715, 0.75) * 100%) 75%, 199 transparent 100%);
238 transparent 100%
239 );
240 200
241 @include assert-equal($gradient10, $expected10, 'Simple linear gradient with custom cubic-bezier easing'); 201 @include assert-equal($gradient10, $expected10, 'Simple linear gradient with custom cubic-bezier easing');
242 202
243 // --------------------------------------------------------------------------- 203 // ---------------------------------------------------------------------------
244 204
245 $gradient11: gradients.easing-gradient( 205 $gradient11: gradients.easing-gradient(linear,
246 linear, 206 to right,
247 to right, 207 #000,
248 #000, 208 steps 4 jump-start,
249 steps 4 jump-start, 209 transparent);
250 transparent
251 );
252 210
253 $expected11: linear-gradient( 211 $expected11: linear-gradient(to right,
254 to right, 212 #000 0,
255 #000 0, 213 mix(transparent, #000, .25 * 100%) 0,
256 mix(transparent, #000, 0.25 * 100%) 0, 214 mix(transparent, #000, .25 * 100%) 25%,
257 mix(transparent, #000, 0.25 * 100%) 25%, 215 mix(transparent, #000, .5 * 100%) 25%,
258 mix(transparent, #000, 0.5 * 100%) 25%, 216 mix(transparent, #000, .5 * 100%) 50%,
259 mix(transparent, #000, 0.5 * 100%) 50%, 217 mix(transparent, #000, .75 * 100%) 50%,
260 mix(transparent, #000, 0.75 * 100%) 50%, 218 mix(transparent, #000, .75 * 100%) 75%,
261 mix(transparent, #000, 0.75 * 100%) 75%, 219 transparent 75%,
262 transparent 75%, 220 transparent 100%);
263 transparent 100%
264 );
265 221
266 @include assert-equal($gradient11, $expected11, 'Simple linear gradient with custom steps easing'); 222 @include assert-equal($gradient11, $expected11, 'Simple linear gradient with custom steps easing');
267 } 223 }
268} 224}
diff --git a/test/_harmony.scss b/test/_harmony.scss
index c7d309c..3229e8e 100644
--- a/test/_harmony.scss
+++ b/test/_harmony.scss
@@ -4,251 +4,251 @@
4@use '../src/harmony'; 4@use '../src/harmony';
5 5
6@function _limit-decimals($n) { 6@function _limit-decimals($n) {
7 @return math.div(math.floor($n * 1000), 1000); 7 @return math.div(math.floor($n * 1000), 1000);
8} 8}
9 9
10@include describe('harmony') { 10@include describe('harmony') {
11 @include it('modular-scale') { 11 @include it('modular-scale') {
12 @include assert-equal(_limit-decimals(harmony.modular-scale(0, 1em, 1.1)), 1em, 'Zero iterations, 1em base, 1.1 scale'); 12 @include assert-equal(_limit-decimals(harmony.modular-scale(0, 1em, 1.1)), 1em, 'Zero iterations, 1em base, 1.1 scale');
13 @include assert-equal(_limit-decimals(harmony.modular-scale(1, 1em, 1.1)), 1.1em, '1 iteration, 1em base, 1.1 scale'); 13 @include assert-equal(_limit-decimals(harmony.modular-scale(1, 1em, 1.1)), 1.1em, '1 iteration, 1em base, 1.1 scale');
14 @include assert-equal(_limit-decimals(harmony.modular-scale(2, 2px, 1.2)), 2.88px, '2 iterations, 2px base, 1.2 scale'); 14 @include assert-equal(_limit-decimals(harmony.modular-scale(2, 2px, 1.2)), 2.88px, '2 iterations, 2px base, 1.2 scale');
15 @include assert-equal(_limit-decimals(harmony.modular-scale(-1, 2rem, 2)), 1rem, '-1 iteration, 2rem base, 2 scale'); 15 @include assert-equal(_limit-decimals(harmony.modular-scale(-1, 2rem, 2)), 1rem, '-1 iteration, 2rem base, 2 scale');
16 @include assert-equal(_limit-decimals(harmony.modular-scale(-2, 2rem, 2)), 0.5rem, '-2 iterations, 2rem base, 2 scale'); 16 @include assert-equal(_limit-decimals(harmony.modular-scale(-2, 2rem, 2)), .5rem, '-2 iterations, 2rem base, 2 scale');
17 17
18 @include assert-equal(_limit-decimals(harmony.modular-scale(0, 1em 2em, 1.1)), 1em, 'Zero iterations, 1em 2em base, 1.1 scale'); 18 @include assert-equal(_limit-decimals(harmony.modular-scale(0, 1em 2em, 1.1)), 1em, 'Zero iterations, 1em 2em base, 1.1 scale');
19 @include assert-equal(_limit-decimals(harmony.modular-scale(1, 1em 2em, 1.1)), 1.026em, '1 iteration, 1em 2em base, 1.1 scale'); 19 @include assert-equal(_limit-decimals(harmony.modular-scale(1, 1em 2em, 1.1)), 1.026em, '1 iteration, 1em 2em base, 1.1 scale');
20 @include assert-equal(_limit-decimals(harmony.modular-scale(2, 1em 2em, 1.1)), 1.1em, '2 iterations, 1em 2em base, 1.1 scale'); 20 @include assert-equal(_limit-decimals(harmony.modular-scale(2, 1em 2em, 1.1)), 1.1em, '2 iterations, 1em 2em base, 1.1 scale');
21 @include assert-equal(_limit-decimals(harmony.modular-scale(-1, 1em 1.5em, 1.2)), 0.868em, '-1 iteration, 1em 2em base, 1.1 scale'); 21 @include assert-equal(_limit-decimals(harmony.modular-scale(-1, 1em 1.5em, 1.2)), .868em, '-1 iteration, 1em 2em base, 1.1 scale');
22 @include assert-equal(_limit-decimals(harmony.modular-scale(-2, 1em 1.5em, 1.2)), 0.833em, '-2 iterations, 1em 2em base, 1.1 scale'); 22 @include assert-equal(_limit-decimals(harmony.modular-scale(-2, 1em 1.5em, 1.2)), .833em, '-2 iterations, 1em 2em base, 1.1 scale');
23 } 23 }
24 24
25 @include it('responsive-modular-scale') { 25 @include it('responsive-modular-scale') {
26 @include assert('Single-stranded, fluid') { 26 @include assert('Single-stranded, fluid') {
27 $ms: ( 27 $ms: (
28 320px: (1rem, 1.1), 28 320px: (1rem, 1.1),
29 640px: (1rem, 1.2) 29 640px: (1rem, 1.2)
30 ); 30 );
31 31
32 $rem320px: functions.px-to-rem(320px); 32 $rem320px: functions.px-to-rem(320px);
33 $rem640px: functions.px-to-rem(640px); 33 $rem640px: functions.px-to-rem(640px);
34 $diff320px: functions.strip-unit($rem640px - $rem320px); 34 $diff320px: functions.strip-unit($rem640px - $rem320px);
35 35
36 @include output { 36 @include output {
37 h3 { 37 h3 {
38 @include harmony.responsive-modular-scale(font-size, 0, $ms); 38 @include harmony.responsive-modular-scale(font-size, 0, $ms);
39 } 39 }
40 40
41 h2 { 41 h2 {
42 @include harmony.responsive-modular-scale(font-size, 1, $ms); 42 @include harmony.responsive-modular-scale(font-size, 1, $ms);
43 } 43 }
44 44
45 h1 { 45 h1 {
46 @include harmony.responsive-modular-scale(font-size, 2, $ms); 46 @include harmony.responsive-modular-scale(font-size, 2, $ms);
47 } 47 }
48 } 48 }
49 49
50 @include expect { 50 @include expect {
51 h3 { 51 h3 {
52 font-size: 1rem; 52 font-size: 1rem;
53 53
54 @media (min-width: 320px) and (max-width: 640px) { 54 @media (min-width: 320px) and (max-width: 640px) {
55 font-size: calc(1rem + 0 * (100vw - #{$rem320px}) / #{$diff320px}); 55 font-size: calc(1rem + 0 * (100vw - #{$rem320px}) / #{$diff320px});
56 } 56 }
57 57
58 @media (min-width: 640px) { 58 @media (min-width: 640px) {
59 font-size: 1rem; 59 font-size: 1rem;
60 } 60 }
61 } 61 }
62 62
63 h2 { 63 h2 {
64 font-size: 1.1rem; 64 font-size: 1.1rem;
65 65
66 @media (min-width: 320px) and (max-width: 640px) { 66 @media (min-width: 320px) and (max-width: 640px) {
67 font-size: calc(1.1rem + 0.1 * (100vw - #{$rem320px}) / #{$diff320px}); 67 font-size: calc(1.1rem + .1 * (100vw - #{$rem320px}) / #{$diff320px});
68 } 68 }
69 69
70 @media (min-width: 640px) { 70 @media (min-width: 640px) {
71 font-size: 1.2rem; 71 font-size: 1.2rem;
72 } 72 }
73 } 73 }
74 74
75 h1 { 75 h1 {
76 font-size: 1.21rem; 76 font-size: 1.21rem;
77 77
78 @media (min-width: 320px) and (max-width: 640px) { 78 @media (min-width: 320px) and (max-width: 640px) {
79 font-size: calc(1.21rem + 0.23 * (100vw - #{$rem320px}) / #{$diff320px}); 79 font-size: calc(1.21rem + .23 * (100vw - #{$rem320px}) / #{$diff320px});
80 } 80 }
81 81
82 @media (min-width: 640px) { 82 @media (min-width: 640px) {
83 font-size: 1.44rem; 83 font-size: 1.44rem;
84 } 84 }
85 } 85 }
86 } 86 }
87 } 87 }
88 88
89 @include assert('Single-stranded, non-fluid') { 89 @include assert('Single-stranded, non-fluid') {
90 $ms: ( 90 $ms: (
91 320px: (1rem, 1.1), 91 320px: (1rem, 1.1),
92 640px: (1rem, 1.2) 92 640px: (1rem, 1.2)
93 ); 93 );
94 94
95 $rem320px: functions.px-to-rem(320px); 95 $rem320px: functions.px-to-rem(320px);
96 $rem640px: functions.px-to-rem(640px); 96 $rem640px: functions.px-to-rem(640px);
97 $diff320px: functions.strip-unit($rem640px - $rem320px); 97 $diff320px: functions.strip-unit($rem640px - $rem320px);
98 98
99 @include output { 99 @include output {
100 h3 { 100 h3 {
101 @include harmony.responsive-modular-scale(font-size, 0, $ms, false); 101 @include harmony.responsive-modular-scale(font-size, 0, $ms, false);
102 } 102 }
103 103
104 h2 { 104 h2 {
105 @include harmony.responsive-modular-scale(font-size, 1, $ms, false); 105 @include harmony.responsive-modular-scale(font-size, 1, $ms, false);
106 } 106 }
107 107
108 h1 { 108 h1 {
109 @include harmony.responsive-modular-scale(font-size, 2, $ms, false); 109 @include harmony.responsive-modular-scale(font-size, 2, $ms, false);
110 } 110 }
111 } 111 }
112 112
113 @include expect { 113 @include expect {
114 h3 { 114 h3 {
115 font-size: 1rem; 115 font-size: 1rem;
116 116
117 @media (min-width: 640px) { 117 @media (min-width: 640px) {
118 font-size: 1rem; 118 font-size: 1rem;
119 } 119 }
120 } 120 }
121 121
122 h2 { 122 h2 {
123 font-size: 1.1rem; 123 font-size: 1.1rem;
124 124
125 @media (min-width: 640px) { 125 @media (min-width: 640px) {
126 font-size: 1.2rem; 126 font-size: 1.2rem;
127 } 127 }
128 } 128 }
129 129
130 h1 { 130 h1 {
131 font-size: 1.21rem; 131 font-size: 1.21rem;
132 132
133 @media (min-width: 640px) { 133 @media (min-width: 640px) {
134 font-size: 1.44rem; 134 font-size: 1.44rem;
135 } 135 }
136 } 136 }
137 } 137 }
138 } 138 }
139 139
140 @include assert('Double-stranded, fluid') { 140 @include assert('Double-stranded, fluid') {
141 $ms: ( 141 $ms: (
142 320px: (1rem 2rem, 1.1), 142 320px: (1rem 2rem, 1.1),
143 640px: (1rem 2rem, 1.2) 143 640px: (1rem 2rem, 1.2)
144 ); 144 );
145 145
146 $rem320px: functions.px-to-rem(320px); 146 $rem320px: functions.px-to-rem(320px);
147 $rem640px: functions.px-to-rem(640px); 147 $rem640px: functions.px-to-rem(640px);
148 $diff320px: functions.strip-unit($rem640px - $rem320px); 148 $diff320px: functions.strip-unit($rem640px - $rem320px);
149 149
150 @include output { 150 @include output {
151 h3 { 151 h3 {
152 @include harmony.responsive-modular-scale(font-size, 0, $ms); 152 @include harmony.responsive-modular-scale(font-size, 0, $ms);
153 } 153 }
154 154
155 h2 { 155 h2 {
156 @include harmony.responsive-modular-scale(font-size, 1, $ms); 156 @include harmony.responsive-modular-scale(font-size, 1, $ms);
157 } 157 }
158 158
159 h1 { 159 h1 {
160 @include harmony.responsive-modular-scale(font-size, 2, $ms); 160 @include harmony.responsive-modular-scale(font-size, 2, $ms);
161 } 161 }
162 } 162 }
163 163
164 @include expect { 164 @include expect {
165 h3 { 165 h3 {
166 font-size: 1rem; 166 font-size: 1rem;
167 167
168 @media (min-width: 320px) and (max-width: 640px) { 168 @media (min-width: 320px) and (max-width: 640px) {
169 font-size: calc(1rem + 0 * (100vw - #{$rem320px}) / #{$diff320px}); 169 font-size: calc(1rem + 0 * (100vw - #{$rem320px}) / #{$diff320px});
170 } 170 }
171 171
172 @media (min-width: 640px) { 172 @media (min-width: 640px) {
173 font-size: 1rem; 173 font-size: 1rem;
174 } 174 }
175 } 175 }
176 176
177 h2 { 177 h2 {
178 font-size: 1.0263162365rem; 178 font-size: 1.0263162365rem;
179 179
180 @media (min-width: 320px) and (max-width: 640px) { 180 @media (min-width: 320px) and (max-width: 640px) {
181 font-size: calc(1.0263162365rem + 0.1310911709 * (100vw - #{$rem320px}) / #{$diff320px}); 181 font-size: calc(1.0263162365rem + .1310911709 * (100vw - #{$rem320px}) / #{$diff320px});
182 } 182 }
183 183
184 @media (min-width: 640px) { 184 @media (min-width: 640px) {
185 font-size: 1.1574074074rem; 185 font-size: 1.1574074074rem;
186 } 186 }
187 } 187 }
188 188
189 h1 { 189 h1 {
190 font-size: 1.1rem; 190 font-size: 1.1rem;
191 191
192 @media (min-width: 320px) and (max-width: 640px) { 192 @media (min-width: 320px) and (max-width: 640px) {
193 font-size: calc(1.1rem + 0.1 * (100vw - #{$rem320px}) / #{$diff320px}); 193 font-size: calc(1.1rem + .1 * (100vw - #{$rem320px}) / #{$diff320px});
194 } 194 }
195 195
196 @media (min-width: 640px) { 196 @media (min-width: 640px) {
197 font-size: 1.2rem; 197 font-size: 1.2rem;
198 } 198 }
199 } 199 }
200 } 200 }
201 } 201 }
202 202
203 @include assert('Double-stranded, non-fluid') { 203 @include assert('Double-stranded, non-fluid') {
204 $ms: ( 204 $ms: (
205 320px: (1rem 2rem, 1.1), 205 320px: (1rem 2rem, 1.1),
206 640px: (1rem 2rem, 1.2) 206 640px: (1rem 2rem, 1.2)
207 ); 207 );
208 208
209 $rem320px: functions.px-to-rem(320px); 209 $rem320px: functions.px-to-rem(320px);
210 $rem640px: functions.px-to-rem(640px); 210 $rem640px: functions.px-to-rem(640px);
211 $diff320px: functions.strip-unit($rem640px - $rem320px); 211 $diff320px: functions.strip-unit($rem640px - $rem320px);
212 212
213 @include output { 213 @include output {
214 h3 { 214 h3 {
215 @include harmony.responsive-modular-scale(font-size, 0, $ms, false); 215 @include harmony.responsive-modular-scale(font-size, 0, $ms, false);
216 } 216 }
217 217
218 h2 { 218 h2 {
219 @include harmony.responsive-modular-scale(font-size, 1, $ms, false); 219 @include harmony.responsive-modular-scale(font-size, 1, $ms, false);
220 } 220 }
221 221
222 h1 { 222 h1 {
223 @include harmony.responsive-modular-scale(font-size, 2, $ms, false); 223 @include harmony.responsive-modular-scale(font-size, 2, $ms, false);
224 } 224 }
225 } 225 }
226 226
227 @include expect { 227 @include expect {
228 h3 { 228 h3 {
229 font-size: 1rem; 229 font-size: 1rem;
230 230
231 @media (min-width: 640px) { 231 @media (min-width: 640px) {
232 font-size: 1rem; 232 font-size: 1rem;
233 } 233 }
234 } 234 }
235 235
236 h2 { 236 h2 {
237 font-size: 1.0263162365rem;; 237 font-size: 1.0263162365rem;
238 238
239 @media (min-width: 640px) { 239 @media (min-width: 640px) {
240 font-size: 1.1574074074rem;; 240 font-size: 1.1574074074rem;;
241 } 241 }
242 } 242 }
243 243
244 h1 { 244 h1 {
245 font-size: 1.1rem; 245 font-size: 1.1rem;
246 246
247 @media (min-width: 640px) { 247 @media (min-width: 640px) {
248 font-size: 1.2rem; 248 font-size: 1.2rem;
249 } 249 }
250 } 250 }
251 } 251 }
252 } 252 }
253 } 253 }
254} 254}
diff --git a/test/_props.scss b/test/_props.scss
index 1d64080..f8c85ee 100644
--- a/test/_props.scss
+++ b/test/_props.scss
@@ -6,300 +6,273 @@
6@use '../src/props'; 6@use '../src/props';
7 7
8@include describe('Property trees') { 8@include describe('Property trees') {
9 @include it('Validate names') { 9 @include it('Save / Delete') {
10 $map-valid: ( 10 $map: (
11 --background: #fff, 11 --background: #fff,
12 --text: #000, 12 --text: #000,
13 --buttons: ( 13 --buttons: (
14 --primary: ( 14 --primary: (
15 --background: #f00, 15 --background: #f00,
16 --text: #fff 16 --text: #fff
17 ) 17 )
18 ) 18 )
19 ); 19 );
20 20
21 $map-invalid: ( 21 @include assert-equal(props.store($map), null, 'Save default tree');
22 --background: #fff, 22 @include assert-equal(props.clear(), null, 'Delete default tree');
23 --text: #000, 23 }
24 --buttons: (
25 --primary: (
26 background: #f00,
27 text: #fff
28 )
29 )
30 );
31 24
32 @include assert-equal(props.validate($map-valid), true, 'Check valid map'); 25 @include it('Read') {
33 @include assert-equal(props.validate($map-invalid), false, 'Check invalid map'); 26 $map1: (
34 } 27 --background: #fff,
28 --text: #000,
29 --buttons: (
30 --primary: (
31 --background: #f00,
32 --text: #fff
33 )
34 )
35 );
35 36
36 @include it('Save / Delete') { 37 $map2: (
37 $map: ( 38 --background: #222,
38 --background: #fff, 39 --text: #fff,
39 --text: #000, 40 --buttons: (
40 --buttons: ( 41 --primary: (
41 --primary: ( 42 --background: #f00,
42 --background: #f00, 43 --text: #fff
43 --text: #fff 44 )
44 ) 45 )
45 ) 46 );
46 );
47 47
48 @include assert-equal(props.store($map), null, 'Save default tree'); 48 $map3: (
49 @include assert-equal(props.clear(), null, 'Delete default tree'); 49 --background: #666,
50 } 50 --text: #222,
51 --buttons: (
52 --primary: (
53 --background: #0f0,
54 --text: #000
55 )
56 )
57 );
51 58
52 @include it('Read') { 59 @include assert-equal(props.store($map1), null, 'Save default tree');
53 $map1: ( 60 @include assert-equal(props.store($map2, 'test'), null, 'Save "test" tree');
54 --background: #fff,
55 --text: #000,
56 --buttons: (
57 --primary: (
58 --background: #f00,
59 --text: #fff
60 )
61 )
62 );
63 61
64 $map2: ( 62 @include props.namespace('ns') {
65 --background: #222, 63 @include assert-equal(props.store($map3, 'namespaced'), null, 'Save "namespaced" tree');
66 --text: #fff, 64 }
67 --buttons: (
68 --primary: (
69 --background: #f00,
70 --text: #fff
71 )
72 )
73 );
74 65
75 $map3: ( 66 @include assert-equal(props.get-static(--background), map.get($map1, --background), 'Get --background in default');
76 --background: #666, 67 @include assert-equal(props.get-static(--buttons --primary --background), map.get($map1, --buttons, --primary, --background), 'Get --buttons --primary --background in default');
77 --text: #222, 68 @include assert-equal(props.get-static(--box, $default: false), false, 'Get nonexistent in default');
78 --buttons: (
79 --primary: (
80 --background: #0f0,
81 --text: #000
82 )
83 )
84 );
85 69
86 @include assert-equal(props.store($map1), null, 'Save default tree'); 70 @include assert-equal(props.get-static(--background, 'test'), map.get($map2, --background), 'Get --background in "test"');
87 @include assert-equal(props.store($map2, 'test'), null, 'Save "test" tree'); 71 @include assert-equal(props.get-static(--buttons --primary --background, 'test'), map.get($map2, --buttons, --primary, --background), 'Get --buttons --primary --background in "test"');
72 @include assert-equal(props.get-static(--box, 'test', $default: false), false, 'Get nonexistent in "test"');
73
74 @include assert-equal(props.get-static(--background, 'namespaced', $default: false), false, 'Get --background in "namespaced"');
75 @include assert-equal(props.get-static(--ns --background, 'namespaced'), map.get($map3, --background), 'Get --ns --background in "namespaced"');
76 @include props.namespace('ns') {
77 @include assert-equal(props.get-static(--background, 'namespaced'), map.get($map3, --background), 'Get namespaced --background in "namespaced"');
78 @include assert-equal(props.get-static(--buttons --primary --background, 'namespaced'), map.get($map3, --buttons, --primary, --background), 'Get namespaced --buttons --primary --background in "namespaced"');
79 @include assert-equal(props.get-static(--box, 'namespaced', $default: false), false, 'Get namespaced nonexistent in "namespaced"');
80 }
88 81
89 @include props.namespace('ns') { 82 @include assert-equal(props.clear(), null, 'Delete default tree');
90 @include assert-equal(props.store($map3, 'namespaced'), null, 'Save "namespaced" tree'); 83 @include assert-equal(props.clear('test'), null, 'Delete "test" tree');
91 } 84 @include assert-equal(props.clear('namespaced'), null, 'Delete "namespaced" tree');
85 }
92 86
93 @include assert-equal(props.get-static(--background), map-get($map1, --background), 'Get --background in default'); 87 @include it('Overwrite') {
94 @include assert-equal(props.get-static(--buttons --primary --background), map-get($map1, --buttons, --primary, --background), 'Get --buttons --primary --background in default'); 88 $map1: (
95 @include assert-equal(props.get-static(--box, $default: false), false, 'Get nonexistent in default'); 89 --background: #fff,
90 --buttons: (
91 --primary: (
92 --background: #f00,
93 --text: #fff
94 )
95 )
96 );
96 97
97 @include assert-equal(props.get-static(--background, 'test'), map-get($map2, --background), 'Get --background in "test"'); 98 $map2: (
98 @include assert-equal(props.get-static(--buttons --primary --background, 'test'), map-get($map2, --buttons, --primary, --background), 'Get --buttons --primary --background in "test"'); 99 --background: #eee,
99 @include assert-equal(props.get-static(--box, 'test', $default: false), false, 'Get nonexistent in "test"'); 100 --text: #000,
100 101 --buttons: (
101 @include assert-equal(props.get-static(--background, 'namespaced', $default: false), false, 'Get --background in "namespaced"'); 102 --primary: (
102 @include assert-equal(props.get-static(--ns --background, 'namespaced'), map-get($map3, --background), 'Get --ns --background in "namespaced"'); 103 --background: #00f
103 @include props.namespace('ns') { 104 )
104 @include assert-equal(props.get-static(--background, 'namespaced'), map-get($map3, --background), 'Get namespaced --background in "namespaced"'); 105 )
105 @include assert-equal(props.get-static(--buttons --primary --background, 'namespaced'), map-get($map3, --buttons, --primary, --background), 'Get namespaced --buttons --primary --background in "namespaced"'); 106 );
106 @include assert-equal(props.get-static(--box, 'namespaced', $default: false), false, 'Get namespaced nonexistent in "namespaced"');
107 }
108 107
109 @include assert-equal(props.clear(), null, 'Delete default tree'); 108 @include assert-equal(props.store($map1), null, 'Save default tree');
110 @include assert-equal(props.clear('test'), null, 'Delete "test" tree'); 109 @include assert-equal(props.store($map2, $merge: true), null, 'Overwrite default tree');
111 @include assert-equal(props.clear('namespaced'), null, 'Delete "namespaced" tree');
112 }
113 110
114 @include it('Overwrite') { 111 @include assert-equal(props.get-static(), map.deep-merge($map1, $map2), 'After update, get whole map');
115 $map1: ( 112 @include assert-equal(props.get-static(--background), map.get($map2, --background), 'After update, get --background');
116 --background: #fff, 113 @include assert-equal(props.get-static(--text), map.get($map2, --text), 'After update, get --text');
117 --buttons: ( 114 @include assert-equal(props.get-static(--buttons --primary --text), map.get($map1, --buttons, --primary, --text), 'After update, get --buttons --primary --text');
118 --primary: (
119 --background: #f00,
120 --text: #fff
121 )
122 )
123 );
124 115
125 $map2: ( 116 @include assert-equal(props.clear(), null, 'Delete default tree');
126 --background: #eee, 117 }
127 --text: #000,
128 --buttons: (
129 --primary: (
130 --background: #00f
131 )
132 )
133 );
134 118
135 @include assert-equal(props.store($map1), null, 'Save default tree'); 119 @include it('Native assignment') {
136 @include assert-equal(props.store($map2, $merge: true), null, 'Overwrite default tree'); 120 $map: (
121 --background: #fff,
122 --text: #000,
123 --buttons: (
124 --primary: (
125 --background: #f00,
126 --text: #fff
127 ),
128 --default: (
129 --background: #ddd,
130 --text: #000
131 )
132 )
133 );
137 134
138 @include assert-equal(props.get-static(), map.deep-merge($map1, $map2), 'After update, get whole map'); 135 @include assert('Simple') {
139 @include assert-equal(props.get-static(--background), map-get($map2, --background), 'After update, get --background'); 136 @include props.store($map);
140 @include assert-equal(props.get-static(--text), map-get($map2, --text), 'After update, get --text');
141 @include assert-equal(props.get-static(--buttons --primary --text), map-get($map1, --buttons, --primary, --text), 'After update, get --buttons --primary --text');
142 137
143 @include assert-equal(props.clear(), null, 'Delete default tree'); 138 @include output {
144 } 139 @include props.assign;
140 }
145 141
146 @include it('Native assignment') { 142 @include expect {
147 $map: ( 143 --background: #{map.get($map, --background)};
148 --background: #fff, 144 --text: #{map.get($map, --text)};
149 --text: #000, 145 --buttons--primary--background: #{map.get($map, --buttons, --primary, --background)};
150 --buttons: ( 146 --buttons--primary--text: #{map.get($map, --buttons, --primary, --text)};
151 --primary: ( 147 --buttons--default--background: #{map.get($map, --buttons, --default, --background)};
152 --background: #f00, 148 --buttons--default--text: #{map.get($map, --buttons, --default, --text)};
153 --text: #fff 149 }
154 ),
155 --default: (
156 --background: #ddd,
157 --text: #000
158 )
159 )
160 );
161 150
162 @include assert('Simple') { 151 @include props.clear;
163 @include props.store($map); 152 }
164 153
165 @include output { 154 @include assert('Filtered') {
166 @include props.assign; 155 @include props.store($map);
167 }
168 156
169 @include expect { 157 @include output {
170 --background: #{map-get($map, --background)}; 158 @include props.assign($skip: --buttons);
171 --text: #{map-get($map, --text)}; 159 }
172 --buttons--primary--background: #{map-get($map, --buttons, --primary, --background)};
173 --buttons--primary--text: #{map-get($map, --buttons, --primary, --text)};
174 --buttons--default--background: #{map-get($map, --buttons, --default, --background)};
175 --buttons--default--text: #{map-get($map, --buttons, --default, --text)};
176 }
177 160
178 @include props.clear; 161 @include expect {
179 } 162 --background: #{map.get($map, --background)};
163 --text: #{map.get($map, --text)};
164 }
180 165
181 @include assert('Filtered') { 166 @include props.clear;
182 @include props.store($map); 167 }
183 168
184 @include output { 169 @include assert('Namespaced') {
185 @include props.assign($skip: --buttons); 170 @include props.namespace('ns') {
186 } 171 @include props.store($map);
172 }
187 173
188 @include expect { 174 @include output {
189 --background: #{map-get($map, --background)}; 175 @include props.assign;
190 --text: #{map-get($map, --text)}; 176 }
191 }
192 177
193 @include props.clear; 178 @include expect {
194 } 179 --ns--background: #{map.get($map, --background)};
180 --ns--text: #{map.get($map, --text)};
181 --ns--buttons--primary--background: #{map.get($map, --buttons, --primary, --background)};
182 --ns--buttons--primary--text: #{map.get($map, --buttons, --primary, --text)};
183 --ns--buttons--default--background: #{map.get($map, --buttons, --default, --background)};
184 --ns--buttons--default--text: #{map.get($map, --buttons, --default, --text)};
185 }
195 186
196 @include assert('Namespaced') { 187 @include props.clear;
197 @include props.namespace('ns') { 188 }
198 @include props.store($map); 189 }
199 }
200 190
201 @include output { 191 @include it('Native get') {
202 @include props.assign; 192 $map: (
203 } 193 --background: #fff,
194 --text: #000,
195 --buttons: (
196 --primary: (
197 --background: #f00,
198 --text: #fff
199 ),
200 --default: (
201 --background: #ddd,
202 --text: #000
203 )
204 )
205 );
204 206
205 @include expect { 207 @include assert-equal(props.store($map), null, 'Save default tree');
206 --ns--background: #{map-get($map, --background)};
207 --ns--text: #{map-get($map, --text)};
208 --ns--buttons--primary--background: #{map-get($map, --buttons, --primary, --background)};
209 --ns--buttons--primary--text: #{map-get($map, --buttons, --primary, --text)};
210 --ns--buttons--default--background: #{map-get($map, --buttons, --default, --background)};
211 --ns--buttons--default--text: #{map-get($map, --buttons, --default, --text)};
212 }
213 208
214 @include props.clear; 209 @include assert-equal(props.get(--background), var(--background), 'Get --background');
215 } 210 @include assert-equal(props.get(--buttons --primary --text), var(--buttons--primary--text), 'Get --buttons --primary --text');
216 } 211 @include assert-equal(props.get(--buttons --secondary --text, $default: false), var(--buttons--secondary--text, false), 'Get --buttons --secondary --text with default');
212 @include props.namespace('buttons') {
213 @include assert-equal(props.get(--primary --text), var(--buttons--primary--text), 'Get via namespace "buttons" --primary --text');
214 @include assert-equal(props.get(--secondary --text, $default: false), var(--buttons--secondary--text, false), 'Get via namespace "buttons" --secondary --text with default');
215 }
216 @include assert-equal(props.get(--buttons), (
217 --primary: (
218 --background: var(--buttons--primary--background),
219 --text: var(--buttons--primary--text)
220 ),
221 --default: (
222 --background: var(--buttons--default--background),
223 --text: var(--buttons--default--text)
224 )
225 ), 'Get --buttons recursively');
217 226
218 @include it('Native get') { 227 @include assert-equal(props.clear(), null, 'Delete default tree');
219 $map: ( 228 }
220 --background: #fff,
221 --text: #000,
222 --buttons: (
223 --primary: (
224 --background: #f00,
225 --text: #fff
226 ),
227 --default: (
228 --background: #ddd,
229 --text: #000
230 )
231 )
232 );
233 229
234 @include assert-equal(props.store($map), null, 'Save default tree'); 230 @include it('References') {
231 $map1: (
232 --background: #fff,
233 --text: #000,
234 --buttons: (
235 --primary: (
236 --background: #f00,
237 --text: #fff
238 )
239 )
240 );
235 241
236 @include assert-equal(props.get(--background), var(--background), 'Get --background'); 242 $map2: (
237 @include assert-equal(props.get(--buttons --primary --text), var(--buttons--primary--text), 'Get --buttons --primary --text'); 243 --background: #eee,
238 @include assert-equal(props.get(--buttons --secondary --text, $default: false), var(--buttons--secondary--text, false), 'Get --buttons --secondary --text with default'); 244 --buttons: (
239 @include props.namespace('buttons') { 245 --primary: (
240 @include assert-equal(props.get(--primary --text), var(--buttons--primary--text), 'Get via namespace "buttons" --primary --text'); 246 --background: props.ref($key: --background)
241 @include assert-equal(props.get(--secondary --text, $default: false), var(--buttons--secondary--text, false), 'Get via namespace "buttons" --secondary --text with default'); 247 ),
242 } 248 --default: props.ref($key: --buttons --primary)
243 @include assert-equal(props.get(--buttons), ( 249 )
244 --primary: ( 250 );
245 --background: var(--buttons--primary--background),
246 --text: var(--buttons--primary--text)
247 ),
248 --default: (
249 --background: var(--buttons--default--background),
250 --text: var(--buttons--default--text)
251 )
252 ), 'Get --buttons recursively');
253 251
254 @include assert-equal(props.clear(), null, 'Delete default tree'); 252 @include assert-equal(props.store($map1), null, 'Save default tree');
255 } 253 @include assert-equal(props.store($map2, 'second'), null, 'Save "second" tree');
256 254
257 @include it('References') { 255 @include assert-equal(props.get-static(--buttons --primary --background, 'second'), map.get($map1, --background), 'Get referenced value');
258 $map1: ( 256 @include assert-equal(props.get(--buttons --primary --background, 'second'), var(--buttons--primary--background), 'Get referenced value, native');
259 --background: #fff,
260 --text: #000,
261 --buttons: (
262 --primary: (
263 --background: #f00,
264 --text: #fff
265 )
266 )
267 );
268 257
269 $map2: ( 258 @include assert-equal(props.get-static(--buttons --default, 'second'), map.get($map1, --buttons, --primary), 'Get referenced subtree, whole');
270 --background: #eee, 259 @include assert-equal(props.get-static(--buttons --default --background, 'second'), map.get($map1, --buttons, --primary, --background), 'Get referenced subtree, inner value');
271 --buttons: ( 260 @include assert-equal(props.get(--buttons --default --background, 'second'), var(--buttons--default--background), 'Get referenced subtree, native');
272 --primary: ( 261
273 --background: props.ref($key: --background) 262 @include assert('Native assignment') {
274 ), 263 @include output {
275 --default: props.ref($key: --buttons --primary) 264 @include props.assign('second');
276 ) 265 }
277 );
278 266
279 @include assert-equal(props.store($map1), null, 'Save default tree'); 267 @include expect {
280 @include assert-equal(props.store($map2, 'second'), null, 'Save "second" tree'); 268 --background: #{map.get($map2, --background)};
269 --buttons--primary--background: #{map.get($map1, --background)};
270 --buttons--default--background: #{map.get($map1, --buttons, --primary, --background)};
271 --buttons--default--text: #{map.get($map1, --buttons, --primary, --text)};
272 }
273 }
281 274
282 @include assert-equal(props.get-static(--buttons --primary --background, 'second'), map-get($map1, --background), 'Get referenced value'); 275 @include assert-equal(props.clear(), null, 'Delete default tree');
283 @include assert-equal(props.get(--buttons --primary --background, 'second'), var(--buttons--primary--background), 'Get referenced value, native'); 276 @include assert-equal(props.clear('second'), null, 'Delete "second" tree');
284 277 }
285 @include assert-equal(props.get-static(--buttons --default, 'second'), map-get($map1, --buttons, --primary), 'Get referenced subtree, whole');
286 @include assert-equal(props.get-static(--buttons --default --background, 'second'), map-get($map1, --buttons, --primary, --background), 'Get referenced subtree, inner value');
287 @include assert-equal(props.get(--buttons --default --background, 'second'), var(--buttons--default--background), 'Get referenced subtree, native');
288
289 @include assert('Native assignment') {
290 @include output {
291 @include props.assign('second');
292 }
293
294 @include expect {
295 --background: #{map-get($map2, --background)};
296 --buttons--primary--background: #{map-get($map1, --background)};
297 --buttons--default--background: #{map-get($map1, --buttons, --primary, --background)};
298 --buttons--default--text: #{map-get($map1, --buttons, --primary, --text)};
299 }
300 }
301
302 @include assert-equal(props.clear(), null, 'Delete default tree');
303 @include assert-equal(props.clear('second'), null, 'Delete "second" tree');
304 }
305} 278}
diff --git a/test/_responsive.scss b/test/_responsive.scss
index 6780ae6..aa76cfd 100644
--- a/test/_responsive.scss
+++ b/test/_responsive.scss
@@ -3,11 +3,11 @@
3@use '../src/responsive'; 3@use '../src/responsive';
4 4
5@include describe('responsive') { 5@include describe('responsive') {
6 @include it('fluid-calc') { 6 @include it('fluid-calc') {
7 $rem600px: functions.px-to-rem(600px); 7 $rem600px: functions.px-to-rem(600px);
8 $rem800px: functions.px-to-rem(800px); 8 $rem800px: functions.px-to-rem(800px);
9 9
10 @include assert-equal('#{responsive.fluid-calc(2rem, 4rem, 600px, 800px)}', 'calc(2rem + 2 * (100vw - #{$rem600px}) / #{functions.strip-unit($rem800px - $rem600px)})', 'Responsive value from 2rem to 4rem over 600px to 800px'); 10 @include assert-equal('#{responsive.fluid-calc(2rem, 4rem, 600px, 800px)}', 'calc(2rem + 2 * (100vw - #{$rem600px}) / #{functions.strip-unit($rem800px - $rem600px)})', 'Responsive value from 2rem to 4rem over 600px to 800px');
11 @include assert-equal('#{responsive.fluid-calc(4px, 12px, 600px, 800px)}', 'calc(4px + 8 * (100vw - 600px) / 200)', 'Responsive value from 4px to 12px over 600px to 800px'); 11 @include assert-equal('#{responsive.fluid-calc(4px, 12px, 600px, 800px)}', 'calc(4px + 8 * (100vw - 600px) / 200)', 'Responsive value from 4px to 12px over 600px to 800px');
12 } 12 }
13} 13}
diff --git a/test/bem/_at-theme.scss b/test/bem/_at-theme.scss
index 29a4eba..83ea4d1 100644
--- a/test/bem/_at-theme.scss
+++ b/test/bem/_at-theme.scss
@@ -10,49 +10,49 @@
10// 10//
11 11
12@include it('at-theme') { 12@include it('at-theme') {
13 @include assert('single theme') { /// 1 /// 13 @include assert('single theme') { /// 1 ///
14 @include output(false) { 14 @include output(false) {
15 @include bem.block('something') { 15 @include bem.block('something') {
16 @include bem.at-theme('theme') { 16 @include bem.at-theme('theme') {
17 font-size: 2em; 17 font-size: 2em;
18 } 18 }
19 } 19 }
20 } 20 }
21 21
22 @include expect(false) { 22 @include expect(false) {
23 .t-theme .something, 23 .t-theme .something,
24 [class*=' t-'] .t-theme .something, 24 [class*=' t-'] .t-theme .something,
25 [class^='t-'] .t-theme .something { 25 [class^='t-'] .t-theme .something {
26 font-size: 2em; 26 font-size: 2em;
27 } 27 }
28 } 28 }
29 } 29 }
30 30
31 @include assert('with sub-theme') { /// 2 /// 31 @include assert('with sub-theme') { /// 2 ///
32 @include output(false) { 32 @include output(false) {
33 @include bem.block('something') { 33 @include bem.block('something') {
34 @include bem.at-theme('theme') { 34 @include bem.at-theme('theme') {
35 font-size: 2em; 35 font-size: 2em;
36 } 36 }
37 37
38 @include bem.at-theme('theme', 'subtheme') { 38 @include bem.at-theme('theme', 'subtheme') {
39 font-size: 3em; 39 font-size: 3em;
40 } 40 }
41 } 41 }
42 } 42 }
43 43
44 @include expect(false) { 44 @include expect(false) {
45 .t-theme .something, 45 .t-theme .something,
46 [class*=' t-'] .t-theme .something, 46 [class*=' t-'] .t-theme .something,
47 [class^='t-'] .t-theme .something { 47 [class^='t-'] .t-theme .something {
48 font-size: 2em; 48 font-size: 2em;
49 } 49 }
50 50
51 .t-theme .t-subtheme .something, 51 .t-theme .t-subtheme .something,
52 [class*=' t-'] .t-theme .t-subtheme .something, 52 [class*=' t-'] .t-theme .t-subtheme .something,
53 [class^='t-'] .t-theme .t-subtheme .something { 53 [class^='t-'] .t-theme .t-subtheme .something {
54 font-size: 3em; 54 font-size: 3em;
55 } 55 }
56 } 56 }
57 } 57 }
58} 58}
diff --git a/test/bem/_block.scss b/test/bem/_block.scss
index fb3a545..e883567 100644
--- a/test/bem/_block.scss
+++ b/test/bem/_block.scss
@@ -1,5 +1,6 @@
1// sass-lint:disable class-name-format force-element-nesting force-pseudo-nesting mixins-before-declarations 1// sass-lint:disable class-name-format force-element-nesting force-pseudo-nesting mixins-before-declarations
2 2
3@use 'sass:map';
3@use 'true' as *; 4@use 'true' as *;
4@use '../../src/bem'; 5@use '../../src/bem';
5 6
@@ -12,77 +13,83 @@
12// 13//
13 14
14@include it('block') { 15@include it('block') {
15 @include assert('without namespace') { /// 1 /// 16 @include assert('without namespace') { /// 1 ///
16 @include output(false) { 17 @include output(false) {
17 @include bem.block('something') { 18 @include bem.block('something') {
18 font-size: 1em; 19 font-size: 1em;
19 } 20 }
20 } 21 }
21 22
22 @include expect(false) { 23 @include expect(false) {
23 .something { 24 .something {
24 font-size: 1em; 25 font-size: 1em;
25 } 26 }
26 } 27 }
27 } 28 }
28 29
29 @each $ns in map-keys(bem.$namespaces) { 30 @each $ns in map.keys(bem.$namespaces) {
30 @include assert('with namespace "#{$ns}"') { /// 2 /// 31 @include assert('with namespace "#{$ns}"') { /// 2 ///
31 @include output(false) { 32 @include output(false) {
32 @include bem.block('something', $ns) { 33 @include bem.block('something', $ns) {
33 font-size: 1em; 34 font-size: 1em;
34 } 35 }
35 } 36 }
36 37
37 @include expect(false) { 38 @include expect(false) {
38 @if $ns != 'theme' { 39 @layer #{$ns} {
39 .#{map-get(bem.$namespaces, $ns)}-something { 40 @if $ns != 'theme' {
40 font-size: 1em; 41 .#{map-get(bem.$namespaces, $ns)}-something {
41 } 42 font-size: 1em;
42 } @else { 43 }
43 .t-something, 44 } @else {
44 [class*=' t-'] .t-something, 45 .t-something,
45 [class^='t-'] .t-something { 46 [class*=' t-'] .t-something,
46 font-size: 1em; 47 [class^='t-'] .t-something {
47 } 48 font-size: 1em;
48 } 49 }
49 } 50 }
50 } 51 }
51 } 52 }
53 }
54 }
52 55
53 @include assert('nested') { /// 3 /// 56 @include assert('nested') { /// 3 ///
54 @include output(false) { 57 @include output(false) {
55 @include bem.theme('theme') { 58 @include bem.theme('theme') {
56 @include bem.theme('subtheme') { 59 @include bem.theme('subtheme') {
57 @include bem.block('something') { 60 @include bem.block('something') {
58 font-size: 2em; 61 font-size: 2em;
59 } 62 }
60 } 63 }
61 } 64 }
62 } 65 }
63 66
64 @include expect(false) { 67 @include expect(false) {
65 .t-theme .t-subtheme .something, 68 @layer theme {
66 [class*=' t-'] .t-theme .t-subtheme .something, 69 @layer theme {
67 [class^='t-'] .t-theme .t-subtheme .something { 70 .t-theme .t-subtheme .something,
68 font-size: 2em; 71 [class*=' t-'] .t-theme .t-subtheme .something,
69 } 72 [class^='t-'] .t-theme .t-subtheme .something {
70 } 73 font-size: 2em;
71 } 74 }
75 }
76 }
77 }
78 }
72 79
73 @include assert('within selector') { /// 4 /// 80 @include assert('within selector') { /// 4 ///
74 @include output(false) { 81 @include output(false) {
75 .sel { 82 .sel {
76 @include bem.block('something') { 83 @include bem.block('something') {
77 font-size: 2em; 84 font-size: 2em;
78 } 85 }
79 } 86 }
80 } 87 }
81 88
82 @include expect(false) { 89 @include expect(false) {
83 .sel .something { 90 .sel .something {
84 font-size: 2em; 91 font-size: 2em;
85 } 92 }
86 } 93 }
87 } 94 }
88} 95}
diff --git a/test/bem/_composed-of.scss b/test/bem/_composed-of.scss
index fcbf2c4..6a5f4ba 100644
--- a/test/bem/_composed-of.scss
+++ b/test/bem/_composed-of.scss
@@ -1,5 +1,6 @@
1// sass-lint:disable class-name-format force-element-nesting force-pseudo-nesting mixins-before-declarations 1// sass-lint:disable class-name-format force-element-nesting force-pseudo-nesting mixins-before-declarations
2 2
3@use 'sass:map';
3@use 'true' as *; 4@use 'true' as *;
4@use '../../src/bem'; 5@use '../../src/bem';
5 6
@@ -12,141 +13,151 @@
12// 13//
13 14
14@include it('composed-of') { 15@include it('composed-of') {
15 @include assert('without namespace, single') { /// 1 /// 16 @include assert('without namespace, single') { /// 1 ///
16 @include output(false) { 17 @include output(false) {
17 @include bem.block('something') { 18 @include bem.block('something') {
18 font-size: 1em; 19 font-size: 1em;
19 } 20 }
20 21
21 @include bem.block('another') { 22 @include bem.block('another') {
22 @include bem.composed-of('something'); 23 @include bem.composed-of('something');
23 24
24 font-size: 2em; 25 font-size: 2em;
25 } 26 }
26 } 27 }
27 28
28 @include expect(false) { 29 @include expect(false) {
29 .something { 30 .something {
30 font-size: 1em; 31 font-size: 1em;
31 } 32 }
32 33
33 .another { 34 .another {
34 font-size: 2em; 35 font-size: 2em;
35 } 36 }
36 } 37 }
37 } 38 }
38 39
39 @each $ns in map-keys(bem.$namespaces) { 40 @each $ns in map.keys(bem.$namespaces) {
40 @include assert('with namespace "#{$ns}", single') { /// 2 /// 41 @include assert('with namespace "#{$ns}", single') { /// 2 ///
41 @include output(false) { 42 @include output(false) {
42 @include bem.block('something', $ns) { 43 @include bem.block('something', $ns) {
43 font-size: 1em; 44 font-size: 1em;
44 } 45 }
45 46
46 @include bem.block('another') { 47 @include bem.block('another') {
47 @include bem.composed-of('something' $ns); 48 @include bem.composed-of('something' $ns);
48 49
49 font-size: 2em; 50 font-size: 2em;
50 } 51 }
51 } 52 }
52 53
53 @include expect(false) { 54 @include expect(false) {
54 @if $ns != 'theme' { 55 @layer #{$ns} {
55 .#{map-get(bem.$namespaces, $ns)}-something { 56 @if $ns != 'theme' {
56 font-size: 1em; 57 .#{map.get(bem.$namespaces, $ns)}-something {
57 } 58 font-size: 1em;
58 } @else { 59 }
59 .t-something, 60 } @else {
60 [class*=' t-'] .t-something, 61 .t-something,
61 [class^='t-'] .t-something { 62 [class*=' t-'] .t-something,
62 font-size: 1em; 63 [class^='t-'] .t-something {
63 } 64 font-size: 1em;
64 } 65 }
66 }
67 }
65 68
66 .another { 69 .another {
67 font-size: 2em; 70 font-size: 2em;
68 } 71 }
69 } 72 }
70 } 73 }
71 } 74 }
72 75
73 @include assert('without namespace, multiple') { /// 3 /// 76 @include assert('without namespace, multiple') { /// 3 ///
74 @include output(false) { 77 @include output(false) {
75 @include bem.block('something') { 78 @include bem.block('something') {
76 font-size: 1em; 79 font-size: 1em;
77 } 80 }
78 81
79 @include bem.block('somethingElse') { 82 @include bem.block('somethingElse') {
80 font-size: 1em; 83 font-size: 1em;
81 } 84 }
82 85
83 @include bem.block('another') { 86 @include bem.block('another') {
84 @include bem.composed-of('something', 'somethingElse'); 87 @include bem.composed-of('something', 'somethingElse');
85 88
86 font-size: 2em; 89 font-size: 2em;
87 } 90 }
88 } 91 }
89 92
90 @include expect(false) { 93 @include expect(false) {
91 .something { 94 .something {
92 font-size: 1em; 95 font-size: 1em;
93 } 96 }
94 97
95 .somethingElse { 98 .somethingElse {
96 font-size: 1em; 99 font-size: 1em;
97 } 100 }
98 101
99 .another { 102 .another {
100 font-size: 2em; 103 font-size: 2em;
101 } 104 }
102 } 105 }
103 } 106 }
104 107
105 @each $ns in map-keys(bem.$namespaces) { 108 @each $ns in map.keys(bem.$namespaces) {
106 @include assert('with namespace "#{$ns}", multiple') { /// 4 /// 109 @include assert('with namespace "#{$ns}", multiple') { /// 4 ///
107 @include output(false) { 110 @include output(false) {
108 @include bem.block('something', $ns) { 111 @include bem.block('something', $ns) {
109 font-size: 1em; 112 font-size: 1em;
110 } 113 }
111 114
112 @include bem.block('somethingElse', $ns) { 115 @include bem.block('somethingElse', $ns) {
113 font-size: 1em; 116 font-size: 1em;
114 } 117 }
115 118
116 @include bem.block('another') { 119 @include bem.block('another') {
117 @include bem.composed-of('something' $ns, 'somethingElse' $ns); 120 @include bem.composed-of('something' $ns, 'somethingElse' $ns);
118 121
119 font-size: 2em; 122 font-size: 2em;
120 } 123 }
121 } 124 }
122 125
123 @include expect(false) { 126 @include expect(false) {
124 @if $ns != 'theme' { 127 @if $ns != 'theme' {
125 .#{map-get(bem.$namespaces, $ns)}-something { 128 @layer #{$ns} {
126 font-size: 1em; 129 .#{map.get(bem.$namespaces, $ns)}-something {
127 } 130 font-size: 1em;
131 }
132 }
128 133
129 .#{map-get(bem.$namespaces, $ns)}-somethingElse { 134 @layer #{$ns} {
130 font-size: 1em; 135 .#{map.get(bem.$namespaces, $ns)}-somethingElse {
131 } 136 font-size: 1em;
132 } @else { 137 }
133 .t-something, 138 }
134 [class*=' t-'] .t-something, 139 } @else {
135 [class^='t-'] .t-something { 140 @layer #{$ns} {
136 font-size: 1em; 141 .t-something,
137 } 142 [class*=' t-'] .t-something,
143 [class^='t-'] .t-something {
144 font-size: 1em;
145 }
146 }
138 147
139 .t-somethingElse, 148 @layer #{$ns} {
140 [class*=' t-'] .t-somethingElse, 149 .t-somethingElse,
141 [class^='t-'] .t-somethingElse { 150 [class*=' t-'] .t-somethingElse,
142 font-size: 1em; 151 [class^='t-'] .t-somethingElse {
143 } 152 font-size: 1em;
144 } 153 }
154 }
155 }
145 156
146 .another { 157 .another {
147 font-size: 2em; 158 font-size: 2em;
148 } 159 }
149 } 160 }
150 } 161 }
151 } 162 }
152} 163}
diff --git a/test/bem/_element.scss b/test/bem/_element.scss
index c8839de..dd4efd4 100644
--- a/test/bem/_element.scss
+++ b/test/bem/_element.scss
@@ -22,473 +22,473 @@
22// 22//
23 23
24@include it('element') { 24@include it('element') {
25 @include assert('single element') { /// 1 /// 25 @include assert('single element') { /// 1 ///
26 @include output { 26 @include output {
27 @include bem.block('something') { 27 @include bem.block('something') {
28 @include bem.elem('child') { 28 @include bem.elem('child') {
29 font-size: 2em; 29 font-size: 2em;
30 } 30 }
31 } 31 }
32 } 32 }
33 33
34 @include expect { 34 @include expect {
35 .something__child { 35 .something__child {
36 font-size: 2em; 36 font-size: 2em;
37 } 37 }
38 } 38 }
39 } 39 }
40 40
41 @include assert('single element, manual selector in-between') { /// 2 /// 41 @include assert('single element, manual selector in-between') { /// 2 ///
42 @include output(false) { 42 @include output(false) {
43 @include bem.block('something') { 43 @include bem.block('something') {
44 &:hover { 44 &:hover {
45 @include bem.elem('child1') { 45 @include bem.elem('child1') {
46 font-size: 2em; 46 font-size: 2em;
47 } 47 }
48 } 48 }
49 49
50 .test & { 50 .test & {
51 @include bem.elem('child2') { 51 @include bem.elem('child2') {
52 font-size: 2em; 52 font-size: 2em;
53 } 53 }
54 } 54 }
55 } 55 }
56 } 56 }
57 57
58 @include expect(false) { 58 @include expect(false) {
59 .something:hover .something__child1 { 59 .something:hover .something__child1 {
60 font-size: 2em; 60 font-size: 2em;
61 } 61 }
62 62
63 .test .something__child2 { 63 .test .something__child2 {
64 font-size: 2em; 64 font-size: 2em;
65 } 65 }
66 } 66 }
67 } 67 }
68 68
69 @include assert('single element, modifier in-between') { /// 3 /// 69 @include assert('single element, modifier in-between') { /// 3 ///
70 @include output { 70 @include output {
71 @include bem.block('something') { 71 @include bem.block('something') {
72 @include bem.modifier('mod') { 72 @include bem.modifier('mod') {
73 @include bem.elem('child') { 73 @include bem.elem('child') {
74 font-size: 2em; 74 font-size: 2em;
75 } 75 }
76 } 76 }
77 } 77 }
78 } 78 }
79 79
80 @include expect { 80 @include expect {
81 .something--mod .something__child { 81 .something--mod .something__child {
82 font-size: 2em; 82 font-size: 2em;
83 } 83 }
84 } 84 }
85 } 85 }
86 86
87 @include assert('single element, nested') { /// 4 /// 87 @include assert('single element, nested') { /// 4 ///
88 @include output { 88 @include output {
89 @include bem.block('something') { 89 @include bem.block('something') {
90 @include bem.elem('child') { 90 @include bem.elem('child') {
91 font-size: 2em; 91 font-size: 2em;
92 92
93 @include bem.elem('subchild') { 93 @include bem.elem('subchild') {
94 font-size: 3em; 94 font-size: 3em;
95 } 95 }
96 } 96 }
97 } 97 }
98 } 98 }
99 99
100 @include expect { 100 @include expect {
101 .something__child { 101 .something__child {
102 font-size: 2em; 102 font-size: 2em;
103 } 103 }
104 104
105 .something__child .something__subchild { 105 .something__child .something__subchild {
106 font-size: 3em; 106 font-size: 3em;
107 } 107 }
108 } 108 }
109 } 109 }
110 110
111 @include assert('single element, nested, manual selector in-between') { /// 5 /// 111 @include assert('single element, nested, manual selector in-between') { /// 5 ///
112 @include output(false) { 112 @include output(false) {
113 @include bem.block('something') { 113 @include bem.block('something') {
114 &:hover { 114 &:hover {
115 @include bem.elem('child1') { 115 @include bem.elem('child1') {
116 font-size: 2em; 116 font-size: 2em;
117 117
118 @include bem.elem('subchild1') { 118 @include bem.elem('subchild1') {
119 font-size: 3em; 119 font-size: 3em;
120 } 120 }
121 } 121 }
122 } 122 }
123 123
124 .test & { 124 .test & {
125 @include bem.elem('child2') { 125 @include bem.elem('child2') {
126 font-size: 2em; 126 font-size: 2em;
127 127
128 @include bem.elem('subchild2') { 128 @include bem.elem('subchild2') {
129 font-size: 3em; 129 font-size: 3em;
130 } 130 }
131 } 131 }
132 } 132 }
133 133
134 @include bem.elem('child3') { 134 @include bem.elem('child3') {
135 font-size: 2em; 135 font-size: 2em;
136 136
137 &:hover { 137 &:hover {
138 @include bem.elem('subchild3') { 138 @include bem.elem('subchild3') {
139 font-size: 3em; 139 font-size: 3em;
140 } 140 }
141 } 141 }
142 142
143 .test & { 143 .test & {
144 @include bem.elem('subchild4') { 144 @include bem.elem('subchild4') {
145 font-size: 3em; 145 font-size: 3em;
146 } 146 }
147 } 147 }
148 } 148 }
149 } 149 }
150 } 150 }
151 151
152 @include expect(false) { 152 @include expect(false) {
153 .something:hover .something__child1 { 153 .something:hover .something__child1 {
154 font-size: 2em; 154 font-size: 2em;
155 } 155 }
156 156
157 .something:hover .something__child1 .something__subchild1 { 157 .something:hover .something__child1 .something__subchild1 {
158 font-size: 3em; 158 font-size: 3em;
159 } 159 }
160 160
161 .test .something__child2 { 161 .test .something__child2 {
162 font-size: 2em; 162 font-size: 2em;
163 } 163 }
164 164
165 .test .something__child2 .something__subchild2 { 165 .test .something__child2 .something__subchild2 {
166 font-size: 3em; 166 font-size: 3em;
167 } 167 }
168 168
169 .something__child3 { 169 .something__child3 {
170 font-size: 2em; 170 font-size: 2em;
171 } 171 }
172 172
173 .something__child3:hover .something__subchild3 { 173 .something__child3:hover .something__subchild3 {
174 font-size: 3em; 174 font-size: 3em;
175 } 175 }
176 176
177 .test .something__child3 .something__subchild4 { 177 .test .something__child3 .something__subchild4 {
178 font-size: 3em; 178 font-size: 3em;
179 } 179 }
180 } 180 }
181 } 181 }
182 182
183 @include assert('single element, nested, modifier in-between') { /// 6 /// 183 @include assert('single element, nested, modifier in-between') { /// 6 ///
184 @include output { 184 @include output {
185 @include bem.block('something') { 185 @include bem.block('something') {
186 @include bem.modifier('mod') { 186 @include bem.modifier('mod') {
187 @include bem.elem('child') { 187 @include bem.elem('child') {
188 font-size: 2em; 188 font-size: 2em;
189 189
190 @include bem.elem('subchild') { 190 @include bem.elem('subchild') {
191 font-size: 3em; 191 font-size: 3em;
192 } 192 }
193 } 193 }
194 } 194 }
195 195
196 @include bem.elem('child') { 196 @include bem.elem('child') {
197 font-size: 2em; 197 font-size: 2em;
198 198
199 @include bem.modifier('mod') { 199 @include bem.modifier('mod') {
200 @include bem.elem('subchild') { 200 @include bem.elem('subchild') {
201 font-size: 3em; 201 font-size: 3em;
202 } 202 }
203 } 203 }
204 } 204 }
205 } 205 }
206 } 206 }
207 207
208 @include expect { 208 @include expect {
209 .something--mod .something__child { 209 .something--mod .something__child {
210 font-size: 2em; 210 font-size: 2em;
211 } 211 }
212 212
213 .something--mod .something__child .something__subchild { 213 .something--mod .something__child .something__subchild {
214 font-size: 3em; 214 font-size: 3em;
215 } 215 }
216 216
217 .something__child { 217 .something__child {
218 font-size: 2em; 218 font-size: 2em;
219 } 219 }
220 220
221 .something__child--mod .something__subchild { 221 .something__child--mod .something__subchild {
222 font-size: 3em; 222 font-size: 3em;
223 } 223 }
224 } 224 }
225 } 225 }
226 226
227 @include assert('single element, in at-theme') { /// 7 /// 227 @include assert('single element, in at-theme') { /// 7 ///
228 @include output(false) { 228 @include output(false) {
229 @include bem.block('something') { 229 @include bem.block('something') {
230 @include bem.at-theme('dark') { 230 @include bem.at-theme('dark') {
231 @include bem.elem('child') { 231 @include bem.elem('child') {
232 font-size: 2em; 232 font-size: 2em;
233 } 233 }
234 } 234 }
235 } 235 }
236 } 236 }
237 237
238 @include expect(false) { 238 @include expect(false) {
239 .t-dark .something__child, 239 .t-dark .something__child,
240 [class*=' t-'] .t-dark .something__child, 240 [class*=' t-'] .t-dark .something__child,
241 [class^='t-'] .t-dark .something__child { 241 [class^='t-'] .t-dark .something__child {
242 font-size: 2em; 242 font-size: 2em;
243 } 243 }
244 } 244 }
245 } 245 }
246 246
247 @include assert('multiple elements') { /// 8 /// 247 @include assert('multiple elements') { /// 8 ///
248 @include output { 248 @include output {
249 @include bem.block('something') { 249 @include bem.block('something') {
250 @include bem.elem('child1', 'child2') { 250 @include bem.elem('child1', 'child2') {
251 font-size: 2em; 251 font-size: 2em;
252 } 252 }
253 } 253 }
254 } 254 }
255 255
256 @include expect { 256 @include expect {
257 .something__child1, 257 .something__child1,
258 .something__child2 { 258 .something__child2 {
259 font-size: 2em; 259 font-size: 2em;
260 } 260 }
261 } 261 }
262 } 262 }
263 263
264 @include assert('multiple elements, manual selector in-between') { /// 9 /// 264 @include assert('multiple elements, manual selector in-between') { /// 9 ///
265 @include output(false) { 265 @include output(false) {
266 @include bem.block('something') { 266 @include bem.block('something') {
267 &:hover { 267 &:hover {
268 @include bem.elem('child1', 'child2') { 268 @include bem.elem('child1', 'child2') {
269 font-size: 2em; 269 font-size: 2em;
270 } 270 }
271 } 271 }
272 272
273 .test & { 273 .test & {
274 @include bem.elem('child3', 'child4') { 274 @include bem.elem('child3', 'child4') {
275 font-size: 2em; 275 font-size: 2em;
276 } 276 }
277 } 277 }
278 } 278 }
279 } 279 }
280 280
281 @include expect(false) { 281 @include expect(false) {
282 .something:hover .something__child1, 282 .something:hover .something__child1,
283 .something:hover .something__child2 { 283 .something:hover .something__child2 {
284 font-size: 2em; 284 font-size: 2em;
285 } 285 }
286 286
287 .test .something__child3, 287 .test .something__child3,
288 .test .something__child4 { 288 .test .something__child4 {
289 font-size: 2em; 289 font-size: 2em;
290 } 290 }
291 } 291 }
292 } 292 }
293 293
294 @include assert('multiple elements, modifier in-between') { /// 10 /// 294 @include assert('multiple elements, modifier in-between') { /// 10 ///
295 @include output { 295 @include output {
296 @include bem.block('something') { 296 @include bem.block('something') {
297 @include bem.modifier('mod') { 297 @include bem.modifier('mod') {
298 @include bem.elem('child1', 'child2') { 298 @include bem.elem('child1', 'child2') {
299 font-size: 2em; 299 font-size: 2em;
300 } 300 }
301 } 301 }
302 } 302 }
303 } 303 }
304 304
305 @include expect { 305 @include expect {
306 .something--mod .something__child1, 306 .something--mod .something__child1,
307 .something--mod .something__child2 { 307 .something--mod .something__child2 {
308 font-size: 2em; 308 font-size: 2em;
309 } 309 }
310 } 310 }
311 } 311 }
312 312
313 @include assert('multiple elements, nested') { /// 11 /// 313 @include assert('multiple elements, nested') { /// 11 ///
314 @include output { 314 @include output {
315 @include bem.block('something') { 315 @include bem.block('something') {
316 @include bem.elem('child1', 'child2') { 316 @include bem.elem('child1', 'child2') {
317 font-size: 2em; 317 font-size: 2em;
318 318
319 @include bem.elem('subchild1') { 319 @include bem.elem('subchild1') {
320 font-size: 3em; 320 font-size: 3em;
321 } 321 }
322 } 322 }
323 323
324 @include bem.elem('child3') { 324 @include bem.elem('child3') {
325 font-size: 2em; 325 font-size: 2em;
326 326
327 @include bem.elem('subchild2', 'subchild3') { 327 @include bem.elem('subchild2', 'subchild3') {
328 font-size: 3em; 328 font-size: 3em;
329 } 329 }
330 } 330 }
331 } 331 }
332 } 332 }
333 333
334 @include expect { 334 @include expect {
335 .something__child1, 335 .something__child1,
336 .something__child2 { 336 .something__child2 {
337 font-size: 2em; 337 font-size: 2em;
338 } 338 }
339 339
340 .something__child1 .something__subchild1, 340 .something__child1 .something__subchild1,
341 .something__child2 .something__subchild1 { 341 .something__child2 .something__subchild1 {
342 font-size: 3em; 342 font-size: 3em;
343 } 343 }
344 344
345 .something__child3 { 345 .something__child3 {
346 font-size: 2em; 346 font-size: 2em;
347 } 347 }
348 348
349 .something__child3 .something__subchild2, 349 .something__child3 .something__subchild2,
350 .something__child3 .something__subchild3 { 350 .something__child3 .something__subchild3 {
351 font-size: 3em; 351 font-size: 3em;
352 } 352 }
353 } 353 }
354 } 354 }
355 355
356 @include assert('multiple elements, nested, manual selector in-between') { /// 12 /// 356 @include assert('multiple elements, nested, manual selector in-between') { /// 12 ///
357 @include output(false) { 357 @include output(false) {
358 @include bem.block('something') { 358 @include bem.block('something') {
359 @include bem.elem('child1', 'child2') { 359 @include bem.elem('child1', 'child2') {
360 font-size: 2em; 360 font-size: 2em;
361 361
362 &:hover { 362 &:hover {
363 @include bem.elem('subchild1') { 363 @include bem.elem('subchild1') {
364 font-size: 3em; 364 font-size: 3em;
365 } 365 }
366 } 366 }
367 367
368 .test & { 368 .test & {
369 @include bem.elem('subchild2') { 369 @include bem.elem('subchild2') {
370 font-size: 3em; 370 font-size: 3em;
371 } 371 }
372 } 372 }
373 } 373 }
374 374
375 @include bem.elem('child3') { 375 @include bem.elem('child3') {
376 font-size: 2em; 376 font-size: 2em;
377 377
378 &:hover { 378 &:hover {
379 @include bem.elem('subchild3', 'subchild4') { 379 @include bem.elem('subchild3', 'subchild4') {
380 font-size: 3em; 380 font-size: 3em;
381 } 381 }
382 } 382 }
383 383
384 .test & { 384 .test & {
385 @include bem.elem('subchild5', 'subchild6') { 385 @include bem.elem('subchild5', 'subchild6') {
386 font-size: 3em; 386 font-size: 3em;
387 } 387 }
388 } 388 }
389 } 389 }
390 } 390 }
391 } 391 }
392 392
393 @include expect(false) { 393 @include expect(false) {
394 .something__child1, 394 .something__child1,
395 .something__child2 { 395 .something__child2 {
396 font-size: 2em; 396 font-size: 2em;
397 } 397 }
398 398
399 .something__child1:hover .something__subchild1, 399 .something__child1:hover .something__subchild1,
400 .something__child2:hover .something__subchild1 { 400 .something__child2:hover .something__subchild1 {
401 font-size: 3em; 401 font-size: 3em;
402 } 402 }
403 403
404 .test .something__child1 .something__subchild2, 404 .test .something__child1 .something__subchild2,
405 .test .something__child2 .something__subchild2 { 405 .test .something__child2 .something__subchild2 {
406 font-size: 3em; 406 font-size: 3em;
407 } 407 }
408 408
409 .something__child3 { 409 .something__child3 {
410 font-size: 2em; 410 font-size: 2em;
411 } 411 }
412 412
413 .something__child3:hover .something__subchild3, 413 .something__child3:hover .something__subchild3,
414 .something__child3:hover .something__subchild4 { 414 .something__child3:hover .something__subchild4 {
415 font-size: 3em; 415 font-size: 3em;
416 } 416 }
417 417
418 .test .something__child3 .something__subchild5, 418 .test .something__child3 .something__subchild5,
419 .test .something__child3 .something__subchild6 { 419 .test .something__child3 .something__subchild6 {
420 font-size: 3em; 420 font-size: 3em;
421 } 421 }
422 } 422 }
423 } 423 }
424 424
425 @include assert('multiple elements, nested, modifier in-between') { /// 13 /// 425 @include assert('multiple elements, nested, modifier in-between') { /// 13 ///
426 @include output { 426 @include output {
427 @include bem.block('something') { 427 @include bem.block('something') {
428 @include bem.elem('child1', 'child2') { 428 @include bem.elem('child1', 'child2') {
429 font-size: 2em; 429 font-size: 2em;
430 430
431 @include bem.modifier('mod') { 431 @include bem.modifier('mod') {
432 @include bem.elem('subchild1') { 432 @include bem.elem('subchild1') {
433 font-size: 3em; 433 font-size: 3em;
434 } 434 }
435 } 435 }
436 } 436 }
437 437
438 @include bem.elem('child3') { 438 @include bem.elem('child3') {
439 font-size: 2em; 439 font-size: 2em;
440 440
441 @include bem.modifier('mod') { 441 @include bem.modifier('mod') {
442 @include bem.elem('subchild2', 'subchild3') { 442 @include bem.elem('subchild2', 'subchild3') {
443 font-size: 3em; 443 font-size: 3em;
444 } 444 }
445 } 445 }
446 } 446 }
447 } 447 }
448 } 448 }
449 449
450 @include expect { 450 @include expect {
451 .something__child1, 451 .something__child1,
452 .something__child2 { 452 .something__child2 {
453 font-size: 2em; 453 font-size: 2em;
454 } 454 }
455 455
456 .something__child1--mod .something__subchild1, 456 .something__child1--mod .something__subchild1,
457 .something__child2--mod .something__subchild1 { 457 .something__child2--mod .something__subchild1 {
458 font-size: 3em; 458 font-size: 3em;
459 } 459 }
460 460
461 .something__child3 { 461 .something__child3 {
462 font-size: 2em; 462 font-size: 2em;
463 } 463 }
464 464
465 .something__child3--mod .something__subchild2, 465 .something__child3--mod .something__subchild2,
466 .something__child3--mod .something__subchild3 { 466 .something__child3--mod .something__subchild3 {
467 font-size: 3em; 467 font-size: 3em;
468 } 468 }
469 } 469 }
470 } 470 }
471 471
472 @include assert('multiple elements, in at-theme') { /// 14 /// 472 @include assert('multiple elements, in at-theme') { /// 14 ///
473 @include output(false) { 473 @include output(false) {
474 @include bem.block('something') { 474 @include bem.block('something') {
475 @include bem.at-theme('dark') { 475 @include bem.at-theme('dark') {
476 @include bem.elem('child1', 'child2') { 476 @include bem.elem('child1', 'child2') {
477 font-size: 2em; 477 font-size: 2em;
478 } 478 }
479 } 479 }
480 } 480 }
481 } 481 }
482 482
483 @include expect(false) { 483 @include expect(false) {
484 .t-dark .something__child1, 484 .t-dark .something__child1,
485 [class*=' t-'] .t-dark .something__child1, 485 [class*=' t-'] .t-dark .something__child1,
486 [class^='t-'] .t-dark .something__child1, 486 [class^='t-'] .t-dark .something__child1,
487 .t-dark .something__child2, 487 .t-dark .something__child2,
488 [class*=' t-'] .t-dark .something__child2, 488 [class*=' t-'] .t-dark .something__child2,
489 [class^='t-'] .t-dark .something__child2 { 489 [class^='t-'] .t-dark .something__child2 {
490 font-size: 2em; 490 font-size: 2em;
491 } 491 }
492 } 492 }
493 } 493 }
494} 494}
diff --git a/test/bem/_examples.scss b/test/bem/_examples.scss
index 33deca0..9679566 100644
--- a/test/bem/_examples.scss
+++ b/test/bem/_examples.scss
@@ -11,217 +11,223 @@
11// 11//
12 12
13@include it('Examples') { 13@include it('Examples') {
14 @include assert('Media object') { /// 1 /// 14 @include assert('Media object') { /// 1 ///
15 @include output { 15 @include output {
16 @include bem.object('media') { 16 @include bem.object('media') {
17 display: flex; 17 display: flex;
18 align-items: flex-start; 18 align-items: flex-start;
19 justify-content: flex-start; 19 justify-content: flex-start;
20 20
21 @include bem.elem('image') { 21 @include bem.elem('image') {
22 display: block; 22 display: block;
23 flex: 0 0 auto; 23 flex: 0 0 auto;
24 order: 1; 24 order: 1;
25 overflow: hidden; 25 overflow: hidden;
26 } 26 }
27 27
28 @include bem.elem('body') { 28 @include bem.elem('body') {
29 order: 2; 29 order: 2;
30 } 30 }
31 31
32 @include bem.modifier('rtl') { 32 @include bem.modifier('rtl') {
33 justify-content: flex-end; 33 justify-content: flex-end;
34 34
35 @include bem.elem('image') { 35 @include bem.elem('image') {
36 order: 2; 36 order: 2;
37 } 37 }
38 38
39 @include bem.elem('body') { 39 @include bem.elem('body') {
40 order: 1; 40 order: 1;
41 } 41 }
42 } 42 }
43 } 43 }
44 } 44 }
45 45
46 @include expect { 46 @include expect {
47 .o-media { 47 @layer object {
48 display: flex; 48 .o-media {
49 align-items: flex-start; 49 display: flex;
50 justify-content: flex-start; 50 align-items: flex-start;
51 } 51 justify-content: flex-start;
52 }
52 53
53 .o-media__image { 54 .o-media__image {
54 display: block; 55 display: block;
55 flex: 0 0 auto; 56 flex: 0 0 auto;
56 order: 1; 57 order: 1;
57 overflow: hidden; 58 overflow: hidden;
58 } 59 }
59 60
60 .o-media__body { 61 .o-media__body {
61 order: 2; 62 order: 2;
62 } 63 }
63 64
64 .o-media--rtl { 65 .o-media--rtl {
65 justify-content: flex-end; 66 justify-content: flex-end;
66 67
67 .o-media__image { 68 .o-media__image {
68 order: 2; 69 order: 2;
69 } 70 }
70 71
71 .o-media__body { 72 .o-media__body {
72 order: 1; 73 order: 1;
73 } 74 }
74 } 75 }
75 } 76 }
76 } 77 }
78 }
77 79
78 @include assert('Tabs') { /// 2 /// 80 @include assert('Tabs') { /// 2 ///
79 @include output { 81 @include output {
80 @include bem.component('tabs') { 82 @include bem.component('tabs') {
81 position: relative; 83 position: relative;
82 84
83 @include bem.elem('tab') { 85 @include bem.elem('tab') {
84 float: left; 86 float: left;
85 } 87 }
86 88
87 @include bem.elem('tabRadio') { 89 @include bem.elem('tabRadio') {
88 position: absolute; 90 position: absolute;
89 top: -9999px; 91 top: -9999px;
90 left: -9999px; 92 left: -9999px;
91 93
92 &:checked { 94 &:checked {
93 @include bem.sibling-elem('tabLabel') { 95 @include bem.sibling-elem('tabLabel') {
94 font-weight: bold; 96 font-weight: bold;
95 } 97 }
96 98
97 @include bem.sibling-elem('tabContent') { 99 @include bem.sibling-elem('tabContent') {
98 display: block; 100 display: block;
99 } 101 }
100 } 102 }
101 } 103 }
102 104
103 @include bem.elem('tabLabel') { 105 @include bem.elem('tabLabel') {
104 cursor: pointer; 106 cursor: pointer;
105 107
106 &:hover, 108 &:hover,
107 &:active { 109 &:active {
108 text-decoration: underline; 110 text-decoration: underline;
109 } 111 }
110 } 112 }
111 113
112 @include bem.elem('tabContent') { 114 @include bem.elem('tabContent') {
113 position: absolute; 115 position: absolute;
114 left: 0; 116 left: 0;
115 display: none; 117 display: none;
116 } 118 }
117 } 119 }
118 } 120 }
119 121
120 @include expect { 122 @include expect {
121 .c-tabs { 123 @layer component {
122 position: relative; 124 .c-tabs {
123 } 125 position: relative;
126 }
124 127
125 .c-tabs__tab { 128 .c-tabs__tab {
126 float: left; 129 float: left;
127 } 130 }
128 131
129 .c-tabs__tabRadio { 132 .c-tabs__tabRadio {
130 position: absolute; 133 position: absolute;
131 top: -9999px; 134 top: -9999px;
132 left: -9999px; 135 left: -9999px;
133 } 136 }
134 137
135 .c-tabs__tabRadio:checked ~ .c-tabs__tabLabel { 138 .c-tabs__tabRadio:checked ~ .c-tabs__tabLabel {
136 font-weight: bold; 139 font-weight: bold;
137 } 140 }
138 141
139 .c-tabs__tabRadio:checked ~ .c-tabs__tabContent { 142 .c-tabs__tabRadio:checked ~ .c-tabs__tabContent {
140 display: block; 143 display: block;
141 } 144 }
142 145
143 .c-tabs__tabLabel { 146 .c-tabs__tabLabel {
144 cursor: pointer; 147 cursor: pointer;
145 } 148 }
146 149
147 .c-tabs__tabLabel:hover, 150 .c-tabs__tabLabel:hover,
148 .c-tabs__tabLabel:active { 151 .c-tabs__tabLabel:active {
149 text-decoration: underline; 152 text-decoration: underline;
150 } 153 }
151 154
152 .c-tabs__tabContent { 155 .c-tabs__tabContent {
153 position: absolute; 156 position: absolute;
154 left: 0; 157 left: 0;
155 display: none; 158 display: none;
156 } 159 }
157 } 160 }
158 } 161 }
162 }
159 163
160 @include assert('Accordion') { /// 3 /// 164 @include assert('Accordion') { /// 3 ///
161 @include output { 165 @include output {
162 @include bem.component('accordion') { 166 @include bem.component('accordion') {
163 @include bem.elem('section') { 167 @include bem.elem('section') {
164 // nothing to do 168 // nothing to do
165 } 169 }
166 170
167 @include bem.elem('sectionCheckbox') { 171 @include bem.elem('sectionCheckbox') {
168 position: absolute; 172 position: absolute;
169 top: -9999px; 173 top: -9999px;
170 left: -9999px; 174 left: -9999px;
171 175
172 &:checked { 176 &:checked {
173 @include bem.sibling-elem('sectionLabel') { 177 @include bem.sibling-elem('sectionLabel') {
174 font-weight: bold; 178 font-weight: bold;
175 } 179 }
176 180
177 @include bem.sibling-elem('sectionContent') { 181 @include bem.sibling-elem('sectionContent') {
178 display: block; 182 display: block;
179 } 183 }
180 } 184 }
181 } 185 }
182 186
183 @include bem.elem('sectionLabel') { 187 @include bem.elem('sectionLabel') {
184 cursor: pointer; 188 cursor: pointer;
185 189
186 &:hover, 190 &:hover,
187 &:active { 191 &:active {
188 text-decoration: underline; 192 text-decoration: underline;
189 } 193 }
190 } 194 }
191 195
192 @include bem.elem('sectionContent') { 196 @include bem.elem('sectionContent') {
193 display: none; 197 display: none;
194 } 198 }
195 } 199 }
196 } 200 }
197 201
198 @include expect { 202 @include expect {
199 .c-accordion__sectionCheckbox { 203 @layer component {
200 position: absolute; 204 .c-accordion__sectionCheckbox {
201 top: -9999px; 205 position: absolute;
202 left: -9999px; 206 top: -9999px;
203 } 207 left: -9999px;
208 }
204 209
205 .c-accordion__sectionCheckbox:checked ~ .c-accordion__sectionLabel { 210 .c-accordion__sectionCheckbox:checked ~ .c-accordion__sectionLabel {
206 font-weight: bold; 211 font-weight: bold;
207 } 212 }
208 213
209 .c-accordion__sectionCheckbox:checked ~ .c-accordion__sectionContent { 214 .c-accordion__sectionCheckbox:checked ~ .c-accordion__sectionContent {
210 display: block; 215 display: block;
211 } 216 }
212 217
213 .c-accordion__sectionLabel { 218 .c-accordion__sectionLabel {
214 cursor: pointer; 219 cursor: pointer;
215 } 220 }
216 221
217 .c-accordion__sectionLabel:hover, 222 .c-accordion__sectionLabel:hover,
218 .c-accordion__sectionLabel:active { 223 .c-accordion__sectionLabel:active {
219 text-decoration: underline; 224 text-decoration: underline;
220 } 225 }
221 226
222 .c-accordion__sectionContent { 227 .c-accordion__sectionContent {
223 display: none; 228 display: none;
224 } 229 }
225 } 230 }
226 } 231 }
232 }
227} 233}
diff --git a/test/bem/_modifier.scss b/test/bem/_modifier.scss
index 934efa3..419aa91 100644
--- a/test/bem/_modifier.scss
+++ b/test/bem/_modifier.scss
@@ -23,633 +23,633 @@
23// 23//
24 24
25@include it('modifier') { 25@include it('modifier') {
26 @include assert('block modifier') { /// 1 /// 26 @include assert('block modifier') { /// 1 ///
27 @include output { 27 @include output {
28 @include bem.block('something') { 28 @include bem.block('something') {
29 @include bem.modifier('mod') { 29 @include bem.modifier('mod') {
30 font-size: 1.5em; 30 font-size: 1.5em;
31 31
32 @include bem.modifier('submod') { 32 @include bem.modifier('submod') {
33 font-size: 1.75em; 33 font-size: 1.75em;
34 } 34 }
35 } 35 }
36 } 36 }
37 } 37 }
38 38
39 @include expect { 39 @include expect {
40 .something--mod { 40 .something--mod {
41 font-size: 1.5em; 41 font-size: 1.5em;
42 } 42 }
43 43
44 .something--mod.something--submod { 44 .something--mod.something--submod {
45 font-size: 1.75em; 45 font-size: 1.75em;
46 } 46 }
47 } 47 }
48 } 48 }
49 49
50 @include assert('block modifier, in at-theme') { /// 2 /// 50 @include assert('block modifier, in at-theme') { /// 2 ///
51 @include output(false) { 51 @include output(false) {
52 @include bem.block('something') { 52 @include bem.block('something') {
53 @include bem.at-theme('dark') { 53 @include bem.at-theme('dark') {
54 @include bem.modifier('mod') { 54 @include bem.modifier('mod') {
55 font-size: 1.5em; 55 font-size: 1.5em;
56 56
57 @include bem.modifier('submod') { 57 @include bem.modifier('submod') {
58 font-size: 1.75em; 58 font-size: 1.75em;
59 } 59 }
60 } 60 }
61 } 61 }
62 } 62 }
63 } 63 }
64 64
65 @include expect(false) { 65 @include expect(false) {
66 .t-dark .something--mod, 66 .t-dark .something--mod,
67 [class*=' t-'] .t-dark .something--mod, 67 [class*=' t-'] .t-dark .something--mod,
68 [class^='t-'] .t-dark .something--mod { 68 [class^='t-'] .t-dark .something--mod {
69 font-size: 1.5em; 69 font-size: 1.5em;
70 } 70 }
71 71
72 .t-dark .something--mod.something--submod, 72 .t-dark .something--mod.something--submod,
73 [class*=' t-'] .t-dark .something--mod.something--submod, 73 [class*=' t-'] .t-dark .something--mod.something--submod,
74 [class^='t-'] .t-dark .something--mod.something--submod { 74 [class^='t-'] .t-dark .something--mod.something--submod {
75 font-size: 1.75em; 75 font-size: 1.75em;
76 } 76 }
77 } 77 }
78 } 78 }
79 79
80 @include assert('element modifier, single element') { /// 3 /// 80 @include assert('element modifier, single element') { /// 3 ///
81 @include output { 81 @include output {
82 @include bem.block('something') { 82 @include bem.block('something') {
83 @include bem.elem('child') { 83 @include bem.elem('child') {
84 @include bem.modifier('mod') { 84 @include bem.modifier('mod') {
85 font-size: 2.5em; 85 font-size: 2.5em;
86 86
87 @include bem.modifier('submod') { 87 @include bem.modifier('submod') {
88 font-size: 2.75em; 88 font-size: 2.75em;
89 } 89 }
90 } 90 }
91 } 91 }
92 } 92 }
93 } 93 }
94 94
95 @include expect { 95 @include expect {
96 .something__child--mod { 96 .something__child--mod {
97 font-size: 2.5em; 97 font-size: 2.5em;
98 } 98 }
99 99
100 .something__child--mod.something__child--submod { 100 .something__child--mod.something__child--submod {
101 font-size: 2.75em; 101 font-size: 2.75em;
102 } 102 }
103 } 103 }
104 } 104 }
105 105
106 @include assert('element modifier, multiple elements') { /// 4 /// 106 @include assert('element modifier, multiple elements') { /// 4 ///
107 @include output { 107 @include output {
108 @include bem.block('something') { 108 @include bem.block('something') {
109 @include bem.elem('child1', 'child2') { 109 @include bem.elem('child1', 'child2') {
110 @include bem.modifier('mod') { 110 @include bem.modifier('mod') {
111 font-size: 2.5em; 111 font-size: 2.5em;
112 112
113 @include bem.modifier('submod') { 113 @include bem.modifier('submod') {
114 font-size: 2.75em; 114 font-size: 2.75em;
115 } 115 }
116 } 116 }
117 } 117 }
118 } 118 }
119 } 119 }
120 120
121 @include expect { 121 @include expect {
122 .something__child1--mod, 122 .something__child1--mod,
123 .something__child2--mod { 123 .something__child2--mod {
124 font-size: 2.5em; 124 font-size: 2.5em;
125 } 125 }
126 126
127 .something__child1--mod.something__child1--submod, 127 .something__child1--mod.something__child1--submod,
128 .something__child2--mod.something__child2--submod { 128 .something__child2--mod.something__child2--submod {
129 font-size: 2.75em; 129 font-size: 2.75em;
130 } 130 }
131 } 131 }
132 } 132 }
133 133
134 @include assert('element modifier, single related element') { /// 5 /// 134 @include assert('element modifier, single related element') { /// 5 ///
135 @include output { 135 @include output {
136 @include bem.block('something') { 136 @include bem.block('something') {
137 @include bem.elem('child1') { 137 @include bem.elem('child1') {
138 @include bem.next-elem('child2') { 138 @include bem.next-elem('child2') {
139 @include bem.modifier('mod') { 139 @include bem.modifier('mod') {
140 font-size: 2.5em; 140 font-size: 2.5em;
141 141
142 @include bem.modifier('submod') { 142 @include bem.modifier('submod') {
143 font-size: 2.75em; 143 font-size: 2.75em;
144 } 144 }
145 } 145 }
146 } 146 }
147 } 147 }
148 } 148 }
149 } 149 }
150 150
151 @include expect { 151 @include expect {
152 .something__child1 + .something__child2--mod { 152 .something__child1 + .something__child2--mod {
153 font-size: 2.5em; 153 font-size: 2.5em;
154 } 154 }
155 155
156 .something__child1 + .something__child2--mod.something__child2--submod { 156 .something__child1 + .something__child2--mod.something__child2--submod {
157 font-size: 2.75em; 157 font-size: 2.75em;
158 } 158 }
159 } 159 }
160 } 160 }
161 161
162 @include assert('element modifier, multiple related elements') { /// 6 /// 162 @include assert('element modifier, multiple related elements') { /// 6 ///
163 @include output { 163 @include output {
164 @include bem.block('something') { 164 @include bem.block('something') {
165 @include bem.elem('child1') { 165 @include bem.elem('child1') {
166 @include bem.next-elem('child2', 'child3') { 166 @include bem.next-elem('child2', 'child3') {
167 @include bem.modifier('mod') { 167 @include bem.modifier('mod') {
168 font-size: 2.5em; 168 font-size: 2.5em;
169 169
170 @include bem.modifier('submod') { 170 @include bem.modifier('submod') {
171 font-size: 2.75em; 171 font-size: 2.75em;
172 } 172 }
173 } 173 }
174 } 174 }
175 } 175 }
176 } 176 }
177 } 177 }
178 178
179 @include expect { 179 @include expect {
180 .something__child1 + .something__child2--mod, 180 .something__child1 + .something__child2--mod,
181 .something__child1 + .something__child3--mod { 181 .something__child1 + .something__child3--mod {
182 font-size: 2.5em; 182 font-size: 2.5em;
183 } 183 }
184 184
185 .something__child1 + .something__child2--mod.something__child2--submod, 185 .something__child1 + .something__child2--mod.something__child2--submod,
186 .something__child1 + .something__child3--mod.something__child3--submod { 186 .something__child1 + .something__child3--mod.something__child3--submod {
187 font-size: 2.75em; 187 font-size: 2.75em;
188 } 188 }
189 } 189 }
190 } 190 }
191 191
192 @include assert('element modifier, single element, manual selector before') { /// 7 /// 192 @include assert('element modifier, single element, manual selector before') { /// 7 ///
193 @include output(false) { 193 @include output(false) {
194 @include bem.block('something') { 194 @include bem.block('something') {
195 &:hover { 195 &:hover {
196 @include bem.elem('child1') { 196 @include bem.elem('child1') {
197 @include bem.modifier('mod') { 197 @include bem.modifier('mod') {
198 font-size: 2.5em; 198 font-size: 2.5em;
199 199
200 @include bem.modifier('submod') { 200 @include bem.modifier('submod') {
201 font-size: 2.75em; 201 font-size: 2.75em;
202 } 202 }
203 } 203 }
204 } 204 }
205 } 205 }
206 206
207 .test & { 207 .test & {
208 @include bem.elem('child2') { 208 @include bem.elem('child2') {
209 @include bem.modifier('mod') { 209 @include bem.modifier('mod') {
210 font-size: 2.5em; 210 font-size: 2.5em;
211 211
212 @include bem.modifier('submod') { 212 @include bem.modifier('submod') {
213 font-size: 2.75em; 213 font-size: 2.75em;
214 } 214 }
215 } 215 }
216 } 216 }
217 } 217 }
218 } 218 }
219 } 219 }
220 220
221 @include expect(false) { 221 @include expect(false) {
222 .something:hover .something__child1--mod { 222 .something:hover .something__child1--mod {
223 font-size: 2.5em; 223 font-size: 2.5em;
224 } 224 }
225 225
226 .something:hover .something__child1--mod.something__child1--submod { 226 .something:hover .something__child1--mod.something__child1--submod {
227 font-size: 2.75em; 227 font-size: 2.75em;
228 } 228 }
229 229
230 .test .something__child2--mod { 230 .test .something__child2--mod {
231 font-size: 2.5em; 231 font-size: 2.5em;
232 } 232 }
233 233
234 .test .something__child2--mod.something__child2--submod { 234 .test .something__child2--mod.something__child2--submod {
235 font-size: 2.75em; 235 font-size: 2.75em;
236 } 236 }
237 } 237 }
238 } 238 }
239 239
240 @include assert('element modifier, multiple elements, manual selector before') { /// 8 /// 240 @include assert('element modifier, multiple elements, manual selector before') { /// 8 ///
241 @include output(false) { 241 @include output(false) {
242 @include bem.block('something') { 242 @include bem.block('something') {
243 &:hover { 243 &:hover {
244 @include bem.elem('child1', 'child2') { 244 @include bem.elem('child1', 'child2') {
245 @include bem.modifier('mod') { 245 @include bem.modifier('mod') {
246 font-size: 2.5em; 246 font-size: 2.5em;
247 247
248 @include bem.modifier('submod') { 248 @include bem.modifier('submod') {
249 font-size: 2.75em; 249 font-size: 2.75em;
250 } 250 }
251 } 251 }
252 } 252 }
253 } 253 }
254 254
255 .test & { 255 .test & {
256 @include bem.elem('child3', 'child4') { 256 @include bem.elem('child3', 'child4') {
257 @include bem.modifier('mod') { 257 @include bem.modifier('mod') {
258 font-size: 2.5em; 258 font-size: 2.5em;
259 259
260 @include bem.modifier('submod') { 260 @include bem.modifier('submod') {
261 font-size: 2.75em; 261 font-size: 2.75em;
262 } 262 }
263 } 263 }
264 } 264 }
265 } 265 }
266 } 266 }
267 } 267 }
268 268
269 @include expect(false) { 269 @include expect(false) {
270 .something:hover .something__child1--mod, 270 .something:hover .something__child1--mod,
271 .something:hover .something__child2--mod { 271 .something:hover .something__child2--mod {
272 font-size: 2.5em; 272 font-size: 2.5em;
273 } 273 }
274 274
275 .something:hover .something__child1--mod.something__child1--submod, 275 .something:hover .something__child1--mod.something__child1--submod,
276 .something:hover .something__child2--mod.something__child2--submod { 276 .something:hover .something__child2--mod.something__child2--submod {
277 font-size: 2.75em; 277 font-size: 2.75em;
278 } 278 }
279 279
280 .test .something__child3--mod, 280 .test .something__child3--mod,
281 .test .something__child4--mod { 281 .test .something__child4--mod {
282 font-size: 2.5em; 282 font-size: 2.5em;
283 } 283 }
284 284
285 .test .something__child3--mod.something__child3--submod, 285 .test .something__child3--mod.something__child3--submod,
286 .test .something__child4--mod.something__child4--submod { 286 .test .something__child4--mod.something__child4--submod {
287 font-size: 2.75em; 287 font-size: 2.75em;
288 } 288 }
289 } 289 }
290 } 290 }
291 291
292 @include assert('element modifier, single related element, manual selector before') { /// 9 /// 292 @include assert('element modifier, single related element, manual selector before') { /// 9 ///
293 @include output(false) { 293 @include output(false) {
294 @include bem.block('something') { 294 @include bem.block('something') {
295 &:hover { 295 &:hover {
296 @include bem.elem('child1') { 296 @include bem.elem('child1') {
297 @include bem.next-elem('child2') { 297 @include bem.next-elem('child2') {
298 @include bem.modifier('mod1') { 298 @include bem.modifier('mod1') {
299 font-size: 2.5em; 299 font-size: 2.5em;
300 300
301 @include bem.modifier('submod1') { 301 @include bem.modifier('submod1') {
302 font-size: 2.75em; 302 font-size: 2.75em;
303 } 303 }
304 } 304 }
305 } 305 }
306 } 306 }
307 } 307 }
308 308
309 .test & { 309 .test & {
310 @include bem.elem('child3') { 310 @include bem.elem('child3') {
311 @include bem.next-elem('child4') { 311 @include bem.next-elem('child4') {
312 @include bem.modifier('mod1') { 312 @include bem.modifier('mod1') {
313 font-size: 2.5em; 313 font-size: 2.5em;
314 314
315 @include bem.modifier('submod1') { 315 @include bem.modifier('submod1') {
316 font-size: 2.75em; 316 font-size: 2.75em;
317 } 317 }
318 } 318 }
319 } 319 }
320 } 320 }
321 } 321 }
322 322
323 @include bem.elem('child5') { 323 @include bem.elem('child5') {
324 &:hover { 324 &:hover {
325 @include bem.next-elem('child6') { 325 @include bem.next-elem('child6') {
326 @include bem.modifier('mod2') { 326 @include bem.modifier('mod2') {
327 font-size: 2.5em; 327 font-size: 2.5em;
328 328
329 @include bem.modifier('submod2') { 329 @include bem.modifier('submod2') {
330 font-size: 2.75em; 330 font-size: 2.75em;
331 } 331 }
332 } 332 }
333 } 333 }
334 } 334 }
335 335
336 .test & { 336 .test & {
337 @include bem.next-elem('child7') { 337 @include bem.next-elem('child7') {
338 @include bem.modifier('mod2') { 338 @include bem.modifier('mod2') {
339 font-size: 2.5em; 339 font-size: 2.5em;
340 340
341 @include bem.modifier('submod2') { 341 @include bem.modifier('submod2') {
342 font-size: 2.75em; 342 font-size: 2.75em;
343 } 343 }
344 } 344 }
345 } 345 }
346 } 346 }
347 } 347 }
348 } 348 }
349 } 349 }
350 350
351 @include expect(false) { 351 @include expect(false) {
352 .something:hover .something__child1 + .something__child2--mod1 { 352 .something:hover .something__child1 + .something__child2--mod1 {
353 font-size: 2.5em; 353 font-size: 2.5em;
354 } 354 }
355 355
356 .something:hover .something__child1 + .something__child2--mod1.something__child2--submod1 { 356 .something:hover .something__child1 + .something__child2--mod1.something__child2--submod1 {
357 font-size: 2.75em; 357 font-size: 2.75em;
358 } 358 }
359 359
360 .test .something__child3 + .something__child4--mod1 { 360 .test .something__child3 + .something__child4--mod1 {
361 font-size: 2.5em; 361 font-size: 2.5em;
362 } 362 }
363 363
364 .test .something__child3 + .something__child4--mod1.something__child4--submod1 { 364 .test .something__child3 + .something__child4--mod1.something__child4--submod1 {
365 font-size: 2.75em; 365 font-size: 2.75em;
366 } 366 }
367 367
368 .something__child5:hover + .something__child6--mod2 { 368 .something__child5:hover + .something__child6--mod2 {
369 font-size: 2.5em; 369 font-size: 2.5em;
370 } 370 }
371 371
372 .something__child5:hover + .something__child6--mod2.something__child6--submod2 { 372 .something__child5:hover + .something__child6--mod2.something__child6--submod2 {
373 font-size: 2.75em; 373 font-size: 2.75em;
374 } 374 }
375 375
376 .test .something__child5 + .something__child7--mod2 { 376 .test .something__child5 + .something__child7--mod2 {
377 font-size: 2.5em; 377 font-size: 2.5em;
378 } 378 }
379 379
380 .test .something__child5 + .something__child7--mod2.something__child7--submod2 { 380 .test .something__child5 + .something__child7--mod2.something__child7--submod2 {
381 font-size: 2.75em; 381 font-size: 2.75em;
382 } 382 }
383 } 383 }
384 } 384 }
385 385
386 @include assert('element modifier, multiple related elements, manual selector before') { /// 10 /// 386 @include assert('element modifier, multiple related elements, manual selector before') { /// 10 ///
387 @include output(false) { 387 @include output(false) {
388 @include bem.block('something') { 388 @include bem.block('something') {
389 &:hover { 389 &:hover {
390 @include bem.elem('child1') { 390 @include bem.elem('child1') {
391 @include bem.next-elem('child2', 'child3') { 391 @include bem.next-elem('child2', 'child3') {
392 @include bem.modifier('mod1') { 392 @include bem.modifier('mod1') {
393 font-size: 2.5em; 393 font-size: 2.5em;
394 394
395 @include bem.modifier('submod1') { 395 @include bem.modifier('submod1') {
396 font-size: 2.75em; 396 font-size: 2.75em;
397 } 397 }
398 } 398 }
399 } 399 }
400 } 400 }
401 } 401 }
402 402
403 .test & { 403 .test & {
404 @include bem.elem('child4') { 404 @include bem.elem('child4') {
405 @include bem.next-elem('child5', 'child6') { 405 @include bem.next-elem('child5', 'child6') {
406 @include bem.modifier('mod1') { 406 @include bem.modifier('mod1') {
407 font-size: 2.5em; 407 font-size: 2.5em;
408 408
409 @include bem.modifier('submod1') { 409 @include bem.modifier('submod1') {
410 font-size: 2.75em; 410 font-size: 2.75em;
411 } 411 }
412 } 412 }
413 } 413 }
414 } 414 }
415 } 415 }
416 416
417 @include bem.elem('child7') { 417 @include bem.elem('child7') {
418 &:hover { 418 &:hover {
419 @include bem.next-elem('child8', 'child9') { 419 @include bem.next-elem('child8', 'child9') {
420 @include bem.modifier('mod2') { 420 @include bem.modifier('mod2') {
421 font-size: 2.5em; 421 font-size: 2.5em;
422 422
423 @include bem.modifier('submod2') { 423 @include bem.modifier('submod2') {
424 font-size: 2.75em; 424 font-size: 2.75em;
425 } 425 }
426 } 426 }
427 } 427 }
428 } 428 }
429 429
430 .test & { 430 .test & {
431 @include bem.next-elem('child10', 'child11') { 431 @include bem.next-elem('child10', 'child11') {
432 @include bem.modifier('mod2') { 432 @include bem.modifier('mod2') {
433 font-size: 2.5em; 433 font-size: 2.5em;
434 434
435 @include bem.modifier('submod2') { 435 @include bem.modifier('submod2') {
436 font-size: 2.75em; 436 font-size: 2.75em;
437 } 437 }
438 } 438 }
439 } 439 }
440 } 440 }
441 } 441 }
442 } 442 }
443 } 443 }
444 444
445 @include expect(false) { 445 @include expect(false) {
446 .something:hover .something__child1 + .something__child2--mod1, 446 .something:hover .something__child1 + .something__child2--mod1,
447 .something:hover .something__child1 + .something__child3--mod1 { 447 .something:hover .something__child1 + .something__child3--mod1 {
448 font-size: 2.5em; 448 font-size: 2.5em;
449 } 449 }
450 450
451 .something:hover .something__child1 + .something__child2--mod1.something__child2--submod1, 451 .something:hover .something__child1 + .something__child2--mod1.something__child2--submod1,
452 .something:hover .something__child1 + .something__child3--mod1.something__child3--submod1 { 452 .something:hover .something__child1 + .something__child3--mod1.something__child3--submod1 {
453 font-size: 2.75em; 453 font-size: 2.75em;
454 } 454 }
455 455
456 .test .something__child4 + .something__child5--mod1, 456 .test .something__child4 + .something__child5--mod1,
457 .test .something__child4 + .something__child6--mod1 { 457 .test .something__child4 + .something__child6--mod1 {
458 font-size: 2.5em; 458 font-size: 2.5em;
459 } 459 }
460 460
461 .test .something__child4 + .something__child5--mod1.something__child5--submod1, 461 .test .something__child4 + .something__child5--mod1.something__child5--submod1,
462 .test .something__child4 + .something__child6--mod1.something__child6--submod1 { 462 .test .something__child4 + .something__child6--mod1.something__child6--submod1 {
463 font-size: 2.75em; 463 font-size: 2.75em;
464 } 464 }
465 465
466 .something__child7:hover + .something__child8--mod2, 466 .something__child7:hover + .something__child8--mod2,
467 .something__child7:hover + .something__child9--mod2 { 467 .something__child7:hover + .something__child9--mod2 {
468 font-size: 2.5em; 468 font-size: 2.5em;
469 } 469 }
470 470
471 .something__child7:hover + .something__child8--mod2.something__child8--submod2, 471 .something__child7:hover + .something__child8--mod2.something__child8--submod2,
472 .something__child7:hover + .something__child9--mod2.something__child9--submod2 { 472 .something__child7:hover + .something__child9--mod2.something__child9--submod2 {
473 font-size: 2.75em; 473 font-size: 2.75em;
474 } 474 }
475 475
476 .test .something__child7 + .something__child10--mod2, 476 .test .something__child7 + .something__child10--mod2,
477 .test .something__child7 + .something__child11--mod2 { 477 .test .something__child7 + .something__child11--mod2 {
478 font-size: 2.5em; 478 font-size: 2.5em;
479 } 479 }
480 480
481 .test .something__child7 + .something__child10--mod2.something__child10--submod2, 481 .test .something__child7 + .something__child10--mod2.something__child10--submod2,
482 .test .something__child7 + .something__child11--mod2.something__child11--submod2 { 482 .test .something__child7 + .something__child11--mod2.something__child11--submod2 {
483 font-size: 2.75em; 483 font-size: 2.75em;
484 } 484 }
485 } 485 }
486 } 486 }
487 487
488 // @include assert('element modifier, in at-theme') { /// 11 /// 488 // @include assert('element modifier, in at-theme') { /// 11 ///
489 // @include output(false) { 489 // @include output(false) {
490 // @include bem.block('something') { 490 // @include bem.block('something') {
491 // @include bem.at-theme('dark') { 491 // @include bem.at-theme('dark') {
492 // @include bem.elem('child') { 492 // @include bem.elem('child') {
493 // @include bem.modifier('mod') { 493 // @include bem.modifier('mod') {
494 // font-size: 2.5em; 494 // font-size: 2.5em;
495 // 495 //
496 // @include bem.modifier('submod') { 496 // @include bem.modifier('submod') {
497 // font-size: 2.75em; 497 // font-size: 2.75em;
498 // } 498 // }
499 // } 499 // }
500 // } 500 // }
501 // } 501 // }
502 // } 502 // }
503 // } 503 // }
504 // 504 //
505 // @include expect(false) { 505 // @include expect(false) {
506 // .t-dark .something__child--mod, 506 // .t-dark .something__child--mod,
507 // [class*=' t-'] .t-dark .something__child--mod, 507 // [class*=' t-'] .t-dark .something__child--mod,
508 // [class^='t-'] .t-dark .something__child--mod { 508 // [class^='t-'] .t-dark .something__child--mod {
509 // font-size: 2.5em; 509 // font-size: 2.5em;
510 // } 510 // }
511 // 511 //
512 // .t-dark .something__child--mod.something__child--submod, 512 // .t-dark .something__child--mod.something__child--submod,
513 // [class*=' t-'] .t-dark .something__child--mod.something__child--submod, 513 // [class*=' t-'] .t-dark .something__child--mod.something__child--submod,
514 // [class^='t-'] .t-dark .something__child--mod.something__child--submod { 514 // [class^='t-'] .t-dark .something__child--mod.something__child--submod {
515 // font-size: 2.75em; 515 // font-size: 2.75em;
516 // } 516 // }
517 // } 517 // }
518 // } 518 // }
519 519
520 @include assert('nested block modifiers, extending') { /// 12 /// 520 @include assert('nested block modifiers, extending') { /// 12 ///
521 @include output { 521 @include output {
522 @include bem.block('something') { 522 @include bem.block('something') {
523 @include bem.modifier('mod') { 523 @include bem.modifier('mod') {
524 font-size: 1.5em; 524 font-size: 1.5em;
525 525
526 @include bem.modifier('submod' true) { 526 @include bem.modifier('submod' true) {
527 font-size: 1.75em; 527 font-size: 1.75em;
528 } 528 }
529 } 529 }
530 } 530 }
531 } 531 }
532 532
533 @include expect { 533 @include expect {
534 .something--mod { 534 .something--mod {
535 font-size: 1.5em; 535 font-size: 1.5em;
536 } 536 }
537 537
538 .something--mod--submod { 538 .something--mod--submod {
539 font-size: 1.75em; 539 font-size: 1.75em;
540 } 540 }
541 } 541 }
542 } 542 }
543 543
544 @include assert('nested element modifiers, extending') { /// 13 /// 544 @include assert('nested element modifiers, extending') { /// 13 ///
545 @include output { 545 @include output {
546 @include bem.block('something') { 546 @include bem.block('something') {
547 @include bem.elem('child') { 547 @include bem.elem('child') {
548 @include bem.modifier('mod') { 548 @include bem.modifier('mod') {
549 font-size: 2.5em; 549 font-size: 2.5em;
550 550
551 @include bem.modifier('submod' true) { 551 @include bem.modifier('submod' true) {
552 font-size: 2.75em; 552 font-size: 2.75em;
553 } 553 }
554 } 554 }
555 } 555 }
556 } 556 }
557 } 557 }
558 558
559 @include expect { 559 @include expect {
560 .something__child--mod { 560 .something__child--mod {
561 font-size: 2.5em; 561 font-size: 2.5em;
562 } 562 }
563 563
564 .something__child--mod--submod { 564 .something__child--mod--submod {
565 font-size: 2.75em; 565 font-size: 2.75em;
566 } 566 }
567 } 567 }
568 } 568 }
569 569
570 @include assert('block and element modifiers, single element') { /// 14 /// 570 @include assert('block and element modifiers, single element') { /// 14 ///
571 @include output { 571 @include output {
572 @include bem.block('something') { 572 @include bem.block('something') {
573 @include bem.modifier('mod1') { 573 @include bem.modifier('mod1') {
574 font-size: 1.5em; 574 font-size: 1.5em;
575 575
576 @include bem.modifier('submod1') { 576 @include bem.modifier('submod1') {
577 font-size: 1.75em; 577 font-size: 1.75em;
578 } 578 }
579 579
580 @include bem.elem('child') { 580 @include bem.elem('child') {
581 @include bem.modifier('mod2') { 581 @include bem.modifier('mod2') {
582 font-size: 2.5em; 582 font-size: 2.5em;
583 583
584 @include bem.modifier('submod2') { 584 @include bem.modifier('submod2') {
585 font-size: 2.75em; 585 font-size: 2.75em;
586 } 586 }
587 } 587 }
588 } 588 }
589 } 589 }
590 } 590 }
591 } 591 }
592 592
593 @include expect { 593 @include expect {
594 .something--mod1 { 594 .something--mod1 {
595 font-size: 1.5em; 595 font-size: 1.5em;
596 } 596 }
597 597
598 .something--mod1.something--submod1 { 598 .something--mod1.something--submod1 {
599 font-size: 1.75em; 599 font-size: 1.75em;
600 } 600 }
601 601
602 .something--mod1 .something__child--mod2 { 602 .something--mod1 .something__child--mod2 {
603 font-size: 2.5em; 603 font-size: 2.5em;
604 } 604 }
605 605
606 .something--mod1 .something__child--mod2.something__child--submod2 { 606 .something--mod1 .something__child--mod2.something__child--submod2 {
607 font-size: 2.75em; 607 font-size: 2.75em;
608 } 608 }
609 } 609 }
610 } 610 }
611 611
612 @include assert('block and element modifiers, multiple elements') { /// 15 /// 612 @include assert('block and element modifiers, multiple elements') { /// 15 ///
613 @include output { 613 @include output {
614 @include bem.block('something') { 614 @include bem.block('something') {
615 @include bem.modifier('mod1') { 615 @include bem.modifier('mod1') {
616 font-size: 1.5em; 616 font-size: 1.5em;
617 617
618 @include bem.modifier('submod1') { 618 @include bem.modifier('submod1') {
619 font-size: 1.75em; 619 font-size: 1.75em;
620 } 620 }
621 621
622 @include bem.elem('child1', 'child2') { 622 @include bem.elem('child1', 'child2') {
623 @include bem.modifier('mod2') { 623 @include bem.modifier('mod2') {
624 font-size: 2.5em; 624 font-size: 2.5em;
625 625
626 @include bem.modifier('submod2') { 626 @include bem.modifier('submod2') {
627 font-size: 2.75em; 627 font-size: 2.75em;
628 } 628 }
629 } 629 }
630 } 630 }
631 } 631 }
632 } 632 }
633 } 633 }
634 634
635 @include expect { 635 @include expect {
636 .something--mod1 { 636 .something--mod1 {
637 font-size: 1.5em; 637 font-size: 1.5em;
638 } 638 }
639 639
640 .something--mod1.something--submod1 { 640 .something--mod1.something--submod1 {
641 font-size: 1.75em; 641 font-size: 1.75em;
642 } 642 }
643 643
644 .something--mod1 .something__child1--mod2, 644 .something--mod1 .something__child1--mod2,
645 .something--mod1 .something__child2--mod2 { 645 .something--mod1 .something__child2--mod2 {
646 font-size: 2.5em; 646 font-size: 2.5em;
647 } 647 }
648 648
649 .something--mod1 .something__child1--mod2.something__child1--submod2, 649 .something--mod1 .something__child1--mod2.something__child1--submod2,
650 .something--mod1 .something__child2--mod2.something__child2--submod2 { 650 .something--mod1 .something__child2--mod2.something__child2--submod2 {
651 font-size: 2.75em; 651 font-size: 2.75em;
652 } 652 }
653 } 653 }
654 } 654 }
655} 655}
diff --git a/test/bem/_multi.scss b/test/bem/_multi.scss
index 255fb45..88a4cf4 100644
--- a/test/bem/_multi.scss
+++ b/test/bem/_multi.scss
@@ -26,569 +26,569 @@
26// 26//
27 27
28@include it('multi') { 28@include it('multi') {
29 @include assert('in root, 2 blocks') { /// 1 /// 29 @include assert('in root, 2 blocks') { /// 1 ///
30 @include output { 30 @include output {
31 @include bem.multi('component:' 'block1', 'object:' 'block2') { 31 @include bem.multi('component:' 'block1', 'object:' 'block2') {
32 font-size: 1em; 32 font-size: 1em;
33 33
34 @include bem.elem('child2') { 34 @include bem.elem('child2') {
35 font-size: 2em; 35 font-size: 2em;
36 } 36 }
37 } 37 }
38 } 38 }
39 39
40 @include expect { 40 @include expect {
41 .c-block1 { 41 .c-block1 {
42 font-size: 1em; 42 font-size: 1em;
43 } 43 }
44 44
45 .c-block1__child2 { 45 .c-block1__child2 {
46 font-size: 2em; 46 font-size: 2em;
47 } 47 }
48 48
49 .o-block2 { 49 .o-block2 {
50 font-size: 1em; 50 font-size: 1em;
51 } 51 }
52 52
53 .o-block2__child2 { 53 .o-block2__child2 {
54 font-size: 2em; 54 font-size: 2em;
55 } 55 }
56 } 56 }
57 } 57 }
58 58
59 @include assert('in root, 1 block, 1 manual selector') { /// 2 /// 59 @include assert('in root, 1 block, 1 manual selector') { /// 2 ///
60 @include output { 60 @include output {
61 @include bem.multi('component:' 'block1', 'a:hover') { 61 @include bem.multi('component:' 'block1', 'a:hover') {
62 font-size: 1em; 62 font-size: 1em;
63 } 63 }
64 } 64 }
65 65
66 @include expect { 66 @include expect {
67 .c-block1 { 67 .c-block1 {
68 font-size: 1em; 68 font-size: 1em;
69 } 69 }
70 70
71 a:hover { 71 a:hover {
72 font-size: 1em; 72 font-size: 1em;
73 } 73 }
74 } 74 }
75 } 75 }
76 76
77 @include assert('in block, 2 elements') { /// 3 /// 77 @include assert('in block, 2 elements') { /// 3 ///
78 @include output { 78 @include output {
79 @include bem.block('something') { 79 @include bem.block('something') {
80 @include bem.multi('elem:' 'child1' 'child2') { 80 @include bem.multi('elem:' 'child1' 'child2') {
81 font-size: 2em; 81 font-size: 2em;
82 82
83 @include bem.modifier('mod') { 83 @include bem.modifier('mod') {
84 font-size: 2.5em; 84 font-size: 2.5em;
85 } 85 }
86 } 86 }
87 } 87 }
88 } 88 }
89 89
90 @include expect { 90 @include expect {
91 .something__child1, 91 .something__child1,
92 .something__child2 { 92 .something__child2 {
93 font-size: 2em; 93 font-size: 2em;
94 } 94 }
95 95
96 .something__child1--mod, 96 .something__child1--mod,
97 .something__child2--mod { 97 .something__child2--mod {
98 font-size: 2.5em; 98 font-size: 2.5em;
99 } 99 }
100 } 100 }
101 } 101 }
102 102
103 @include assert('in block, 1 element, 1 modifier') { /// 4 /// 103 @include assert('in block, 1 element, 1 modifier') { /// 4 ///
104 @include output { 104 @include output {
105 @include bem.block('something') { 105 @include bem.block('something') {
106 @include bem.multi('elem:' 'child', 'modifier:' 'mod1') { 106 @include bem.multi('elem:' 'child', 'modifier:' 'mod1') {
107 font-size: 2em; 107 font-size: 2em;
108 108
109 @include bem.modifier('mod2') { 109 @include bem.modifier('mod2') {
110 font-size: 2.5em; 110 font-size: 2.5em;
111 } 111 }
112 } 112 }
113 } 113 }
114 } 114 }
115 115
116 @include expect { 116 @include expect {
117 .something__child { 117 .something__child {
118 font-size: 2em; 118 font-size: 2em;
119 } 119 }
120 120
121 .something__child--mod2 { 121 .something__child--mod2 {
122 font-size: 2.5em; 122 font-size: 2.5em;
123 } 123 }
124 124
125 .something--mod1 { 125 .something--mod1 {
126 font-size: 2em; 126 font-size: 2em;
127 } 127 }
128 128
129 .something--mod1.something--mod2 { 129 .something--mod1.something--mod2 {
130 font-size: 2.5em; 130 font-size: 2.5em;
131 } 131 }
132 } 132 }
133 } 133 }
134 134
135 @include assert('in block, 1 element, 1 extending modifier') { /// 5 /// 135 @include assert('in block, 1 element, 1 extending modifier') { /// 5 ///
136 @include output { 136 @include output {
137 @include bem.block('something') { 137 @include bem.block('something') {
138 @include bem.multi('elem:' 'child', 'modifier:' 'mod1') { 138 @include bem.multi('elem:' 'child', 'modifier:' 'mod1') {
139 font-size: 2em; 139 font-size: 2em;
140 140
141 @include bem.modifier('mod2' true) { 141 @include bem.modifier('mod2' true) {
142 font-size: 2.5em; 142 font-size: 2.5em;
143 } 143 }
144 } 144 }
145 } 145 }
146 } 146 }
147 147
148 @include expect { 148 @include expect {
149 .something__child { 149 .something__child {
150 font-size: 2em; 150 font-size: 2em;
151 } 151 }
152 152
153 .something__child--mod2 { 153 .something__child--mod2 {
154 font-size: 2.5em; 154 font-size: 2.5em;
155 } 155 }
156 156
157 .something--mod1 { 157 .something--mod1 {
158 font-size: 2em; 158 font-size: 2em;
159 } 159 }
160 160
161 .something--mod1--mod2 { 161 .something--mod1--mod2 {
162 font-size: 2.5em; 162 font-size: 2.5em;
163 } 163 }
164 } 164 }
165 } 165 }
166 166
167 @include assert('in block, 1 element, 1 & selector') { /// 6 /// 167 @include assert('in block, 1 element, 1 & selector') { /// 6 ///
168 @include output { 168 @include output {
169 @include bem.block('something') { 169 @include bem.block('something') {
170 @include bem.multi('&', 'elem:' 'child') { 170 @include bem.multi('&', 'elem:' 'child') {
171 font-size: 2em; 171 font-size: 2em;
172 172
173 @include bem.modifier('mod') { 173 @include bem.modifier('mod') {
174 font-size: 2.5em; 174 font-size: 2.5em;
175 } 175 }
176 } 176 }
177 } 177 }
178 } 178 }
179 179
180 @include expect { 180 @include expect {
181 .something { 181 .something {
182 font-size: 2em; 182 font-size: 2em;
183 } 183 }
184 184
185 .something--mod { 185 .something--mod {
186 font-size: 2.5em; 186 font-size: 2.5em;
187 } 187 }
188 188
189 .something__child { 189 .something__child {
190 font-size: 2em; 190 font-size: 2em;
191 } 191 }
192 192
193 .something__child--mod { 193 .something__child--mod {
194 font-size: 2.5em; 194 font-size: 2.5em;
195 } 195 }
196 } 196 }
197 } 197 }
198 198
199 @include assert('in block, 1 element, 1 manual selector') { /// 7 /// 199 @include assert('in block, 1 element, 1 manual selector') { /// 7 ///
200 @include output { 200 @include output {
201 @include bem.block('something') { 201 @include bem.block('something') {
202 @include bem.multi('> a:hover', 'elem:' 'child1') { 202 @include bem.multi('> a:hover', 'elem:' 'child1') {
203 font-size: 2em; 203 font-size: 2em;
204 204
205 @include bem.elem('child2') { 205 @include bem.elem('child2') {
206 font-size: 3em; 206 font-size: 3em;
207 } 207 }
208 } 208 }
209 } 209 }
210 } 210 }
211 211
212 @include expect { 212 @include expect {
213 .something > a:hover { 213 .something > a:hover {
214 font-size: 2em; 214 font-size: 2em;
215 } 215 }
216 216
217 .something > a:hover .something__child2 { 217 .something > a:hover .something__child2 {
218 font-size: 3em; 218 font-size: 3em;
219 } 219 }
220 220
221 .something__child1 { 221 .something__child1 {
222 font-size: 2em; 222 font-size: 2em;
223 } 223 }
224 224
225 .something__child1 .something__child2 { 225 .something__child1 .something__child2 {
226 font-size: 3em; 226 font-size: 3em;
227 } 227 }
228 } 228 }
229 } 229 }
230 230
231 @include assert('in element, 2 elements, 1 modifier') { /// 8 /// 231 @include assert('in element, 2 elements, 1 modifier') { /// 8 ///
232 @include output { 232 @include output {
233 @include bem.block('something') { 233 @include bem.block('something') {
234 @include bem.elem('child') { 234 @include bem.elem('child') {
235 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod1') { 235 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod1') {
236 font-size: 3em; 236 font-size: 3em;
237 237
238 @include bem.modifier('mod2') { 238 @include bem.modifier('mod2') {
239 font-size: 3.5em; 239 font-size: 3.5em;
240 } 240 }
241 } 241 }
242 } 242 }
243 } 243 }
244 } 244 }
245 245
246 @include expect { 246 @include expect {
247 .something__child .something__subchild1, 247 .something__child .something__subchild1,
248 .something__child .something__subchild2 { 248 .something__child .something__subchild2 {
249 font-size: 3em; 249 font-size: 3em;
250 } 250 }
251 251
252 .something__child .something__subchild1--mod2, 252 .something__child .something__subchild1--mod2,
253 .something__child .something__subchild2--mod2 { 253 .something__child .something__subchild2--mod2 {
254 font-size: 3.5em; 254 font-size: 3.5em;
255 } 255 }
256 256
257 .something__child--mod1 { 257 .something__child--mod1 {
258 font-size: 3em; 258 font-size: 3em;
259 } 259 }
260 260
261 .something__child--mod1.something__child--mod2 { 261 .something__child--mod1.something__child--mod2 {
262 font-size: 3.5em; 262 font-size: 3.5em;
263 } 263 }
264 } 264 }
265 } 265 }
266 266
267 @include assert('in element, 1 element, 1 & selector') { /// 9 /// 267 @include assert('in element, 1 element, 1 & selector') { /// 9 ///
268 @include output { 268 @include output {
269 @include bem.block('something') { 269 @include bem.block('something') {
270 @include bem.elem('child') { 270 @include bem.elem('child') {
271 @include bem.multi('elem:' 'subchild', '&') { 271 @include bem.multi('elem:' 'subchild', '&') {
272 font-size: 3em; 272 font-size: 3em;
273 273
274 @include bem.modifier('mod') { 274 @include bem.modifier('mod') {
275 font-size: 3.5em; 275 font-size: 3.5em;
276 } 276 }
277 } 277 }
278 } 278 }
279 } 279 }
280 } 280 }
281 281
282 @include expect { 282 @include expect {
283 .something__child .something__subchild { 283 .something__child .something__subchild {
284 font-size: 3em; 284 font-size: 3em;
285 } 285 }
286 286
287 .something__child .something__subchild--mod { 287 .something__child .something__subchild--mod {
288 font-size: 3.5em; 288 font-size: 3.5em;
289 } 289 }
290 290
291 .something__child { 291 .something__child {
292 font-size: 3em; 292 font-size: 3em;
293 } 293 }
294 294
295 .something__child--mod { 295 .something__child--mod {
296 font-size: 3.5em; 296 font-size: 3.5em;
297 } 297 }
298 } 298 }
299 } 299 }
300 300
301 @include assert('in element in manual selector, 2 elements') { /// 10 /// 301 @include assert('in element in manual selector, 2 elements') { /// 10 ///
302 @include output { 302 @include output {
303 @include bem.block('something') { 303 @include bem.block('something') {
304 @include bem.elem('child') { 304 @include bem.elem('child') {
305 &:hover { 305 &:hover {
306 @include bem.multi('elem:' 'subchild1' 'subchild2') { 306 @include bem.multi('elem:' 'subchild1' 'subchild2') {
307 font-size: 3em; 307 font-size: 3em;
308 308
309 @include bem.modifier('mod2') { 309 @include bem.modifier('mod2') {
310 font-size: 3.5em; 310 font-size: 3.5em;
311 } 311 }
312 } 312 }
313 } 313 }
314 } 314 }
315 } 315 }
316 } 316 }
317 317
318 @include expect { 318 @include expect {
319 .something__child:hover .something__subchild1, 319 .something__child:hover .something__subchild1,
320 .something__child:hover .something__subchild2 { 320 .something__child:hover .something__subchild2 {
321 font-size: 3em; 321 font-size: 3em;
322 } 322 }
323 323
324 .something__child:hover .something__subchild1--mod2, 324 .something__child:hover .something__subchild1--mod2,
325 .something__child:hover .something__subchild2--mod2 { 325 .something__child:hover .something__subchild2--mod2 {
326 font-size: 3.5em; 326 font-size: 3.5em;
327 } 327 }
328 } 328 }
329 } 329 }
330 330
331 @include assert('in element in manual selector, 1 element, 1 & selector') { /// 11 /// 331 @include assert('in element in manual selector, 1 element, 1 & selector') { /// 11 ///
332 @include output { 332 @include output {
333 @include bem.block('something') { 333 @include bem.block('something') {
334 @include bem.elem('child') { 334 @include bem.elem('child') {
335 &:hover { 335 &:hover {
336 @include bem.multi('elem:' 'subchild', '&') { 336 @include bem.multi('elem:' 'subchild', '&') {
337 font-size: 3em; 337 font-size: 3em;
338 } 338 }
339 } 339 }
340 } 340 }
341 } 341 }
342 } 342 }
343 343
344 @include expect { 344 @include expect {
345 .something__child:hover .something__subchild { 345 .something__child:hover .something__subchild {
346 font-size: 3em; 346 font-size: 3em;
347 } 347 }
348 348
349 .something__child:hover { 349 .something__child:hover {
350 font-size: 3em; 350 font-size: 3em;
351 } 351 }
352 } 352 }
353 } 353 }
354 354
355 @include assert('in multiple elements, 2 elements, 1 modifier') { /// 12 /// 355 @include assert('in multiple elements, 2 elements, 1 modifier') { /// 12 ///
356 @include output { 356 @include output {
357 @include bem.block('something') { 357 @include bem.block('something') {
358 @include bem.elem('child1', 'child2') { 358 @include bem.elem('child1', 'child2') {
359 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod') { 359 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod') {
360 font-size: 3em; 360 font-size: 3em;
361 } 361 }
362 } 362 }
363 } 363 }
364 } 364 }
365 365
366 @include expect { 366 @include expect {
367 .something__child1 .something__subchild1, 367 .something__child1 .something__subchild1,
368 .something__child2 .something__subchild1, 368 .something__child2 .something__subchild1,
369 .something__child1 .something__subchild2, 369 .something__child1 .something__subchild2,
370 .something__child2 .something__subchild2 { 370 .something__child2 .something__subchild2 {
371 font-size: 3em; 371 font-size: 3em;
372 } 372 }
373 373
374 .something__child1--mod, 374 .something__child1--mod,
375 .something__child2--mod { 375 .something__child2--mod {
376 font-size: 3em; 376 font-size: 3em;
377 } 377 }
378 } 378 }
379 } 379 }
380 380
381 @include assert('in multiple elements, 1 element, 1 & selector') { /// 13 /// 381 @include assert('in multiple elements, 1 element, 1 & selector') { /// 13 ///
382 @include output { 382 @include output {
383 @include bem.block('something') { 383 @include bem.block('something') {
384 @include bem.elem('child1', 'child2') { 384 @include bem.elem('child1', 'child2') {
385 @include bem.multi('elem:' 'subchild', '&') { 385 @include bem.multi('elem:' 'subchild', '&') {
386 font-size: 3em; 386 font-size: 3em;
387 387
388 @include bem.modifier('mod') { 388 @include bem.modifier('mod') {
389 font-size: 3.5em; 389 font-size: 3.5em;
390 } 390 }
391 } 391 }
392 } 392 }
393 } 393 }
394 } 394 }
395 395
396 @include expect { 396 @include expect {
397 .something__child1 .something__subchild, 397 .something__child1 .something__subchild,
398 .something__child2 .something__subchild { 398 .something__child2 .something__subchild {
399 font-size: 3em; 399 font-size: 3em;
400 } 400 }
401 401
402 .something__child1 .something__subchild--mod, 402 .something__child1 .something__subchild--mod,
403 .something__child2 .something__subchild--mod { 403 .something__child2 .something__subchild--mod {
404 font-size: 3.5em; 404 font-size: 3.5em;
405 } 405 }
406 406
407 .something__child1, 407 .something__child1,
408 .something__child2 { 408 .something__child2 {
409 font-size: 3em; 409 font-size: 3em;
410 } 410 }
411 411
412 .something__child1--mod, 412 .something__child1--mod,
413 .something__child2--mod { 413 .something__child2--mod {
414 font-size: 3.5em; 414 font-size: 3.5em;
415 } 415 }
416 } 416 }
417 } 417 }
418 418
419 @include assert('in related elements, 2 elements, 1 modifier') { /// 14 /// 419 @include assert('in related elements, 2 elements, 1 modifier') { /// 14 ///
420 @include output { 420 @include output {
421 @include bem.block('something') { 421 @include bem.block('something') {
422 @include bem.elem('child1') { 422 @include bem.elem('child1') {
423 @include bem.next-elem('child2', 'child3') { 423 @include bem.next-elem('child2', 'child3') {
424 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod') { 424 @include bem.multi('elem:' 'subchild1' 'subchild2', 'modifier:' 'mod') {
425 font-size: 3em; 425 font-size: 3em;
426 } 426 }
427 } 427 }
428 } 428 }
429 } 429 }
430 } 430 }
431 431
432 @include expect { 432 @include expect {
433 .something__child1 + .something__child2 .something__subchild1, 433 .something__child1 + .something__child2 .something__subchild1,
434 .something__child1 + .something__child3 .something__subchild1, 434 .something__child1 + .something__child3 .something__subchild1,
435 .something__child1 + .something__child2 .something__subchild2, 435 .something__child1 + .something__child2 .something__subchild2,
436 .something__child1 + .something__child3 .something__subchild2 { 436 .something__child1 + .something__child3 .something__subchild2 {
437 font-size: 3em; 437 font-size: 3em;
438 } 438 }
439 439
440 .something__child1 + .something__child2--mod, 440 .something__child1 + .something__child2--mod,
441 .something__child1 + .something__child3--mod { 441 .something__child1 + .something__child3--mod {
442 font-size: 3em; 442 font-size: 3em;
443 } 443 }
444 } 444 }
445 } 445 }
446 446
447 @include assert('in related elements, 1 element, 1 & selector') { /// 15 /// 447 @include assert('in related elements, 1 element, 1 & selector') { /// 15 ///
448 @include output { 448 @include output {
449 @include bem.block('something') { 449 @include bem.block('something') {
450 @include bem.elem('child1') { 450 @include bem.elem('child1') {
451 @include bem.next-elem('child2', 'child3') { 451 @include bem.next-elem('child2', 'child3') {
452 @include bem.multi('elem:' 'subchild', '&') { 452 @include bem.multi('elem:' 'subchild', '&') {
453 font-size: 4em; 453 font-size: 4em;
454 454
455 @include bem.modifier('mod') { 455 @include bem.modifier('mod') {
456 font-size: 4.5em; 456 font-size: 4.5em;
457 } 457 }
458 } 458 }
459 } 459 }
460 } 460 }
461 } 461 }
462 } 462 }
463 463
464 @include expect { 464 @include expect {
465 .something__child1 + .something__child2 .something__subchild, 465 .something__child1 + .something__child2 .something__subchild,
466 .something__child1 + .something__child3 .something__subchild { 466 .something__child1 + .something__child3 .something__subchild {
467 font-size: 4em; 467 font-size: 4em;
468 } 468 }
469 469
470 .something__child1 + .something__child2 .something__subchild--mod, 470 .something__child1 + .something__child2 .something__subchild--mod,
471 .something__child1 + .something__child3 .something__subchild--mod { 471 .something__child1 + .something__child3 .something__subchild--mod {
472 font-size: 4.5em; 472 font-size: 4.5em;
473 } 473 }
474 474
475 .something__child1 + .something__child2, 475 .something__child1 + .something__child2,
476 .something__child1 + .something__child3 { 476 .something__child1 + .something__child3 {
477 font-size: 4em; 477 font-size: 4em;
478 } 478 }
479 479
480 .something__child1 + .something__child2--mod, 480 .something__child1 + .something__child2--mod,
481 .something__child1 + .something__child3--mod { 481 .something__child1 + .something__child3--mod {
482 font-size: 4.5em; 482 font-size: 4.5em;
483 } 483 }
484 } 484 }
485 } 485 }
486 486
487 @include assert('in element, 2 related elements, 1 modifier') { /// 16 /// 487 @include assert('in element, 2 related elements, 1 modifier') { /// 16 ///
488 @include output { 488 @include output {
489 @include bem.block('something') { 489 @include bem.block('something') {
490 @include bem.elem('child1') { 490 @include bem.elem('child1') {
491 @include bem.multi('next-elem:' 'child2' 'child3', 'modifier:' 'mod1') { 491 @include bem.multi('next-elem:' 'child2' 'child3', 'modifier:' 'mod1') {
492 font-size: 3em; 492 font-size: 3em;
493 493
494 @include bem.modifier('mod2') { 494 @include bem.modifier('mod2') {
495 font-size: 3.5em; 495 font-size: 3.5em;
496 } 496 }
497 } 497 }
498 } 498 }
499 } 499 }
500 } 500 }
501 501
502 @include expect { 502 @include expect {
503 .something__child1 + .something__child2, 503 .something__child1 + .something__child2,
504 .something__child1 + .something__child3 { 504 .something__child1 + .something__child3 {
505 font-size: 3em; 505 font-size: 3em;
506 } 506 }
507 507
508 .something__child1 + .something__child2--mod2, 508 .something__child1 + .something__child2--mod2,
509 .something__child1 + .something__child3--mod2 { 509 .something__child1 + .something__child3--mod2 {
510 font-size: 3.5em; 510 font-size: 3.5em;
511 } 511 }
512 512
513 .something__child1--mod1 { 513 .something__child1--mod1 {
514 font-size: 3em; 514 font-size: 3em;
515 } 515 }
516 516
517 .something__child1--mod1.something__child1--mod2 { 517 .something__child1--mod1.something__child1--mod2 {
518 font-size: 3.5em; 518 font-size: 3.5em;
519 } 519 }
520 } 520 }
521 } 521 }
522 522
523 @include assert('in element, 1 twin element, 1 modifier') { /// 17 /// 523 @include assert('in element, 1 twin element, 1 modifier') { /// 17 ///
524 @include output { 524 @include output {
525 @include bem.block('something') { 525 @include bem.block('something') {
526 @include bem.elem('child') { 526 @include bem.elem('child') {
527 @include bem.multi('next-twin-elem', 'modifier:' 'mod1') { 527 @include bem.multi('next-twin-elem', 'modifier:' 'mod1') {
528 font-size: 3em; 528 font-size: 3em;
529 529
530 @include bem.modifier('mod2') { 530 @include bem.modifier('mod2') {
531 font-size: 3.5em; 531 font-size: 3.5em;
532 } 532 }
533 } 533 }
534 } 534 }
535 } 535 }
536 } 536 }
537 537
538 @include expect { 538 @include expect {
539 .something__child + .something__child { 539 .something__child + .something__child {
540 font-size: 3em; 540 font-size: 3em;
541 } 541 }
542 542
543 .something__child + .something__child--mod2 { 543 .something__child + .something__child--mod2 {
544 font-size: 3.5em; 544 font-size: 3.5em;
545 } 545 }
546 546
547 .something__child--mod1 { 547 .something__child--mod1 {
548 font-size: 3em; 548 font-size: 3em;
549 } 549 }
550 550
551 .something__child--mod1.something__child--mod2 { 551 .something__child--mod1.something__child--mod2 {
552 font-size: 3.5em; 552 font-size: 3.5em;
553 } 553 }
554 } 554 }
555 } 555 }
556 556
557 @include assert('in multiple elements, 1 twin element, 1 modifier') { /// 18 /// 557 @include assert('in multiple elements, 1 twin element, 1 modifier') { /// 18 ///
558 @include output { 558 @include output {
559 @include bem.block('something') { 559 @include bem.block('something') {
560 @include bem.elem('child1', 'child2') { 560 @include bem.elem('child1', 'child2') {
561 @include bem.multi('next-twin-elem', 'modifier:' 'mod1') { 561 @include bem.multi('next-twin-elem', 'modifier:' 'mod1') {
562 font-size: 3em; 562 font-size: 3em;
563 563
564 @include bem.modifier('mod2') { 564 @include bem.modifier('mod2') {
565 font-size: 3.5em; 565 font-size: 3.5em;
566 } 566 }
567 } 567 }
568 } 568 }
569 } 569 }
570 } 570 }
571 571
572 @include expect { 572 @include expect {
573 .something__child1 + .something__child1, 573 .something__child1 + .something__child1,
574 .something__child2 + .something__child2 { 574 .something__child2 + .something__child2 {
575 font-size: 3em; 575 font-size: 3em;
576 } 576 }
577 577
578 .something__child1 + .something__child1--mod2, 578 .something__child1 + .something__child1--mod2,
579 .something__child2 + .something__child2--mod2 { 579 .something__child2 + .something__child2--mod2 {
580 font-size: 3.5em; 580 font-size: 3.5em;
581 } 581 }
582 582
583 .something__child1--mod1, 583 .something__child1--mod1,
584 .something__child2--mod1 { 584 .something__child2--mod1 {
585 font-size: 3em; 585 font-size: 3em;
586 } 586 }
587 587
588 .something__child1--mod1.something__child1--mod2, 588 .something__child1--mod1.something__child1--mod2,
589 .something__child2--mod1.something__child2--mod2 { 589 .something__child2--mod1.something__child2--mod2 {
590 font-size: 3.5em; 590 font-size: 3.5em;
591 } 591 }
592 } 592 }
593 } 593 }
594} 594}
diff --git a/test/bem/_next-twin-element.scss b/test/bem/_next-twin-element.scss
index 355e635..3365a0b 100644
--- a/test/bem/_next-twin-element.scss
+++ b/test/bem/_next-twin-element.scss
@@ -14,143 +14,143 @@
14// 14//
15 15
16@include it('next-twin-elem') { 16@include it('next-twin-elem') {
17 @include assert('single element') { /// 1 /// 17 @include assert('single element') { /// 1 ///
18 @include output { 18 @include output {
19 @include bem.block('something') { 19 @include bem.block('something') {
20 @include bem.elem('child') { 20 @include bem.elem('child') {
21 @include bem.next-twin-elem { 21 @include bem.next-twin-elem {
22 font-size: 2em; 22 font-size: 2em;
23 } 23 }
24 } 24 }
25 } 25 }
26 } 26 }
27 27
28 @include expect { 28 @include expect {
29 .something__child + .something__child { 29 .something__child + .something__child {
30 font-size: 2em; 30 font-size: 2em;
31 } 31 }
32 } 32 }
33 } 33 }
34 34
35 @include assert('single element, manual selector in-between') { /// 2 /// 35 @include assert('single element, manual selector in-between') { /// 2 ///
36 @include output(false) { 36 @include output(false) {
37 @include bem.block('something') { 37 @include bem.block('something') {
38 @include bem.elem('child') { 38 @include bem.elem('child') {
39 &:hover { 39 &:hover {
40 @include bem.next-twin-elem { 40 @include bem.next-twin-elem {
41 font-size: 2em; 41 font-size: 2em;
42 } 42 }
43 } 43 }
44 44
45 .test & { 45 .test & {
46 @include bem.next-twin-elem { 46 @include bem.next-twin-elem {
47 font-size: 2em; 47 font-size: 2em;
48 } 48 }
49 } 49 }
50 } 50 }
51 } 51 }
52 } 52 }
53 53
54 @include expect(false) { 54 @include expect(false) {
55 .something__child:hover + .something__child { 55 .something__child:hover + .something__child {
56 font-size: 2em; 56 font-size: 2em;
57 } 57 }
58 58
59 .test .something__child + .something__child { 59 .test .something__child + .something__child {
60 font-size: 2em; 60 font-size: 2em;
61 } 61 }
62 } 62 }
63 } 63 }
64 64
65 @include assert('single element, modifier in-between') { /// 3 /// 65 @include assert('single element, modifier in-between') { /// 3 ///
66 @include output { 66 @include output {
67 @include bem.block('something') { 67 @include bem.block('something') {
68 @include bem.elem('child') { 68 @include bem.elem('child') {
69 @include bem.modifier('mod') { 69 @include bem.modifier('mod') {
70 @include bem.next-twin-elem { 70 @include bem.next-twin-elem {
71 font-size: 2.5em; 71 font-size: 2.5em;
72 } 72 }
73 } 73 }
74 } 74 }
75 } 75 }
76 } 76 }
77 77
78 @include expect { 78 @include expect {
79 .something__child--mod + .something__child { 79 .something__child--mod + .something__child {
80 font-size: 2.5em; 80 font-size: 2.5em;
81 } 81 }
82 } 82 }
83 } 83 }
84 84
85 @include assert('multiple elements') { /// 4 /// 85 @include assert('multiple elements') { /// 4 ///
86 @include output { 86 @include output {
87 @include bem.block('something') { 87 @include bem.block('something') {
88 @include bem.elem('child1', 'child2') { 88 @include bem.elem('child1', 'child2') {
89 @include bem.next-twin-elem { 89 @include bem.next-twin-elem {
90 font-size: 2em; 90 font-size: 2em;
91 } 91 }
92 } 92 }
93 } 93 }
94 } 94 }
95 95
96 @include expect { 96 @include expect {
97 .something__child1 + .something__child1, 97 .something__child1 + .something__child1,
98 .something__child2 + .something__child2 { 98 .something__child2 + .something__child2 {
99 font-size: 2em; 99 font-size: 2em;
100 } 100 }
101 } 101 }
102 } 102 }
103 103
104 @include assert('multiple elements, manual selector in-between') { /// 5 /// 104 @include assert('multiple elements, manual selector in-between') { /// 5 ///
105 @include output(false) { 105 @include output(false) {
106 @include bem.block('something') { 106 @include bem.block('something') {
107 @include bem.elem('child1', 'child2') { 107 @include bem.elem('child1', 'child2') {
108 &:hover { 108 &:hover {
109 @include bem.next-twin-elem { 109 @include bem.next-twin-elem {
110 font-size: 2em; 110 font-size: 2em;
111 } 111 }
112 } 112 }
113 113
114 .test & { 114 .test & {
115 @include bem.next-twin-elem { 115 @include bem.next-twin-elem {
116 font-size: 2em; 116 font-size: 2em;
117 } 117 }
118 } 118 }
119 } 119 }
120 } 120 }
121 } 121 }
122 122
123 @include expect(false) { 123 @include expect(false) {
124 .something__child1:hover + .something__child1, 124 .something__child1:hover + .something__child1,
125 .something__child2:hover + .something__child2 { 125 .something__child2:hover + .something__child2 {
126 font-size: 2em; 126 font-size: 2em;
127 } 127 }
128 128
129 .test .something__child1 + .something__child1, 129 .test .something__child1 + .something__child1,
130 .test .something__child2 + .something__child2 { 130 .test .something__child2 + .something__child2 {
131 font-size: 2em; 131 font-size: 2em;
132 } 132 }
133 } 133 }
134 } 134 }
135 135
136 @include assert('multiple elements, modifier in-between') { /// 6 /// 136 @include assert('multiple elements, modifier in-between') { /// 6 ///
137 @include output { 137 @include output {
138 @include bem.block('something') { 138 @include bem.block('something') {
139 @include bem.elem('child1', 'child2') { 139 @include bem.elem('child1', 'child2') {
140 @include bem.modifier('mod') { 140 @include bem.modifier('mod') {
141 @include bem.next-twin-elem { 141 @include bem.next-twin-elem {
142 font-size: 2.5em; 142 font-size: 2.5em;
143 } 143 }
144 } 144 }
145 } 145 }
146 } 146 }
147 } 147 }
148 148
149 @include expect { 149 @include expect {
150 .something__child1--mod + .something__child1, 150 .something__child1--mod + .something__child1,
151 .something__child2--mod + .something__child2 { 151 .something__child2--mod + .something__child2 {
152 font-size: 2.5em; 152 font-size: 2.5em;
153 } 153 }
154 } 154 }
155 } 155 }
156} 156}
diff --git a/test/bem/_related-element.scss b/test/bem/_related-element.scss
index 5a829e8..48b3457 100644
--- a/test/bem/_related-element.scss
+++ b/test/bem/_related-element.scss
@@ -20,443 +20,443 @@
20// 20//
21 21
22@include it('related-element') { 22@include it('related-element') {
23 @include assert('single element, single related element') { /// 1 /// 23 @include assert('single element, single related element') { /// 1 ///
24 @include output { 24 @include output {
25 @include bem.block('something') { 25 @include bem.block('something') {
26 @include bem.elem('child') { 26 @include bem.elem('child') {
27 @include bem.related-elem('+', 'subchild1') { 27 @include bem.related-elem('+', 'subchild1') {
28 font-size: 2em; 28 font-size: 2em;
29 } 29 }
30 30
31 @include bem.related-elem('~', 'subchild2') { 31 @include bem.related-elem('~', 'subchild2') {
32 font-size: 2em; 32 font-size: 2em;
33 } 33 }
34 } 34 }
35 } 35 }
36 } 36 }
37 37
38 @include expect { 38 @include expect {
39 .something__child + .something__subchild1 { 39 .something__child + .something__subchild1 {
40 font-size: 2em; 40 font-size: 2em;
41 } 41 }
42 42
43 .something__child ~ .something__subchild2 { 43 .something__child ~ .something__subchild2 {
44 font-size: 2em; 44 font-size: 2em;
45 } 45 }
46 } 46 }
47 } 47 }
48 48
49 @include assert('single element, single related element, manual selector in-between') { /// 2 /// 49 @include assert('single element, single related element, manual selector in-between') { /// 2 ///
50 @include output(false) { 50 @include output(false) {
51 @include bem.block('something') { 51 @include bem.block('something') {
52 @include bem.elem('child') { 52 @include bem.elem('child') {
53 &:hover { 53 &:hover {
54 @include bem.related-elem('+', 'subchild1') { 54 @include bem.related-elem('+', 'subchild1') {
55 font-size: 2em; 55 font-size: 2em;
56 } 56 }
57 57
58 @include bem.related-elem('~', 'subchild2') { 58 @include bem.related-elem('~', 'subchild2') {
59 font-size: 2em; 59 font-size: 2em;
60 } 60 }
61 } 61 }
62 62
63 .test & { 63 .test & {
64 @include bem.related-elem('+', 'subchild3') { 64 @include bem.related-elem('+', 'subchild3') {
65 font-size: 2em; 65 font-size: 2em;
66 } 66 }
67 67
68 @include bem.related-elem('~', 'subchild4') { 68 @include bem.related-elem('~', 'subchild4') {
69 font-size: 2em; 69 font-size: 2em;
70 } 70 }
71 } 71 }
72 } 72 }
73 } 73 }
74 } 74 }
75 75
76 @include expect(false) { 76 @include expect(false) {
77 .something__child:hover + .something__subchild1 { 77 .something__child:hover + .something__subchild1 {
78 font-size: 2em; 78 font-size: 2em;
79 } 79 }
80 80
81 .something__child:hover ~ .something__subchild2 { 81 .something__child:hover ~ .something__subchild2 {
82 font-size: 2em; 82 font-size: 2em;
83 } 83 }
84 84
85 .test .something__child + .something__subchild3 { 85 .test .something__child + .something__subchild3 {
86 font-size: 2em; 86 font-size: 2em;
87 } 87 }
88 88
89 .test .something__child ~ .something__subchild4 { 89 .test .something__child ~ .something__subchild4 {
90 font-size: 2em; 90 font-size: 2em;
91 } 91 }
92 } 92 }
93 } 93 }
94 94
95 @include assert('single element, single related element, modifier in-between') { /// 3 /// 95 @include assert('single element, single related element, modifier in-between') { /// 3 ///
96 @include output { 96 @include output {
97 @include bem.block('something') { 97 @include bem.block('something') {
98 @include bem.elem('child') { 98 @include bem.elem('child') {
99 @include bem.modifier('mod') { 99 @include bem.modifier('mod') {
100 @include bem.related-elem('+', 'subchild1') { 100 @include bem.related-elem('+', 'subchild1') {
101 font-size: 2.5em; 101 font-size: 2.5em;
102 } 102 }
103 103
104 @include bem.related-elem('~', 'subchild2') { 104 @include bem.related-elem('~', 'subchild2') {
105 font-size: 2.5em; 105 font-size: 2.5em;
106 } 106 }
107 } 107 }
108 } 108 }
109 } 109 }
110 } 110 }
111 111
112 @include expect { 112 @include expect {
113 .something__child--mod + .something__subchild1 { 113 .something__child--mod + .something__subchild1 {
114 font-size: 2.5em; 114 font-size: 2.5em;
115 } 115 }
116 116
117 .something__child--mod ~ .something__subchild2 { 117 .something__child--mod ~ .something__subchild2 {
118 font-size: 2.5em; 118 font-size: 2.5em;
119 } 119 }
120 } 120 }
121 } 121 }
122 122
123 @include assert('single element, multiple related elements') { /// 4 /// 123 @include assert('single element, multiple related elements') { /// 4 ///
124 @include output { 124 @include output {
125 @include bem.block('something') { 125 @include bem.block('something') {
126 @include bem.elem('child') { 126 @include bem.elem('child') {
127 @include bem.related-elem('+', 'subchild1', 'subchild2') { 127 @include bem.related-elem('+', 'subchild1', 'subchild2') {
128 font-size: 2.5em; 128 font-size: 2.5em;
129 } 129 }
130 130
131 @include bem.related-elem('~', 'subchild3', 'subchild4') { 131 @include bem.related-elem('~', 'subchild3', 'subchild4') {
132 font-size: 2.5em; 132 font-size: 2.5em;
133 } 133 }
134 } 134 }
135 } 135 }
136 } 136 }
137 137
138 @include expect { 138 @include expect {
139 .something__child + .something__subchild1, 139 .something__child + .something__subchild1,
140 .something__child + .something__subchild2 { 140 .something__child + .something__subchild2 {
141 font-size: 2.5em; 141 font-size: 2.5em;
142 } 142 }
143 143
144 .something__child ~ .something__subchild3, 144 .something__child ~ .something__subchild3,
145 .something__child ~ .something__subchild4 { 145 .something__child ~ .something__subchild4 {
146 font-size: 2.5em; 146 font-size: 2.5em;
147 } 147 }
148 } 148 }
149 } 149 }
150 150
151 @include assert('single element, multiple related elements, manual selector in-between') { /// 5 /// 151 @include assert('single element, multiple related elements, manual selector in-between') { /// 5 ///
152 @include output(false) { 152 @include output(false) {
153 @include bem.block('something') { 153 @include bem.block('something') {
154 @include bem.elem('child') { 154 @include bem.elem('child') {
155 &:hover { 155 &:hover {
156 @include bem.related-elem('+', 'subchild1', 'subchild2') { 156 @include bem.related-elem('+', 'subchild1', 'subchild2') {
157 font-size: 2.5em; 157 font-size: 2.5em;
158 } 158 }
159 159
160 @include bem.related-elem('~', 'subchild3', 'subchild4') { 160 @include bem.related-elem('~', 'subchild3', 'subchild4') {
161 font-size: 2.5em; 161 font-size: 2.5em;
162 } 162 }
163 } 163 }
164 164
165 .test & { 165 .test & {
166 @include bem.related-elem('+', 'subchild5', 'subchild6') { 166 @include bem.related-elem('+', 'subchild5', 'subchild6') {
167 font-size: 2.5em; 167 font-size: 2.5em;
168 } 168 }
169 169
170 @include bem.related-elem('~', 'subchild7', 'subchild8') { 170 @include bem.related-elem('~', 'subchild7', 'subchild8') {
171 font-size: 2.5em; 171 font-size: 2.5em;
172 } 172 }
173 } 173 }
174 } 174 }
175 } 175 }
176 } 176 }
177 177
178 @include expect(false) { 178 @include expect(false) {
179 .something__child:hover + .something__subchild1, 179 .something__child:hover + .something__subchild1,
180 .something__child:hover + .something__subchild2 { 180 .something__child:hover + .something__subchild2 {
181 font-size: 2.5em; 181 font-size: 2.5em;
182 } 182 }
183 183
184 .something__child:hover ~ .something__subchild3, 184 .something__child:hover ~ .something__subchild3,
185 .something__child:hover ~ .something__subchild4 { 185 .something__child:hover ~ .something__subchild4 {
186 font-size: 2.5em; 186 font-size: 2.5em;
187 } 187 }
188 188
189 .test .something__child + .something__subchild5, 189 .test .something__child + .something__subchild5,
190 .test .something__child + .something__subchild6 { 190 .test .something__child + .something__subchild6 {
191 font-size: 2.5em; 191 font-size: 2.5em;
192 } 192 }
193 193
194 .test .something__child ~ .something__subchild7, 194 .test .something__child ~ .something__subchild7,
195 .test .something__child ~ .something__subchild8 { 195 .test .something__child ~ .something__subchild8 {
196 font-size: 2.5em; 196 font-size: 2.5em;
197 } 197 }
198 } 198 }
199 } 199 }
200 200
201 @include assert('single element, multiple related elements, modifier in-between') { /// 6 /// 201 @include assert('single element, multiple related elements, modifier in-between') { /// 6 ///
202 @include output { 202 @include output {
203 @include bem.block('something') { 203 @include bem.block('something') {
204 @include bem.elem('child') { 204 @include bem.elem('child') {
205 @include bem.modifier('mod') { 205 @include bem.modifier('mod') {
206 @include bem.related-elem('+', 'subchild1', 'subchild2') { 206 @include bem.related-elem('+', 'subchild1', 'subchild2') {
207 font-size: 2.5em; 207 font-size: 2.5em;
208 } 208 }
209 209
210 @include bem.related-elem('~', 'subchild3', 'subchild4') { 210 @include bem.related-elem('~', 'subchild3', 'subchild4') {
211 font-size: 2.5em; 211 font-size: 2.5em;
212 } 212 }
213 } 213 }
214 } 214 }
215 } 215 }
216 } 216 }
217 217
218 @include expect { 218 @include expect {
219 .something__child--mod + .something__subchild1, 219 .something__child--mod + .something__subchild1,
220 .something__child--mod + .something__subchild2 { 220 .something__child--mod + .something__subchild2 {
221 font-size: 2.5em; 221 font-size: 2.5em;
222 } 222 }
223 223
224 .something__child--mod ~ .something__subchild3, 224 .something__child--mod ~ .something__subchild3,
225 .something__child--mod ~ .something__subchild4 { 225 .something__child--mod ~ .something__subchild4 {
226 font-size: 2.5em; 226 font-size: 2.5em;
227 } 227 }
228 } 228 }
229 } 229 }
230 230
231 @include assert('multiple elements, single related element') { /// 7 /// 231 @include assert('multiple elements, single related element') { /// 7 ///
232 @include output { 232 @include output {
233 @include bem.block('something') { 233 @include bem.block('something') {
234 @include bem.elem('child1', 'child2') { 234 @include bem.elem('child1', 'child2') {
235 @include bem.related-elem('+', 'subchild1') { 235 @include bem.related-elem('+', 'subchild1') {
236 font-size: 2em; 236 font-size: 2em;
237 } 237 }
238 238
239 @include bem.related-elem('~', 'subchild2') { 239 @include bem.related-elem('~', 'subchild2') {
240 font-size: 2em; 240 font-size: 2em;
241 } 241 }
242 } 242 }
243 } 243 }
244 } 244 }
245 245
246 @include expect { 246 @include expect {
247 .something__child1 + .something__subchild1, 247 .something__child1 + .something__subchild1,
248 .something__child2 + .something__subchild1 { 248 .something__child2 + .something__subchild1 {
249 font-size: 2em; 249 font-size: 2em;
250 } 250 }
251 251
252 .something__child1 ~ .something__subchild2, 252 .something__child1 ~ .something__subchild2,
253 .something__child2 ~ .something__subchild2 { 253 .something__child2 ~ .something__subchild2 {
254 font-size: 2em; 254 font-size: 2em;
255 } 255 }
256 } 256 }
257 } 257 }
258 258
259 @include assert('multiple elements, single related element, manual selector in-between') { /// 8 /// 259 @include assert('multiple elements, single related element, manual selector in-between') { /// 8 ///
260 @include output(false) { 260 @include output(false) {
261 @include bem.block('something') { 261 @include bem.block('something') {
262 @include bem.elem('child1', 'child2') { 262 @include bem.elem('child1', 'child2') {
263 &:hover { 263 &:hover {
264 @include bem.related-elem('+', 'subchild1') { 264 @include bem.related-elem('+', 'subchild1') {
265 font-size: 2em; 265 font-size: 2em;
266 } 266 }
267 267
268 @include bem.related-elem('~', 'subchild2') { 268 @include bem.related-elem('~', 'subchild2') {
269 font-size: 2em; 269 font-size: 2em;
270 } 270 }
271 } 271 }
272 272
273 .test & { 273 .test & {
274 @include bem.related-elem('+', 'subchild3') { 274 @include bem.related-elem('+', 'subchild3') {
275 font-size: 2em; 275 font-size: 2em;
276 } 276 }
277 277
278 @include bem.related-elem('~', 'subchild4') { 278 @include bem.related-elem('~', 'subchild4') {
279 font-size: 2em; 279 font-size: 2em;
280 } 280 }
281 } 281 }
282 } 282 }
283 } 283 }
284 } 284 }
285 285
286 @include expect(false) { 286 @include expect(false) {
287 .something__child1:hover + .something__subchild1, 287 .something__child1:hover + .something__subchild1,
288 .something__child2:hover + .something__subchild1 { 288 .something__child2:hover + .something__subchild1 {
289 font-size: 2em; 289 font-size: 2em;
290 } 290 }
291 291
292 .something__child1:hover ~ .something__subchild2, 292 .something__child1:hover ~ .something__subchild2,
293 .something__child2:hover ~ .something__subchild2 { 293 .something__child2:hover ~ .something__subchild2 {
294 font-size: 2em; 294 font-size: 2em;
295 } 295 }
296 296
297 .test .something__child1 + .something__subchild3, 297 .test .something__child1 + .something__subchild3,
298 .test .something__child2 + .something__subchild3 { 298 .test .something__child2 + .something__subchild3 {
299 font-size: 2em; 299 font-size: 2em;
300 } 300 }
301 301
302 .test .something__child1 ~ .something__subchild4, 302 .test .something__child1 ~ .something__subchild4,
303 .test .something__child2 ~ .something__subchild4 { 303 .test .something__child2 ~ .something__subchild4 {
304 font-size: 2em; 304 font-size: 2em;
305 } 305 }
306 } 306 }
307 } 307 }
308 308
309 @include assert('multiple elements, single related element, modifier in-between') { /// 9 /// 309 @include assert('multiple elements, single related element, modifier in-between') { /// 9 ///
310 @include output { 310 @include output {
311 @include bem.block('something') { 311 @include bem.block('something') {
312 @include bem.elem('child1', 'child2') { 312 @include bem.elem('child1', 'child2') {
313 @include bem.modifier('mod') { 313 @include bem.modifier('mod') {
314 @include bem.related-elem('+', 'subchild1') { 314 @include bem.related-elem('+', 'subchild1') {
315 font-size: 2.5em; 315 font-size: 2.5em;
316 } 316 }
317 317
318 @include bem.related-elem('~', 'subchild2') { 318 @include bem.related-elem('~', 'subchild2') {
319 font-size: 2.5em; 319 font-size: 2.5em;
320 } 320 }
321 } 321 }
322 } 322 }
323 } 323 }
324 } 324 }
325 325
326 @include expect { 326 @include expect {
327 .something__child1--mod + .something__subchild1, 327 .something__child1--mod + .something__subchild1,
328 .something__child2--mod + .something__subchild1 { 328 .something__child2--mod + .something__subchild1 {
329 font-size: 2.5em; 329 font-size: 2.5em;
330 } 330 }
331 331
332 .something__child1--mod ~ .something__subchild2, 332 .something__child1--mod ~ .something__subchild2,
333 .something__child2--mod ~ .something__subchild2 { 333 .something__child2--mod ~ .something__subchild2 {
334 font-size: 2.5em; 334 font-size: 2.5em;
335 } 335 }
336 } 336 }
337 } 337 }
338 338
339 @include assert('multiple elements, multiple related elements') { /// 10 /// 339 @include assert('multiple elements, multiple related elements') { /// 10 ///
340 @include output { 340 @include output {
341 @include bem.block('something') { 341 @include bem.block('something') {
342 @include bem.elem('child1', 'child2') { 342 @include bem.elem('child1', 'child2') {
343 @include bem.related-elem('+', 'subchild1', 'subchild2') { 343 @include bem.related-elem('+', 'subchild1', 'subchild2') {
344 font-size: 2em; 344 font-size: 2em;
345 } 345 }
346 346
347 @include bem.related-elem('~', 'subchild3', 'subchild4') { 347 @include bem.related-elem('~', 'subchild3', 'subchild4') {
348 font-size: 2em; 348 font-size: 2em;
349 } 349 }
350 } 350 }
351 } 351 }
352 } 352 }
353 353
354 @include expect { 354 @include expect {
355 .something__child1 + .something__subchild1, 355 .something__child1 + .something__subchild1,
356 .something__child2 + .something__subchild1, 356 .something__child2 + .something__subchild1,
357 .something__child1 + .something__subchild2, 357 .something__child1 + .something__subchild2,
358 .something__child2 + .something__subchild2 { 358 .something__child2 + .something__subchild2 {
359 font-size: 2em; 359 font-size: 2em;
360 } 360 }
361 361
362 .something__child1 ~ .something__subchild3, 362 .something__child1 ~ .something__subchild3,
363 .something__child2 ~ .something__subchild3, 363 .something__child2 ~ .something__subchild3,
364 .something__child1 ~ .something__subchild4, 364 .something__child1 ~ .something__subchild4,
365 .something__child2 ~ .something__subchild4 { 365 .something__child2 ~ .something__subchild4 {
366 font-size: 2em; 366 font-size: 2em;
367 } 367 }
368 } 368 }
369 } 369 }
370 370
371 @include assert('multiple elements, multiple related elements, manual selector in-between') { /// 11 /// 371 @include assert('multiple elements, multiple related elements, manual selector in-between') { /// 11 ///
372 @include output(false) { 372 @include output(false) {
373 @include bem.block('something') { 373 @include bem.block('something') {
374 @include bem.elem('child1', 'child2') { 374 @include bem.elem('child1', 'child2') {
375 &:hover { 375 &:hover {
376 @include bem.related-elem('+', 'subchild1', 'subchild2') { 376 @include bem.related-elem('+', 'subchild1', 'subchild2') {
377 font-size: 2em; 377 font-size: 2em;
378 } 378 }
379 379
380 @include bem.related-elem('~', 'subchild3', 'subchild4') { 380 @include bem.related-elem('~', 'subchild3', 'subchild4') {
381 font-size: 2em; 381 font-size: 2em;
382 } 382 }
383 } 383 }
384 384
385 .test & { 385 .test & {
386 @include bem.related-elem('+', 'subchild5', 'subchild6') { 386 @include bem.related-elem('+', 'subchild5', 'subchild6') {
387 font-size: 2em; 387 font-size: 2em;
388 } 388 }
389 389
390 @include bem.related-elem('~', 'subchild7', 'subchild8') { 390 @include bem.related-elem('~', 'subchild7', 'subchild8') {
391 font-size: 2em; 391 font-size: 2em;
392 } 392 }
393 } 393 }
394 } 394 }
395 } 395 }
396 } 396 }
397 397
398 @include expect(false) { 398 @include expect(false) {
399 .something__child1:hover + .something__subchild1, 399 .something__child1:hover + .something__subchild1,
400 .something__child2:hover + .something__subchild1, 400 .something__child2:hover + .something__subchild1,
401 .something__child1:hover + .something__subchild2, 401 .something__child1:hover + .something__subchild2,
402 .something__child2:hover + .something__subchild2 { 402 .something__child2:hover + .something__subchild2 {
403 font-size: 2em; 403 font-size: 2em;
404 } 404 }
405 405
406 .something__child1:hover ~ .something__subchild3, 406 .something__child1:hover ~ .something__subchild3,
407 .something__child2:hover ~ .something__subchild3, 407 .something__child2:hover ~ .something__subchild3,
408 .something__child1:hover ~ .something__subchild4, 408 .something__child1:hover ~ .something__subchild4,
409 .something__child2:hover ~ .something__subchild4 { 409 .something__child2:hover ~ .something__subchild4 {
410 font-size: 2em; 410 font-size: 2em;
411 } 411 }
412 412
413 .test .something__child1 + .something__subchild5, 413 .test .something__child1 + .something__subchild5,
414 .test .something__child2 + .something__subchild5, 414 .test .something__child2 + .something__subchild5,
415 .test .something__child1 + .something__subchild6, 415 .test .something__child1 + .something__subchild6,
416 .test .something__child2 + .something__subchild6 { 416 .test .something__child2 + .something__subchild6 {
417 font-size: 2em; 417 font-size: 2em;
418 } 418 }
419 419
420 .test .something__child1 ~ .something__subchild7, 420 .test .something__child1 ~ .something__subchild7,
421 .test .something__child2 ~ .something__subchild7, 421 .test .something__child2 ~ .something__subchild7,
422 .test .something__child1 ~ .something__subchild8, 422 .test .something__child1 ~ .something__subchild8,
423 .test .something__child2 ~ .something__subchild8 { 423 .test .something__child2 ~ .something__subchild8 {
424 font-size: 2em; 424 font-size: 2em;
425 } 425 }
426 } 426 }
427 } 427 }
428 428
429 @include assert('multiple elements, multiple related elements, modifier in-between') { /// 12 /// 429 @include assert('multiple elements, multiple related elements, modifier in-between') { /// 12 ///
430 @include output { 430 @include output {
431 @include bem.block('something') { 431 @include bem.block('something') {
432 @include bem.elem('child1', 'child2') { 432 @include bem.elem('child1', 'child2') {
433 @include bem.modifier('mod') { 433 @include bem.modifier('mod') {
434 @include bem.related-elem('+', 'subchild1', 'subchild2') { 434 @include bem.related-elem('+', 'subchild1', 'subchild2') {
435 font-size: 2em; 435 font-size: 2em;
436 } 436 }
437 437
438 @include bem.related-elem('~', 'subchild3', 'subchild4') { 438 @include bem.related-elem('~', 'subchild3', 'subchild4') {
439 font-size: 2em; 439 font-size: 2em;
440 } 440 }
441 } 441 }
442 } 442 }
443 } 443 }
444 } 444 }
445 445
446 @include expect { 446 @include expect {
447 .something__child1--mod + .something__subchild1, 447 .something__child1--mod + .something__subchild1,
448 .something__child2--mod + .something__subchild1, 448 .something__child2--mod + .something__subchild1,
449 .something__child1--mod + .something__subchild2, 449 .something__child1--mod + .something__subchild2,
450 .something__child2--mod + .something__subchild2 { 450 .something__child2--mod + .something__subchild2 {
451 font-size: 2em; 451 font-size: 2em;
452 } 452 }
453 453
454 .something__child1--mod ~ .something__subchild3, 454 .something__child1--mod ~ .something__subchild3,
455 .something__child2--mod ~ .something__subchild3, 455 .something__child2--mod ~ .something__subchild3,
456 .something__child1--mod ~ .something__subchild4, 456 .something__child1--mod ~ .something__subchild4,
457 .something__child2--mod ~ .something__subchild4 { 457 .something__child2--mod ~ .something__subchild4 {
458 font-size: 2em; 458 font-size: 2em;
459 } 459 }
460 } 460 }
461 } 461 }
462} 462}
diff --git a/test/bem/_state.scss b/test/bem/_state.scss
index 674da5f..5a1e1d6 100644
--- a/test/bem/_state.scss
+++ b/test/bem/_state.scss
@@ -14,167 +14,167 @@
14// 14//
15 15
16@include it('state') { 16@include it('state') {
17 @include assert('single block, single state') { /// 1 /// 17 @include assert('single block, single state') { /// 1 ///
18 @include output { 18 @include output {
19 @include bem.block('something') { 19 @include bem.block('something') {
20 @include bem.is('active') { 20 @include bem.is('active') {
21 font-size: 1.25em; 21 font-size: 1.25em;
22 } 22 }
23 23
24 @include bem.has('state') { 24 @include bem.has('state') {
25 font-size: 1.75em; 25 font-size: 1.75em;
26 } 26 }
27 } 27 }
28 } 28 }
29 29
30 @include expect { 30 @include expect {
31 .something.is-active { 31 .something.is-active {
32 font-size: 1.25em; 32 font-size: 1.25em;
33 } 33 }
34 34
35 .something.has-state { 35 .something.has-state {
36 font-size: 1.75em; 36 font-size: 1.75em;
37 } 37 }
38 } 38 }
39 } 39 }
40 40
41 @include assert('single element, single state') { /// 2 /// 41 @include assert('single element, single state') { /// 2 ///
42 @include output { 42 @include output {
43 @include bem.block('something') { 43 @include bem.block('something') {
44 @include bem.elem('child') { 44 @include bem.elem('child') {
45 @include bem.is('active') { 45 @include bem.is('active') {
46 font-size: 2.25em; 46 font-size: 2.25em;
47 } 47 }
48 48
49 @include bem.has('state') { 49 @include bem.has('state') {
50 font-size: 2.75em; 50 font-size: 2.75em;
51 } 51 }
52 } 52 }
53 } 53 }
54 } 54 }
55 55
56 @include expect { 56 @include expect {
57 .something__child.is-active { 57 .something__child.is-active {
58 font-size: 2.25em; 58 font-size: 2.25em;
59 } 59 }
60 60
61 .something__child.has-state { 61 .something__child.has-state {
62 font-size: 2.75em; 62 font-size: 2.75em;
63 } 63 }
64 } 64 }
65 } 65 }
66 66
67 @include assert('single block, multiple states') { /// 3 /// 67 @include assert('single block, multiple states') { /// 3 ///
68 @include output { 68 @include output {
69 @include bem.block('something') { 69 @include bem.block('something') {
70 @include bem.is('active', 'primary') { 70 @include bem.is('active', 'primary') {
71 font-size: 1.25em; 71 font-size: 1.25em;
72 } 72 }
73 73
74 @include bem.has('state', 'indicator') { 74 @include bem.has('state', 'indicator') {
75 font-size: 1.75em; 75 font-size: 1.75em;
76 } 76 }
77 } 77 }
78 } 78 }
79 79
80 @include expect { 80 @include expect {
81 .something.is-active, 81 .something.is-active,
82 .something.is-primary { 82 .something.is-primary {
83 font-size: 1.25em; 83 font-size: 1.25em;
84 } 84 }
85 85
86 .something.has-state, 86 .something.has-state,
87 .something.has-indicator { 87 .something.has-indicator {
88 font-size: 1.75em; 88 font-size: 1.75em;
89 } 89 }
90 } 90 }
91 } 91 }
92 92
93 @include assert('single element, multiple states') { /// 4 /// 93 @include assert('single element, multiple states') { /// 4 ///
94 @include output { 94 @include output {
95 @include bem.block('something') { 95 @include bem.block('something') {
96 @include bem.elem('child') { 96 @include bem.elem('child') {
97 @include bem.is('active', 'primary') { 97 @include bem.is('active', 'primary') {
98 font-size: 2.25em; 98 font-size: 2.25em;
99 } 99 }
100 100
101 @include bem.has('state', 'indicator') { 101 @include bem.has('state', 'indicator') {
102 font-size: 2.75em; 102 font-size: 2.75em;
103 } 103 }
104 } 104 }
105 } 105 }
106 } 106 }
107 107
108 @include expect { 108 @include expect {
109 .something__child.is-active, 109 .something__child.is-active,
110 .something__child.is-primary { 110 .something__child.is-primary {
111 font-size: 2.25em; 111 font-size: 2.25em;
112 } 112 }
113 113
114 .something__child.has-state, 114 .something__child.has-state,
115 .something__child.has-indicator { 115 .something__child.has-indicator {
116 font-size: 2.75em; 116 font-size: 2.75em;
117 } 117 }
118 } 118 }
119 } 119 }
120 120
121 @include assert('multiple elements, single state') { /// 5 /// 121 @include assert('multiple elements, single state') { /// 5 ///
122 @include output { 122 @include output {
123 @include bem.block('something') { 123 @include bem.block('something') {
124 @include bem.elem('child1', 'child2') { 124 @include bem.elem('child1', 'child2') {
125 @include bem.is('active') { 125 @include bem.is('active') {
126 font-size: 2.25em; 126 font-size: 2.25em;
127 } 127 }
128 128
129 @include bem.has('state') { 129 @include bem.has('state') {
130 font-size: 2.75em; 130 font-size: 2.75em;
131 } 131 }
132 } 132 }
133 } 133 }
134 } 134 }
135 135
136 @include expect { 136 @include expect {
137 .something__child1.is-active, 137 .something__child1.is-active,
138 .something__child2.is-active { 138 .something__child2.is-active {
139 font-size: 2.25em; 139 font-size: 2.25em;
140 } 140 }
141 141
142 .something__child1.has-state, 142 .something__child1.has-state,
143 .something__child2.has-state { 143 .something__child2.has-state {
144 font-size: 2.75em; 144 font-size: 2.75em;
145 } 145 }
146 } 146 }
147 } 147 }
148 148
149 @include assert('multiple elements, multiple states') { /// 6 /// 149 @include assert('multiple elements, multiple states') { /// 6 ///
150 @include output { 150 @include output {
151 @include bem.block('something') { 151 @include bem.block('something') {
152 @include bem.elem('child1', 'child2') { 152 @include bem.elem('child1', 'child2') {
153 @include bem.is('active', 'primary') { 153 @include bem.is('active', 'primary') {
154 font-size: 2.25em; 154 font-size: 2.25em;
155 } 155 }
156 156
157 @include bem.has('state', 'indicator') { 157 @include bem.has('state', 'indicator') {
158 font-size: 2.75em; 158 font-size: 2.75em;
159 } 159 }
160 } 160 }
161 } 161 }
162 } 162 }
163 163
164 @include expect { 164 @include expect {
165 .something__child1.is-active, 165 .something__child1.is-active,
166 .something__child2.is-active, 166 .something__child2.is-active,
167 .something__child1.is-primary, 167 .something__child1.is-primary,
168 .something__child2.is-primary { 168 .something__child2.is-primary {
169 font-size: 2.25em; 169 font-size: 2.25em;
170 } 170 }
171 171
172 .something__child1.has-state, 172 .something__child1.has-state,
173 .something__child2.has-state, 173 .something__child2.has-state,
174 .something__child1.has-indicator, 174 .something__child1.has-indicator,
175 .something__child2.has-indicator { 175 .something__child2.has-indicator {
176 font-size: 2.75em; 176 font-size: 2.75em;
177 } 177 }
178 } 178 }
179 } 179 }
180} 180}
diff --git a/test/bem/_suffix.scss b/test/bem/_suffix.scss
index 34f55b6..cfec25b 100644
--- a/test/bem/_suffix.scss
+++ b/test/bem/_suffix.scss
@@ -12,86 +12,86 @@
12// 12//
13 13
14@include it('suffix') { 14@include it('suffix') {
15 @include assert('block suffix') { /// 1 /// 15 @include assert('block suffix') { /// 1 ///
16 @include output { 16 @include output {
17 @include bem.block('something') { 17 @include bem.block('something') {
18 @include bem.suffix('sm') { 18 @include bem.suffix('sm') {
19 font-size: 1.5em; 19 font-size: 1.5em;
20 } 20 }
21 } 21 }
22 } 22 }
23 23
24 @include expect { 24 @include expect {
25 .something\@sm { 25 .something\@sm {
26 font-size: 1.5em; 26 font-size: 1.5em;
27 } 27 }
28 } 28 }
29 } 29 }
30 30
31 @include assert('element suffix') { /// 2 /// 31 @include assert('element suffix') { /// 2 ///
32 @include output { 32 @include output {
33 @include bem.block('something') { 33 @include bem.block('something') {
34 @include bem.elem('child') { 34 @include bem.elem('child') {
35 @include bem.suffix('sm') { 35 @include bem.suffix('sm') {
36 font-size: 2.5em; 36 font-size: 2.5em;
37 } 37 }
38 } 38 }
39 } 39 }
40 } 40 }
41 41
42 @include expect { 42 @include expect {
43 .something__child\@sm { 43 .something__child\@sm {
44 font-size: 2.5em; 44 font-size: 2.5em;
45 } 45 }
46 } 46 }
47 } 47 }
48 48
49 @include assert('modifier suffix') { /// 3 /// 49 @include assert('modifier suffix') { /// 3 ///
50 @include output { 50 @include output {
51 @include bem.block('something') { 51 @include bem.block('something') {
52 @include bem.modifier('mod1') { 52 @include bem.modifier('mod1') {
53 @include bem.suffix('sm') { 53 @include bem.suffix('sm') {
54 font-size: 1.75em; 54 font-size: 1.75em;
55 } 55 }
56 } 56 }
57 57
58 @include bem.elem('child') { 58 @include bem.elem('child') {
59 @include bem.modifier('mod2') { 59 @include bem.modifier('mod2') {
60 @include bem.suffix('sm') { 60 @include bem.suffix('sm') {
61 font-size: 2.75em; 61 font-size: 2.75em;
62 } 62 }
63 } 63 }
64 } 64 }
65 } 65 }
66 } 66 }
67 67
68 @include expect { 68 @include expect {
69 .something--mod1\@sm { 69 .something--mod1\@sm {
70 font-size: 1.75em; 70 font-size: 1.75em;
71 } 71 }
72 72
73 .something__child--mod2\@sm { 73 .something__child--mod2\@sm {
74 font-size: 2.75em; 74 font-size: 2.75em;
75 } 75 }
76 } 76 }
77 } 77 }
78 78
79 @include assert('multiple element suffix') { /// 4 /// 79 @include assert('multiple element suffix') { /// 4 ///
80 @include output { 80 @include output {
81 @include bem.block('something') { 81 @include bem.block('something') {
82 @include bem.elem('child1', 'child2') { 82 @include bem.elem('child1', 'child2') {
83 @include bem.suffix('sm') { 83 @include bem.suffix('sm') {
84 font-size: 2.5em; 84 font-size: 2.5em;
85 } 85 }
86 } 86 }
87 } 87 }
88 } 88 }
89 89
90 @include expect { 90 @include expect {
91 .something__child1\@sm, 91 .something__child1\@sm,
92 .something__child2\@sm { 92 .something__child2\@sm {
93 font-size: 2.5em; 93 font-size: 2.5em;
94 } 94 }
95 } 95 }
96 } 96 }
97} 97}
diff --git a/test/test.scss b/test/test.scss
index bddd801..39e369a 100644
--- a/test/test.scss
+++ b/test/test.scss
@@ -9,6 +9,6 @@ gradients.$easing-gradient-steps: 4;
9@import 'responsive'; 9@import 'responsive';
10@import 'harmony'; 10@import 'harmony';
11@import 'gradients'; 11@import 'gradients';
12@import 'props'; 12//@import 'props';
13 13
14@include report; 14@include report;