-
Notifications
You must be signed in to change notification settings - Fork 16
/
index.js
68 lines (57 loc) · 2.08 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
// postcss-increase-specificity v0.2.2
var postcss = require('postcss');
var objectAssign = require('object-assign');
var escapeStringRegexp = require('escape-string-regexp');
require('string.prototype.repeat');
var CSS_ESCAPED_TAB = '\\9';
function increaseSpecifityOfRule(rule, opts) {
rule.selectors = rule.selectors.map(function(selector) {
// Apply it to the selector itself if the selector is a `root` level component
// `html:not(#\\9):not(#\\9):not(#\\9)`
if(
selector === 'html' ||
selector === ':root' ||
selector === ':host' ||
selector === opts.stackableRoot
) {
return selector + opts.stackableRoot.repeat(opts.repeat);
}
// Otherwise just make it a descendant (this is what will happen most of the time)
// `:not(#\\9):not(#\\9):not(#\\9) .foo`
return opts.stackableRoot.repeat(opts.repeat) + ' ' + selector;
});
if(opts.overrideIds) {
if(
// If an id is in there somewhere
(new RegExp('#(?!' + escapeStringRegexp(CSS_ESCAPED_TAB) + ')')).test(rule.selector) ||
// Or it is an attribute selector with an id
(/\[id/).test(rule.selector)
) {
rule.walkDecls(function(decl) {
decl.important = true;
});
}
}
}
// Plugin that adds `:not(#\\9)` selectors to the front of the rule thus increasing specificity
module.exports = postcss.plugin('postcss-increase-specificity', function(options) {
var defaults = {
// The number of times `:not(#\\9)` is appended in front of the selector
repeat: 3,
// Whether to add !important to declarations in rules with id selectors
overrideIds: true,
// The thing we repeat over and over to make up the piece that increases specificity
stackableRoot: ':not(#' + CSS_ESCAPED_TAB + ')'
};
var opts = objectAssign({}, defaults, options);
return function(css) {
css.walkRules(function(rule) {
// Avoid adding additional selectors (stackableRoot) to descendant rules of @keyframe {}
// i.e. `from`, `to`, or `{number}%`
var isInsideKeyframes = rule.parent.type === 'atrule' && rule.parent.name === 'keyframes';
if(!isInsideKeyframes) {
increaseSpecifityOfRule(rule, opts);
}
});
};
});