Skip to content

Commit

Permalink
Avoid mangling rules inside @Keyframes
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanKalinin authored and MadLittleMods committed Oct 9, 2017
1 parent 8adccd4 commit add9c6a
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 31 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
npm-debug.log

todo.md
.history/
.vscode/
todo.md
67 changes: 39 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,40 @@ 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 = {
Expand All @@ -22,36 +56,13 @@ module.exports = postcss.plugin('postcss-increase-specificity', function(options

return function(css) {
css.walkRules(function(rule) {
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;
});
// 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(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;
});
}
if(!isInsideKeyframes) {
increaseSpecifityOfRule(rule, opts);
}
});

};
});
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
},
"main": "index.js",
"scripts": {
"test": "mocha"
"test": "mocha",
"mocha": "mocha"
},
"dependencies": {
"escape-string-regexp": "^1.0.5",
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/keyframes.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@keyframes custom-animation {
from { opacity: 0; }
50% { opacity: 0.5; }
60%, 70% {opacity: 0.7; }
to { opacity: 1; }
}
6 changes: 6 additions & 0 deletions test/fixtures/keyframes.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@keyframes custom-animation {
from { opacity: 0; }
50% { opacity: 0.5; }
60%, 70% {opacity: 0.7; }
to { opacity: 1; }
}
4 changes: 4 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,8 @@ describe('postcss-increase-specificity', function() {
}
);
});

it('should not change the descendant rules of @keyframes', function() {
return testPlugin('./test/fixtures/keyframes.css', './test/fixtures/keyframes.expected.css');
});
});

0 comments on commit add9c6a

Please sign in to comment.