vkbeautify.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
  3. *
  4. * Version - 0.99.00.beta
  5. * Copyright (c) 2012 Vadim Kiryukhin
  6. * vkiryukhin @ gmail.com
  7. * http://www.eslinstructor.net/vkbeautify/
  8. *
  9. * Dual licensed under the MIT and GPL licenses:
  10. * http://www.opensource.org/licenses/mit-license.php
  11. * http://www.gnu.org/licenses/gpl.html
  12. *
  13. * Pretty print
  14. *
  15. * vkbeautify.xml(text [,indent_pattern]);
  16. * vkbeautify.json(text [,indent_pattern]);
  17. * vkbeautify.css(text [,indent_pattern]);
  18. * vkbeautify.sql(text [,indent_pattern]);
  19. *
  20. * @text - String; text to beatufy;
  21. * @indent_pattern - Integer | String;
  22. * Integer: number of white spaces;
  23. * String: character string to visualize indentation ( can also be a set of white spaces )
  24. * Minify
  25. *
  26. * vkbeautify.xmlmin(text [,preserve_comments]);
  27. * vkbeautify.jsonmin(text);
  28. * vkbeautify.cssmin(text [,preserve_comments]);
  29. * vkbeautify.sqlmin(text);
  30. *
  31. * @text - String; text to minify;
  32. * @preserve_comments - Bool; [optional];
  33. * Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
  34. *
  35. * Examples:
  36. * vkbeautify.xml(text); // pretty print XML
  37. * vkbeautify.json(text, 4 ); // pretty print JSON
  38. * vkbeautify.css(text, '. . . .'); // pretty print CSS
  39. * vkbeautify.sql(text, '----'); // pretty print SQL
  40. *
  41. * vkbeautify.xmlmin(text, true);// minify XML, preserve comments
  42. * vkbeautify.jsonmin(text);// minify JSON
  43. * vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
  44. * vkbeautify.sqlmin(text);// minify SQL
  45. *
  46. */
  47. (function() {
  48. function createShiftArr(step) {
  49. var space = ' ';
  50. if ( isNaN(parseInt(step)) ) { // argument is string
  51. space = step;
  52. } else { // argument is integer
  53. switch(step) {
  54. case 1: space = ' '; break;
  55. case 2: space = ' '; break;
  56. case 3: space = ' '; break;
  57. case 4: space = ' '; break;
  58. case 5: space = ' '; break;
  59. case 6: space = ' '; break;
  60. case 7: space = ' '; break;
  61. case 8: space = ' '; break;
  62. case 9: space = ' '; break;
  63. case 10: space = ' '; break;
  64. case 11: space = ' '; break;
  65. case 12: space = ' '; break;
  66. }
  67. }
  68. var shift = ['\n']; // array of shifts
  69. for(ix=0;ix<100;ix++){
  70. shift.push(shift[ix]+space);
  71. }
  72. return shift;
  73. }
  74. function vkbeautify(){
  75. this.step = ' '; // 4 spaces
  76. this.shift = createShiftArr(this.step);
  77. };
  78. vkbeautify.prototype.xml = function(text,step) {
  79. var ar = text.replace(/>\s{0,}</g,"><")
  80. .replace(/</g,"~::~<")
  81. .replace(/\s*xmlns\:/g,"~::~xmlns:")
  82. .replace(/\s*xmlns\=/g,"~::~xmlns=")
  83. .split('~::~'),
  84. len = ar.length,
  85. inComment = false,
  86. deep = 0,
  87. str = '',
  88. ix = 0,
  89. shift = step ? createShiftArr(step) : this.shift;
  90. for(ix=0;ix<len;ix++) {
  91. // start comment or <![CDATA[...]]> or <!DOCTYPE //
  92. if(ar[ix].search(/<!/) > -1) {
  93. str += shift[deep]+ar[ix];
  94. inComment = true;
  95. // end comment or <![CDATA[...]]> //
  96. if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) {
  97. inComment = false;
  98. }
  99. } else
  100. // end comment or <![CDATA[...]]> //
  101. if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) {
  102. str += ar[ix];
  103. inComment = false;
  104. } else
  105. // <elm></elm> //
  106. if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) &&
  107. /^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) {
  108. str += ar[ix];
  109. if(!inComment) deep--;
  110. } else
  111. // <elm> //
  112. if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) {
  113. str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];
  114. } else
  115. // <elm>...</elm> //
  116. if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
  117. str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
  118. } else
  119. // </elm> //
  120. if(ar[ix].search(/<\//) > -1) {
  121. str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];
  122. } else
  123. // <elm/> //
  124. if(ar[ix].search(/\/>/) > -1 ) {
  125. str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
  126. } else
  127. // <? xml ... ?> //
  128. if(ar[ix].search(/<\?/) > -1) {
  129. str += shift[deep]+ar[ix];
  130. } else
  131. // xmlns //
  132. if( ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) {
  133. str += shift[deep]+ar[ix];
  134. }
  135. else {
  136. str += ar[ix];
  137. }
  138. }
  139. return (str[0] == '\n') ? str.slice(1) : str;
  140. }
  141. vkbeautify.prototype.json = function(text,step) {
  142. var step = step ? step : this.step;
  143. if (typeof JSON === 'undefined' ) return text;
  144. if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step);
  145. if ( typeof text === "object" ) return JSON.stringify(text, null, step);
  146. return text; // text is not string nor object
  147. }
  148. vkbeautify.prototype.css = function(text, step) {
  149. var ar = text.replace(/\s{1,}/g,' ')
  150. .replace(/\{/g,"{~::~")
  151. .replace(/\}/g,"~::~}~::~")
  152. .replace(/\;/g,";~::~")
  153. .replace(/\/\*/g,"~::~/*")
  154. .replace(/\*\//g,"*/~::~")
  155. .replace(/~::~\s{0,}~::~/g,"~::~")
  156. .split('~::~'),
  157. len = ar.length,
  158. deep = 0,
  159. str = '',
  160. ix = 0,
  161. shift = step ? createShiftArr(step) : this.shift;
  162. for(ix=0;ix<len;ix++) {
  163. if( /\{/.exec(ar[ix])) {
  164. str += shift[deep++]+ar[ix];
  165. } else
  166. if( /\}/.exec(ar[ix])) {
  167. str += shift[--deep]+ar[ix];
  168. } else
  169. if( /\*\\/.exec(ar[ix])) {
  170. str += shift[deep]+ar[ix];
  171. }
  172. else {
  173. str += shift[deep]+ar[ix];
  174. }
  175. }
  176. return str.replace(/^\n{1,}/,'');
  177. }
  178. //----------------------------------------------------------------------------
  179. function isSubquery(str, parenthesisLevel) {
  180. return parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
  181. }
  182. function split_sql(str, tab) {
  183. return str.replace(/\s{1,}/g," ")
  184. .replace(/ AND /ig,"~::~"+tab+tab+"AND ")
  185. .replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
  186. .replace(/ CASE /ig,"~::~"+tab+"CASE ")
  187. .replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
  188. .replace(/ END /ig,"~::~"+tab+"END ")
  189. .replace(/ FROM /ig,"~::~FROM ")
  190. .replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
  191. .replace(/ HAVING /ig,"~::~HAVING ")
  192. //.replace(/ SET /ig," SET~::~")
  193. .replace(/ IN /ig," IN ")
  194. .replace(/ JOIN /ig,"~::~JOIN ")
  195. .replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
  196. .replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
  197. .replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
  198. .replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")
  199. .replace(/ ON /ig,"~::~"+tab+"ON ")
  200. .replace(/ OR /ig,"~::~"+tab+tab+"OR ")
  201. .replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
  202. .replace(/ OVER /ig,"~::~"+tab+"OVER ")
  203. .replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
  204. .replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")
  205. .replace(/ THEN /ig," THEN~::~"+tab+"")
  206. .replace(/ UNION /ig,"~::~UNION~::~")
  207. .replace(/ USING /ig,"~::~USING ")
  208. .replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
  209. .replace(/ WHERE /ig,"~::~WHERE ")
  210. .replace(/ WITH /ig,"~::~WITH ")
  211. //.replace(/\,\s{0,}\(/ig,",~::~( ")
  212. //.replace(/\,/ig,",~::~"+tab+tab+"")
  213. .replace(/ ALL /ig," ALL ")
  214. .replace(/ AS /ig," AS ")
  215. .replace(/ ASC /ig," ASC ")
  216. .replace(/ DESC /ig," DESC ")
  217. .replace(/ DISTINCT /ig," DISTINCT ")
  218. .replace(/ EXISTS /ig," EXISTS ")
  219. .replace(/ NOT /ig," NOT ")
  220. .replace(/ NULL /ig," NULL ")
  221. .replace(/ LIKE /ig," LIKE ")
  222. .replace(/\s{0,}SELECT /ig,"SELECT ")
  223. .replace(/\s{0,}UPDATE /ig,"UPDATE ")
  224. .replace(/ SET /ig," SET ")
  225. .replace(/~::~{1,}/g,"~::~")
  226. .split('~::~');
  227. }
  228. vkbeautify.prototype.sql = function(text,step) {
  229. var ar_by_quote = text.replace(/\s{1,}/g," ")
  230. .replace(/\'/ig,"~::~\'")
  231. .split('~::~'),
  232. len = ar_by_quote.length,
  233. ar = [],
  234. deep = 0,
  235. tab = this.step,//+this.step,
  236. inComment = true,
  237. inQuote = false,
  238. parenthesisLevel = 0,
  239. str = '',
  240. ix = 0,
  241. shift = step ? createShiftArr(step) : this.shift;;
  242. for(ix=0;ix<len;ix++) {
  243. if(ix%2) {
  244. ar = ar.concat(ar_by_quote[ix]);
  245. } else {
  246. ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
  247. }
  248. }
  249. len = ar.length;
  250. for(ix=0;ix<len;ix++) {
  251. parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
  252. if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
  253. ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
  254. }
  255. if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix])) {
  256. ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
  257. }
  258. if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
  259. deep++;
  260. str += shift[deep]+ar[ix];
  261. } else
  262. if( /\'/.exec(ar[ix]) ) {
  263. if(parenthesisLevel<1 && deep) {
  264. deep--;
  265. }
  266. str += ar[ix];
  267. }
  268. else {
  269. str += shift[deep]+ar[ix];
  270. if(parenthesisLevel<1 && deep) {
  271. deep--;
  272. }
  273. }
  274. var junk = 0;
  275. }
  276. str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
  277. return str;
  278. }
  279. vkbeautify.prototype.xmlmin = function(text, preserveComments) {
  280. var str = preserveComments ? text
  281. : text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"")
  282. .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
  283. return str.replace(/>\s{0,}</g,"><");
  284. }
  285. vkbeautify.prototype.jsonmin = function(text) {
  286. if (typeof JSON === 'undefined' ) return text;
  287. return JSON.stringify(JSON.parse(text), null, 0);
  288. }
  289. vkbeautify.prototype.cssmin = function(text, preserveComments) {
  290. var str = preserveComments ? text
  291. : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ;
  292. return str.replace(/\s{1,}/g,' ')
  293. .replace(/\{\s{1,}/g,"{")
  294. .replace(/\}\s{1,}/g,"}")
  295. .replace(/\;\s{1,}/g,";")
  296. .replace(/\/\*\s{1,}/g,"/*")
  297. .replace(/\*\/\s{1,}/g,"*/");
  298. }
  299. vkbeautify.prototype.sqlmin = function(text) {
  300. return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")");
  301. }
  302. window.vkbeautify = new vkbeautify();
  303. })();