New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

gulp-css-usage

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gulp-css-usage - npm Package Compare versions

Comparing version 1.0.10 to 2.0.0

232

dist/index.js
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});

@@ -34,118 +34,120 @@

var getAllSelectorsFromCSSFile = function getAllSelectorsFromCSSFile(cssFile) {
var contents = cssFile.contents.toString();
var selectors = {};
var matches = cssSelectorRegex.exec(contents);
while (matches != null) {
var selector = matches[1];
selectors[selector] = selector;
matches = cssSelectorRegex.exec(contents);
}
var contents = cssFile.contents.toString();
var selectors = {};
var matches = cssSelectorRegex.exec(contents);
while (matches != null) {
var selector = matches[1];
selectors[selector] = selector;
matches = cssSelectorRegex.exec(contents);
}
return selectors;
return selectors;
};
var makeDiff = function makeDiff(cssSelectors, jsxAttributes) {
var needless = [];
Object.keys(cssSelectors).forEach(function (selector) {
if (!jsxAttributes[selector.substring(1)]) {
needless.push(selector);
}
});
var needless = [];
return needless;
var cssSelectorKeys = Object.keys(cssSelectors);
cssSelectorKeys.forEach(function (selector) {
if (!jsxAttributes[selector.substring(1)]) {
needless.push(selector);
}
});
var statistics = (needless.length / cssSelectorKeys.length * 100).toFixed(0);
return { needless: needless, statistics: statistics };
};
var printNeedlessSelectorList = function printNeedlessSelectorList(list) {
_gulpUtil2.default.log('');
_gulpUtil2.default.log(_gulpUtil2.default.colors.yellow(PLUGIN_NAME + ': The following selectors are not in use'));
list.forEach(function (selector) {
return _gulpUtil2.default.log(selector);
});
_gulpUtil2.default.log('');
var printNeedlessSelectorList = function printNeedlessSelectorList(list, statistics) {
_gulpUtil2.default.log('');
_gulpUtil2.default.log(_gulpUtil2.default.colors.yellow(PLUGIN_NAME + ': ' + statistics + '% of your css selectors are not in use!'));
_gulpUtil2.default.log(_gulpUtil2.default.colors.yellow(PLUGIN_NAME + ': The selectors are:'));
list.forEach(function (selector) {
return _gulpUtil2.default.log(selector);
});
_gulpUtil2.default.log('');
};
var parseAndExtractJsxAttributes = function parseAndExtractJsxAttributes(jsxFileContents) {
var babylonPlugins = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var babylonPlugins = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var jsxAttributes = {};
var plugins = ['jsx', 'flow', 'classProperties'];
if (babylonPlugins.length) {
plugins = plugins.concat(babylonPlugins);
}
var jsxAttributes = {};
var plugins = ['jsx', 'flow', 'classProperties'];
if (babylonPlugins.length) {
plugins = plugins.concat(babylonPlugins);
}
// use babylon.parse and then babel traverse for dynamic class names and other attributes on the jsx code.
// might come up with a bit more strings but the needless stuff are not here anyway.
var ast = (0, _babylon.parse)(jsxFileContents, { sourceType: 'module', plugins: plugins });
(0, _babelTraverse2.default)(ast, {
enter: function enter(path) {
var _path$node = path.node;
var type = _path$node.type;
var value = _path$node.value;
// use babylon.parse and then babel traverse for dynamic class names and other attributes on the jsx code.
// might come up with a bit more strings but the needless stuff are not here anyway.
var ast = (0, _babylon.parse)(jsxFileContents, { sourceType: 'module', plugins: plugins });
(0, _babelTraverse2.default)(ast, {
enter: function enter(path) {
var _path$node = path.node;
var type = _path$node.type;
var value = _path$node.value;
if (type === 'StringLiteral') {
var attributes = value.split(' ');
attributes.forEach(function (attr) {
return jsxAttributes[attr] = attr;
});
}
}
});
if (type === 'StringLiteral') {
var attributes = value.split(' ');
attributes.forEach(function (attr) {
return jsxAttributes[attr] = attr;
});
}
}
});
return jsxAttributes;
return jsxAttributes;
};
var validateInput = function validateInput(cssFilePath, threshold) {
if (!cssFilePath) {
throw new PluginError(PLUGIN_NAME, 'Missing css field!');
}
if (typeof cssFilePath !== 'string') {
throw new PluginError(PLUGIN_NAME, 'css field must be a string!');
}
if (threshold && (typeof threshold !== 'number' || threshold > 100 || threshold < 0)) {
throw new PluginError(PLUGIN_NAME, 'threshold value should be a number between 0-100!');
}
};
var gulpCssUsage = function gulpCssUsage() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var cssFilePath = options.css;
var babylon = options.babylon;
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var cssFilePath = options.css;
var babylon = options.babylon;
var threshold = options.threshold;
if (!cssFilePath) {
throw new PluginError(PLUGIN_NAME, 'Missing css field!');
}
if (typeof cssFilePath !== 'string') {
throw new PluginError(PLUGIN_NAME, 'css field must be a string!');
}
var cssFile = new _gulpUtil2.default.File({ path: cssFilePath, contents: _fs2.default.readFileSync(cssFilePath) });
var cssSelectors = getAllSelectorsFromCSSFile(cssFile);
var fileBuffer = undefined;
var allAttributes = {};
var transformers = function transformers(file, enc, cb) {
var currentJsxAttributes = undefined;
if (file.isNull()) {
return cb(error, file);
}
if (file.isBuffer()) {
currentJsxAttributes = parseAndExtractJsxAttributes(file.contents.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
cb(error, file);
}
if (file.isStream()) {
_gulpUtil2.default.log(_gulpUtil2.default.colors.magenta(PLUGIN_NAME + ': streaming is deprecated and will not be supported soon'));
if (enc !== 'utf8') {
file.contents.setEncoding('utf8');
}
if (!fileBuffer) {
fileBuffer = new Buffer([]); // utf8 by default
}
validateInput(cssFilePath, threshold);
file.contents.on('data', function (chunk) {
return fileBuffer = Buffer.concat([new Buffer(chunk), fileBuffer]);
});
file.contents.on('end', function () {
currentJsxAttributes = parseAndExtractJsxAttributes(fileBuffer.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
fileBuffer = undefined;
cb(error, file);
});
}
};
var cssFile = new _gulpUtil2.default.File({ path: cssFilePath, contents: _fs2.default.readFileSync(cssFilePath) });
var cssSelectors = getAllSelectorsFromCSSFile(cssFile);
var flush = function flush(cb) {
var needless = makeDiff(cssSelectors, allAttributes);
printNeedlessSelectorList(needless);
cb();
};
return _through2.default.obj(function (file, enc, cb) {
var currentJsxAttributes = void 0;
if (file.isNull()) {
return cb(error, file);
}
if (file.isStream()) {
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
}
return _through2.default.obj({}, transformers, flush);
var allAttributes = {};
// file is buffer
currentJsxAttributes = parseAndExtractJsxAttributes(file.contents.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
var _makeDiff = makeDiff(cssSelectors, allAttributes);
var needless = _makeDiff.needless;
var statistics = _makeDiff.statistics;
printNeedlessSelectorList(needless, statistics);
if (threshold && statistics >= threshold) {
return cb(new PluginError(PLUGIN_NAME, 'too many unused css selectors!'));
}
cb(error, file);
});
};

@@ -156,26 +158,26 @@

if (typeof Object.assign != 'function') {
(function () {
Object.assign = function (target) {
'use strict';
(function () {
Object.assign = function (target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}
exports.default = gulpCssUsage;

@@ -14,106 +14,107 @@ import through from 'through2';

let getAllSelectorsFromCSSFile = (cssFile) => {
let contents = cssFile.contents.toString();
let selectors = {};
let matches = cssSelectorRegex.exec(contents);
while (matches != null) {
let selector = matches[1];
selectors[selector] = selector;
matches = cssSelectorRegex.exec(contents);
}
let contents = cssFile.contents.toString();
let selectors = {};
let matches = cssSelectorRegex.exec(contents);
while (matches != null) {
let selector = matches[1];
selectors[selector] = selector;
matches = cssSelectorRegex.exec(contents);
}
return selectors;
return selectors;
};
let makeDiff = (cssSelectors, jsxAttributes) => {
let needless = [];
Object.keys(cssSelectors).forEach(selector => {
if (!jsxAttributes[selector.substring(1)]) {
needless.push(selector);
}
});
let needless = [];
return needless;
let cssSelectorKeys = Object.keys(cssSelectors);
cssSelectorKeys.forEach(selector => {
if (!jsxAttributes[selector.substring(1)]) {
needless.push(selector);
}
});
let statistics = ((needless.length / cssSelectorKeys.length) * 100).toFixed(0);
return {needless, statistics};
};
let printNeedlessSelectorList = (list) => {
gutil.log('');
gutil.log(gutil.colors.yellow(PLUGIN_NAME + ': The following selectors are not in use'));
list.forEach(selector => gutil.log(selector));
gutil.log('');
let printNeedlessSelectorList = (list, statistics) => {
gutil.log('');
gutil.log(gutil.colors.yellow(PLUGIN_NAME + ': ' + statistics + '% of your css selectors are not in use!'));
gutil.log(gutil.colors.yellow(PLUGIN_NAME + ': The selectors are:'));
list.forEach(selector => gutil.log(selector));
gutil.log('');
};
let parseAndExtractJsxAttributes = (jsxFileContents, babylonPlugins = []) => {
let jsxAttributes = {};
let plugins = ['jsx', 'flow', 'classProperties'];
if(babylonPlugins.length) {
plugins = plugins.concat(babylonPlugins);
}
let jsxAttributes = {};
let plugins = ['jsx', 'flow', 'classProperties'];
if (babylonPlugins.length) {
plugins = plugins.concat(babylonPlugins);
}
// use babylon.parse and then babel traverse for dynamic class names and other attributes on the jsx code.
// might come up with a bit more strings but the needless stuff are not here anyway.
let ast = parse(jsxFileContents, {sourceType: 'module', plugins: plugins});
traverse(ast, {
enter: function (path) {
let {type, value} = path.node;
if (type === 'StringLiteral') {
let attributes = value.split(' ');
attributes.forEach(attr => jsxAttributes[attr] = attr);
}
}
});
// use babylon.parse and then babel traverse for dynamic class names and other attributes on the jsx code.
// might come up with a bit more strings but the needless stuff are not here anyway.
let ast = parse(jsxFileContents, {sourceType: 'module', plugins: plugins});
traverse(ast, {
enter: function (path) {
let {type, value} = path.node;
if (type === 'StringLiteral') {
let attributes = value.split(' ');
attributes.forEach(attr => jsxAttributes[attr] = attr);
}
}
});
return jsxAttributes;
return jsxAttributes;
};
let validateInput = (cssFilePath, threshold) => {
if (!cssFilePath) {
throw new PluginError(PLUGIN_NAME, 'Missing css field!');
}
if (typeof cssFilePath !== 'string') {
throw new PluginError(PLUGIN_NAME, 'css field must be a string!');
}
if(threshold && (typeof threshold !== 'number' || threshold > 100 || threshold < 0)){
throw new PluginError(PLUGIN_NAME, 'threshold value should be a number between 0-100!');
}
};
let gulpCssUsage = (options = {}) => {
let {css: cssFilePath, babylon} = options;
if (!cssFilePath) {
throw new PluginError(PLUGIN_NAME, 'Missing css field!');
}
if(typeof cssFilePath !== 'string'){
throw new PluginError(PLUGIN_NAME, 'css field must be a string!');
}
let {css: cssFilePath, babylon, threshold} = options;
let cssFile = new gutil.File({path: cssFilePath, contents: fs.readFileSync(cssFilePath)});
let cssSelectors = getAllSelectorsFromCSSFile(cssFile);
let fileBuffer;
let allAttributes = {};
let transformers = (file, enc, cb) => {
let currentJsxAttributes;
if (file.isNull()) {
return cb(error, file);
}
if (file.isBuffer()) {
currentJsxAttributes = parseAndExtractJsxAttributes(file.contents.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
cb(error, file);
}
if (file.isStream()) {
gutil.log(gutil.colors.magenta(PLUGIN_NAME + ': streaming is deprecated and will not be supported soon'));
if (enc !== 'utf8') {
file.contents.setEncoding('utf8');
}
if (!fileBuffer) {
fileBuffer = new Buffer([]); // utf8 by default
}
validateInput(cssFilePath, threshold);
file.contents.on('data', chunk => fileBuffer = Buffer.concat([new Buffer(chunk), fileBuffer]));
file.contents.on('end', () => {
currentJsxAttributes = parseAndExtractJsxAttributes(fileBuffer.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
fileBuffer = undefined;
cb(error, file);
});
}
};
let cssFile = new gutil.File({path: cssFilePath, contents: fs.readFileSync(cssFilePath)});
let cssSelectors = getAllSelectorsFromCSSFile(cssFile);
let flush = (cb) => {
let needless = makeDiff(cssSelectors, allAttributes);
printNeedlessSelectorList(needless);
cb();
};
return through.obj((file, enc, cb) => {
let currentJsxAttributes;
if (file.isNull()) {
return cb(error, file);
}
if (file.isStream()) {
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
}
return through.obj({}, transformers, flush);
let allAttributes = {};
// file is buffer
currentJsxAttributes = parseAndExtractJsxAttributes(file.contents.toString(), babylon);
Object.assign(allAttributes, currentJsxAttributes);
let {needless, statistics} = makeDiff(cssSelectors, allAttributes);
printNeedlessSelectorList(needless, statistics);
if(threshold && statistics >= threshold){
return cb(new PluginError(PLUGIN_NAME, 'too many unused css selectors!'));
}
cb(error, file);
});
};

@@ -124,25 +125,25 @@

if (typeof Object.assign != 'function') {
(function () {
Object.assign = function (target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
(function () {
Object.assign = function (target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}
export default gulpCssUsage;
{
"name": "gulp-css-usage",
"version": "1.0.10",
"version": "2.0.0",
"description": "A Gulp task which scans your JavaScript classes, including React JSX files support (.jsx/.js), your CSS files, and gives you a report of CSS coverage. i.e how many class names are needless and which are those class names.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -41,2 +41,9 @@ # gulp-css-usage

### threshold
Type: 'Number', (between 0-100)
If set, `gulp-css-usage` will check the amount of unused selectors, and if the amount of it is above the threshold then it fails the task.
### babylon

@@ -43,0 +50,0 @@ Type: `Array:String` Default: `['jsx', 'flow', 'classProperties']`

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc