How to mangle JavaScript strings using hexadecimal escape? - javascript

I need to mangle (obfuscate) JavaScript strings using hexadecimal encoding.
Source code:
var a = 'a';
Mangled code:
var a = '\x61';
It is easy to convert string to a hexadecimal value:
var map = {
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
};
var hex = function (str) {
var result = '';
for (var i = 0, l = str.length; i < l; i++) {
var char = str[i];
if (map[char]) {
result += map[char];
} else if ('\\' == char) {
result += '\\' + str[++i];
} else {
result += '\\x' + str.charCodeAt(i).toString(16);
}
}
return result;
};
But when I add this string to the output file I get:
var a = '\\x61';
P.S. I use esprima/escodegen/estraverse to work with AST.

Below is an draft of implementation based on Качалов Тимофей's solution:
var esprima = require('esprima');
var estraverse = require('estraverse');
var escodegen = require('escodegen');
function stringToUnicode(string) {
return '"' + string.replace(/[\s\S]/g, function (escape) {
return '\\u' + ('0000' + escape.charCodeAt().toString(16)).slice(-4);
}) + '"';
}
var tree = esprima.parse(code);
//...
estraverse.replace(tree, {
leave: function(node){
if (node.type === 'Literal' && (node.raw[0] === '"' || node.raw[0] === '\'' )){
node['x-verbatim-property'] = {
content : stringToUnicode(node.value),
precedence: escodegen.Precedence.Primary
};
}
}
});
//...
var result = escodegen.generate(tree, {verbatim: 'x-verbatim-property'});

Related

How to output json prettry formt as html using javascript? [duplicate]

How can I display JSON in an easy-to-read (for human readers) format? I'm looking primarily for indentation and whitespace, with perhaps even colors / font-styles / etc.
Pretty-printing is implemented natively in JSON.stringify(). The third argument enables pretty printing and sets the spacing to use:
var str = JSON.stringify(obj, null, 2); // spacing level = 2
If you need syntax highlighting, you might use some regex magic like so:
function syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
See in action here: jsfiddle
Or a full snippet provided below:
function output(inp) {
document.body.appendChild(document.createElement('pre')).innerHTML = inp;
}
function syntaxHighlight(json) {
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
var obj = {a:1, 'b':'foo', c:[false,'false',null, 'null', {d:{e:1.3e5,f:'1.3e5'}}]};
var str = JSON.stringify(obj, undefined, 4);
output(str);
output(syntaxHighlight(str));
pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
User Pumbaa80's answer is great if you have an object you want pretty printed. If you're starting from a valid JSON string that you want to pretty printed, you need to convert it to an object first:
var jsonString = '{"some":"json"}';
var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);
This builds a JSON object from the string, and then converts it back to a string using JSON stringify's pretty print.
Better way.
Prettify JSON Array in Javascript
JSON.stringify(jsonobj,null,'\t')
var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07", "postalCode": "75007", "countryCode": "FRA", "countryLabel": "France" };
document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);
In case of displaying in HTML, you should to add a balise <pre></pre>
document.getElementById("result-after").innerHTML = "<pre>"+JSON.stringify(jsonObj,undefined, 2) +"</pre>"
Example:
var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07", "postalCode": "75007", "countryCode": "FRA", "countryLabel": "France" };
document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);
document.getElementById("result-after").innerHTML = "<pre>"+JSON.stringify(jsonObj,undefined, 2) +"</pre>"
div { float:left; clear:both; margin: 1em 0; }
<div id="result-before"></div>
<div id="result-after"></div>
Based on Pumbaa80's answer I have modified the code to use the console.log colours (working on Chrome for sure) and not HTML. Output can be seen inside console. You can edit the _variables inside the function adding some more styling.
function JSONstringify(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, '\t');
}
var
arr = [],
_string = 'color:green',
_number = 'color:darkorange',
_boolean = 'color:blue',
_null = 'color:magenta',
_key = 'color:red';
json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var style = _number;
if (/^"/.test(match)) {
if (/:$/.test(match)) {
style = _key;
} else {
style = _string;
}
} else if (/true|false/.test(match)) {
style = _boolean;
} else if (/null/.test(match)) {
style = _null;
}
arr.push(style);
arr.push('');
return '%c' + match + '%c';
});
arr.unshift(json);
console.log.apply(console, arr);
}
Here is a bookmarklet you can use:
javascript:function JSONstringify(json) {if (typeof json != 'string') {json = JSON.stringify(json, undefined, '\t');}var arr = [],_string = 'color:green',_number = 'color:darkorange',_boolean = 'color:blue',_null = 'color:magenta',_key = 'color:red';json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {var style = _number;if (/^"/.test(match)) {if (/:$/.test(match)) {style = _key;} else {style = _string;}} else if (/true|false/.test(match)) {style = _boolean;} else if (/null/.test(match)) {style = _null;}arr.push(style);arr.push('');return '%c' + match + '%c';});arr.unshift(json);console.log.apply(console, arr);};void(0);
Usage:
var obj = {a:1, 'b':'foo', c:[false,null, {d:{e:1.3e5}}]};
JSONstringify(obj);
Edit: I just tried to escape the % symbol with this line, after the variables declaration:
json = json.replace(/%/g, '%%');
But I find out that Chrome is not supporting % escaping in the console. Strange... Maybe this will work in the future.
Cheers!
I think you're looking for something like this :
JSON.stringify(obj, null, '\t');
This "pretty-prints" your JSON string, using a tab for indentation.
If you prefer to use spaces instead of tabs, you could also use a number for the number of spaces you'd like :
JSON.stringify(obj, null, 2);
You can use console.dir(), which is a shortcut for console.log(util.inspect()).
(The only difference is that it bypasses any custom inspect() function defined on an object.)
It uses syntax-highlighting, smart indentation, removes quotes from keys and just makes the output as pretty as it gets.
const object = JSON.parse(jsonString)
console.dir(object, {depth: null, colors: true})
and for the command line:
cat package.json | node -e "process.stdin.pipe(new stream.Writable({write: chunk => console.dir(JSON.parse(chunk), {depth: null, colors: true})}))"
I use the JSONView Chrome extension (it is as pretty as it gets :):
Edit: added jsonreport.js
I've also released an online stand-alone JSON pretty print viewer, jsonreport.js, that provides a human readable HTML5 report you can use to view any JSON data.
You can read more about the format in New JavaScript HTML5 Report Format.
If you are using ES5, simply call JSON.stringify with:
2nd arg: replacer; set to null,
3rd arg: space; use tab.
JSON.stringify(anObject, null, '\t');
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Here's user123444555621's awesome HTML one adapted for terminals. Handy for debugging Node scripts:
function prettyJ(json) {
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, 2);
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
function (match) {
let cls = "\x1b[36m";
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = "\x1b[34m";
} else {
cls = "\x1b[32m";
}
} else if (/true|false/.test(match)) {
cls = "\x1b[35m";
} else if (/null/.test(match)) {
cls = "\x1b[31m";
}
return cls + match + "\x1b[0m";
}
);
}
Usage:
// thing = any json OR string of json
prettyJ(thing);
For debugging purpose I use:
console.debug("%o", data);
https://getfirebug.com/wiki/index.php/Console_API
https://developer.mozilla.org/en-US/docs/DOM/console
You can use JSON.stringify(your object, null, 2)
The second parameter can be used as a replacer function which takes key and Val as parameters.This can be used in case you want to modify something within your JSON object.
more reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Unsatisfied with other pretty printers for Ruby, I wrote my own (NeatJSON) and then ported it to JavaScript including a free online formatter. The code is free under MIT license (quite permissive).
Features (all optional):
Set a line width and wrap in a way that keeps objects and arrays on the same line when they fit, wrapping one value per line when they don't.
Sort object keys if you like.
Align object keys (line up the colons).
Format floating point numbers to specific number of decimals, without messing up the integers.
'Short' wrapping mode puts opening and closing brackets/braces on the same line as values, providing a format that some prefer.
Granular control over spacing for arrays and objects, between brackets, before/after colons and commas.
Function is made available to both web browsers and Node.js.
I'll copy the source code here so that this is not just a link to a library, but I encourage you to go to the GitHub project page, as that will be kept up-to-date and the code below will not.
(function(exports){
exports.neatJSON = neatJSON;
function neatJSON(value,opts){
opts = opts || {}
if (!('wrap' in opts)) opts.wrap = 80;
if (opts.wrap==true) opts.wrap = -1;
if (!('indent' in opts)) opts.indent = ' ';
if (!('arrayPadding' in opts)) opts.arrayPadding = ('padding' in opts) ? opts.padding : 0;
if (!('objectPadding' in opts)) opts.objectPadding = ('padding' in opts) ? opts.padding : 0;
if (!('afterComma' in opts)) opts.afterComma = ('aroundComma' in opts) ? opts.aroundComma : 0;
if (!('beforeComma' in opts)) opts.beforeComma = ('aroundComma' in opts) ? opts.aroundComma : 0;
if (!('afterColon' in opts)) opts.afterColon = ('aroundColon' in opts) ? opts.aroundColon : 0;
if (!('beforeColon' in opts)) opts.beforeColon = ('aroundColon' in opts) ? opts.aroundColon : 0;
var apad = repeat(' ',opts.arrayPadding),
opad = repeat(' ',opts.objectPadding),
comma = repeat(' ',opts.beforeComma)+','+repeat(' ',opts.afterComma),
colon = repeat(' ',opts.beforeColon)+':'+repeat(' ',opts.afterColon);
return build(value,'');
function build(o,indent){
if (o===null || o===undefined) return indent+'null';
else{
switch(o.constructor){
case Number:
var isFloat = (o === +o && o !== (o|0));
return indent + ((isFloat && ('decimals' in opts)) ? o.toFixed(opts.decimals) : (o+''));
case Array:
var pieces = o.map(function(v){ return build(v,'') });
var oneLine = indent+'['+apad+pieces.join(comma)+apad+']';
if (opts.wrap===false || oneLine.length<=opts.wrap) return oneLine;
if (opts.short){
var indent2 = indent+' '+apad;
pieces = o.map(function(v){ return build(v,indent2) });
pieces[0] = pieces[0].replace(indent2,indent+'['+apad);
pieces[pieces.length-1] = pieces[pieces.length-1]+apad+']';
return pieces.join(',\n');
}else{
var indent2 = indent+opts.indent;
return indent+'[\n'+o.map(function(v){ return build(v,indent2) }).join(',\n')+'\n'+indent+']';
}
case Object:
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [JSON.stringify(k), build(o[k],'')];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
keyvals = keyvals.map(function(kv){ return kv.join(colon) }).join(comma);
var oneLine = indent+"{"+opad+keyvals+opad+"}";
if (opts.wrap===false || oneLine.length<opts.wrap) return oneLine;
if (opts.short){
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [indent+' '+opad+JSON.stringify(k),o[k]];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
keyvals[0][0] = keyvals[0][0].replace(indent+' ',indent+'{');
if (opts.aligned){
var longest = 0;
for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
var padding = repeat(' ',longest);
for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
}
for (var i=keyvals.length;i--;){
var k=keyvals[i][0], v=keyvals[i][1];
var indent2 = repeat(' ',(k+colon).length);
var oneLine = k+colon+build(v,'');
keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
}
return keyvals.join(',\n') + opad + '}';
}else{
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [indent+opts.indent+JSON.stringify(k),o[k]];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
if (opts.aligned){
var longest = 0;
for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
var padding = repeat(' ',longest);
for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
}
var indent2 = indent+opts.indent;
for (var i=keyvals.length;i--;){
var k=keyvals[i][0], v=keyvals[i][1];
var oneLine = k+colon+build(v,'');
keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
}
return indent+'{\n'+keyvals.join(',\n')+'\n'+indent+'}'
}
default:
return indent+JSON.stringify(o);
}
}
}
function repeat(str,times){ // http://stackoverflow.com/a/17800645/405017
var result = '';
while(true){
if (times & 1) result += str;
times >>= 1;
if (times) str += str;
else break;
}
return result;
}
function padRight(pad, str){
return (str + pad).substring(0, pad.length);
}
}
neatJSON.version = "0.5";
})(typeof exports === 'undefined' ? this : exports);
Thanks a lot #all!
Based on the previous answers, here is another variant method providing custom replacement rules as parameter:
renderJSON : function(json, rr, code, pre){
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, '\t');
}
var rules = {
def : 'color:black;',
defKey : function(match){
return '<strong>' + match + '</strong>';
},
types : [
{
name : 'True',
regex : /true/,
type : 'boolean',
style : 'color:lightgreen;'
},
{
name : 'False',
regex : /false/,
type : 'boolean',
style : 'color:lightred;'
},
{
name : 'Unicode',
regex : /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/,
type : 'string',
style : 'color:green;'
},
{
name : 'Null',
regex : /null/,
type : 'nil',
style : 'color:magenta;'
},
{
name : 'Number',
regex : /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/,
type : 'number',
style : 'color:darkorange;'
},
{
name : 'Whitespace',
regex : /\s+/,
type : 'whitespace',
style : function(match){
return '&nbsp';
}
}
],
keys : [
{
name : 'Testkey',
regex : /("testkey")/,
type : 'key',
style : function(match){
return '<h1>' + match + '</h1>';
}
}
],
punctuation : {
name : 'Punctuation',
regex : /([\,\.\}\{\[\]])/,
type : 'punctuation',
style : function(match){
return '<p>________</p>';
}
}
};
if('undefined' !== typeof jQuery){
rules = $.extend(rules, ('object' === typeof rr) ? rr : {});
}else{
for(var k in rr ){
rules[k] = rr[k];
}
}
var str = json.replace(/([\,\.\}\{\[\]]|"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var i = 0, p;
if (rules.punctuation.regex.test(match)) {
if('string' === typeof rules.punctuation.style){
return '<span style="'+ rules.punctuation.style + '">' + match + '</span>';
}else if('function' === typeof rules.punctuation.style){
return rules.punctuation.style(match);
} else{
return match;
}
}
if (/^"/.test(match)) {
if (/:$/.test(match)) {
for(i=0;i<rules.keys.length;i++){
p = rules.keys[i];
if (p.regex.test(match)) {
if('string' === typeof p.style){
return '<span style="'+ p.style + '">' + match + '</span>';
}else if('function' === typeof p.style){
return p.style(match);
} else{
return match;
}
}
}
return ('function'===typeof rules.defKey) ? rules.defKey(match) : '<span style="'+ rules.defKey + '">' + match + '</span>';
} else {
return ('function'===typeof rules.def) ? rules.def(match) : '<span style="'+ rules.def + '">' + match + '</span>';
}
} else {
for(i=0;i<rules.types.length;i++){
p = rules.types[i];
if (p.regex.test(match)) {
if('string' === typeof p.style){
return '<span style="'+ p.style + '">' + match + '</span>';
}else if('function' === typeof p.style){
return p.style(match);
} else{
return match;
}
}
}
}
});
if(true === pre)str = '<pre>' + str + '</pre>';
if(true === code)str = '<code>' + str + '</code>';
return str;
}
It works well:
console.table()
Read more here: https://developer.mozilla.org/pt-BR/docs/Web/API/Console/table
Here is a simple JSON format/color component written in React:
const HighlightedJSON = ({ json }: Object) => {
const highlightedJSON = jsonObj =>
Object.keys(jsonObj).map(key => {
const value = jsonObj[key];
let valueType = typeof value;
const isSimpleValue =
["string", "number", "boolean"].includes(valueType) || !value;
if (isSimpleValue && valueType === "object") {
valueType = "null";
}
return (
<div key={key} className="line">
<span className="key">{key}:</span>
{isSimpleValue ? (
<span className={valueType}>{`${value}`}</span>
) : (
highlightedJSON(value)
)}
</div>
);
});
return <div className="json">{highlightedJSON(json)}</div>;
};
See it working in this CodePen:
https://codepen.io/benshope/pen/BxVpjo
Hope that helps!
Couldn't find any solution that had good syntax highlighting for the console, so here's my 2p
Install & Add cli-highlight dependency
npm install cli-highlight --save
Define logjson globally
const highlight = require('cli-highlight').highlight
console.logjson = (obj) => console.log(
highlight( JSON.stringify(obj, null, 4),
{ language: 'json', ignoreIllegals: true } ));
Use
console.logjson({foo: "bar", someArray: ["string1", "string2"]});
I'd like to show my jsonAnalyze method here, it does a pretty print of the JSON structure only, but in some cases can be more usefull that printing the whole JSON.
Say you have a complex JSON like this:
let theJson = {
'username': 'elen',
'email': 'elen#test.com',
'state': 'married',
'profiles': [
{'name': 'elenLove', 'job': 'actor' },
{'name': 'elenDoe', 'job': 'spy'}
],
'hobbies': ['run', 'movies'],
'status': {
'home': {
'ownsHome': true,
'addresses': [
{'town': 'Mexico', 'address': '123 mexicoStr'},
{'town': 'Atlanta', 'address': '4B atlanta 45-48'},
]
},
'car': {
'ownsCar': true,
'cars': [
{'brand': 'Nissan', 'plate': 'TOKY-114', 'prevOwnersIDs': ['4532354531', '3454655344', '5566753422']},
{'brand': 'Benz', 'plate': 'ELEN-1225', 'prevOwnersIDs': ['4531124531', '97864655344', '887666753422']}
]
}
},
'active': true,
'employed': false,
};
Then the method will return the structure like this:
username
email
state
profiles[]
profiles[].name
profiles[].job
hobbies[]
status{}
status{}.home{}
status{}.home{}.ownsHome
status{}.home{}.addresses[]
status{}.home{}.addresses[].town
status{}.home{}.addresses[].address
status{}.car{}
status{}.car{}.ownsCar
status{}.car{}.cars[]
status{}.car{}.cars[].brand
status{}.car{}.cars[].plate
status{}.car{}.cars[].prevOwnersIDs[]
active
employed
So this is the jsonAnalyze() code:
function jsonAnalyze(obj) {
let arr = [];
analyzeJson(obj, null, arr);
return logBeautifiedDotNotation(arr);
function analyzeJson(obj, parentStr, outArr) {
let opt;
if (!outArr) {
return "no output array given"
}
for (let prop in obj) {
opt = parentStr ? parentStr + '.' + prop : prop;
if (Array.isArray(obj[prop]) && obj[prop] !== null) {
let arr = obj[prop];
if ((Array.isArray(arr[0]) || typeof arr[0] == "object") && arr[0] != null) {
outArr.push(opt + '[]');
analyzeJson(arr[0], opt + '[]', outArr);
} else {
outArr.push(opt + '[]');
}
} else if (typeof obj[prop] == "object" && obj[prop] !== null) {
outArr.push(opt + '{}');
analyzeJson(obj[prop], opt + '{}', outArr);
} else {
if (obj.hasOwnProperty(prop) && typeof obj[prop] != 'function') {
outArr.push(opt);
}
}
}
}
function logBeautifiedDotNotation(arr) {
retStr = '';
arr.map(function (item) {
let dotsAmount = item.split(".").length - 1;
let dotsString = Array(dotsAmount + 1).join(' ');
retStr += dotsString + item + '\n';
console.log(dotsString + item)
});
return retStr;
}
}
jsonAnalyze(theJson);
Douglas Crockford's JSON in JavaScript library will pretty print JSON via the stringify method.
You may also find the answers to this older question useful: How can I pretty-print JSON in (unix) shell script?
I ran into an issue today with #Pumbaa80's code. I'm trying to apply JSON syntax highlighting to data that I'm rendering in a Mithril view, so I need to create DOM nodes for everything in the JSON.stringify output.
I split the really long regex into its component parts as well.
render_json = (data) ->
# wraps JSON data in span elements so that syntax highlighting may be
# applied. Should be placed in a `whitespace: pre` context
if typeof(data) isnt 'string'
data = JSON.stringify(data, undefined, 2)
unicode = /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/
keyword = /\b(true|false|null)\b/
whitespace = /\s+/
punctuation = /[,.}{\[\]]/
number = /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/
syntax = '(' + [unicode, keyword, whitespace,
punctuation, number].map((r) -> r.source).join('|') + ')'
parser = new RegExp(syntax, 'g')
nodes = data.match(parser) ? []
select_class = (node) ->
if punctuation.test(node)
return 'punctuation'
if /^\s+$/.test(node)
return 'whitespace'
if /^\"/.test(node)
if /:$/.test(node)
return 'key'
return 'string'
if /true|false/.test(node)
return 'boolean'
if /null/.test(node)
return 'null'
return 'number'
return nodes.map (node) ->
cls = select_class(node)
return Mithril('span', {class: cls}, node)
Code in context on Github here
If you're looking for a nice library to prettify json on a web page...
Prism.js is pretty good.
http://prismjs.com/
I found using JSON.stringify(obj, undefined, 2) to get the indentation, and then using prism to add a theme was a good approach.
If you're loading in JSON via an ajax call, then you can run one of Prism's utility methods to prettify
For example:
Prism.highlightAll()
Quick pretty human-readable JSON output in 1 line code (without colors):
document.documentElement.innerHTML='<pre>'+JSON.stringify(obj, null, 2)+'</pre>';
If you need this to work in a textarea the accepted solution will not work.
<textarea id='textarea'></textarea>
$("#textarea").append(formatJSON(JSON.stringify(jsonobject),true));
function formatJSON(json,textarea) {
var nl;
if(textarea) {
nl = "
";
} else {
nl = "<br>";
}
var tab = "    ";
var ret = "";
var numquotes = 0;
var betweenquotes = false;
var firstquote = false;
for (var i = 0; i < json.length; i++) {
var c = json[i];
if(c == '"') {
numquotes ++;
if((numquotes + 2) % 2 == 1) {
betweenquotes = true;
} else {
betweenquotes = false;
}
if((numquotes + 3) % 4 == 0) {
firstquote = true;
} else {
firstquote = false;
}
}
if(c == '[' && !betweenquotes) {
ret += c;
ret += nl;
continue;
}
if(c == '{' && !betweenquotes) {
ret += tab;
ret += c;
ret += nl;
continue;
}
if(c == '"' && firstquote) {
ret += tab + tab;
ret += c;
continue;
} else if (c == '"' && !firstquote) {
ret += c;
continue;
}
if(c == ',' && !betweenquotes) {
ret += c;
ret += nl;
continue;
}
if(c == '}' && !betweenquotes) {
ret += nl;
ret += tab;
ret += c;
continue;
}
if(c == ']' && !betweenquotes) {
ret += nl;
ret += c;
continue;
}
ret += c;
} // i loop
return ret;
}
This is nice:
https://github.com/mafintosh/json-markup from mafintosh
const jsonMarkup = require('json-markup')
const html = jsonMarkup({hello:'world'})
document.querySelector('#myElem').innerHTML = html
HTML
<link ref="stylesheet" href="style.css">
<div id="myElem></div>
Example stylesheet can be found here
https://raw.githubusercontent.com/mafintosh/json-markup/master/style.css
To highlight and beautify it in HTML using Bootstrap:
function prettifyJson(json, prettify) {
if (typeof json !== 'string') {
if (prettify) {
json = JSON.stringify(json, undefined, 4);
} else {
json = JSON.stringify(json);
}
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
function(match) {
let cls = "<span>";
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = "<span class='text-danger'>";
} else {
cls = "<span>";
}
} else if (/true|false/.test(match)) {
cls = "<span class='text-primary'>";
} else if (/null/.test(match)) {
cls = "<span class='text-info'>";
}
return cls + match + "</span>";
}
);
}
based on #user123444555621, just slightly more modern.
const clsMap = [
[/^".*:$/, "key"],
[/^"/, "string"],
[/true|false/, "boolean"],
[/null/, "key"],
[/.*/, "number"],
]
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span class="${clsMap.find(([regex]) => regex.test(match))[1]}">${match}</span>`);
you can also specify the colors inside js (no CSS needed)
const clsMap = [
[/^".*:$/, "red"],
[/^"/, "green"],
[/true|false/, "blue"],
[/null/, "magenta"],
[/.*/, "darkorange"],
]
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span style="color:${clsMap.find(([regex]) => regex.test(match))[1]}">${match}</span>`);
and a version with less regex
const clsMap = [
[match => match.startsWith('"') && match.endsWith(':'), "red"],
[match => match.startsWith('"'), "green"],
[match => match === "true" || match === "false" , "blue"],
[match => match === "null", "magenta"],
[() => true, "darkorange"],
];
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span style="color:${clsMap.find(([fn]) => fn(match))[1]}">${match}</span>`);
it's for Laravel, Codeigniter
Html:
<pre class="jsonPre"> </pre>
Controller: Return the JSON value from the controller as like as
return json_encode($data, JSON_PRETTY_PRINT);
In script:
<script> $('.jsonPre').html(result); </script>
result will be
Here is how you can print without using native function.
function pretty(ob, lvl = 0) {
let temp = [];
if(typeof ob === "object"){
for(let x in ob) {
if(ob.hasOwnProperty(x)) {
temp.push( getTabs(lvl+1) + x + ":" + pretty(ob[x], lvl+1) );
}
}
return "{\n"+ temp.join(",\n") +"\n" + getTabs(lvl) + "}";
}
else {
return ob;
}
}
function getTabs(n) {
let c = 0, res = "";
while(c++ < n)
res+="\t";
return res;
}
let obj = {a: {b: 2}, x: {y: 3}};
console.log(pretty(obj));
/*
{
a: {
b: 2
},
x: {
y: 3
}
}
*/
The simplest way to display an object for debugging purposes:
console.log("data",data) // lets you unfold the object manually
If you want to display the object in the DOM, you should consider that it could contain strings that would be interpreted as HTML. Therefore, you need to do some escaping...
var s = JSON.stringify(data,null,2) // format
var e = new Option(s).innerHTML // escape
document.body.insertAdjacentHTML('beforeend','<pre>'+e+'</pre>') // display
<!-- here is a complete example pretty print with more space between lines-->
<!-- be sure to pass a json string not a json object -->
<!-- use line-height to increase or decrease spacing between json lines -->
<style type="text/css">
.preJsonTxt{
font-size: 18px;
text-overflow: ellipsis;
overflow: hidden;
line-height: 200%;
}
.boxedIn{
border: 1px solid black;
margin: 20px;
padding: 20px;
}
</style>
<div class="boxedIn">
<h3>Configuration Parameters</h3>
<pre id="jsonCfgParams" class="preJsonTxt">{{ cfgParams }}</pre>
</div>
<script language="JavaScript">
$( document ).ready(function()
{
$(formatJson);
<!-- this will do a pretty print on the json cfg params -->
function formatJson() {
var element = $("#jsonCfgParams");
var obj = JSON.parse(element.text());
element.html(JSON.stringify(obj, undefined, 2));
}
});
</script>

Expansion of algebraic term

I am trying to expand an algebraic term.
(x+1)(x+1)/x => x + 2 + x^-1
(x+1)^3 => x^3 + 3x^2 + 3x + 1
(x^2*x)(x^2) => x^5
This is my attempt at it. I have tried a lot of ways trying to fix the problems below.
Problems:
Like terms should be added together
(x+1)(x+1)(x+1) should be valid.
(x+1)^2 should be equal to (x+1)(x+1)
x(x+1) should be valid
1x^n should just be x^n
There should be no 0x^n terms.
nx^0 terms should just be n
Code Snippet:
function split(input) {
return ((((input.split(")(")).toString()).replace(/\)/g, "")).replace(/\(/g, "")).split(','); }
function strVali(str) {
str = str.replace(/\s+/g, "");
var parts = str.match(/[+\-]?[^+\-]+/g);
// accumulate the results
return parts.reduce(function(res, part) {
var coef = parseFloat(part) || +(part[0] + "1") || 1;
var x = part.indexOf('x');
var power = x === -1 ?
0:
part[x + 1] === "^" ?
+part.slice(x + 2) :
1;
res[power] = (res[power] || 0) + coef;
return res;
}, {});
}
function getCoeff(coeff) {
var powers = Object.keys(strVali(coeff));
var max = Math.max.apply(null, powers);
var result = [];
for(var i = max; i >= 0; i--)
result.push(strVali(coeff)[i] || 0);
return result; }
function evaluate(expression) {
var term1 = getCoeff(expression[0]);
var term2 = getCoeff(expression[1]);
var expand = "";
for ( var j = 0; j < term1.length; j++ ) {
for ( var i = 0; i < term2.length; i++ ) {
expand += Number(term1[j] * term2[i]) + 'x^ ' + (Number(term1.length) - 1 - j + Number(term2.length) - 1 - i) + ' + ';
}}
var final = "";
for ( var Z = 0; Z < getCoeff(expand).length; Z++) {
final += ' ' + getCoeff(expand)[Z] + 'x^ {' + (getCoeff(expand).length - Z - 1) + '} +';
}
final = "$$" + ((((((final.replace(/\+[^\d]0x\^ \{[\d]+\}/g,'')).replace(/x\^ \{0}/g,'')).replace(/x\^ \{1}/g,'x')).replace(/[^\d]1x\^ /g,'+ x^')).replace(/\+ -/g,' - ')).slice(0, -1)).substring(1,(final.length)) + "$$";
document.getElementById('result').innerHTML = final;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
}
function caller() {
var input = document.getElementById('input').value;
evaluate(split(input)); }
div.wrapper {
width: 100%;
height:100%;
border:0px solid black;
}
input[type="text"] {
display: block;
margin : 0 auto;
padding: 10px;
font-size:20px;
}
button{
margin:auto;
display:block;
background-color: white;
color: black;
border: 2px solid #555555;
padding-left: 20px;
padding-right: 20px;
font-size: 20px;
margin-top:10px;
}
button:hover {
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
}
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<div class='wrapper'><input id="input" title="Enter Expression" type="text" value="(x^2+x+1)(x^2+x+1)"></div>
<div> <button onclick="caller()">Click</button></div>
<div id="result">$$x^4 + 2x^3 + 3x^2 + 2x + 1$$</div>
Reference:
How to calculate coefficients of polynomial expansion in javascript
Getting coefficients of algebraic term
How to get a term before a character?
Edit: I have re-written my original answer from when the question did not include the - and / operators). My new answer supports - and /.
Since you have not defined a precise grammar, I have made some assumptions. I support the +, -, /, ^ operators and the implicit multiply. These can operate on numbers, x and (...) expressions, except that right hand side of the ^ operator must be a number. I allow spaces between tokens.
Limitations: The -is a binary not unary - operator, So x-2 if OK, -2 on its own is a syntax error. The / is limited. You may divide by a value with a single coefficient such as 2, 'x', 2x^2, but not by cannot have 1/(x^2+1), which would evaluate to an infinite series.
It first takes the string and wraps it in a 'tokenizer' which lets you look it one token at a time, where a token is a number, x, ( ) or operator.
It then calls evaluateSum() which evaluates things separated by + or -, where each thing is a product evaluated by evaluateProduct(). This in turn uses evaluatePower() to evalue the ^. Finally evaluateTerm() looks for x, numbers and bracketed sub-expressions which are evaluates recursively with evaluateSum(). This hierarchy creates the correct operator precedence and evaluation order.
Each layer of the evaluation returns a 'coefficients' object which s array-like, but may contain megative indexes. For example [1,0,1] means 1+x^2.
It can cope with any number of nested brackets and a lot of other case such as xx(x) is x^3, 2^3 is 8. I have added a few throws for syntax errors, for example 2^x is illegal.
function makeTokenizer(source) {
var c, i, tokenizer;
i = 0; // The index of the current character.
c = source.charAt(i); // The current character.
function consumeChar() { // Move to next c, return previous c.
var prevC = c;
i += 1;
c = source.charAt(i);
return prevC;
}
tokenizer = {
next : function () {
var str;
while (c === ' ') { // Skip spaces
consumeChar();
}
if (!c) {
tokenizer.token = undefined; // End of source
} else if (c >= '0' && c <= '9') { // number
str = consumeChar(); // First digit
while (c >= '0' && c <= '9') { // Look for more digits.
str += consumeChar();
}
tokenizer.token = Number(str);
} else if (c === "x") {
tokenizer.token = consumeChar();
} else { // single-character operator
tokenizer.token = consumeChar();
}
}
};
tokenizer.next(); // Load first token.
return tokenizer;
}
function makeCoefficients() { // Make like an array but can have -ve indexes
var min = 0, max = 0, c = {};
return {
get: function (i) {
return c[i] || 0;
},
set: function (i, value) {
c[i] = value;
min = Math.min(i, min);
max = Math.max(i + 1, max);
return this; // for chaining
},
forEach: function (callback) {
var i;
for (i = min; i < max; i += 1) {
if (this.get(i)) {
callback(this.get(i), i);
}
}
},
toString: function () {
var result = "", first = true;
this.forEach(function (val, power) {
result += (val < 0 || first) ? "" : "+";
first = false;
result += (val === 1 && power !== 0) ? "" : val;
if (power) {
result += "x";
if (power !== 1) {
result += "^" + power;
}
}
});
return result;
},
toPowerOf: function (power) {
if (power === 0) {
return makeCoefficients().set(0, 1); // Anything ^0 = 1
}
if (power === 1) {
return this;
}
if (power < 0) {
throw "cannot raise to negative powers";
}
return this.multiply(this.toPowerOf(power - 1));
},
multiply: function (coefficients) {
var result = makeCoefficients();
this.forEach(function (a, i) {
coefficients.forEach(function (b, j) {
result.set(i + j, result.get(i + j) + a * b);
});
});
return result;
},
divide: function (coefficients) {
// Division is hard, for example we cannot do infinite series like:
// 1/(1 + x^2) = sum_(n=0 to infinity) 1/2 x^n ((-i)^n + i^n)
// So we do a few easy cases only.
var that = this, result = makeCoefficients(), done;
coefficients.forEach(function (value, pow) {
that.forEach(function (value2, pow2) {
result.set(pow2 - pow, value2 / value);
});
if (done) {
throw "cannot divide by " + coefficients.toString();
}
done = true;
});
return result;
},
add: function (coefficients, op) {
var result = makeCoefficients();
this.forEach(function (value, i) {
result.set(value, i);
});
op = (op === "-" ? -1 : 1);
coefficients.forEach(function (value, i) {
result.set(i, result.get(i) + value * op);
});
return result;
}
};
}
var evaluateSum; // Called recursively
function evaluateTerm(tokenizer) {
var result;
if (tokenizer.token === "(") {
tokenizer.next();
result = evaluateSum(tokenizer);
if (tokenizer.token !== ")") {
throw ") missing";
}
tokenizer.next();
} else if (typeof tokenizer.token === "number") {
result = makeCoefficients().set(0, tokenizer.token);
tokenizer.next();
} else if (tokenizer.token === "x") {
tokenizer.next();
result = makeCoefficients().set(1, 1); // x^1
} else {
return false; // Not a 'term'
}
return result;
}
function evaluatePower(tokenizer) {
var result;
result = evaluateTerm(tokenizer);
if (tokenizer.token === "^") {
tokenizer.next();
if (typeof tokenizer.token !== "number") {
throw "number expected after ^";
}
result = result.toPowerOf(tokenizer.token);
tokenizer.next();
}
return result;
}
function evaluateProduct(tokenizer) {
var result, term, divOp;
result = evaluatePower(tokenizer);
if (!result) {
throw "Term not found";
}
while (true) {
divOp = (tokenizer.token === "/");
if (divOp) {
tokenizer.next();
term = evaluatePower(tokenizer);
result = result.divide(term);
} else {
term = evaluatePower(tokenizer);
if (!term) {
break;
}
result = result.multiply(term);
}
}
return result;
}
function evaluateSum(tokenizer) {
var result, op;
result = evaluateProduct(tokenizer);
while (tokenizer.token === "+" || tokenizer.token === "-") {
op = tokenizer.token;
tokenizer.next();
result = result.add(evaluateProduct(tokenizer), op);
}
return result;
}
function evaluate(source) {
var tokenizer = makeTokenizer(source),
coefficients = evaluateSum(tokenizer);
if (tokenizer.token) {
throw "Unexpected token " + tokenizer.token;
}
console.log(source + " => " + coefficients.toString());
}
// Examples:
evaluate("(x+1)(x+1)"); // => 1+2x+x^2
evaluate("(x+1)^2"); // => 1+2x+x^2
evaluate("(x+1)(x+1)(x+1)"); // => 1+3x+3x^2+x^3
evaluate("(x+1)^3"); // => 1+3x+3x^2+x^3
evaluate("(x)(x+1)"); // => x+x^2
evaluate("(x+1)(x)"); // => x+x^2
evaluate("3x^0"); // => 3
evaluate("2^3"); // => 8
evaluate("(x+2x(x+2(x+1)x))"); // => x+6x^2+4x^3
evaluate("(x+1)(x-1)"); // => -1+x^2
evaluate("(x+1)(x+1)/x"); // x^-1+2+x
//evaluate("(x+1)/(x^2 + 1)"); //throws cannot divide by 1+2x
It can handle +, -, / and implicit multiplication. It expands the parenthesis accordingly and adds them to the original expression while removing the parenthesised version. It collects like terms accordingly. Limitations: It cannot divide by a polynomial and it does not support the * operator.
function strVali(str) {
str = str.replace(/\s+/g, "");
var parts = str.match(/[+\-]?[^+\-]+/g);
return parts.reduce(function(res, part) {
var coef = parseFloat(part) || +(part[0] + "1") || 1;
var x = part.indexOf('x');
var power = x === -1 ?
0:
part[x + 1] === "^" ?
+part.slice(x + 2) :
1;
res[power] = (res[power] || 0) + coef;
return res;
}, {});
}
function getCoeff(coeff) {
var powers = Object.keys(strVali(coeff));
var max = Math.max.apply(null, powers);
var result = [];
for(var i = max; i >= 0; i--)
result.push(strVali(coeff)[i] || 0);
return result; }
function format(str) {
str = ' ' + str;
str = str.replace(/-/g,'+-').replace(/x(?!\^)/g,'x^1').replace(/([+\/*)(])(\d+)([+\/*)(])/g,'$1$2x^0$3').replace(/([^\d])(x\^-?\d+)/g,'$11$2').replace(/(-?\d+x\^\d+)(?=\()/g,'($1)').replace(/(\))(-?\d+x\^\d+)/g,'$1($2)').replace(/([^\)\/])(\()([^\*\/\(\)]+?)(\))(?![(^\/])/g,'$1$3');
str = str.replace(/(\([^\(\)]+?\))\/(\d+x\^-?\d+)/g,'$1/($2)').replace(/(\d+x\^-?\d+)\/(\d+x\^-?\d+)/g,'($1)/($2)').replace(/(\d+x\^-?\d+)\/(\(\d+x\^-?\d+\))/g,'($1)/$2');
return str;
}
function expBrackets(str) {
var repeats = str.match(/\([^\(\)]+?\)\^\d+/g);
if ( repeats === null ) { return str; } else { var totalRepeat = '';
for ( var t = 0; t < repeats.length; t++ ) { var repeat = repeats[t].match(/\d+$/); for ( var u = 0; u < Number(repeat); u++ ) { totalRepeat += repeats[t].replace(/\^\d+$/,''); }
str = str.replace(/\([^\(\)]+?\)\^\d+/, totalRepeat); totalRepeat = ''; }
return str; }
}
function multiply(str) {
var pairs = str.match(/\([^\(\)]+?\)\([^\(\)]+?\)/g);
if ( pairs !== null ) { while ( pairs !== null ) { var output = '';
for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].slice(1).slice(0, -1).split(')('); var firstCoeff = getCoeff(pair[0]); var secondCoeff = getCoeff(pair[1]);
for (var j = 0; j < firstCoeff.length; j++) {
for (var k = 0; k < secondCoeff.length; k++) { output += firstCoeff[j] * secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j + secondCoeff.length - 1 - k) + '+'; } }
var regexp = new RegExp(pairs[i].replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\)/g,'\\)').replace(/\^/g,'\\^').replace(/\-/g,'\\-'));
str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\d]0x\^\d+/g,'')) + ')');
output = ''; }
pairs = str.match(/\([^\(\)]+?\)\([^\(\)]+?\)/g); } }
else { }
str = str.replace(/\+/g,' + ');
return str;
}
function divide(str) {
if ( str.match(/\/(\(-?\d+x\^-?\d+.+?\))/g) === null && str.match(/\//g) !== null ) {
while ( pairs !== null ) {
var pairs = str.match(/\([^\(\)]+?\)\/\([^\(\)]+?\)/g);
var output = '';
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].slice(1).slice(0, -1).split(')/(');
var firstCoeff = getCoeff(pair[0]);
var secondCoeff = getCoeff(pair[1]);
for (var j = 0; j < firstCoeff.length; j++) {
for (var k = 0; k < secondCoeff.length; k++) {
output += firstCoeff[j] / secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j - secondCoeff.length + 1 + k) + '+';
output = output.replace(/([+-])Infinityx\^\-?\d+/g,'').replace(/([+-])NaNx\^\-?\d+/g,'');
} }
var regexp = new RegExp(pairs[i].replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\)/g,'\\)').replace(/\^/g,'\\^').replace(/\-/g,'\\-'));
str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\d]0x\^-?\d+/g,'')) + ')');
output = ''; }
pairs = str.match(/\([^\(\)]+?\)\/\([^\(\)]+?\)/g); } }
else { }
return str;
}
function evaluate(str) {
var result = format(divide(format(multiply(expBrackets(format((str)))))));
var resultCollect = '';
result = result.replace(/\s+/g, "").replace(/[^\d]0x\^-?\d+/g,'').replace(/\+/g,' + ');
if ( result === '') {
document.getElementById('result').innerHTML = '$$' + str + '$$' + '$$ = 0 $$';
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
} else if ( result.match(/-?\d+x\^-\d+/g) === null && str.match(/\/(\(-?\d+x\^-?\d+.+?\))/g) === null) {
for ( var i = 0; i < getCoeff(result).length; i++ ) {
resultCollect += getCoeff(result)[i] + 'x^' + Number(getCoeff(result).length - 1 - i) + '+' ; }
if ( resultCollect !== '')
resultCollect = '$$ = ' + resultCollect.slice(0,-1).replace(/[^\d]0x\^-?\d+/g,'').replace(/\+/g,' + ').replace(/x\^0/g,'').replace(/x\^1(?!\d+)/g,'x').replace(/\^(-?\d+)/g,'\^\{$1\}').replace(/\+ -/g,' - ') + '$$';
else
resultCollect = 'Error: Trying to divide by a polynomial ';
document.getElementById('result').innerHTML = '$$' + str.replace(/\^(-?\d+)/g,'\^\{$1\}') + '$$' + resultCollect;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
} else {
resultCollect = '$$ = ' + result.replace(/\^(-?\d+)/g,'\^\{$1\}') + '$$';
document.getElementById('result').innerHTML = '$$' + str.replace(/\^(-?\d+)/g,'\^\{$1\}').replace(/\+ -/g,' - ') + '$$' + resultCollect;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
}
}
function caller() {
var input = document.getElementById('input').value;
evaluate(input);
}
div.wrapper {
width: 100%;
height:100%;
border:0 solid black;
}
input[type="text"] {
display: block;
margin : 0 auto;
padding: 10px;
font-size:20px;
}
button{
margin:auto;
display:block;
background-color: white;
color: black;
border: 2px solid #555555;
padding-left: 20px;
padding-right: 20px;
font-size: 20px;
margin-top:10px;
}
button:hover {
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
}
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<input id="input" type="text" title="Enter Expression: ">
<button onclick="caller()">Click</button>
<div id="result"></div>
<div id="errors"></div>
My approach utilizes two helper classes:
-Term: This stores a coefficient and an object, the keys of which are variables and the values of which are the exponents. It has methods for determining whether terms are the "same" (i.e. whether they have the same variables with the same exponents, thus allowing them to be added), adding terms, and multiplying terms.
-Polynomial: This stores an array of terms. It has methods for adding two polynomials, multiplying two polynomials, and simplifying polynomials (eliminating terms with 0 coefficients and combining like terms).
It has two substantial helper functions:
-findOuterParens - Given a string, this function returns the indices of the first outermost pair of left and right parentheses.
-parseExpressionStr - This function uses a regular expression to split a string into three types of substrings: 1) a number, 2) a symbol (i.e. a variable, like 'x' or 'y'), or 3) an operator (*, -, +, ^, /). It creates Polynomial objects for the first two types and leaves the operators as strings.
The expand function runs the show. It takes in a string and returns a Polynomial object representing the expanded form of the polynomial in the string. It does this as follows:
1) It deals with parentheses by recursion. It uses findOuterParens to find all outermost parenthsized substrings. So for "3x*(x+4)+(2(y+1))*t", for instance, it would find "x+4" and "2(y+1)" as parenthsized substrings. It then passes these to itself for further parsing. For "2(y+1)", it would identify "y+1" as a parenthesized substring, and pass this to itself, for three levels of recursion for this example.
2) It deals with other parts of the string using parseExpressionStr. After steps 1 and 2, it has an array containing Polynomial objects and operators (stored as strings). It then proceeds to simplifying and expanding.
3) It converts subtraction subproblems to addition subproblems by replacing all -'s with +'s and multiplying all polynomials following -'s by -1.
4) It converts division subproblems to multiplication subproblems by replacing /'s with *'s and inverting the Polynomial following the /. If the polynomial following the / has more than one term, it throws an error.
5) It converts power subproblems to multiplication subproblems by replacing ^'s with a series of multiplications.
6) It adds in implicit *'s. I.e. if two Polynomial elements are right next to each other in the array, then it's inferred that they are being multiplied, so, e.g. '2*x' == '2x'.
7) Now the array has polynomial objects alternating with either '+' or '*'. It first performs all polynomial multiplications and then performs all additions.
8) It performs a final simplification step and returns the resulting expanded polynomial.
<html>
<head></head>
<body></body>
<script>
function findOuterParens(str) {
var leftIndex = str.indexOf('('), leftNum = 1, rightNum = 0;
if (leftIndex === -1)
return
for (var i=leftIndex+1; i<str.length; i++) {
if (str[i] === '(')
leftNum++;
else if (str[i] === ')')
rightNum++, rightIndex=i;
if (leftNum === rightNum)
return {start: leftIndex, end: rightIndex}
}
throw Error('Parenthesis at position ' + leftIndex + ' of "' + str + '" is unpaired.');
}
function parseExpressionStr(inputString) {
var result = [], str = inputString;
while (str) {
var nextPart = str.match(/([\d]+)|([\+\-\^\*\/])|([a-zA-z])/);
if (!nextPart)
return result;
if (nextPart.length === 0)
throw Error('Unable to parse expression string "' + inputString + '". Remainder "' + str + '" could not be parsed.');
else if (nextPart[1]) // First group (digits) matched
result.push(new Polynomial(parseFloat(nextPart[0])));
else if (nextPart[3]) // Third group (symbol) matched
result.push(new Polynomial(nextPart[0]));
else // Second group (operator) matched
result.push(nextPart[0]);
str = str.substring(nextPart.index+nextPart[0].length);
}
return result
}
function isOperator(char) {
return char === '*' || char === '/' || char === '^' || char === '+' || char === '-';
}
function Polynomial(value) {
this.terms = (value!==undefined) ? [new Term(value)] : [];
}
Polynomial.prototype.simplify = function() {
for (var i=0; i<this.terms.length-1; i++) {
if (this.terms[i].coeff === 0) {
this.terms.splice(i--, 1);
continue;
}
for (var j=i+1; j<this.terms.length; j++) {
if (Term.same(this.terms[i], this.terms[j])) {
this.terms[i] = Term.add(this.terms[i], this.terms[j]);
this.terms.splice(j--, 1);
}
}
}
}
Polynomial.add = function(a, b) {
var result = new Polynomial();
result.terms = a.terms.concat(b.terms);
result.simplify();
return result
}
Polynomial.multiply = function(a, b) {
var result = new Polynomial();
a.terms.forEach(function(aTerm) {
b.terms.forEach(function (bTerm) {
result.terms.push(Term.multiply(aTerm, bTerm));
});
});
result.simplify();
return result
}
Polynomial.prototype.toHtml = function() {
var html = ''
for (var i=0; i<this.terms.length; i++) {
var term = this.terms[i];
if (i !== 0)
html += (term.coeff < 0) ? ' - ' : ' + ';
else
html += (term.coeff < 0) ? '-' : '';
var coeff = Math.abs(term.coeff);
html += (coeff === 1 && Object.keys(term.symbols).length > 0) ? '' : coeff;
for (var symbol in term.symbols) {
var exp = term.symbols[symbol];
exp = (exp !== 1) ? exp : '';
html += symbol + '<sup>' + exp + '</sup>';
}
}
return html;
}
function Term(value) {
this.symbols = {};
if (typeof value==='string') { // Symbol
this.symbols[value] = 1;
this.coeff = 1;
} else if (typeof value==='number') { // Number
this.coeff = value;
} else {
this.coeff = 1;
}
}
Term.same = function(a, b) {
if (Object.keys(a.symbols).length != Object.keys(b.symbols).length)
return false
else
for (var aSymbol in a.symbols)
if (a.symbols[aSymbol] != b.symbols[aSymbol]) return false
return true
}
Term.add = function(a, b) {
var result = new Term();
Object.assign(result.symbols, a.symbols);
result.coeff = a.coeff + b.coeff;
return result
}
Term.multiply = function(a, b) {
var result = new Term();
Object.assign(result.symbols, a.symbols);
for (var symbol in b.symbols) {
if (!(symbol in result.symbols))
result.symbols[symbol] = 0;
result.symbols[symbol] += b.symbols[symbol];
if (result.symbols[symbol] === 0)
delete result.symbols[symbol];
}
result.coeff = a.coeff * b.coeff;
return result
}
function expand(str) {
var result = [];
var parens = findOuterParens(str);
while (parens) {
result = result.concat(parseExpressionStr(str.slice(0,parens.start)));
result.push(expand(str.slice(parens.start+1, parens.end)))
str = str.slice(parens.end+1);
parens = findOuterParens(str);
}
result = result.concat(parseExpressionStr(str));
// Move -s to coefficients
var minus = result.indexOf('-'), minusPoly = new Polynomial(-1);
while (minus !== -1) {
result[minus] = '+';
result[minus+1] = Polynomial.multiply(minusPoly, result[minus+1]);
minus = result.indexOf('-');
}
// Get rid of +s that follow another operator
var plus = result.indexOf('+');
while (plus !== -1) {
if (plus===0 || isOperator(result[plus-1])) {
result.splice(plus--, 1);
}
plus = result.indexOf('+', plus+1);
}
// Convert /s to *s
var divide = result.indexOf('/');
while (divide !== -1) {
result[divide] = '*';
var termsToInvert = result[divide+1].terms;
if (termsToInvert.length > 1)
throw Error('Attempt to divide by a polynomial with more than one term.');
var termToInvert = termsToInvert[0];
for (var symbol in termToInvert.symbols) {
termToInvert.symbols[symbol] = -termToInvert.symbols[symbol];
}
termToInvert.coeff = 1/termToInvert.coeff;
divide = result.indexOf('/');
}
// Convert ^s to *s
var power = result.indexOf('^');
while (power !== -1) {
var exp = result[power+1];
if (exp.terms.length > 1 || Object.keys(exp.terms[0].symbols).length != 0)
throw Error('Attempt to use non-number as an exponent');
exp = exp.terms[0].coeff;
var base = result[power-1];
var expanded = [power-1, 3, base];
for (var i=0; i<exp-1; i++) {
expanded.push('*');
expanded.push(base);
}
result.splice.apply(result, expanded);
power = result.indexOf('^');
}
// Add implicit *s
for (var i=0; i<result.length-1; i++)
if (!isOperator(result[i]) && !(isOperator(result[i+1])))
result.splice(i+1, 0, '*');
// Multiply
var mult = result.indexOf('*');
while (mult !== -1) {
var product = Polynomial.multiply(result[mult-1], result[mult+1]);
result.splice(mult-1, 3, product);
mult = result.indexOf('*');
}
// Add
var add = result.indexOf('+');
while (add !== -1) {
var sum = Polynomial.add(result[add-1], result[add+1]);
result.splice(add-1, 3, sum);
add = result.indexOf('+');
}
result[0].simplify();
return result[0];
}
var problems = ['(x+1)(x+1)/x', '(x+1)^3', '(x^2*x)(x^2)', '(x+1)(x+1)(x+1)',
'(x+1)^2', 'x(x+1)', '1x^4', '(x + (x+2))(x+5)', '3x^0', '2^3',
'(x+2x(x+2(x+1)x))', '(x+1)(x-1)', '(x+1)(y+1)', '(x+y+t)(q+x+7)'];
var solutionHTML = '';
for (var i = 0; i<problems.length; i++) {
solutionHTML += problems[i] + ' => ' + expand(problems[i]).toHtml() + '<br>';
}
document.body.innerHTML = solutionHTML;
</script>
</html>
It outputs:

Making JSON output "pretty" with CSS [duplicate]

How can I display JSON in an easy-to-read (for human readers) format? I'm looking primarily for indentation and whitespace, with perhaps even colors / font-styles / etc.
Pretty-printing is implemented natively in JSON.stringify(). The third argument enables pretty printing and sets the spacing to use:
var str = JSON.stringify(obj, null, 2); // spacing level = 2
If you need syntax highlighting, you might use some regex magic like so:
function syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
See in action here: jsfiddle
Or a full snippet provided below:
function output(inp) {
document.body.appendChild(document.createElement('pre')).innerHTML = inp;
}
function syntaxHighlight(json) {
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
var obj = {a:1, 'b':'foo', c:[false,'false',null, 'null', {d:{e:1.3e5,f:'1.3e5'}}]};
var str = JSON.stringify(obj, undefined, 4);
output(str);
output(syntaxHighlight(str));
pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
User Pumbaa80's answer is great if you have an object you want pretty printed. If you're starting from a valid JSON string that you want to pretty printed, you need to convert it to an object first:
var jsonString = '{"some":"json"}';
var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);
This builds a JSON object from the string, and then converts it back to a string using JSON stringify's pretty print.
Better way.
Prettify JSON Array in Javascript
JSON.stringify(jsonobj,null,'\t')
var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07", "postalCode": "75007", "countryCode": "FRA", "countryLabel": "France" };
document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);
In case of displaying in HTML, you should to add a balise <pre></pre>
document.getElementById("result-after").innerHTML = "<pre>"+JSON.stringify(jsonObj,undefined, 2) +"</pre>"
Example:
var jsonObj = {"streetLabel": "Avenue Anatole France", "city": "Paris 07", "postalCode": "75007", "countryCode": "FRA", "countryLabel": "France" };
document.getElementById("result-before").innerHTML = JSON.stringify(jsonObj);
document.getElementById("result-after").innerHTML = "<pre>"+JSON.stringify(jsonObj,undefined, 2) +"</pre>"
div { float:left; clear:both; margin: 1em 0; }
<div id="result-before"></div>
<div id="result-after"></div>
Based on Pumbaa80's answer I have modified the code to use the console.log colours (working on Chrome for sure) and not HTML. Output can be seen inside console. You can edit the _variables inside the function adding some more styling.
function JSONstringify(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, '\t');
}
var
arr = [],
_string = 'color:green',
_number = 'color:darkorange',
_boolean = 'color:blue',
_null = 'color:magenta',
_key = 'color:red';
json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var style = _number;
if (/^"/.test(match)) {
if (/:$/.test(match)) {
style = _key;
} else {
style = _string;
}
} else if (/true|false/.test(match)) {
style = _boolean;
} else if (/null/.test(match)) {
style = _null;
}
arr.push(style);
arr.push('');
return '%c' + match + '%c';
});
arr.unshift(json);
console.log.apply(console, arr);
}
Here is a bookmarklet you can use:
javascript:function JSONstringify(json) {if (typeof json != 'string') {json = JSON.stringify(json, undefined, '\t');}var arr = [],_string = 'color:green',_number = 'color:darkorange',_boolean = 'color:blue',_null = 'color:magenta',_key = 'color:red';json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {var style = _number;if (/^"/.test(match)) {if (/:$/.test(match)) {style = _key;} else {style = _string;}} else if (/true|false/.test(match)) {style = _boolean;} else if (/null/.test(match)) {style = _null;}arr.push(style);arr.push('');return '%c' + match + '%c';});arr.unshift(json);console.log.apply(console, arr);};void(0);
Usage:
var obj = {a:1, 'b':'foo', c:[false,null, {d:{e:1.3e5}}]};
JSONstringify(obj);
Edit: I just tried to escape the % symbol with this line, after the variables declaration:
json = json.replace(/%/g, '%%');
But I find out that Chrome is not supporting % escaping in the console. Strange... Maybe this will work in the future.
Cheers!
I think you're looking for something like this :
JSON.stringify(obj, null, '\t');
This "pretty-prints" your JSON string, using a tab for indentation.
If you prefer to use spaces instead of tabs, you could also use a number for the number of spaces you'd like :
JSON.stringify(obj, null, 2);
You can use console.dir(), which is a shortcut for console.log(util.inspect()).
(The only difference is that it bypasses any custom inspect() function defined on an object.)
It uses syntax-highlighting, smart indentation, removes quotes from keys and just makes the output as pretty as it gets.
const object = JSON.parse(jsonString)
console.dir(object, {depth: null, colors: true})
and for the command line:
cat package.json | node -e "process.stdin.pipe(new stream.Writable({write: chunk => console.dir(JSON.parse(chunk), {depth: null, colors: true})}))"
I use the JSONView Chrome extension (it is as pretty as it gets :):
Edit: added jsonreport.js
I've also released an online stand-alone JSON pretty print viewer, jsonreport.js, that provides a human readable HTML5 report you can use to view any JSON data.
You can read more about the format in New JavaScript HTML5 Report Format.
If you are using ES5, simply call JSON.stringify with:
2nd arg: replacer; set to null,
3rd arg: space; use tab.
JSON.stringify(anObject, null, '\t');
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Here's user123444555621's awesome HTML one adapted for terminals. Handy for debugging Node scripts:
function prettyJ(json) {
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, 2);
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
function (match) {
let cls = "\x1b[36m";
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = "\x1b[34m";
} else {
cls = "\x1b[32m";
}
} else if (/true|false/.test(match)) {
cls = "\x1b[35m";
} else if (/null/.test(match)) {
cls = "\x1b[31m";
}
return cls + match + "\x1b[0m";
}
);
}
Usage:
// thing = any json OR string of json
prettyJ(thing);
For debugging purpose I use:
console.debug("%o", data);
https://getfirebug.com/wiki/index.php/Console_API
https://developer.mozilla.org/en-US/docs/DOM/console
You can use JSON.stringify(your object, null, 2)
The second parameter can be used as a replacer function which takes key and Val as parameters.This can be used in case you want to modify something within your JSON object.
more reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Unsatisfied with other pretty printers for Ruby, I wrote my own (NeatJSON) and then ported it to JavaScript including a free online formatter. The code is free under MIT license (quite permissive).
Features (all optional):
Set a line width and wrap in a way that keeps objects and arrays on the same line when they fit, wrapping one value per line when they don't.
Sort object keys if you like.
Align object keys (line up the colons).
Format floating point numbers to specific number of decimals, without messing up the integers.
'Short' wrapping mode puts opening and closing brackets/braces on the same line as values, providing a format that some prefer.
Granular control over spacing for arrays and objects, between brackets, before/after colons and commas.
Function is made available to both web browsers and Node.js.
I'll copy the source code here so that this is not just a link to a library, but I encourage you to go to the GitHub project page, as that will be kept up-to-date and the code below will not.
(function(exports){
exports.neatJSON = neatJSON;
function neatJSON(value,opts){
opts = opts || {}
if (!('wrap' in opts)) opts.wrap = 80;
if (opts.wrap==true) opts.wrap = -1;
if (!('indent' in opts)) opts.indent = ' ';
if (!('arrayPadding' in opts)) opts.arrayPadding = ('padding' in opts) ? opts.padding : 0;
if (!('objectPadding' in opts)) opts.objectPadding = ('padding' in opts) ? opts.padding : 0;
if (!('afterComma' in opts)) opts.afterComma = ('aroundComma' in opts) ? opts.aroundComma : 0;
if (!('beforeComma' in opts)) opts.beforeComma = ('aroundComma' in opts) ? opts.aroundComma : 0;
if (!('afterColon' in opts)) opts.afterColon = ('aroundColon' in opts) ? opts.aroundColon : 0;
if (!('beforeColon' in opts)) opts.beforeColon = ('aroundColon' in opts) ? opts.aroundColon : 0;
var apad = repeat(' ',opts.arrayPadding),
opad = repeat(' ',opts.objectPadding),
comma = repeat(' ',opts.beforeComma)+','+repeat(' ',opts.afterComma),
colon = repeat(' ',opts.beforeColon)+':'+repeat(' ',opts.afterColon);
return build(value,'');
function build(o,indent){
if (o===null || o===undefined) return indent+'null';
else{
switch(o.constructor){
case Number:
var isFloat = (o === +o && o !== (o|0));
return indent + ((isFloat && ('decimals' in opts)) ? o.toFixed(opts.decimals) : (o+''));
case Array:
var pieces = o.map(function(v){ return build(v,'') });
var oneLine = indent+'['+apad+pieces.join(comma)+apad+']';
if (opts.wrap===false || oneLine.length<=opts.wrap) return oneLine;
if (opts.short){
var indent2 = indent+' '+apad;
pieces = o.map(function(v){ return build(v,indent2) });
pieces[0] = pieces[0].replace(indent2,indent+'['+apad);
pieces[pieces.length-1] = pieces[pieces.length-1]+apad+']';
return pieces.join(',\n');
}else{
var indent2 = indent+opts.indent;
return indent+'[\n'+o.map(function(v){ return build(v,indent2) }).join(',\n')+'\n'+indent+']';
}
case Object:
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [JSON.stringify(k), build(o[k],'')];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
keyvals = keyvals.map(function(kv){ return kv.join(colon) }).join(comma);
var oneLine = indent+"{"+opad+keyvals+opad+"}";
if (opts.wrap===false || oneLine.length<opts.wrap) return oneLine;
if (opts.short){
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [indent+' '+opad+JSON.stringify(k),o[k]];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
keyvals[0][0] = keyvals[0][0].replace(indent+' ',indent+'{');
if (opts.aligned){
var longest = 0;
for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
var padding = repeat(' ',longest);
for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
}
for (var i=keyvals.length;i--;){
var k=keyvals[i][0], v=keyvals[i][1];
var indent2 = repeat(' ',(k+colon).length);
var oneLine = k+colon+build(v,'');
keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
}
return keyvals.join(',\n') + opad + '}';
}else{
var keyvals=[],i=0;
for (var k in o) keyvals[i++] = [indent+opts.indent+JSON.stringify(k),o[k]];
if (opts.sorted) keyvals = keyvals.sort(function(kv1,kv2){ kv1=kv1[0]; kv2=kv2[0]; return kv1<kv2?-1:kv1>kv2?1:0 });
if (opts.aligned){
var longest = 0;
for (var i=keyvals.length;i--;) if (keyvals[i][0].length>longest) longest = keyvals[i][0].length;
var padding = repeat(' ',longest);
for (var i=keyvals.length;i--;) keyvals[i][0] = padRight(padding,keyvals[i][0]);
}
var indent2 = indent+opts.indent;
for (var i=keyvals.length;i--;){
var k=keyvals[i][0], v=keyvals[i][1];
var oneLine = k+colon+build(v,'');
keyvals[i] = (opts.wrap===false || oneLine.length<=opts.wrap || !v || typeof v!="object") ? oneLine : (k+colon+build(v,indent2).replace(/^\s+/,''));
}
return indent+'{\n'+keyvals.join(',\n')+'\n'+indent+'}'
}
default:
return indent+JSON.stringify(o);
}
}
}
function repeat(str,times){ // http://stackoverflow.com/a/17800645/405017
var result = '';
while(true){
if (times & 1) result += str;
times >>= 1;
if (times) str += str;
else break;
}
return result;
}
function padRight(pad, str){
return (str + pad).substring(0, pad.length);
}
}
neatJSON.version = "0.5";
})(typeof exports === 'undefined' ? this : exports);
Thanks a lot #all!
Based on the previous answers, here is another variant method providing custom replacement rules as parameter:
renderJSON : function(json, rr, code, pre){
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, '\t');
}
var rules = {
def : 'color:black;',
defKey : function(match){
return '<strong>' + match + '</strong>';
},
types : [
{
name : 'True',
regex : /true/,
type : 'boolean',
style : 'color:lightgreen;'
},
{
name : 'False',
regex : /false/,
type : 'boolean',
style : 'color:lightred;'
},
{
name : 'Unicode',
regex : /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/,
type : 'string',
style : 'color:green;'
},
{
name : 'Null',
regex : /null/,
type : 'nil',
style : 'color:magenta;'
},
{
name : 'Number',
regex : /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/,
type : 'number',
style : 'color:darkorange;'
},
{
name : 'Whitespace',
regex : /\s+/,
type : 'whitespace',
style : function(match){
return '&nbsp';
}
}
],
keys : [
{
name : 'Testkey',
regex : /("testkey")/,
type : 'key',
style : function(match){
return '<h1>' + match + '</h1>';
}
}
],
punctuation : {
name : 'Punctuation',
regex : /([\,\.\}\{\[\]])/,
type : 'punctuation',
style : function(match){
return '<p>________</p>';
}
}
};
if('undefined' !== typeof jQuery){
rules = $.extend(rules, ('object' === typeof rr) ? rr : {});
}else{
for(var k in rr ){
rules[k] = rr[k];
}
}
var str = json.replace(/([\,\.\}\{\[\]]|"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var i = 0, p;
if (rules.punctuation.regex.test(match)) {
if('string' === typeof rules.punctuation.style){
return '<span style="'+ rules.punctuation.style + '">' + match + '</span>';
}else if('function' === typeof rules.punctuation.style){
return rules.punctuation.style(match);
} else{
return match;
}
}
if (/^"/.test(match)) {
if (/:$/.test(match)) {
for(i=0;i<rules.keys.length;i++){
p = rules.keys[i];
if (p.regex.test(match)) {
if('string' === typeof p.style){
return '<span style="'+ p.style + '">' + match + '</span>';
}else if('function' === typeof p.style){
return p.style(match);
} else{
return match;
}
}
}
return ('function'===typeof rules.defKey) ? rules.defKey(match) : '<span style="'+ rules.defKey + '">' + match + '</span>';
} else {
return ('function'===typeof rules.def) ? rules.def(match) : '<span style="'+ rules.def + '">' + match + '</span>';
}
} else {
for(i=0;i<rules.types.length;i++){
p = rules.types[i];
if (p.regex.test(match)) {
if('string' === typeof p.style){
return '<span style="'+ p.style + '">' + match + '</span>';
}else if('function' === typeof p.style){
return p.style(match);
} else{
return match;
}
}
}
}
});
if(true === pre)str = '<pre>' + str + '</pre>';
if(true === code)str = '<code>' + str + '</code>';
return str;
}
It works well:
console.table()
Read more here: https://developer.mozilla.org/pt-BR/docs/Web/API/Console/table
Here is a simple JSON format/color component written in React:
const HighlightedJSON = ({ json }: Object) => {
const highlightedJSON = jsonObj =>
Object.keys(jsonObj).map(key => {
const value = jsonObj[key];
let valueType = typeof value;
const isSimpleValue =
["string", "number", "boolean"].includes(valueType) || !value;
if (isSimpleValue && valueType === "object") {
valueType = "null";
}
return (
<div key={key} className="line">
<span className="key">{key}:</span>
{isSimpleValue ? (
<span className={valueType}>{`${value}`}</span>
) : (
highlightedJSON(value)
)}
</div>
);
});
return <div className="json">{highlightedJSON(json)}</div>;
};
See it working in this CodePen:
https://codepen.io/benshope/pen/BxVpjo
Hope that helps!
Couldn't find any solution that had good syntax highlighting for the console, so here's my 2p
Install & Add cli-highlight dependency
npm install cli-highlight --save
Define logjson globally
const highlight = require('cli-highlight').highlight
console.logjson = (obj) => console.log(
highlight( JSON.stringify(obj, null, 4),
{ language: 'json', ignoreIllegals: true } ));
Use
console.logjson({foo: "bar", someArray: ["string1", "string2"]});
I'd like to show my jsonAnalyze method here, it does a pretty print of the JSON structure only, but in some cases can be more usefull that printing the whole JSON.
Say you have a complex JSON like this:
let theJson = {
'username': 'elen',
'email': 'elen#test.com',
'state': 'married',
'profiles': [
{'name': 'elenLove', 'job': 'actor' },
{'name': 'elenDoe', 'job': 'spy'}
],
'hobbies': ['run', 'movies'],
'status': {
'home': {
'ownsHome': true,
'addresses': [
{'town': 'Mexico', 'address': '123 mexicoStr'},
{'town': 'Atlanta', 'address': '4B atlanta 45-48'},
]
},
'car': {
'ownsCar': true,
'cars': [
{'brand': 'Nissan', 'plate': 'TOKY-114', 'prevOwnersIDs': ['4532354531', '3454655344', '5566753422']},
{'brand': 'Benz', 'plate': 'ELEN-1225', 'prevOwnersIDs': ['4531124531', '97864655344', '887666753422']}
]
}
},
'active': true,
'employed': false,
};
Then the method will return the structure like this:
username
email
state
profiles[]
profiles[].name
profiles[].job
hobbies[]
status{}
status{}.home{}
status{}.home{}.ownsHome
status{}.home{}.addresses[]
status{}.home{}.addresses[].town
status{}.home{}.addresses[].address
status{}.car{}
status{}.car{}.ownsCar
status{}.car{}.cars[]
status{}.car{}.cars[].brand
status{}.car{}.cars[].plate
status{}.car{}.cars[].prevOwnersIDs[]
active
employed
So this is the jsonAnalyze() code:
function jsonAnalyze(obj) {
let arr = [];
analyzeJson(obj, null, arr);
return logBeautifiedDotNotation(arr);
function analyzeJson(obj, parentStr, outArr) {
let opt;
if (!outArr) {
return "no output array given"
}
for (let prop in obj) {
opt = parentStr ? parentStr + '.' + prop : prop;
if (Array.isArray(obj[prop]) && obj[prop] !== null) {
let arr = obj[prop];
if ((Array.isArray(arr[0]) || typeof arr[0] == "object") && arr[0] != null) {
outArr.push(opt + '[]');
analyzeJson(arr[0], opt + '[]', outArr);
} else {
outArr.push(opt + '[]');
}
} else if (typeof obj[prop] == "object" && obj[prop] !== null) {
outArr.push(opt + '{}');
analyzeJson(obj[prop], opt + '{}', outArr);
} else {
if (obj.hasOwnProperty(prop) && typeof obj[prop] != 'function') {
outArr.push(opt);
}
}
}
}
function logBeautifiedDotNotation(arr) {
retStr = '';
arr.map(function (item) {
let dotsAmount = item.split(".").length - 1;
let dotsString = Array(dotsAmount + 1).join(' ');
retStr += dotsString + item + '\n';
console.log(dotsString + item)
});
return retStr;
}
}
jsonAnalyze(theJson);
Douglas Crockford's JSON in JavaScript library will pretty print JSON via the stringify method.
You may also find the answers to this older question useful: How can I pretty-print JSON in (unix) shell script?
I ran into an issue today with #Pumbaa80's code. I'm trying to apply JSON syntax highlighting to data that I'm rendering in a Mithril view, so I need to create DOM nodes for everything in the JSON.stringify output.
I split the really long regex into its component parts as well.
render_json = (data) ->
# wraps JSON data in span elements so that syntax highlighting may be
# applied. Should be placed in a `whitespace: pre` context
if typeof(data) isnt 'string'
data = JSON.stringify(data, undefined, 2)
unicode = /"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?/
keyword = /\b(true|false|null)\b/
whitespace = /\s+/
punctuation = /[,.}{\[\]]/
number = /-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/
syntax = '(' + [unicode, keyword, whitespace,
punctuation, number].map((r) -> r.source).join('|') + ')'
parser = new RegExp(syntax, 'g')
nodes = data.match(parser) ? []
select_class = (node) ->
if punctuation.test(node)
return 'punctuation'
if /^\s+$/.test(node)
return 'whitespace'
if /^\"/.test(node)
if /:$/.test(node)
return 'key'
return 'string'
if /true|false/.test(node)
return 'boolean'
if /null/.test(node)
return 'null'
return 'number'
return nodes.map (node) ->
cls = select_class(node)
return Mithril('span', {class: cls}, node)
Code in context on Github here
If you're looking for a nice library to prettify json on a web page...
Prism.js is pretty good.
http://prismjs.com/
I found using JSON.stringify(obj, undefined, 2) to get the indentation, and then using prism to add a theme was a good approach.
If you're loading in JSON via an ajax call, then you can run one of Prism's utility methods to prettify
For example:
Prism.highlightAll()
Quick pretty human-readable JSON output in 1 line code (without colors):
document.documentElement.innerHTML='<pre>'+JSON.stringify(obj, null, 2)+'</pre>';
If you need this to work in a textarea the accepted solution will not work.
<textarea id='textarea'></textarea>
$("#textarea").append(formatJSON(JSON.stringify(jsonobject),true));
function formatJSON(json,textarea) {
var nl;
if(textarea) {
nl = "
";
} else {
nl = "<br>";
}
var tab = "    ";
var ret = "";
var numquotes = 0;
var betweenquotes = false;
var firstquote = false;
for (var i = 0; i < json.length; i++) {
var c = json[i];
if(c == '"') {
numquotes ++;
if((numquotes + 2) % 2 == 1) {
betweenquotes = true;
} else {
betweenquotes = false;
}
if((numquotes + 3) % 4 == 0) {
firstquote = true;
} else {
firstquote = false;
}
}
if(c == '[' && !betweenquotes) {
ret += c;
ret += nl;
continue;
}
if(c == '{' && !betweenquotes) {
ret += tab;
ret += c;
ret += nl;
continue;
}
if(c == '"' && firstquote) {
ret += tab + tab;
ret += c;
continue;
} else if (c == '"' && !firstquote) {
ret += c;
continue;
}
if(c == ',' && !betweenquotes) {
ret += c;
ret += nl;
continue;
}
if(c == '}' && !betweenquotes) {
ret += nl;
ret += tab;
ret += c;
continue;
}
if(c == ']' && !betweenquotes) {
ret += nl;
ret += c;
continue;
}
ret += c;
} // i loop
return ret;
}
This is nice:
https://github.com/mafintosh/json-markup from mafintosh
const jsonMarkup = require('json-markup')
const html = jsonMarkup({hello:'world'})
document.querySelector('#myElem').innerHTML = html
HTML
<link ref="stylesheet" href="style.css">
<div id="myElem></div>
Example stylesheet can be found here
https://raw.githubusercontent.com/mafintosh/json-markup/master/style.css
To highlight and beautify it in HTML using Bootstrap:
function prettifyJson(json, prettify) {
if (typeof json !== 'string') {
if (prettify) {
json = JSON.stringify(json, undefined, 4);
} else {
json = JSON.stringify(json);
}
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
function(match) {
let cls = "<span>";
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = "<span class='text-danger'>";
} else {
cls = "<span>";
}
} else if (/true|false/.test(match)) {
cls = "<span class='text-primary'>";
} else if (/null/.test(match)) {
cls = "<span class='text-info'>";
}
return cls + match + "</span>";
}
);
}
based on #user123444555621, just slightly more modern.
const clsMap = [
[/^".*:$/, "key"],
[/^"/, "string"],
[/true|false/, "boolean"],
[/null/, "key"],
[/.*/, "number"],
]
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span class="${clsMap.find(([regex]) => regex.test(match))[1]}">${match}</span>`);
you can also specify the colors inside js (no CSS needed)
const clsMap = [
[/^".*:$/, "red"],
[/^"/, "green"],
[/true|false/, "blue"],
[/null/, "magenta"],
[/.*/, "darkorange"],
]
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span style="color:${clsMap.find(([regex]) => regex.test(match))[1]}">${match}</span>`);
and a version with less regex
const clsMap = [
[match => match.startsWith('"') && match.endsWith(':'), "red"],
[match => match.startsWith('"'), "green"],
[match => match === "true" || match === "false" , "blue"],
[match => match === "null", "magenta"],
[() => true, "darkorange"],
];
const syntaxHighlight = obj => JSON.stringify(obj, null, 4)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, match => `<span style="color:${clsMap.find(([fn]) => fn(match))[1]}">${match}</span>`);
it's for Laravel, Codeigniter
Html:
<pre class="jsonPre"> </pre>
Controller: Return the JSON value from the controller as like as
return json_encode($data, JSON_PRETTY_PRINT);
In script:
<script> $('.jsonPre').html(result); </script>
result will be
Here is how you can print without using native function.
function pretty(ob, lvl = 0) {
let temp = [];
if(typeof ob === "object"){
for(let x in ob) {
if(ob.hasOwnProperty(x)) {
temp.push( getTabs(lvl+1) + x + ":" + pretty(ob[x], lvl+1) );
}
}
return "{\n"+ temp.join(",\n") +"\n" + getTabs(lvl) + "}";
}
else {
return ob;
}
}
function getTabs(n) {
let c = 0, res = "";
while(c++ < n)
res+="\t";
return res;
}
let obj = {a: {b: 2}, x: {y: 3}};
console.log(pretty(obj));
/*
{
a: {
b: 2
},
x: {
y: 3
}
}
*/
The simplest way to display an object for debugging purposes:
console.log("data",data) // lets you unfold the object manually
If you want to display the object in the DOM, you should consider that it could contain strings that would be interpreted as HTML. Therefore, you need to do some escaping...
var s = JSON.stringify(data,null,2) // format
var e = new Option(s).innerHTML // escape
document.body.insertAdjacentHTML('beforeend','<pre>'+e+'</pre>') // display
<!-- here is a complete example pretty print with more space between lines-->
<!-- be sure to pass a json string not a json object -->
<!-- use line-height to increase or decrease spacing between json lines -->
<style type="text/css">
.preJsonTxt{
font-size: 18px;
text-overflow: ellipsis;
overflow: hidden;
line-height: 200%;
}
.boxedIn{
border: 1px solid black;
margin: 20px;
padding: 20px;
}
</style>
<div class="boxedIn">
<h3>Configuration Parameters</h3>
<pre id="jsonCfgParams" class="preJsonTxt">{{ cfgParams }}</pre>
</div>
<script language="JavaScript">
$( document ).ready(function()
{
$(formatJson);
<!-- this will do a pretty print on the json cfg params -->
function formatJson() {
var element = $("#jsonCfgParams");
var obj = JSON.parse(element.text());
element.html(JSON.stringify(obj, undefined, 2));
}
});
</script>

How to join a string in javascript based on a regex or if string starts with some value?

for instance I have this string:
013227004871996 300234060903250 013227003498171 013227003493834 300234010640390
013227003512963 300234061401690 013227004865956 013226009142122 013227008391574
300234061405690 013227003400573 300234061404700 013227003501479 013227003394495
013227004876284 300234061349230 013227004876284 013227004862011
and what I want to happen is that to separate the entry if it encounters 01322, so for instance in the example it will have array[0] = 013227004871996 300234060903250, array[1] = 013227003498171,
array[2] = 013227003493834
so basically I want to split it if the next entry starts with "013227".
This seems to work. Im matching everything that starts and is followed by 013227. Then I'm matching the last segment with .+
str.match(/013227.+?(?=013227)|.+/g)
Or even better:
str.split(/(?=013227)/)
var numbersStr = "013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 013227004876284 300234061349230 013227004876284 013227004862011";
var pattern = new RegExp('01322[\\d]+');
var numbersArr = numbersStr.split(' ');
var numbersArrLength = numbersArr.length - 1;
for (var i = numbersArrLength; i >= 0; i--) {
if (!pattern.test(numbersArr[i])) {
numbersArr.splice(i, 1);
}
}
var separator = '01322';
"013227004871996 300234060903250 013227003498171 013227003493834 300234010640390"
.split(separator)
.filter(function(item){
return item;
}).map(function(item){
return separator + item;
})
var s = "013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 "
+ "013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 "
+ "300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 "
+ "013227004876284 300234061349230 013227004876284 013227004862011";
var sp = s.split(" ");
var res = new Array();
var count=0;
sp.forEach(function(a) {
if(a.search("01322") === 0) {
if(res[count] === undefined) {
res[count] = a;
} else {
++count;
res[count] = a;
}
} else {
if(res[count] === undefined) {
res[count] = a;
} else {
res[count]+=" "+a;
}
}
});
console.log(res);
[ '013227004871996 300234060903250',
'013227003498171',
'013227003493834 300234010640390',
'013227003512963 300234061401690',
'013227004865956',
'013226009142122',
'013227008391574 300234061405690',
'013227003400573 300234061404700',
'013227003501479',
'013227003394495',
'013227004876284 300234061349230',
'013227004876284',
'013227004862011' ]
try this
function niceslice( string, delimiter ){
var result = string.split(delimiter);
for(var i = 1; i < result.length; i++){
result[i] = delimiter + result[i];
}
return result;
}
take note that this will not eliminate spaces in your example (but should be easily built in)
example usage
var str = 'anton albert andrew';
var output = niceslice( str, 'a' );
console.log( output ); // returns ['', 'anton ', 'albert ', 'andrew']
or in your case
var str = '013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 013227004876284 300234061349230 013227004876284 013227004862011';
var output = niceslice( str, '013227' );

How to replace all capture groups if it is generated dynamically?

Consider the following code:
function Matcher(source, search) {
var opts = search.split('');
for (var i = 0; i < opts.length; i++) {
opts[i] = '(' + opts[i] + ')';
}
opts = opts.join('.*');
var regexp = new RegExp(opts, 'gi');
source = source.replace(regexp, function () {
console.log(arguments);
return arguments[1];
});
return source;
}
You call the function passing the source as the first parameter and what you need to match as the second one.
What i need is to replace all capture groups with a bold tag around the coincidence.
As an example, consider the following:
var patt = /m([a-z0-9\-_]*?)r([a-z0-9\-_]*?)i([a-z0-9\-_]*?)e([a-z0-9\-_]*\.[a-z]+)/gi;
var newFileName = fileName.replace(patt, "<strong>m</strong>$1<strong>r</strong>$2<strong>i</strong>$3<strong>e</strong>$4");
This code is an answer from Terry on my previous question but the problem here is that you need to know exactly what you want to replace, and i need it dynamically.
Any thoughts?
It seems like you're creating the pattern the wrong way round. Instead of building a(.*?)b(.*?)c, you create (a).*(b).*(c) - with the capturing groups around the parts you already know. Better:
function wrapEachLetter(source, search, tag) {
var opts = search.split('');
tag = tag || "strong";
return source.replace(new RegExp(opts.join("(.*?)"), 'gi'), function () {
var str = '<'+tag+'>'+opts[0]+'</'+tag+'>';
for (var i=1; i<opts.length; i++)
str += arguments[i] + '<'+tag+'>'+opts[i]+'</'+tag+'>';
return str;
});
}
Example:
> wrapEachLetter("testExampleString", "tex", "b")
"<b>t<b><b>e<b>stE<b>x<b>ampleString"
Capture the delimiters too and then process only even subgroups, leaving odd ones as is:
s = "ABC---DEF---HIJ"
re = /(\w+)(.*?)(\w+)(.*?)(\w+)/
s.replace(re, function() {
return [].slice.call(arguments, 1, -2).map(function(a, n) {
return n & 1 ? a : "<strong>" + a + "</strong>"
}).join("")
})
> "<strong>ABC</strong>---<strong>DEF</strong>---<strong>HIJ</strong>"
However, if your goal is to highlight only individual characters, it's much simpler this way:
str = "myfile.js"
letters = "mis"
re = new RegExp("[" + letters + "]", "gi")
str.replace(re, "<b>$&</b>")
> "<b>m</b>yf<b>i</b>le.j<b>s</b>"
or, without regular expressions:
str = "myfile.js"
letters = "mis"
str.split("").map(function(s) {
return letters.indexOf(s) >= 0 ? "<b>" + s + "</b>" : s
}).join("")
> "<b>m</b>yf<b>i</b>le.j<b>s</b>"
var input = "aBcDeFgHiJk",
match = 'be';
str = '',
reg = '',
i = 0;
function escapeRegExp(c) {
return c.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
// /(.*)(b)(.*)(e)(.*)/gi
// '$1<b>$2</b>$3<b>$4</b>$5'
for (var c in match) {
if (i == 0) {
str += '$' + ++i;
reg += '(.*)';
i++;
}
str += '<b>$' + i++ + '</b>$' + i++;
reg += '(' + escapeRegExp(match[c]) + ')(.*)';
}
alert(input.replace(new RegExp(reg, 'ig'), str)); // <- a<b>B</b>cD<b>e</b>FgHiJk

Categories

Resources