96 lines
2.8 KiB
JavaScript
96 lines
2.8 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const esprima = require('esprima');
|
||
|
const os = require('os');
|
||
|
|
||
|
////////////////////////////////////////////////////
|
||
|
// Automatically calculates and returns End of Line,
|
||
|
// based on the input text.
|
||
|
function getEOL(text) {
|
||
|
let idx = 0, unix = 0, windows = 0;
|
||
|
while (idx < text.length) {
|
||
|
idx = text.indexOf('\n', idx);
|
||
|
if (idx == -1) {
|
||
|
break;
|
||
|
}
|
||
|
if (idx > 0 && text[idx - 1] === '\r') {
|
||
|
windows++;
|
||
|
} else {
|
||
|
unix++;
|
||
|
}
|
||
|
idx++;
|
||
|
}
|
||
|
if (unix === windows) {
|
||
|
return os.EOL;
|
||
|
}
|
||
|
return unix > windows ? '\n' : '\r\n';
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// Tokenizes JSON or JavaScript via Esprima, enumerates and returns
|
||
|
// all regular expressions as an array of absolute location indexes
|
||
|
// within the source: [{start, end}, {start, end},...]
|
||
|
function parseRegEx(code) {
|
||
|
const result = [];
|
||
|
// NOTE: Even though we do not need the location details,
|
||
|
// using option `loc` makes `tokenize` perform 40% faster.
|
||
|
esprima.tokenize(code, {loc: true, range: true}, node => {
|
||
|
if (node.type === 'RegularExpression') {
|
||
|
result.push({
|
||
|
start: node.range[0] + 1, // next after the opening `/`
|
||
|
end: node.range[1] - 1 // previous to the closing `/`
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
// Executes a linear search through an array of absolute regEx indexes,
|
||
|
// to find whether the passed index is inside one of the regEx entries.
|
||
|
function indexInRegEx(idx, regExData) {
|
||
|
// regExData - the output provided by parseRegEx;
|
||
|
let mid, low = 0, high = regExData.length - 1;
|
||
|
while (low <= high) {
|
||
|
mid = Math.round((low + high) / 2);
|
||
|
const a = regExData[mid];
|
||
|
if (idx >= a.start) {
|
||
|
if (idx <= a.end) {
|
||
|
return true;
|
||
|
}
|
||
|
low = mid + 1;
|
||
|
} else {
|
||
|
high = mid - 1;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
// Checks the text for being HTML, by verifying
|
||
|
// whether `<` is the first non-empty symbol.
|
||
|
function isHtml(text) {
|
||
|
let s, idx = 0;
|
||
|
do {
|
||
|
s = text[idx];
|
||
|
if (s !== ' ' && s !== '\t' && s !== '\r' && s !== '\n') {
|
||
|
return s === '<';
|
||
|
}
|
||
|
} while (++idx < text.length);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////
|
||
|
// Returns space symbol multiplied n times.
|
||
|
//
|
||
|
function getSpaces(n) {
|
||
|
return ' '.repeat(n);
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
getEOL: getEOL,
|
||
|
getSpaces: getSpaces,
|
||
|
parseRegEx: parseRegEx,
|
||
|
indexInRegEx: indexInRegEx,
|
||
|
isHtml: isHtml
|
||
|
};
|