Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quoted Reserved Words #3

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,19 @@ customization
-------------

These are the default styles and settings used by _eyes_.

styles: { // Styles applied to stdout
all: 'cyan', // Overall style applied to everything
label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]`
other: 'inverted', // Objects which don't have a literal representation, such as functions
key: 'bold', // The keys in object literals, like 'a' in `{a: 1}`

special: 'grey', // null, undefined...
string: 'green',
number: 'magenta',
bool: 'blue', // true false
regexp: 'green', // /\d+/
},

pretty: true, // Indent object literals
hideFunctions: false, // Don't output functions at all
stream: process.stdout, // Stream to write to, or null
Expand Down
243 changes: 187 additions & 56 deletions lib/eyes.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,42 @@ eyes.defaults = {
regexp: 'green', // /\d+/
},
pretty: true, // Indent object literals
indent: 4,
hideFunctions: false,
stream: process.stdout,
maxLength: 2048 // Truncate output if longer
showHidden: false,
sortKeys: false,
stream: process && process.stdout,
maxLength: 2048, // Truncate output if longer
colors: true,
html: false,
json: false,
escape: true,
functions: false
};

// Return a curried inspect() function, with the `options` argument filled in.
eyes.inspector = function (options) {
var that = this;
return function (obj, label, opts) {
return that.inspect.call(that, obj, label,
merge(options || {}, opts || {}));
var myopts=merge(options || {}, opts || {});
var result=that.inspect.call(that, obj, label, myopts);
if (myopts.html && !myopts.stream) {
return '<pre class="eyes" style="padding:8px;background-color: black;'+((myopts && myopts.styles && myopts.styles.all)?('color:'+myopts.styles.all+';'):'')+'">'+result+'</pre>';
} else {
return result;
}
};
};

// If we have a `stream` defined, use it to print a styled string,
// if not, we just return the stringified object.
eyes.inspect = function (obj, label, options) {
options = merge(this.defaults, options || {});

stack = [];
if (options.stream) {
return this.print(stringify(obj, options), label, options);
} else {
return stringify(obj, options) + (options.styles ? '\033[39m' : '');
return stringify(obj, options) + (options.styles ? (options.html?'':(options.colors?'\033[39m':'')) : '');
}
};

Expand All @@ -61,41 +74,63 @@ eyes.inspect = function (obj, label, options) {
// versus a printable character (`c`). So we resort to counting the
// length manually.
eyes.print = function (str, label, options) {
for (var c = 0, i = 0; i < str.length; i++) {
if (str.charAt(i) === '\033') { i += 4 } // `4` because '\033[25m'.length + 1 == 5
else if (c === options.maxLength) {
str = str.slice(0, i - 1) + '…';
break;
} else { c++ }
if (!this.html) {
for (var c = 0, i = 0; i < str.length; i++) {
if (str.charAt(i) === '\033') { i += 4 } // `4` because '\033[25m'.length + 1 == 5
else if (c === options.maxLength) {
str = str.slice(0, i - 1) + '…';
break;
} else { c++ }
}
}
return options.stream.write.call(options.stream, (label ?
this.stylize(label, options.styles.label, options.styles) + ': ' : '') +
this.stylize(str, options.styles.all, options.styles) + '\033[0m' + "\n");
this.stylize(label, options.styles.label, options) + ': ' : '') +
this.stylize(str, options.styles.all, options) + (this.html?'':(options.colors?'\033[0m':'')) + "\n");
};

// Apply a style to a string, eventually,
// I'd like this to support passing multiple
// styles.
eyes.stylize = function (str, style, styles) {
var codes = {
'bold' : [1, 22],
'underline' : [4, 24],
'inverse' : [7, 27],
'cyan' : [36, 39],
'magenta' : [35, 39],
'blue' : [34, 39],
'yellow' : [33, 39],
'green' : [32, 39],
'red' : [31, 39],
'grey' : [90, 39]
}, endCode;

if (style && codes[style]) {
endCode = (codes[style][1] === 39 && styles.all) ? codes[styles.all][0]
: codes[style][1];
return '\033[' + codes[style][0] + 'm' + str +
'\033[' + endCode + 'm';
} else { return str }
eyes.stylize = function (str, style, options) {
if (options.colors) {
if (options.html) {
var codes = {
'bold' : 'font-weight:bold',
'underline' : 'text-decoration: underline',
};
if (style) {
if (codes[style]) {
return '<span style="'+style+'">'+str+'</span>';
} else {
return '<span style="color:'+style+'">'+str+'</span>';
}
} else {
return str;
}
} else {
var codes = {
'bold' : [1, 22],
'underline' : [4, 24],
'inverse' : [7, 27],
'cyan' : [36, 39],
'magenta' : [35, 39],
'blue' : [34, 39],
'yellow' : [33, 39],
'green' : [32, 39],
'red' : [31, 39],
'grey' : [90, 39]
}, endCode;

if (style && codes[style]) {
endCode = (codes[style][1] === 39 && options.styles.all) ? codes[options.styles.all][0]
: codes[style][1];
return '\033[' + codes[style][0] + 'm' + str +
'\033[' + endCode + 'm';
} else { return str }
}
} else {
return str;
}
};

// Convert any object to a string, ready for output.
Expand All @@ -104,7 +139,7 @@ eyes.stylize = function (str, style, styles) {
// stringify().
function stringify(obj, options) {
var that = this, stylize = function (str, style) {
return eyes.stylize(str, options.styles[style], options.styles)
return eyes.stylize(str, options.styles[style], options)
}, index, result;

if ((index = stack.indexOf(obj)) !== -1) {
Expand All @@ -114,16 +149,16 @@ function stringify(obj, options) {

result = (function (obj) {
switch (typeOf(obj)) {
case "string" : obj = stringifyString(obj.indexOf("'") === -1 ? "'" + obj + "'"
: '"' + obj + '"');
case "string" : obj = stringifyString((obj.indexOf("'") === -1 && !options.json)? ("'" + obj.replace(/'/g,"\\'") + "'") : ('"' + obj.replace(/"/g,'\\"') + '"'),options);
return stylize(obj, 'string');
case "regexp" : return stylize('/' + obj.source + '/', 'regexp');
case "number" : return stylize(obj + '', 'number');
case "function" : return options.stream ? stylize("Function", 'other') : '[Function]';
case "function" : return options.stream ? stylize(options.functions?obj.toString():"Function", 'other') : '[Function]';
case "null" : return stylize("null", 'special');
case "undefined": return stylize("undefined", 'special');
case "boolean" : return stylize(obj + '', 'bool');
case "date" : return stylize(obj.toUTCString());
case "date" : return stylize(obj.toUTCString(),'date');
case "array" : return stringifyArray(obj, options, stack.length);
case "object" : return stringifyObject(obj, options, stack.length);
}
Expand All @@ -133,13 +168,73 @@ function stringify(obj, options) {
return result;
};

function htmlspecialchars (string, quote_style, charset, double_encode) {
var optTemp = 0,
i = 0,
noquotes = false;
if (typeof quote_style === 'undefined' || quote_style === null) {
quote_style = 2;
}
string = string.toString();
if (double_encode !== false) {
string = string.replace(/&/g, '&amp;');
}
string = string.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// console.log(string);
var OPTS = {
'ENT_NOQUOTES': 0,
'ENT_HTML_QUOTE_SINGLE': 1,
'ENT_HTML_QUOTE_DOUBLE': 2,
'ENT_COMPAT': 2,
'ENT_QUOTES': 3,
'ENT_IGNORE': 4
};
if (quote_style === 0) {
noquotes = true;
}
if (typeof quote_style !== 'number') {
quote_style = [].concat(quote_style);
for (var i = 0; i < quote_style.length; i++) {
if (OPTS[quote_style[i]] === 0) {
noquotes = true;
}
else if (OPTS[quote_style[i]]) {
optTemp = optTemp | OPTS[quote_style[i]];
}
}
quote_style = optTemp;
}
if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
string = string.replace(/'/g, '&#039;');
}
if (!noquotes) {
string = string.replace(/"/g, '&quot;');
}
return string;
}

// Escape invisible characters in a string
function stringifyString (str, options) {
return str.replace(/\\/g, '\\\\')
.replace(/\n/g, '\\n')
.replace(/[\u0001-\u001F]/g, function (match) {
return '\\0' + match[0].charCodeAt(0).toString(8);
});
var result;
if (options.escape) {
result=str.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/[\u0001-\u001F]/g, function (match) {
return '\\0' + match[0].charCodeAt(0).toString(8);
});
if (options.html) {
result=htmlspecialchars(result);
}
} else {
result=str;
}

// Truncate the string if a maximum length is configured
var truncate = options.hasOwnProperty('maxStringLength') && options.maxStringLength >= 0;
if(truncate && result.length > options.maxStringLength) {
var length = Math.min(result.length, options.maxStringLength - 3);
result = result.substr(0, length) + "...";
}

return result;
}

// Convert an array to a string, such as [1, 2, 3].
Expand All @@ -148,47 +243,84 @@ function stringifyString (str, options) {
function stringifyArray(ary, options, level) {
var out = [];
var pretty = options.pretty && (ary.length > 4 || ary.some(function (o) {
return (typeof(o) === 'object' && Object.keys(o).length > 0) ||
return (o !== null && typeof(o) === 'object' && Object.keys(o).length > 0) ||
(Array.isArray(o) && o.length > 0);
}));
var ws = pretty ? '\n' + new(Array)(level * 4 + 1).join(' ') : ' ';
var ws = pretty ? '\n' + new(Array)(level * options.indent + 1).join(' ') : ' ';

for (var i = 0; i < ary.length; i++) {
var truncate = options.hasOwnProperty('maxArrayLength') && options.maxArrayLength >= 0;

var length = truncate ? Math.min(ary.length, options.maxArrayLength) : ary.length;
for (var i = 0; i < length; i++) {
out.push(stringify(ary[i], options));
}

// Add a special String if the array was truncated
if(length < ary.length) {
out.push('<<truncated>>');
}

if (out.length === 0) {
return '[]';
} else {
return '[' + ws
+ out.join(',' + (pretty ? ws : ' '))
+ (pretty ? ws.slice(0, -4) : ws) +
+ (pretty ? ws.slice(0, -1*options.indent) : ws) +
']';
}
};

var quote_reserved_words = function(word) {
var reserved_words=['abstract', 'else', 'instanceof', 'switch', 'boolean', 'enum', 'int', 'synchronized', 'break', 'export', 'interface', 'this', 'byte', 'extends', 'long', 'throw', 'case', 'false', 'native', 'throws', 'catch', 'final', 'new', 'transient', 'char', 'finally', 'null', 'true', 'class', 'float', 'package', 'try', 'const', 'for', 'private', 'typeof', 'continue', 'function', 'protected', 'var', 'debugger', 'goto', 'public', 'void', 'default', 'if', 'return', 'volatile', 'delete', 'implements', 'short', 'while', 'do', 'import', 'static', 'with', 'double', 'in', 'super'];
return function(word) {
for (var i in reserved_words) {
if (word === reserved_words[i]) {
return "'" + word + "'";
}
}
return word;
}
}();


// Convert an object to a string, such as {a: 1}.
// This function calls stringify() for each of its values,
// and does not output functions or prototype values.
function stringifyObject(obj, options, level) {
if ( obj instanceof Buffer) return 'Buffer';
var out = [];
var pretty = options.pretty && (Object.keys(obj).length > 2 ||
Object.keys(obj).some(function (k) { return typeof(obj[k]) === 'object' }));
var ws = pretty ? '\n' + new(Array)(level * 4 + 1).join(' ') : ' ';
var ws = pretty ? '\n' + new(Array)(level * options.indent + 1).join(' ') : ' ';

Object.keys(obj).forEach(function (k) {
if (obj.hasOwnProperty(k) && !(obj[k] instanceof Function && options.hideFunctions)) {
out.push(eyes.stylize(k, options.styles.key, options.styles) + ': ' +
stringify(obj[k], options));
}
var keys = options.showHidden ? Object.keys(obj) : Object.getOwnPropertyNames(obj);
if (options.sortKeys) keys.sort();

var truncate = options.hasOwnProperty('maxObjectKeys') && options.maxObjectKeys >= 0;

// Slice the keys to the maximum length if they exceed the maxObjectKeys option
var includeKeys = (truncate) ? keys.slice(0, options.maxObjectKeys) : keys;
includeKeys.forEach(function (k) {
if (!(level== 1 && options.exclude && ~options.exclude.indexOf(k))) {
if (Object.prototype.hasOwnProperty.call(obj, k)
&& !(obj[k] instanceof Function && options.hideFunctions)) {
out.push((options.json?'"':'')+eyes.stylize(options.json?k:quote_reserved_words(k), options.styles.key, options) + (options.json?'"':'') + ': ' +
stringify(obj[k], options));
}
}
});

// Append a special String if the Object was truncated
if (includeKeys.length < keys.length) {
out.push(eyes.stylize('<<truncated>>', options.styles.key, options.styles));
}

if (out.length === 0) {
return '{}';
} else {
return "{" + ws
+ out.join(',' + (pretty ? ws : ' '))
+ (pretty ? ws.slice(0, -4) : ws) +
+ (pretty ? ws.slice(0, -1*options.indent) : ws) +
"}";
}
};
Expand Down Expand Up @@ -230,4 +362,3 @@ function merge(/* variable args */) {
});
return target;
}

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
"name" : "eyes",
"description" : "a customizable value inspector",
"url" : "http://github.com/cloudhead/eyes.js",
"repository" : { "type": "git", "url": "https://github.com/cloudhead/eyes.js.git" },
"keywords" : ["inspector", "debug", "inspect", "print"],
"author" : "Alexis Sellier <self@cloudhead.net>",
"contributors" : [],
"contributors" : [{ "name": "Charlie Robbins", "email": "charlie@nodejitsu.com" }],
"licenses" : ["MIT"],
"dependencies" : [],
"main" : "./lib/eyes",
"version" : "0.1.6",
"version" : "0.1.8",
"scripts" : { "test": "node test/*-test.js" },
"directories" : { "lib": "./lib", "test": "./test" },
"engines" : { "node": "> 0.1.90" }
}
Loading