visible
Version:
Print whitespace and non-ASCII characters in a stream. Like vis or cat -v.
169 lines (168 loc) • 5.53 kB
JavaScript
function padLeft(str, padding, length) {
while (str.length < length) {
str = padding + str;
}
return str;
}
var controlCharacterNames = {
// 0x00 through 0x0F
0: 'NUL',
1: 'SOH',
2: 'STX',
3: 'ETX',
4: 'EOT',
5: 'ENQ',
6: 'ACK',
7: 'BEL',
8: 'BS',
9: 'TAB',
10: 'LF',
11: 'VT',
12: 'FF',
13: 'CR',
14: 'SO',
15: 'SI',
// 0x10 through 0x1F
16: 'DLE',
17: 'DC1',
18: 'DC2',
19: 'DC3',
20: 'DC4',
21: 'NAK',
22: 'SYN',
23: 'ETB',
24: 'CAN',
25: 'EM',
26: 'SUB',
27: 'ESC',
28: 'FS',
29: 'GS',
30: 'RS',
31: 'US',
// 0x20
32: 'SP',
// 0x7F
127: 'DEL',
// 0x85
133: 'NEL',
};
var backslashEscapes = {
0: '\\0',
8: '\\b',
9: '\\t',
10: '\\n',
11: '\\v',
12: '\\f',
13: '\\r',
};
var Escaper = (function () {
function Escaper(_a) {
var _b = _a.escapeSlash, escapeSlash = _b === void 0 ? false : _b, _c = _a.literalVisibles, literalVisibles = _c === void 0 ? true : _c, _d = _a.literalEOL, literalEOL = _d === void 0 ? true : _d, _e = _a.literalSpace, literalSpace = _e === void 0 ? true : _e, _f = _a.useControlCharacterNames, useControlCharacterNames = _f === void 0 ? false : _f, _g = _a.useBackslashEscapes, useBackslashEscapes = _g === void 0 ? false : _g, _h = _a.base, base = _h === void 0 ? 'hexadecimal' : _h;
this.options = { escapeSlash: escapeSlash, literalVisibles: literalVisibles, literalEOL: literalEOL, literalSpace: literalSpace, useControlCharacterNames: useControlCharacterNames, useBackslashEscapes: useBackslashEscapes, base: base };
}
/**
Escape a Buffer.
*/
Escaper.prototype.transformBuffer = function (buffer) {
var strings = [];
for (var i = 0, l = buffer.length; i < l; i++) {
var charCode = buffer[i];
var string = this.transformCharCode(charCode);
strings.push(string);
}
return strings.join('');
};
/**
Escape a numeric character code.
*/
Escaper.prototype.transformCharCode = function (charCode) {
if (this.options.escapeSlash && charCode == 92) {
return '\\\\';
}
else if (this.options.literalVisibles && charCode >= 33 && charCode <= 126) {
// TODO: consider all utf8 visibles?
return String.fromCharCode(charCode);
}
else if (this.options.literalEOL && (charCode === 10)) {
// \r doesn't count, since it can be destructive
// TODO: consolidate \r\n, \r, and \n all to \n
return String.fromCharCode(charCode);
}
else if (this.options.literalSpace && charCode === 32) {
return String.fromCharCode(charCode);
}
else if (this.options.useControlCharacterNames && charCode in controlCharacterNames) {
return controlCharacterNames[charCode];
}
else if (this.options.useBackslashEscapes && charCode in backslashEscapes) {
return backslashEscapes[charCode];
}
else if (this.options.base == 'octal' && charCode < 256) {
var octal = charCode.toString(8);
return '\\' + padLeft(octal, '0', 3);
}
else if (this.options.base == 'hexadecimal' && charCode < 256) {
var hexadecimal = charCode.toString(16);
return '\\x' + padLeft(hexadecimal, '0', 2);
}
// catch-all
var charCode_hexadecimal = charCode.toString(16);
if (this.options.base == 'ubrace') {
return '\\u{' + charCode_hexadecimal + '}';
}
return '\\u' + padLeft(charCode_hexadecimal, '0', 4);
};
/**
Never modify the given `value`!
*/
Escaper.prototype.simplify = function (value, seen, depth, maxDepth) {
var _this = this;
if (seen === void 0) { seen = []; }
if (depth === void 0) { depth = 0; }
if (maxDepth === void 0) { maxDepth = 10; }
if (value === undefined) {
return value;
}
else if (value === null) {
return value;
}
else if (Buffer.isBuffer(value)) {
// return value.toString('utf8');
return this.transformBuffer(value);
}
else if (typeof value.toJSON === 'function') {
return this.simplify(value.toJSON(), seen, depth, maxDepth);
}
else if (Array.isArray(value)) {
if (seen.indexOf(value) > -1) {
return '[Circular Array]';
}
if (depth > maxDepth) {
return '[excessive depth]...';
}
var array = value.map(function (child) { return _this.simplify(child, seen, depth + 1, maxDepth); });
seen.push(array);
return array;
}
else if (typeof value === 'object') {
if (seen.indexOf(value) > -1) {
return '[Circular Object]';
}
if (depth > maxDepth) {
return '[excessive depth]...';
}
var object = {};
for (var key in value) {
if (value.hasOwnProperty(key)) {
object[key] = this.simplify(value[key], seen, depth + 1, maxDepth);
}
}
seen.push(object);
return object;
}
// catch-all
return value;
};
return Escaper;
})();
exports.Escaper = Escaper;