Skip to content

Commit

Permalink
Close #11 PR: Add filter option. Fixes #10
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximum Hallinan authored and sindresorhus committed Aug 10, 2015
1 parent 25bc6a8 commit 130c41c
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 18 deletions.
38 changes: 33 additions & 5 deletions index.js
@@ -1,13 +1,28 @@
'use strict'; 'use strict';
var isRegExp = require('is-regexp');

module.exports = function (str, opts) { module.exports = function (str, opts) {
str = str.toString(); str = str.toString();
opts = opts || {}; opts = opts || {};


var preserve = !opts.all; var comment = '';
var currentChar = ''; var currentChar = '';
var insideString = false; var insideString = false;
var preserveFilter;
var preserveImportant = !(opts.preserve === false || opts.all === true);
var ret = ''; var ret = '';


// use preserveFilter as an interface for opts.preserve function and RegExp valuess
if (typeof opts.preserve === 'function') {
preserveImportant = false;
preserveFilter = opts.preserve;
} else if (isRegExp(opts.preserve)) {
preserveImportant = false;
preserveFilter = function (comment) {
return opts.preserve.test(comment);
};
}

for (var i = 0; i < str.length; i++) { for (var i = 0; i < str.length; i++) {
currentChar = str[i]; currentChar = str[i];


Expand All @@ -21,16 +36,29 @@ module.exports = function (str, opts) {
} }
} }


// start /* type comment // find beginning of /* type comment
if (!insideString && currentChar === '/' && str[i + 1] === '*') { if (!insideString && currentChar === '/' && str[i + 1] === '*') {
if (!preserve || preserve && str[i + 2] !== '!') { // ignore important comment when configured to preserve comments using important syntax: /*!
// start skipping until we reach end of comment if (!(preserveImportant && str[i + 2] === '!')) {
// iterate over comment
for (var j = i + 2; j < str.length; j++) { for (var j = i + 2; j < str.length; j++) {
// find end of comment
if (str[j] === '*' && str[j + 1] === '/') { if (str[j] === '*' && str[j + 1] === '/') {
if (preserveFilter) {
//evaluate comment text
ret = preserveFilter(comment) ? ret + ('/*' + comment + '*/') : ret;
comment = '';
}

break; break;
} }

// store comment text to be evaluated by the filter when the end of the comment is reached
if (preserveFilter) {
comment += str[j];
}
} }
// skip i to the end of the comment // resume iteration over CSS string from the end of the comment
i = j + 1; i = j + 1;
continue; continue;
} }
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -38,6 +38,7 @@
], ],
"dependencies": { "dependencies": {
"get-stdin": "^4.0.1", "get-stdin": "^4.0.1",
"is-regexp": "^1.0.0",
"meow": "^3.3.0" "meow": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {
Expand Down
34 changes: 27 additions & 7 deletions readme.md
Expand Up @@ -18,9 +18,26 @@ var stripCssComments = require('strip-css-comments');
stripCssComments('/*! <copyright> */ body { /* unicorns */color: hotpink; }'); stripCssComments('/*! <copyright> */ body { /* unicorns */color: hotpink; }');
//=> '/*! <copyright> */ body { color: hotpink; }' //=> '/*! <copyright> */ body { color: hotpink; }'


// use the `all: true` option to strip everything // assign the preserve option `false` to strip all comments including `/*!`
stripCssComments('/*! <copyright> */ body { /* unicorns */color: hotpink; }', {all: true}); stripCssComments(
//=> ' body { color: hotpink; }' '/*! <copyright> */ body { /* unicorns */color: hotpink; }',
{preserve: false}
);
//=> 'body { color: hotpink; }'

// assign the preserve option a regular expression to strip comments not matching the pattern
stripCssComments(
'/*! <copyright> */ body { /* unicorns */color: hotpink; }',
{preserve: /^\!/}
);
//=> '/*! <copyright> */ body { color: hotpink; }'

// assign the preserve option a function that returns `true` to preserve the comment or `false` to strip the comment
stripCssComments(
'/*! <copyright> */ body { /* unicorns */color: hotpink; }',
{preserve: function(comment){/^\!/.test(comment);}}
);
//=> '/*! <copyright> */ body { color: hotpink; }'
``` ```




Expand All @@ -37,12 +54,15 @@ String with CSS.


## options ## options


### all ### preserve


Type: `boolean` Type: `boolean`, `RegExp`, or `function`
Default: `false` Default: `true`


Whether *important* CSS comments *(those starting with `/*!`)* should be stripped. - `preserve: true` - (default) preserve comments that use the `/*! */` syntax;
- `preserve: false` - strip all comments;
- `preserve: [RegExp]` - preserve comments that match a regular expression. The comment text but not the comment syntax (`/**/`) will be tested by the RegExp.
- `preserve: function (comment) { ... }` - a function that returns `true` to preserve the comment or `false` to strip it. The comment is invoked with a single argument, the string found between the comment syntax (`/**/`).




## CLI ## CLI
Expand Down
48 changes: 42 additions & 6 deletions test.js
Expand Up @@ -20,14 +20,50 @@ test(function (t) {
t.assert(strip('body{/*!"\'\\"*/}') === 'body{/*!"\'\\"*/}'); t.assert(strip('body{/*!"\'\\"*/}') === 'body{/*!"\'\\"*/}');


t.assert(strip('/*!//comment*/body{}', {all: true}) === 'body{}'); t.assert(strip('/*!//comment*/body{}', {all: true}) === 'body{}');
t.assert(strip('body{/*!comment*/}', {all: true}) === 'body{}'); t.assert(strip('/*!//comment*/body{}', {all: true}) === 'body{}');
t.assert(strip('body{/*!\ncomment\n\\*/}', {all: true}) === 'body{}'); t.assert(strip('body{/*!comment*/}', {all: true}) === 'body{}');
t.assert(strip('body{content: "\'/*!ad*/\' \\""}', {all: true}) === 'body{content: "\'/*!ad*/\' \\""}'); t.assert(strip('body{/*!\ncomment\n\\*/}', {all: true}) === 'body{}');
t.assert(strip('body{\r\n /*!\n\n\n\nfoo*/\n}', {all: true}) === 'body{\r\n \n}'); t.assert(strip('body{content: "\'/*!ad*/\' \\""}', {all: true}) === 'body{content: "\'/*!ad*/\' \\""}');
t.assert(strip('body/*!foo*/{}', {all: true}) === 'body{}'); t.assert(strip('body{\r\n /*!\n\n\n\nfoo*/\n}', {all: true}) === 'body{\r\n \n}');
t.assert(strip('body{/*!"\'\\"*/}', {all: true}) === 'body{}'); t.assert(strip('body/*!foo*/{}', {all: true}) === 'body{}');
t.assert(strip('body{/*!"\'\\"*/}', {all: true}) === 'body{}');

t.assert(strip('/*!//comment*/body{}', {preserve: false}) === 'body{}');
t.assert(strip('body{/*!comment*/}', {preserve: false}) === 'body{}');
t.assert(strip('body{/*!\ncomment\n\\*/}', {preserve: false}) === 'body{}');
t.assert(strip('body{content: "\'/*!ad*/\' \\""}', {preserve: false}) === 'body{content: "\'/*!ad*/\' \\""}');
t.assert(strip('body{\r\n /*!\n\n\n\nfoo*/\n}', {preserve: false}) === 'body{\r\n \n}');
t.assert(strip('body/*!foo*/{}', {preserve: false}) === 'body{}');
t.assert(strip('body{/*!"\'\\"*/}', {preserve: false}) === 'body{}');


t.assert(strip(new Buffer('body{/*comment*/}')) === 'body{}'); t.assert(strip(new Buffer('body{/*comment*/}')) === 'body{}');


t.assert(strip('body{/*##foo##*/}', {preserve: /^##foo##/}) === 'body{/*##foo##*/}');
t.assert(strip('body{/*foo*/}', {preserve: /^##foo##/}) === 'body{}');
t.assert(strip('body{/*##foo##*//*foo*/}', {preserve: /^##foo##/}) === 'body{/*##foo##*/}');
t.assert(strip('body{/*##foo##*//*!foo*/}', {preserve: /^##foo##/}) === 'body{/*##foo##*/}');
t.assert(strip('body{/*!##foo##*//*foo*/}', {preserve: /^##foo##/}) === 'body{}');

t.assert(
strip('body{/*##foo##*/}', {
preserve: function(comment){return /^##foo##/.test(comment);}
}) === 'body{/*##foo##*/}');
t.assert(
strip('body{/*foo*/}', {
preserve: function(comment){return /^##foo##/.test(comment);}
}) === 'body{}');
t.assert(
strip('body{/*##foo##*//*foo*/}', {
preserve: function(comment){return /^##foo##/.test(comment);}
}) === 'body{/*##foo##*/}');
t.assert(
strip('body{/*##foo##*//*!foo*/}', {
preserve: function(comment){return /^##foo##/.test(comment);}
}) === 'body{/*##foo##*/}');
t.assert(
strip('body{/*!##foo##*//*foo*/}', {
preserve: function(comment){return /^##foo##/.test(comment);}
}) === 'body{}');

t.end(); t.end();
}); });

0 comments on commit 130c41c

Please sign in to comment.