Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added ability to exclude current rule with an ignore comment placed in… #210

Merged
merged 2 commits into from
Oct 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion __tests__/purgecssDefault.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,14 @@ describe('purge methods with files and default extractor', () => {
})
purgecssResult = purgecss.purge()[0].css
})
it('ignores h1', () => {
it('ignores h1 h2', () => {
expect(purgecssResult.includes('h1')).toBe(true)
expect(purgecssResult.includes('h3')).toBe(true)
})

it('removes the comment', () => {
expect(purgecssResult.includes('/* purgecss ignore */')).toBe(false)
expect(purgecssResult.includes('/* purgecss ignore current */')).toBe(false)
})
})

Expand Down
7 changes: 6 additions & 1 deletion __tests__/test_examples/ignore_comment/ignore_comment.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@
h1 {
color: blue;

}
}

h3 {
/* purgecss ignore current */
color: red;
}
107 changes: 81 additions & 26 deletions lib/purgecss.es.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ var defaultOptions = {
rejected: false
};

var IGNORE_ANNOTATION_CURRENT = 'purgecss ignore current';
var IGNORE_ANNOTATION_NEXT = 'purgecss ignore';
var IGNORE_ANNOTATION_START = 'purgecss start ignore';
var IGNORE_ANNOTATION_END = 'purgecss end ignore';
Expand Down Expand Up @@ -582,6 +583,16 @@ function () {
}
}
}
/**
* Strips quotes at the end and at the end of a string
* @param {string} value the string to be stripped
*/

}, {
key: "stripQuotes",
value: function stripQuotes(value) {
return value.replace(/(^["'])|(["']$)/g, '');
}
/**
* Extract the selectors present in the passed string using a purgecss extractor
* @param {array} content Array of content
Expand Down Expand Up @@ -787,6 +798,10 @@ function () {
return;
}

if (this.hasIgnoreAnnotation(node)) {
return;
}

var keepSelector = true;
node.selector = selectorParser(function (selectorsParsed) {
selectorsParsed.walk(function (selector) {
Expand Down Expand Up @@ -881,7 +896,30 @@ function () {

if (this.options.fontFace) {
if (prop === 'font-family') {
this.usedFontFaces.add(value);
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;

try {
for (var _iterator10 = value.split(',')[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var fontName = _step10.value;
var cleanedFontFace = this.stripQuotes(fontName.trim());
this.usedFontFaces.add(cleanedFontFace);
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
_iterator10.return();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
}
}
}
}
}
}
Expand Down Expand Up @@ -920,34 +958,34 @@ function () {
}

if (this.options.fontFace && node.name === 'font-face') {
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;
var _iteratorNormalCompletion11 = true;
var _didIteratorError11 = false;
var _iteratorError11 = undefined;

try {
for (var _iterator10 = node.nodes[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var _step10$value = _step10.value,
prop = _step10$value.prop,
value = _step10$value.value;
for (var _iterator11 = node.nodes[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
var _step11$value = _step11.value,
prop = _step11$value.prop,
value = _step11$value.value;

if (prop === 'font-family') {
this.atRules.fontFace.push({
name: value,
name: this.stripQuotes(value),
node: node
});
}
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
_didIteratorError11 = true;
_iteratorError11 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
_iterator10.return();
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
_iterator11.return();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
if (_didIteratorError11) {
throw _iteratorError11;
}
}
}
Expand Down Expand Up @@ -979,6 +1017,23 @@ function () {

return false;
}
/**
* Check if the node has a css comment to ignore current selector rule
* @param {object} rule Node of postcss abstract syntax tree
*/

}, {
key: "hasIgnoreAnnotation",
value: function hasIgnoreAnnotation(rule) {
var found = false;
rule.walkComments(function (node) {
if (node && node.type === 'comment' && node.text.includes(IGNORE_ANNOTATION_CURRENT)) {
found = true;
node.remove();
}
});
return found;
}
/**
* Check if the node correspond to an empty css rule
* @param {object} node Node of postcss abstract syntax tree
Expand All @@ -1002,13 +1057,13 @@ function () {
}, {
key: "shouldKeepSelector",
value: function shouldKeepSelector(selectorsInContent, selectorsInRule) {
var _iteratorNormalCompletion11 = true;
var _didIteratorError11 = false;
var _iteratorError11 = undefined;
var _iteratorNormalCompletion12 = true;
var _didIteratorError12 = false;
var _iteratorError12 = undefined;

try {
for (var _iterator11 = selectorsInRule[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
var selector = _step11.value;
for (var _iterator12 = selectorsInRule[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
var selector = _step12.value;
// pseudo class
var unescapedSelector = selector.replace(/\\/g, '');

Expand All @@ -1027,16 +1082,16 @@ function () {
}
}
} catch (err) {
_didIteratorError11 = true;
_iteratorError11 = err;
_didIteratorError12 = true;
_iteratorError12 = err;
} finally {
try {
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
_iterator11.return();
if (!_iteratorNormalCompletion12 && _iterator12.return != null) {
_iterator12.return();
}
} finally {
if (_didIteratorError11) {
throw _iteratorError11;
if (_didIteratorError12) {
throw _iteratorError12;
}
}
}
Expand Down
107 changes: 81 additions & 26 deletions lib/purgecss.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ var defaultOptions = {
rejected: false
};

var IGNORE_ANNOTATION_CURRENT = 'purgecss ignore current';
var IGNORE_ANNOTATION_NEXT = 'purgecss ignore';
var IGNORE_ANNOTATION_START = 'purgecss start ignore';
var IGNORE_ANNOTATION_END = 'purgecss end ignore';
Expand Down Expand Up @@ -586,6 +587,16 @@ function () {
}
}
}
/**
* Strips quotes at the end and at the end of a string
* @param {string} value the string to be stripped
*/

}, {
key: "stripQuotes",
value: function stripQuotes(value) {
return value.replace(/(^["'])|(["']$)/g, '');
}
/**
* Extract the selectors present in the passed string using a purgecss extractor
* @param {array} content Array of content
Expand Down Expand Up @@ -791,6 +802,10 @@ function () {
return;
}

if (this.hasIgnoreAnnotation(node)) {
return;
}

var keepSelector = true;
node.selector = selectorParser(function (selectorsParsed) {
selectorsParsed.walk(function (selector) {
Expand Down Expand Up @@ -885,7 +900,30 @@ function () {

if (this.options.fontFace) {
if (prop === 'font-family') {
this.usedFontFaces.add(value);
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;

try {
for (var _iterator10 = value.split(',')[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var fontName = _step10.value;
var cleanedFontFace = this.stripQuotes(fontName.trim());
this.usedFontFaces.add(cleanedFontFace);
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
_iterator10.return();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
}
}
}
}
}
}
Expand Down Expand Up @@ -924,34 +962,34 @@ function () {
}

if (this.options.fontFace && node.name === 'font-face') {
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;
var _iteratorNormalCompletion11 = true;
var _didIteratorError11 = false;
var _iteratorError11 = undefined;

try {
for (var _iterator10 = node.nodes[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var _step10$value = _step10.value,
prop = _step10$value.prop,
value = _step10$value.value;
for (var _iterator11 = node.nodes[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
var _step11$value = _step11.value,
prop = _step11$value.prop,
value = _step11$value.value;

if (prop === 'font-family') {
this.atRules.fontFace.push({
name: value,
name: this.stripQuotes(value),
node: node
});
}
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
_didIteratorError11 = true;
_iteratorError11 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10.return != null) {
_iterator10.return();
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
_iterator11.return();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
if (_didIteratorError11) {
throw _iteratorError11;
}
}
}
Expand Down Expand Up @@ -983,6 +1021,23 @@ function () {

return false;
}
/**
* Check if the node has a css comment to ignore current selector rule
* @param {object} rule Node of postcss abstract syntax tree
*/

}, {
key: "hasIgnoreAnnotation",
value: function hasIgnoreAnnotation(rule) {
var found = false;
rule.walkComments(function (node) {
if (node && node.type === 'comment' && node.text.includes(IGNORE_ANNOTATION_CURRENT)) {
found = true;
node.remove();
}
});
return found;
}
/**
* Check if the node correspond to an empty css rule
* @param {object} node Node of postcss abstract syntax tree
Expand All @@ -1006,13 +1061,13 @@ function () {
}, {
key: "shouldKeepSelector",
value: function shouldKeepSelector(selectorsInContent, selectorsInRule) {
var _iteratorNormalCompletion11 = true;
var _didIteratorError11 = false;
var _iteratorError11 = undefined;
var _iteratorNormalCompletion12 = true;
var _didIteratorError12 = false;
var _iteratorError12 = undefined;

try {
for (var _iterator11 = selectorsInRule[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
var selector = _step11.value;
for (var _iterator12 = selectorsInRule[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
var selector = _step12.value;
// pseudo class
var unescapedSelector = selector.replace(/\\/g, '');

Expand All @@ -1031,16 +1086,16 @@ function () {
}
}
} catch (err) {
_didIteratorError11 = true;
_iteratorError11 = err;
_didIteratorError12 = true;
_iteratorError12 = err;
} finally {
try {
if (!_iteratorNormalCompletion11 && _iterator11.return != null) {
_iterator11.return();
if (!_iteratorNormalCompletion12 && _iterator12.return != null) {
_iterator12.return();
}
} finally {
if (_didIteratorError11) {
throw _iteratorError11;
if (_didIteratorError12) {
throw _iteratorError12;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/constants/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const IGNORE_ANNOTATION_CURRENT = 'purgecss ignore current'
export const IGNORE_ANNOTATION_NEXT = 'purgecss ignore'
export const IGNORE_ANNOTATION_START = 'purgecss start ignore'
export const IGNORE_ANNOTATION_END = 'purgecss end ignore'
Expand Down