summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/detect-indent/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/detect-indent/index.js')
-rw-r--r--deps/npm/node_modules/detect-indent/index.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/deps/npm/node_modules/detect-indent/index.js b/deps/npm/node_modules/detect-indent/index.js
new file mode 100644
index 0000000000..eda0b1b1aa
--- /dev/null
+++ b/deps/npm/node_modules/detect-indent/index.js
@@ -0,0 +1,122 @@
+'use strict';
+
+// detect either spaces or tabs but not both to properly handle tabs
+// for indentation and spaces for alignment
+const INDENT_RE = /^(?:( )+|\t+)/;
+
+function getMostUsed(indents) {
+ let result = 0;
+ let maxUsed = 0;
+ let maxWeight = 0;
+
+ for (const entry of indents) {
+ // TODO: use destructuring when targeting Node.js 6
+ const key = entry[0];
+ const val = entry[1];
+
+ const u = val[0];
+ const w = val[1];
+
+ if (u > maxUsed || (u === maxUsed && w > maxWeight)) {
+ maxUsed = u;
+ maxWeight = w;
+ result = Number(key);
+ }
+ }
+
+ return result;
+}
+
+module.exports = str => {
+ if (typeof str !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ // used to see if tabs or spaces are the most used
+ let tabs = 0;
+ let spaces = 0;
+
+ // remember the size of previous line's indentation
+ let prev = 0;
+
+ // remember how many indents/unindents as occurred for a given size
+ // and how much lines follow a given indentation
+ //
+ // indents = {
+ // 3: [1, 0],
+ // 4: [1, 5],
+ // 5: [1, 0],
+ // 12: [1, 0],
+ // }
+ const indents = new Map();
+
+ // pointer to the array of last used indent
+ let current;
+
+ // whether the last action was an indent (opposed to an unindent)
+ let isIndent;
+
+ for (const line of str.split(/\n/g)) {
+ if (!line) {
+ // ignore empty lines
+ continue;
+ }
+
+ let indent;
+ const matches = line.match(INDENT_RE);
+
+ if (matches) {
+ indent = matches[0].length;
+
+ if (matches[1]) {
+ spaces++;
+ } else {
+ tabs++;
+ }
+ } else {
+ indent = 0;
+ }
+
+ const diff = indent - prev;
+ prev = indent;
+
+ if (diff) {
+ // an indent or unindent has been detected
+
+ isIndent = diff > 0;
+
+ current = indents.get(isIndent ? diff : -diff);
+
+ if (current) {
+ current[0]++;
+ } else {
+ current = [1, 0];
+ indents.set(diff, current);
+ }
+ } else if (current) {
+ // if the last action was an indent, increment the weight
+ current[1] += Number(isIndent);
+ }
+ }
+
+ const amount = getMostUsed(indents);
+
+ let type;
+ let indent;
+ if (!amount) {
+ type = null;
+ indent = '';
+ } else if (spaces >= tabs) {
+ type = 'space';
+ indent = ' '.repeat(amount);
+ } else {
+ type = 'tab';
+ indent = '\t'.repeat(amount);
+ }
+
+ return {
+ amount,
+ type,
+ indent
+ };
+};