First pass formatting with Prettier

* Added .prettierrc.json
* Added .prettierignore
* Formatted
This commit is contained in:
Bryan Ashby
2022-06-05 14:04:25 -06:00
parent eecfb33ad5
commit 4881c2123a
172 changed files with 23696 additions and 18029 deletions

View File

@@ -1,20 +1,22 @@
/* jslint node: true */
'use strict';
const EnigError = require('./enig_error.js').EnigError;
const EnigError = require('./enig_error.js').EnigError;
const {
pad,
stylizeString,
renderStringLength,
renderSubstr,
formatByteSize, formatByteSizeAbbr,
formatCount, formatCountAbbr,
} = require('./string_util.js');
formatByteSize,
formatByteSizeAbbr,
formatCount,
formatCountAbbr,
} = require('./string_util.js');
// deps
const _ = require('lodash');
const moment = require('moment');
const _ = require('lodash');
const moment = require('moment');
/*
String formatting HEAVILY inspired by David Chambers string-format library
@@ -25,27 +27,27 @@ const moment = require('moment');
and ANSI escape sequences.
*/
class ValueError extends EnigError { }
class KeyError extends EnigError { }
class ValueError extends EnigError {}
class KeyError extends EnigError {}
const SpecRegExp = {
FillAlign : /^(.)?([<>=^])/,
Sign : /^[ +-]/,
Width : /^\d*/,
Precision : /^\d+/,
FillAlign: /^(.)?([<>=^])/,
Sign: /^[ +-]/,
Width: /^\d*/,
Precision: /^\d+/,
};
function tokenizeFormatSpec(spec) {
const tokens = {
fill : '',
align : '',
sign : '',
'#' : false,
'0' : false,
width : '',
',' : false,
precision : '',
type : '',
fill: '',
align: '',
sign: '',
'#': false,
0: false,
width: '',
',': false,
precision: '',
type: '',
};
let index = 0;
@@ -56,8 +58,8 @@ function tokenizeFormatSpec(spec) {
}
match = SpecRegExp.FillAlign.exec(spec);
if(match) {
if(match[1]) {
if (match) {
if (match[1]) {
tokens.fill = match[1];
}
tokens.align = match[2];
@@ -65,17 +67,17 @@ function tokenizeFormatSpec(spec) {
}
match = SpecRegExp.Sign.exec(spec.slice(index));
if(match) {
if (match) {
tokens.sign = match[0];
incIndexByMatch();
}
if('#' === spec.charAt(index)) {
if ('#' === spec.charAt(index)) {
tokens['#'] = true;
++index;
}
if('0' === spec.charAt(index)) {
if ('0' === spec.charAt(index)) {
tokens['0'] = true;
++index;
}
@@ -84,16 +86,16 @@ function tokenizeFormatSpec(spec) {
tokens.width = match[0];
incIndexByMatch();
if(',' === spec.charAt(index)) {
if (',' === spec.charAt(index)) {
tokens[','] = true;
++index;
}
if('.' === spec.charAt(index)) {
if ('.' === spec.charAt(index)) {
++index;
match = SpecRegExp.Precision.exec(spec.slice(index));
if(!match) {
if (!match) {
throw new ValueError('Format specifier missing precision');
}
@@ -101,17 +103,17 @@ function tokenizeFormatSpec(spec) {
incIndexByMatch();
}
if(index < spec.length) {
if (index < spec.length) {
tokens.type = spec.charAt(index);
++index;
}
if(index < spec.length) {
if (index < spec.length) {
throw new ValueError('Invalid conversion specification');
}
if(tokens[','] && 's' === tokens.type) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
if (tokens[','] && 's' === tokens.type) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
}
return tokens;
@@ -122,120 +124,142 @@ function quote(s) {
}
function getPadAlign(align) {
return {
'<' : 'left',
'>' : 'right',
'^' : 'center',
}[align] || '>';
return (
{
'<': 'left',
'>': 'right',
'^': 'center',
}[align] || '>'
);
}
function formatString(value, tokens) {
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '<');
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '<');
const precision = Number(tokens.precision || renderStringLength(value) + 1);
if('' !== tokens.type && 's' !== tokens.type) {
if ('' !== tokens.type && 's' !== tokens.type) {
throw new ValueError(`Unknown format code "${tokens.type}" for String object`);
}
if(tokens[',']) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
if (tokens[',']) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
}
if(tokens.sign) {
if (tokens.sign) {
throw new ValueError('Sign not allowed in string format specifier');
}
if(tokens['#']) {
if (tokens['#']) {
throw new ValueError('Alternate form (#) not allowed in string format specifier');
}
if('=' === align) {
if ('=' === align) {
throw new ValueError('"=" alignment not allowed in string format specifier');
}
return pad(renderSubstr(value, 0, precision), Number(tokens.width), fill, getPadAlign(align));
return pad(
renderSubstr(value, 0, precision),
Number(tokens.width),
fill,
getPadAlign(align)
);
}
const FormatNumRegExp = {
UpperType : /[A-Z]/,
ExponentRep : /e[+-](?=\d$)/,
UpperType: /[A-Z]/,
ExponentRep: /e[+-](?=\d$)/,
};
function formatNumberHelper(n, precision, type) {
if(FormatNumRegExp.UpperType.test(type)) {
if (FormatNumRegExp.UpperType.test(type)) {
return formatNumberHelper(n, precision, type.toLowerCase()).toUpperCase();
}
switch(type) {
case 'c' : return String.fromCharCode(n);
case 'd' : return n.toString(10);
case 'b' : return n.toString(2);
case 'o' : return n.toString(8);
case 'x' : return n.toString(16);
case 'e' : return n.toExponential(precision).replace(FormatNumRegExp.ExponentRep, '$&0');
case 'f' : return n.toFixed(precision);
case 'g' :
switch (type) {
case 'c':
return String.fromCharCode(n);
case 'd':
return n.toString(10);
case 'b':
return n.toString(2);
case 'o':
return n.toString(8);
case 'x':
return n.toString(16);
case 'e':
return n.toExponential(precision).replace(FormatNumRegExp.ExponentRep, '$&0');
case 'f':
return n.toFixed(precision);
case 'g':
// we don't want useless trailing zeros. parseFloat -> back to string fixes this for us
return parseFloat(n.toPrecision(precision || 1)).toString();
case '%' : return formatNumberHelper(n * 100, precision, 'f') + '%';
case '' : return formatNumberHelper(n, precision, 'd');
case '%':
return formatNumberHelper(n * 100, precision, 'f') + '%';
case '':
return formatNumberHelper(n, precision, 'd');
default :
throw new ValueError(`Unknown format code "${type}" for object of type 'float'`);
default:
throw new ValueError(
`Unknown format code "${type}" for object of type 'float'`
);
}
}
function formatNumber(value, tokens) {
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '>');
const width = Number(tokens.width);
const type = tokens.type || (tokens.precision ? 'g' : '');
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '>');
const width = Number(tokens.width);
const type = tokens.type || (tokens.precision ? 'g' : '');
if( [ 'c', 'd', 'b', 'o', 'x', 'X' ].indexOf(type) > -1) {
if(0 !== value % 1) {
throw new ValueError(`Cannot format non-integer with format specifier "${type}"`);
if (['c', 'd', 'b', 'o', 'x', 'X'].indexOf(type) > -1) {
if (0 !== value % 1) {
throw new ValueError(
`Cannot format non-integer with format specifier "${type}"`
);
}
if('' !== tokens.sign && 'c' !== type) {
if ('' !== tokens.sign && 'c' !== type) {
throw new ValueError(`Sign not allowed with integer format specifier 'c'`); // eslint-disable-line quotes
}
if(tokens[','] && 'd' !== type) {
if (tokens[','] && 'd' !== type) {
throw new ValueError(`Cannot specify ',' with '${type}'`);
}
if('' !== tokens.precision) {
if ('' !== tokens.precision) {
throw new ValueError('Precision not allowed in integer format specifier');
}
} else if( [ 'e', 'E', 'f', 'F', 'g', 'G', '%' ].indexOf(type) > - 1) {
if(tokens['#']) {
throw new ValueError('Alternate form (#) not allowed in float format specifier');
} else if (['e', 'E', 'f', 'F', 'g', 'G', '%'].indexOf(type) > -1) {
if (tokens['#']) {
throw new ValueError(
'Alternate form (#) not allowed in float format specifier'
);
}
}
const s = formatNumberHelper(Math.abs(value), Number(tokens.precision || 6), type);
const sign = value < 0 || 1 / value < 0 ?
'-' :
'-' === tokens.sign ? '' : tokens.sign;
const s = formatNumberHelper(Math.abs(value), Number(tokens.precision || 6), type);
const sign =
value < 0 || 1 / value < 0 ? '-' : '-' === tokens.sign ? '' : tokens.sign;
const prefix = tokens['#'] && ( [ 'b', 'o', 'x', 'X' ].indexOf(type) > -1 ) ? '0' + type : '';
const prefix =
tokens['#'] && ['b', 'o', 'x', 'X'].indexOf(type) > -1 ? '0' + type : '';
if(tokens[',']) {
const match = /^(\d*)(.*)$/.exec(s);
if (tokens[',']) {
const match = /^(\d*)(.*)$/.exec(s);
const separated = match[1].replace(/.(?=(...)+$)/g, '$&,') + match[2];
if('=' !== align) {
if ('=' !== align) {
return pad(sign + separated, width, fill, getPadAlign(align));
}
if('0' === fill) {
if ('0' === fill) {
const shortfall = Math.max(0, width - sign.length - separated.length);
const digits = /^\d*/.exec(separated)[0].length;
let padding = '';
const digits = /^\d*/.exec(separated)[0].length;
let padding = '';
// :TODO: do this differntly...
for(let n = 0; n < shortfall; n++) {
for (let n = 0; n < shortfall; n++) {
padding = ((digits + n) % 4 === 3 ? ',' : '0') + padding;
}
@@ -245,12 +269,16 @@ function formatNumber(value, tokens) {
return sign + pad(separated, width - sign.length, fill, getPadAlign('>'));
}
if(0 === width) {
if (0 === width) {
return sign + prefix + s;
}
if('=' === align) {
return sign + prefix + pad(s, width - sign.length - prefix.length, fill, getPadAlign('>'));
if ('=' === align) {
return (
sign +
prefix +
pad(s, width - sign.length - prefix.length, fill, getPadAlign('>'))
);
}
return pad(sign + prefix + s, width, fill, getPadAlign(align));
@@ -258,51 +286,51 @@ function formatNumber(value, tokens) {
const transformers = {
// String standard
toUpperCase : String.prototype.toUpperCase,
toLowerCase : String.prototype.toLowerCase,
toUpperCase: String.prototype.toUpperCase,
toLowerCase: String.prototype.toLowerCase,
// some super l33b BBS styles!!
styleUpper : (s) => stylizeString(s, 'upper'),
styleLower : (s) => stylizeString(s, 'lower'),
styleTitle : (s) => stylizeString(s, 'title'),
styleFirstLower : (s) => stylizeString(s, 'first lower'),
styleSmallVowels : (s) => stylizeString(s, 'small vowels'),
styleBigVowels : (s) => stylizeString(s, 'big vowels'),
styleSmallI : (s) => stylizeString(s, 'small i'),
styleMixed : (s) => stylizeString(s, 'mixed'),
styleL33t : (s) => stylizeString(s, 'l33t'),
styleUpper: s => stylizeString(s, 'upper'),
styleLower: s => stylizeString(s, 'lower'),
styleTitle: s => stylizeString(s, 'title'),
styleFirstLower: s => stylizeString(s, 'first lower'),
styleSmallVowels: s => stylizeString(s, 'small vowels'),
styleBigVowels: s => stylizeString(s, 'big vowels'),
styleSmallI: s => stylizeString(s, 'small i'),
styleMixed: s => stylizeString(s, 'mixed'),
styleL33t: s => stylizeString(s, 'l33t'),
// :TODO:
// toMegs(), toKilobytes(), ...
// toList(), toCommaList(),
sizeWithAbbr : (n) => formatByteSize(n, true, 2),
sizeWithoutAbbr : (n) => formatByteSize(n, false, 2),
sizeAbbr : (n) => formatByteSizeAbbr(n),
countWithAbbr : (n) => formatCount(n, true, 0),
countWithoutAbbr : (n) => formatCount(n, false, 0),
countAbbr : (n) => formatCountAbbr(n),
sizeWithAbbr: n => formatByteSize(n, true, 2),
sizeWithoutAbbr: n => formatByteSize(n, false, 2),
sizeAbbr: n => formatByteSizeAbbr(n),
countWithAbbr: n => formatCount(n, true, 0),
countWithoutAbbr: n => formatCount(n, false, 0),
countAbbr: n => formatCountAbbr(n),
durationHours : (h) => moment.duration(h, 'hours').humanize(),
durationMinutes : (m) => moment.duration(m, 'minutes').humanize(),
durationSeconds : (s) => moment.duration(s, 'seconds').humanize(),
durationHours: h => moment.duration(h, 'hours').humanize(),
durationMinutes: m => moment.duration(m, 'minutes').humanize(),
durationSeconds: s => moment.duration(s, 'seconds').humanize(),
};
function transformValue(transformerName, value) {
if(transformerName in transformers) {
if (transformerName in transformers) {
const transformer = transformers[transformerName];
value = transformer.apply(value, [ value ] );
value = transformer.apply(value, [value]);
}
return value;
}
// :TODO: Use explicit set of chars for paths & function/transforms such that } is allowed as fill/etc.
const REGEXP_BASIC_FORMAT = /{([^.!:}]+(?:\.[^.!:}]+)*)(?:!([^:}]+))?(?::([^}]+))?}/g;
const REGEXP_BASIC_FORMAT = /{([^.!:}]+(?:\.[^.!:}]+)*)(?:!([^:}]+))?(?::([^}]+))?}/g;
function getValue(obj, path) {
const value = _.get(obj, path);
if(!_.isUndefined(value)) {
if (!_.isUndefined(value)) {
return _.isFunction(value) ? value() : value;
}
@@ -310,58 +338,56 @@ function getValue(obj, path) {
}
module.exports = function format(fmt, obj) {
const re = REGEXP_BASIC_FORMAT;
re.lastIndex = 0; // reset from prev
re.lastIndex = 0; // reset from prev
let match;
let pos;
let out = '';
let objPath ;
let objPath;
let transformer;
let formatSpec;
let value;
let tokens;
do {
pos = re.lastIndex;
match = re.exec(fmt);
pos = re.lastIndex;
match = re.exec(fmt);
if(match) {
if(match.index > pos) {
if (match) {
if (match.index > pos) {
out += fmt.slice(pos, match.index);
}
objPath = match[1];
objPath = match[1];
transformer = match[2];
formatSpec = match[3];
formatSpec = match[3];
try {
value = getValue(obj, objPath);
if(transformer) {
value = getValue(obj, objPath);
if (transformer) {
value = transformValue(transformer, value);
}
tokens = tokenizeFormatSpec(formatSpec || '');
if(_.isNumber(value)) {
if (_.isNumber(value)) {
out += formatNumber(value, tokens);
} else {
out += formatString(value, tokens);
}
} catch(e) {
if(e instanceof KeyError) {
out += match[0]; // preserve full thing
} else if(e instanceof ValueError) {
} catch (e) {
if (e instanceof KeyError) {
out += match[0]; // preserve full thing
} else if (e instanceof ValueError) {
out += value.toString();
}
}
}
} while(0 !== re.lastIndex);
} while (0 !== re.lastIndex);
// remainder
if(pos < fmt.length) {
if (pos < fmt.length) {
out += fmt.slice(pos);
}