Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 807ef4d90048a5f150c10fd8a722ef4758589154 @getify committed Jun 22, 2010
Showing with 142 additions and 0 deletions.
  1. +15 −0 README.txt
  2. +11 −0 json2.js
  3. +60 −0 minify.json.js
  4. +56 −0 test.minify.html
15 README.txt
@@ -0,0 +1,15 @@
+/*! JSON.minify()
+ v0.1 (c) Kyle Simpson
+ MIT License
+*/
+
+JSON.minify() minifies blocks of JSON by removing all whitespace *and* comments.
+
+JSON.parse() does not consider JSON with comments to be valid and parseable. So,
+the intended usage is to minify development-friendly JSON (with comments) to
+valid JSON before parsing, such as:
+
+JSON.parse(JSON.minify(str));
+
+Now you can maintain development-friendly JSON documents, but minify them before
+parsing or before transmitting them over-the-wire.
11 json2.js
@@ -0,0 +1,11 @@
+/*!
+ http://www.JSON.org/json2.js
+ 2009-09-29
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+*/
+if(!this.JSON){this.JSON={}}(function(){function l(c){return c<10?'0'+c:c}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(c){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(c){return this.valueOf()}}var o=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,p=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,h,m,r={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},j;function q(a){p.lastIndex=0;return p.test(a)?'"'+a.replace(p,function(c){var f=r[c];return typeof f==='string'?f:'\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function n(c,f){var a,e,d,i,k=h,g,b=f[c];if(b&&typeof b==='object'&&typeof b.toJSON==='function'){b=b.toJSON(c)}if(typeof j==='function'){b=j.call(f,c,b)}switch(typeof b){case'string':return q(b);case'number':return isFinite(b)?String(b):'null';case'boolean':case'null':return String(b);case'object':if(!b){return'null'}h+=m;g=[];if(Object.prototype.toString.apply(b)==='[object Array]'){i=b.length;for(a=0;a<i;a+=1){g[a]=n(a,b)||'null'}d=g.length===0?'[]':h?'[\n'+h+g.join(',\n'+h)+'\n'+k+']':'['+g.join(',')+']';h=k;return d}if(j&&typeof j==='object'){i=j.length;for(a=0;a<i;a+=1){e=j[a];if(typeof e==='string'){d=n(e,b);if(d){g.push(q(e)+(h?': ':':')+d)}}}}else{for(e in b){if(Object.hasOwnProperty.call(b,e)){d=n(e,b);if(d){g.push(q(e)+(h?': ':':')+d)}}}}d=g.length===0?'{}':h?'{\n'+h+g.join(',\n'+h)+'\n'+k+'}':'{'+g.join(',')+'}';h=k;return d}}if(typeof JSON.stringify!=='function'){JSON.stringify=function(c,f,a){var e;h='';m='';if(typeof a==='number'){for(e=0;e<a;e+=1){m+=' '}}else if(typeof a==='string'){m=a}j=f;if(f&&typeof f!=='function'&&(typeof f!=='object'||typeof f.length!=='number')){throw new Error('JSON.stringify');}return n('',{'':c})}}if(typeof JSON.parse!=='function'){JSON.parse=function(i,k){var g;function b(c,f){var a,e,d=c[f];if(d&&typeof d==='object'){for(a in d){if(Object.hasOwnProperty.call(d,a)){e=b(d,a);if(e!==undefined){d[a]=e}else{delete d[a]}}}}return k.call(c,f,d)}o.lastIndex=0;if(o.test(i)){i=i.replace(o,function(c){return'\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(i.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){g=eval('('+i+')');return typeof k==='function'?b({'':g},''):g}throw new SyntaxError('JSON.parse');}}}());
60 minify.json.js
@@ -0,0 +1,60 @@
+/*! JSON.minify()
+ v0.1 (c) Kyle Simpson
+ MIT License
+*/
+
+(function(global){
+ if (typeof global.JSON == "undefined" || !global.JSON) {
+ global.JSON = {};
+ }
+
+ global.JSON.minify = function(str) {
+
+ var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
+ in_string = false,
+ in_multiline_comment = false,
+ in_singleline_comment = false,
+ tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
+ ;
+
+ tokenizer.lastIndex = 0;
+
+ while (tmp = tokenizer.exec(str)) {
+ lc = RegExp.leftContext;
+ rc = RegExp.rightContext;
+ if (!in_multiline_comment && !in_singleline_comment) {
+ tmp2 = lc.substring(from);
+ if (!in_string) {
+ tmp2 = tmp2.replace(/(\n|\r|\s)*/g,"");
+ }
+ new_str[ns++] = tmp2;
+ }
+ from = tokenizer.lastIndex;
+
+ if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
+ tmp2 = lc.match(/(\\)*$/);
+ if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string
+ in_string = !in_string;
+ }
+ from--; // include " character in next catch
+ }
+ else if (tmp[0] == "/*" && !in_string && !in_multiline_comment && !in_singleline_comment) {
+ in_multiline_comment = true;
+ }
+ else if (tmp[0] == "*/" && !in_string && in_multiline_comment && !in_singleline_comment) {
+ in_multiline_comment = false;
+ }
+ else if (tmp[0] == "//" && !in_string && !in_multiline_comment && !in_singleline_comment) {
+ in_singleline_comment = true;
+ }
+ else if ((tmp[0] == "\n" || tmp[0] == "\r") && !in_string && !in_multiline_comment && in_singleline_comment) {
+ in_singleline_comment = false;
+ }
+ else if (!in_multiline_comment && !in_singleline_comment && !(/\n|\r|\s/.test(tmp[0]))) {
+ new_str[ns++] = tmp[0];
+ }
+ }
+ new_str[ns++] = rc;
+ return new_str.join("");
+ };
+})(this);
56 test.minify.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Test JSON.minify()</title>
+
+<script type="text/javascript" src="json2.js"></script>
+<script type="text/javascript" src="minify.json.js"></script>
+
+</head>
+
+<body>
+<h1>Test JSON.minify()</h1>
+
+<p>test #1</p>
+<textarea id="orig_json1" cols="50" rows="12">
+
+{"/*":"*/","//":"",/*"//"*/"/*/"://
+"//"}
+
+</textarea>
+<p>result #1</p>
+<textarea id="new_json1" cols="50" rows="12"></textarea>
+
+
+<p>test #2</p>
+<textarea id="orig_json2" cols="50" rows="12">
+/*
+this is a
+multi line comment */{
+
+"foo"
+:
+ "bar/*"// something
+ , "b\"az":/*
+something else */"blah"
+
+}
+</textarea>
+<p>result #2</p>
+<textarea id="new_json2" cols="50" rows="12"></textarea>
+
+
+
+<script type="text/javascript">
+
+var old;
+for (var i=1; i<=2; i++) {
+ old = document.getElementById("orig_json"+i).value;
+ document.getElementById("new_json"+i).value = JSON.minify(old);
+}
+
+</script>
+
+</body>
+</html>

3 comments on commit 807ef4d

@jimbojw

Re: README.txt

I think people are having trouble with the line "JSON.minify() minifies blocks of JSON by removing all whitespace and comments." Sticklers for standards will say that if the input has comments, then it's not technically JSON. They're right! But it's kind of like getting all riled up over sneaked vs snuck - as long as people understand what you mean, the exact wording doesn't matter.

So, to get those people to move along, you could change the text to this:

"JSON.minify() minifies blocks of JSON-like inupt by removing all whitespace and comments."

This statement is true to the standard, and still gets your point across. Now, of course, you're under no obligation to make this change. I think that the people complaining that JSON shouldn't have comments are focusing their energies on the wrong things.

@getify
Owner

thanks for the suggestion. changed. :)

@jimbojw

Good work, by the way, on the minifier - I think you're doing the world a service. It's painfully obvious that JSON.parse's rejection of comments is a detriment to development environments, where the comments are particularly helpful. A JSON comment stripper in JavaScript was clearly needed - thanks!

Please sign in to comment.