Skip to content

Instantly share code, notes, and snippets.

@deoxxa
Created May 3, 2016 00:28
Show Gist options
  • Select an option

  • Save deoxxa/4627787704a50d68a143be54bc962d4a to your computer and use it in GitHub Desktop.

Select an option

Save deoxxa/4627787704a50d68a143be54bc962d4a to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
var babylon = require('babylon');
var fs = require('fs');
function isObject(e) {
return typeof e === 'object' && e !== null;
}
function match(h, n) {
if (isObject(n) && isObject(h)) {
return Object.keys(n).every(function(k) {
return Object.hasOwnProperty.call(h, k) && match(h[k], n[k]);
});
}
return h === n;
}
function matchDeep(h, n) {
var r = [];
if (isObject(h)) {
if (Array.isArray(h)) {
h.forEach(function(v) {
r = r.concat(matchDeep(v, n));
});
} else {
Object.keys(h).forEach(function(k) {
r = r.concat(matchDeep(h[k], n));
});
}
}
if (match(h, n)) {
r = r.concat(h);
}
return r;
}
var seen = {};
process.argv.slice(2).forEach(function(f) {
try {
var ast = babylon.parse(fs.readFileSync(f, 'utf8'), {
sourceType: 'module',
plugins: [
'jsx',
'flow',
'classConstructorCall',
'trailingFunctionCommas',
'objectRestSpread',
'decorators',
'classProperties',
'exportExtensions',
'functionBind',
],
});
var classNames = matchDeep(ast, {
type: 'JSXAttribute',
name: {name: 'className'},
value: {type: 'StringLiteral'},
});
classNames.forEach(function(e) {
e.value.value.split(' ').forEach(function(s) {
seen[s] = seen[s] || [];
seen[s].push({
file: f,
line: e.loc.start.line,
kind: 'inline',
});
});
});
matchDeep(ast, {
type: 'CallExpression',
callee: { name: 'classNames' },
}).forEach(function(c) {
c.arguments.forEach(function(a) {
switch (a.type) {
case 'StringLiteral':
a.value.split(' ').forEach(function(s) {
seen[s] = seen[s] || [];
seen[s].push({
file: f,
line: a.loc.start.line,
kind: 'composed',
});
});
break;
case 'ObjectExpression':
a.properties.forEach(function(p) {
switch (p.key.type) {
case 'StringLiteral':
p.key.value.split(' ').forEach(function(s) {
seen[s] = seen[s] || [];
seen[s].push({
file: f,
line: p.key.loc.start.line,
kind: 'composed',
});
});
break;
case 'Identifier':
seen[p.key.name] = seen[p.key.name] || [];
seen[p.key.name].push({
file: f,
line: p.key.loc.start.line,
kind: 'composed',
});
break;
default:
// nothing
}
});
break;
default:
// nothing
}
});
});
console.warn('parsed %s', f);
} catch (e) {
console.warn('failed parsing %s (%s)', f, e.message);
}
});
var pairs = Object.keys(seen).map(function(k) {
return [k, seen[k]];
}).sort(function(a, b) { return b[1].length - a[1].length; });
pairs.filter(function(e) { return e[1].length > 1; }).forEach(function(e) {
console.log('[%d] %s', e[1].length, e[0]);
e[1].forEach(function(o) {
console.log(' %s:%d (%s)', o.file, o.line, o.kind);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment