Advertisement
Guest User

Untitled

a guest
May 2nd, 2016
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.26 KB | None | 0 0
  1. #!/usr/bin/env node
  2.  
  3. var babylon = require('babylon');
  4. var fs = require('fs');
  5.  
  6. function isObject(e) {
  7. return typeof e === 'object' && e !== null;
  8. }
  9.  
  10. function match(h, n) {
  11. if (isObject(n) && isObject(h)) {
  12. return Object.keys(n).every(function(k) {
  13. return Object.hasOwnProperty.call(h, k) && match(h[k], n[k]);
  14. });
  15. }
  16.  
  17. return h === n;
  18. }
  19.  
  20. function matchDeep(h, n) {
  21. var r = [];
  22.  
  23. if (isObject(h)) {
  24. if (Array.isArray(h)) {
  25. h.forEach(function(v) {
  26. r = r.concat(matchDeep(v, n));
  27. });
  28. } else {
  29. Object.keys(h).forEach(function(k) {
  30. r = r.concat(matchDeep(h[k], n));
  31. });
  32. }
  33. }
  34.  
  35. if (match(h, n)) {
  36. r = r.concat(h);
  37. }
  38.  
  39. return r;
  40. }
  41.  
  42. var seen = {};
  43.  
  44. process.argv.slice(2).forEach(function(f) {
  45. try {
  46. var ast = babylon.parse(fs.readFileSync(f, 'utf8'), {
  47. sourceType: 'module',
  48. plugins: [
  49. 'jsx',
  50. 'flow',
  51. 'classConstructorCall',
  52. 'trailingFunctionCommas',
  53. 'objectRestSpread',
  54. 'decorators',
  55. 'classProperties',
  56. 'exportExtensions',
  57. 'functionBind',
  58. ],
  59. });
  60.  
  61. var classNames = matchDeep(ast, {
  62. type: 'JSXAttribute',
  63. name: {name: 'className'},
  64. value: {type: 'StringLiteral'},
  65. });
  66.  
  67. classNames.forEach(function(e) {
  68. e.value.value.split(' ').forEach(function(s) {
  69. seen[s] = seen[s] || [];
  70. seen[s].push({
  71. file: f,
  72. line: e.loc.start.line,
  73. kind: 'inline',
  74. });
  75. });
  76. });
  77.  
  78. matchDeep(ast, {
  79. type: 'CallExpression',
  80. callee: { name: 'classNames' },
  81. }).forEach(function(c) {
  82. c.arguments.forEach(function(a) {
  83. switch (a.type) {
  84. case 'StringLiteral':
  85. a.value.split(' ').forEach(function(s) {
  86. seen[s] = seen[s] || [];
  87. seen[s].push({
  88. file: f,
  89. line: a.loc.start.line,
  90. kind: 'composed',
  91. });
  92. });
  93. break;
  94. case 'ObjectExpression':
  95. a.properties.forEach(function(p) {
  96. switch (p.key.type) {
  97. case 'StringLiteral':
  98. p.key.value.split(' ').forEach(function(s) {
  99. seen[s] = seen[s] || [];
  100. seen[s].push({
  101. file: f,
  102. line: p.key.loc.start.line,
  103. kind: 'composed',
  104. });
  105. });
  106. break;
  107. case 'Identifier':
  108. seen[p.key.name] = seen[p.key.name] || [];
  109. seen[p.key.name].push({
  110. file: f,
  111. line: p.key.loc.start.line,
  112. kind: 'composed',
  113. });
  114. break;
  115. default:
  116. // nothing
  117. }
  118. });
  119. break;
  120. default:
  121. // nothing
  122. }
  123. });
  124. });
  125.  
  126. console.warn('parsed %s', f);
  127. } catch (e) {
  128. console.warn('failed parsing %s (%s)', f, e.message);
  129. }
  130. });
  131.  
  132. var pairs = Object.keys(seen).map(function(k) {
  133. return [k, seen[k]];
  134. }).sort(function(a, b) { return b[1].length - a[1].length; });
  135.  
  136. pairs.filter(function(e) { return e[1].length > 1; }).forEach(function(e) {
  137. console.log('[%d] %s', e[1].length, e[0]);
  138.  
  139. e[1].forEach(function(o) {
  140. console.log(' %s:%d (%s)', o.file, o.line, o.kind);
  141. });
  142. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement