Projekt

Obecné

Profil

Stáhnout (2.17 KB) Statistiky
| Větev: | Revize:
1 3a515b92 cagy
/* eslint-disable guard-for-in */
2
'use strict';
3
var repeating = require('repeating');
4
5
// detect either spaces or tabs but not both to properly handle tabs
6
// for indentation and spaces for alignment
7
var INDENT_RE = /^(?:( )+|\t+)/;
8
9
function getMostUsed(indents) {
10
	var result = 0;
11
	var maxUsed = 0;
12
	var maxWeight = 0;
13
14
	for (var n in indents) {
15
		var indent = indents[n];
16
		var u = indent[0];
17
		var w = indent[1];
18
19
		if (u > maxUsed || u === maxUsed && w > maxWeight) {
20
			maxUsed = u;
21
			maxWeight = w;
22
			result = Number(n);
23
		}
24
	}
25
26
	return result;
27
}
28
29
module.exports = function (str) {
30
	if (typeof str !== 'string') {
31
		throw new TypeError('Expected a string');
32
	}
33
34
	// used to see if tabs or spaces are the most used
35
	var tabs = 0;
36
	var spaces = 0;
37
38
	// remember the size of previous line's indentation
39
	var prev = 0;
40
41
	// remember how many indents/unindents as occurred for a given size
42
	// and how much lines follow a given indentation
43
	//
44
	// indents = {
45
	//    3: [1, 0],
46
	//    4: [1, 5],
47
	//    5: [1, 0],
48
	//   12: [1, 0],
49
	// }
50
	var indents = {};
51
52
	// pointer to the array of last used indent
53
	var current;
54
55
	// whether the last action was an indent (opposed to an unindent)
56
	var isIndent;
57
58
	str.split(/\n/g).forEach(function (line) {
59
		if (!line) {
60
			// ignore empty lines
61
			return;
62
		}
63
64
		var indent;
65
		var matches = line.match(INDENT_RE);
66
67
		if (!matches) {
68
			indent = 0;
69
		} else {
70
			indent = matches[0].length;
71
72
			if (matches[1]) {
73
				spaces++;
74
			} else {
75
				tabs++;
76
			}
77
		}
78
79
		var diff = indent - prev;
80
		prev = indent;
81
82
		if (diff) {
83
			// an indent or unindent has been detected
84
85
			isIndent = diff > 0;
86
87
			current = indents[isIndent ? diff : -diff];
88
89
			if (current) {
90
				current[0]++;
91
			} else {
92
				current = indents[diff] = [1, 0];
93
			}
94
		} else if (current) {
95
			// if the last action was an indent, increment the weight
96
			current[1] += Number(isIndent);
97
		}
98
	});
99
100
	var amount = getMostUsed(indents);
101
102
	var type;
103
	var actual;
104
	if (!amount) {
105
		type = null;
106
		actual = '';
107
	} else if (spaces >= tabs) {
108
		type = 'space';
109
		actual = repeating(' ', amount);
110
	} else {
111
		type = 'tab';
112
		actual = repeating('\t', amount);
113
	}
114
115
	return {
116
		amount: amount,
117
		type: type,
118
		indent: actual
119
	};
120
};