index.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. // detect either spaces or tabs but not both to properly handle tabs
  3. // for indentation and spaces for alignment
  4. var INDENT_RE = /^(?:( )+|\t+)/;
  5. var repeating = require('repeating');
  6. module.exports = function (str) {
  7. if (typeof str !== 'string') {
  8. throw new TypeError('Expected a string');
  9. }
  10. // used to if tabs or spaces are the most used
  11. var t = 0;
  12. var s = 0;
  13. // remember the indentation used for the previous line
  14. var prev = 0;
  15. // remember how much a given indentation size was used
  16. var indents = {};
  17. str.split(/\n/g).forEach(function (line) {
  18. if (!line) {
  19. // ignore empty lines
  20. return;
  21. }
  22. var matches = line.match(INDENT_RE);
  23. var indent;
  24. if (!matches) {
  25. indent = 0;
  26. } else {
  27. indent = matches[0].length;
  28. if (matches[1]) {
  29. // spaces were used
  30. s++;
  31. } else {
  32. // tabs were used
  33. t++;
  34. }
  35. }
  36. var diff = Math.abs(indent - prev);
  37. prev = indent;
  38. if (diff) {
  39. // an indent or deindent has been detected
  40. indents[diff] = (indents[diff] || 0) + 1;
  41. }
  42. });
  43. // find most frequent indentation
  44. var amount = 0;
  45. var max = 0;
  46. var n;
  47. for (var diff in indents) {
  48. n = indents[diff];
  49. if (n > max) {
  50. max = n;
  51. amount = +diff;
  52. }
  53. }
  54. var type;
  55. var actual;
  56. if (!amount) {
  57. type = null;
  58. actual = '';
  59. } else if (s >= t) {
  60. type = 'space';
  61. actual = repeating(' ', amount);
  62. } else {
  63. type = 'tab';
  64. actual = repeating('\t', amount);
  65. }
  66. return {
  67. amount: amount,
  68. type: type,
  69. indent: actual
  70. };
  71. };