forked from pazams/postcss-scopify
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
101 lines (82 loc) · 2.28 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
101
'use strict';
var postcss = require('postcss');
var selectorParser = require('postcss-selector-parser');
var conditionalGroupRules = ['media','supports','document'];
module.exports = postcss.plugin('postcss-scopify', scopify);
function scopify(scope, options) {
options = options || {};
// special case for the '&' selector, resolves to scope
var processor = selectorParser(function (selectors) {
var hasNestingSelector = false;
selectors.walkNesting(function (selector) {
hasNestingSelector = true;
selector.replaceWith(
selectorParser.string({value: scope})
);
});
if (!hasNestingSelector) {
selectors.first.prepend(
selectorParser.string({value: scope + ' '})
);
}
});
return function(root) {
// guard statment- allow only valid scopes
if(!isValidScope(scope)){
throw root.error('invalid scope', { plugin: 'postcss-scopify' });
}
root.walkRules(function (rule) {
// skip scoping of special rules (certain At-rules, nested, etc')
if(!isRuleScopable(rule)){
return rule;
}
rule.selectors = rule.selectors.map(function(selector) {
if (isScopeApplied(selector,scope)) {
return selector;
}
return processor.processSync(selector);
});
});
};
}
/**
* Determine if selector is already scoped
*
* @param {string} selector
* @param {string} scope
*/
function isScopeApplied(selector,scope) {
var selectorTopScope = selector.split(" ",1)[0];
return selectorTopScope === scope;
}
/**
* Determine if scope is valid
*
* @param {string} scope
*/
function isValidScope(scope) {
if (scope){
return scope.indexOf(',') === -1;
}
else{
return false;
}
}
/**
* Determine if rule should be scoped
*
* @param {rule} rule
*/
function isRuleScopable(rule){
if(rule.parent.type !== 'root') {
if (rule.parent.type === 'atrule' && conditionalGroupRules.indexOf(rule.parent.name) > -1){
return true;
}
else {
return false;
}
}
else {
return true;
}
}