This repository was archived by the owner on Aug 19, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
100 lines (79 loc) · 3.26 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import postcss from 'postcss';
const modDelim = process.env.REBEM_MOD_DELIM || '_';
const elemDelim = process.env.REBEM_ELEM_DELIM || '__';
function buildSelector (ctx, mod) {
let selector = '.';
if (ctx.blockName) {
selector += ctx.blockName;
}
if (ctx.elemName) {
selector += elemDelim + ctx.elemName;
}
if (mod) {
selector += modDelim + mod;
}
return selector;
}
export default postcss.plugin('rebem-css', () => (css) => {
css.walkRules((rule) => {
rule.selector = rule.selector
.replace(/(:block\(.+)/g, (match, rawSelector) => {
// ":block(b):mod(m v) div :block(b2)" -> [":block(b):mod(m v)", "div", "block(b2)"]
const groups = rawSelector.split(/\s+(?![\w\s->'",]+\))/gi);
const re = /(:+)([\w-]+)(\((['",\w->\s]+)\))?/g;
const ctx = { blockName: false, elemName: false };
// Convert all groups to CSS selectors
// :block(b):mod(m v) -> .b_m_v
const result = [];
for (const group of groups) {
if (!group.match(re)) {
result.push(group);
continue;
}
let selector = '';
let mathes = null;
let requiredBuild = false;
while ((mathes = re.exec(group)) !== null) {
const _spliter = 1;
const _tag = 2;
const _rawValue = 3;
const _value = 4;
const spliter = mathes[_spliter];
const tag = mathes[_tag];
const rawValue = mathes[_rawValue];
const value = mathes[_value] ?
mathes[_value].replace(/([\(\)'"])/g, '').trim() : false;
if (tag === 'block') {
requiredBuild = true;
ctx.blockName = value;
ctx.elemName = false;
continue;
}
if (tag === 'elem') {
requiredBuild = true;
ctx.elemName = value;
continue;
}
if (tag === 'mod') {
requiredBuild = false;
const mod = value.replace(/(\s?->\s?|,\s?|\s+?)/g, modDelim);
selector += buildSelector(ctx, mod);
continue;
}
// For pseudo-classes
selector += requiredBuild ? buildSelector(ctx) : '';
selector += spliter + tag;
if (rawValue) {
selector += rawValue;
}
requiredBuild = false;
}
if (requiredBuild) {
selector += buildSelector(ctx);
}
result.push(selector);
}
return result.join(' ');
});
});
});