@visulima/fs
Version:
Human friendly file system utilities for Node.js
101 lines (99 loc) • 3.09 kB
JavaScript
const INDENT_REGEX = /^(?:( )+|\t+)/;
const INDENT_TYPE_SPACE = "space";
const INDENT_TYPE_TAB = "tab";
function shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, value) {
return ignoreSingleSpaces && indentType === INDENT_TYPE_SPACE && value === 1;
}
function makeIndentsMap(string, ignoreSingleSpaces) {
const indents = /* @__PURE__ */ new Map();
let previousSize = 0;
let previousIndentType;
let key;
for (const line of string.split(/\n/g)) {
if (!line) {
continue;
}
const matches = line.match(INDENT_REGEX);
if (matches === null) {
previousSize = 0;
previousIndentType = "";
} else {
const indent = matches[0].length;
const indentType = matches[1] ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB;
if (shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, indent)) {
continue;
}
if (indentType !== previousIndentType) {
previousSize = 0;
}
previousIndentType = indentType;
let use = 1;
let weight = 0;
const indentDifference = indent - previousSize;
previousSize = indent;
if (indentDifference === 0) {
use = 0;
weight = 1;
} else {
const absoluteIndentDifference = Math.abs(indentDifference);
if (shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, absoluteIndentDifference)) {
continue;
}
key = encodeIndentsKey(indentType, absoluteIndentDifference);
}
const entry = indents.get(key);
indents.set(key, entry === void 0 ? [1, 0] : [entry[0] + use, entry[1] + weight]);
}
}
return indents;
}
function encodeIndentsKey(indentType, indentAmount) {
const typeCharacter = indentType === INDENT_TYPE_SPACE ? "s" : "t";
return typeCharacter + String(indentAmount);
}
function decodeIndentsKey(indentsKey) {
const keyHasTypeSpace = indentsKey[0] === "s";
const type = keyHasTypeSpace ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB;
const amount = Number(indentsKey.slice(1));
return { type, amount };
}
function getMostUsedKey(indents) {
let result;
let maxUsed = 0;
let maxWeight = 0;
for (const [key, [usedCount, weight]] of indents) {
if (usedCount > maxUsed || usedCount === maxUsed && weight > maxWeight) {
maxUsed = usedCount;
maxWeight = weight;
result = key;
}
}
return result;
}
function makeIndentString(type, amount) {
const indentCharacter = type === INDENT_TYPE_SPACE ? " " : " ";
return indentCharacter.repeat(amount);
}
function detectIndent(string) {
if (typeof string !== "string") {
throw new TypeError("Expected a string");
}
let indents = makeIndentsMap(string, true);
if (indents.size === 0) {
indents = makeIndentsMap(string, false);
}
const keyOfMostUsedIndent = getMostUsedKey(indents);
let type;
let amount = 0;
let indent = "";
if (keyOfMostUsedIndent !== void 0) {
({ type, amount } = decodeIndentsKey(keyOfMostUsedIndent));
indent = makeIndentString(type, amount);
}
return {
amount,
type,
indent
};
}
export { detectIndent as d };