Skip to content

Instantly share code, notes, and snippets.

@natecavanaugh
Created January 14, 2014 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save natecavanaugh/8420209 to your computer and use it in GitHub Desktop.
Save natecavanaugh/8420209 to your computer and use it in GitHub Desktop.
Scan CSS for source formatting patterns
#!/usr/bin/env node
var colors = require('colors');
var fs = require('fs');
var argv = require('optimist').boolean('q').argv;
colors.setTheme({
help: 'cyan',
warn: 'yellow',
error: 'red',
subtle: 'grey'
});
var args = argv._;
var INDENT = ' ';
var QUIET = argv.q;
var REGEX_LEADING_SPACE = /^\s+/;
var REGEX_PROP_KEY = /^\s*([^:]+)(?:)/;
var REGEX_PROPERTY = /^\t*[^:]+:[^;]+;$/;
var REGEX_SUB = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g;
var REGEX_ZERO_UNIT = /\b0(?!s\b)[a-zA-Z]{1,}\b/;
var REGEX_HEX_REDUNDANT = /#([0-9A-Fa-f])\1([0-9A-Fa-f])\2([0-9A-Fa-f])\3/;
var REGEX_HEX_LOWER = /[a-f]/;
var REGEX_HEX = /#[0-9A-Fa-f]{3,6}/;
var REPLACE_REGEX_REDUNDANT = '#$1$2$3';
var hasProperty = function(item) {
return REGEX_PROPERTY.test(item);
};
var hasLowerCaseRegex = function(item) {
var match = item.match(REGEX_HEX);
var lowerCaseRegex = false;
if (match) {
lowerCaseRegex = REGEX_HEX_LOWER.test(match);
}
return lowerCaseRegex;
};
var hasRedundantRegex = function(item) {
return REGEX_HEX_REDUNDANT.test(item);
};
var hasNeedlessUnit = function(item) {
return REGEX_ZERO_UNIT.test(item);
};
var sub = function(str, obj) {
var objType = typeof obj;
if (objType !== 'object' && objType !== 'function') {
obj = Array.prototype.slice.call(arguments, 1);
}
return str.replace ? str.replace(REGEX_SUB, function(match, key) {
return (typeof obj[key] !== 'undefined') ? obj[key] : match;
}) : s;
};
args.forEach(
function(file) {
fs.readFile(file, 'utf-8', function (err, data) {
if (err) {
throw err;
}
var file1 = data.split('\n');
var errors = [];
file1.forEach(
function(item, index, collection) {
var lineNum = index + 1;
var nextItem = collection[lineNum];
if (hasProperty(item)) {
item = item.replace(REGEX_LEADING_SPACE, '');
var nextItemMatch;
var itemMatch = item.match(REGEX_PROP_KEY);
if (nextItem && hasProperty(nextItem)) {
nextItem = nextItem.replace(REGEX_LEADING_SPACE, '');
nextItemMatch = nextItem && hasProperty(nextItem) && nextItem.match(REGEX_PROP_KEY);
}
if (itemMatch && nextItemMatch) {
if (itemMatch[0] > nextItemMatch[0]) {
errors.push(sub('Line: {0} Sort: {1} {2}', lineNum, item, nextItem).warn);
}
}
}
var hexMatch = item.match(REGEX_HEX);
if (hexMatch) {
hexMatch = hexMatch[0];
if (hasLowerCaseRegex(hexMatch)) {
errors.push(sub('Line {0} Hex code should be all uppercase: {1}', lineNum, item).warn);
}
if (hasRedundantRegex(hexMatch)) {
errors.push(sub('Line {0} Hex code can be reduced to {2}: {1}', lineNum, item, hexMatch.replace(REGEX_HEX_REDUNDANT, REPLACE_REGEX_REDUNDANT)).warn);
}
}
if (hasNeedlessUnit(item)) {
errors.push(sub('Line {0} Needless unit: {1}', lineNum, item).warn);
}
}
);
var includeHeaderFooter = (errors.length || !QUIET);
if (includeHeaderFooter) {
console.log('File:'.blackBG + ' ' + file.underline);
}
if (errors.length) {
console.log(INDENT + errors.join('\n' + INDENT));
}
else if (includeHeaderFooter) {
console.log(INDENT + 'clear');
}
if (includeHeaderFooter) {
console.log('----'.subtle);
}
});
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment