Skip to content

Commit 4419428

Browse files
committed
[fix] Make BEM more robust
1 parent a83ced2 commit 4419428

2 files changed

Lines changed: 91 additions & 96 deletions

File tree

src/mixins/function.scss

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,34 @@
22

33
/* BEM support Func
44
-------------------------- */
5-
@function selectorToString($selector) {
6-
$selector: inspect($selector);
7-
$selector: str-slice($selector, 2, -2);
85

9-
@return $selector;
10-
}
11-
12-
@function containsModifier($selector) {
13-
$selector: selectorToString($selector);
14-
15-
@if str-index($selector, $modifier-separator) {
16-
@return true;
17-
} @else {
18-
@return false;
19-
}
20-
}
6+
/// See [Combinators](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#Combinators "CSS selectors")
7+
$_selector-combinators: ("+", "~", ">", "||");
218

22-
@function containWhenFlag($selector) {
23-
$selector: selectorToString($selector);
9+
@function bem-extend($selectors, $extendee, $extender) {
10+
$returns: ();
2411

25-
@if str-index($selector, '.' + $state-prefix) {
26-
@return true;
27-
} @else {
28-
@return false;
12+
@if null == $selectors {
13+
$selectors: selector-parse("");
2914
}
30-
}
3115

32-
@function containPseudoClass($selector) {
33-
$selector: selectorToString($selector);
34-
35-
@if str-index($selector, ':') {
36-
@return true;
37-
} @else {
38-
@return false;
16+
@each $selector in $selectors {
17+
$len: length($selector);
18+
19+
@if nth($selector, $len) == $extendee {
20+
@if $len >= 2 {
21+
@if index($_selector-combinators, nth($selector, $len - 1)) == null {
22+
$returns: append($returns, set-nth($selector, $len, $extender), "comma");
23+
} @else {
24+
$returns: append($returns, append($selector, $extender), "comma");
25+
}
26+
} @else {
27+
$returns: append($returns, ($extender), "comma");
28+
}
29+
} @else {
30+
$returns: append($returns, append($selector, $extender), "comma");
31+
}
3932
}
40-
}
4133

42-
@function hitAllSpecialNestRule($selector) {
43-
@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
34+
@return $returns;
4435
}

src/mixins/mixins.scss

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -67,98 +67,102 @@
6767

6868
/* BEM
6969
-------------------------- */
70+
71+
$_BEM: (null, null, null);
72+
7073
@mixin b($block) {
71-
$B: $namespace+'-'+$block !global;
74+
$lastBEM: $_BEM;
75+
$_BEM: ($block, null, null) !global;
7276

73-
.#{$B} {
77+
.#{$namespace}-#{$block} {
7478
@content;
7579
}
80+
81+
$_BEM: $lastBEM !global;
7682
}
7783

78-
@mixin e($element) {
79-
$E: $element !global;
80-
$selector: &;
81-
$currentSelector: "";
82-
@each $unit in $element {
83-
$currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
84-
}
84+
@mixin e($elements) {
85+
$block: nth($_BEM, 1);
8586

86-
@if hitAllSpecialNestRule($selector) {
87-
@at-root {
88-
#{$selector} {
89-
#{$currentSelector} {
90-
@content;
91-
}
92-
}
93-
}
87+
@if null == $block {
88+
@error "Base-level rules cannot contain an element mixin";
9489
} @else {
95-
@at-root {
96-
#{$currentSelector} {
97-
@content;
98-
}
99-
}
100-
}
101-
}
90+
$selects: &;
10291

103-
@mixin m($modifier) {
104-
$selector: &;
105-
$currentSelector: "";
106-
@each $unit in $modifier {
107-
$currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
108-
}
92+
@if (null != nth($_BEM, 2)) {
93+
$selects: ();
10994

110-
@at-root {
111-
#{$currentSelector} {
112-
@content;
95+
@each $old-select in & {
96+
$selects: append($selects, set-nth($old-select, length($old-select), ".#{$namespace}-#{$block}"), "comma")
97+
}
11398
}
114-
}
115-
}
11699

117-
@mixin configurable-m($modifier, $E-flag: false) {
118-
$selector: &;
119-
$interpolation: '';
100+
$lastBEM: $_BEM;
101+
$_BEM: ($block, $elements, null) !global;
120102

121-
@if $E-flag {
122-
$interpolation: $element-separator + $E-flag;
123-
}
103+
$parent: ".#{$namespace}-#{$block}";
104+
$current: ();
124105

125-
@at-root {
126-
#{$selector} {
127-
.#{$B+$interpolation+$modifier-separator+$modifier} {
106+
@each $element in $elements {
107+
$current: append(
108+
$current,
109+
bem-extend($selects, $parent, "#{$parent}#{$element-separator}#{$element}"),
110+
"comma",
111+
);
112+
}
113+
114+
@at-root {
115+
#{$current} {
128116
@content;
129117
}
130118
}
119+
120+
$_BEM: $lastBEM !global;
131121
}
132122
}
133123

134-
@mixin spec-selector($specSelector: '', $element: $E, $modifier: false, $block: $B) {
135-
$modifierCombo: '';
124+
@mixin m($modifiers) {
125+
$block: nth($_BEM, 1);
136126

137-
@if $modifier {
138-
$modifierCombo: $modifier-separator + $modifier;
139-
}
127+
@if null == $block {
128+
@error "Base-level rules cannot contain a modifier mixin";
129+
} @else if null != nth($_BEM, 3) {
130+
@error "Modifier-level rules cannot contain another modifier mixin";
131+
} @else {
132+
$elements: nth($_BEM, 2);
140133

141-
@at-root {
142-
#{&}#{$specSelector}.#{$block+$element-separator+$element+$modifierCombo} {
143-
@content;
134+
@if (null == $elements) {
135+
$elements: (null);
144136
}
145-
}
146-
}
147137

148-
@mixin meb($modifier: false, $element: $E, $block: $B) {
149-
$selector: &;
150-
$modifierCombo: '';
138+
$lastBEM: $_BEM;
139+
$_BEM: ($block, $elements, $modifiers) !global;
151140

152-
@if $modifier {
153-
$modifierCombo: $modifier-separator + $modifier;
154-
}
141+
@each $element in $elements {
142+
$parent: ".#{$namespace}-#{$block}";
155143

156-
@at-root {
157-
#{$selector} {
158-
.#{$block+$element-separator+$element+$modifierCombo} {
159-
@content;
144+
@if (null != $element) {
145+
$parent: "#{$parent}#{$element-separator}#{$element}";
146+
}
147+
148+
$current: ();
149+
150+
@each $modifier in $modifiers {
151+
$current: append(
152+
$current,
153+
bem-extend(&, $parent, "#{$parent}#{$modifier-separator}#{$modifier}"),
154+
"comma",
155+
);
156+
}
157+
158+
@at-root {
159+
#{$current} {
160+
@content;
161+
}
160162
}
161163
}
164+
165+
$_BEM: $lastBEM !global;
162166
}
163167
}
164168

0 commit comments

Comments
 (0)