UNPKG

prettydiff2

Version:

Latest version of Pretty Diff for use in Atom Beautify to field test it in the wild before moving on to Pretty Diff 3.

965 lines (960 loc) 387 kB
/*prettydiff.com topcoms:true,insize:4,inchar:" ",vertical:true */ /*jshint laxbreak: true*/ /*global __dirname, ace, define, global, module, process, require*/ /* Special thanks to Harry Whitfield for assistance in providing test cases. jspretty is written by Austin Cheney on 2 Nov 2012 Please see the license.txt file associated with the Pretty Diff application for license information. ----------------------------------------------------------------------- */ (function jspretty_init() { "use strict"; var jspretty = function jspretty_(options) { var sourcemap = [ 0, "" ], json = (options.lang === "json"), globalerror = "", // all data that is created from the tokization process is stored in the // following four arrays: token, types, level, and lines. All of this data // passes from the tokenization process to be analyzed by the algorithm token = [], //stores parsed tokens types = [], //parallel array that describes the tokens level = [], //parallel array that list indentation per token lines = [], //used to preserve empty lines depth = [], //describes the token's current container begin = [], //index where current container starts globals = [], //which variables are declared globals // meta used to find scope and variables for jsscope these values are assigned in parallel to the other arrays //* irrelevant tokens are represented with an empty string // * first '(' following 'function' is token index number of function's closing // curly brace //* variables are represented with the value 'v' //* the closing brace of a function is an array of variables meta = [], // lists a number at the opening paren of a function that points to the token // index of the function's closing curly brace. At the closing curly brace // index this array stores an array indicating the names of variables declared // in the current function for coloring by function depth in jsscope. This // array is ignored if jsscope is false varlist = [], // groups variables from a variable list into a child array as well as // properties of objects. This array for adding extra space so that the "=" // following declared variables of a variable list is vertically aligned and // likewise of the ":" with object properties markupvar = [], // notes a token index of a JSX markup tag assigned to JavaScript variable. This // is necessary for indentation apart from syntactical factors. error = [], news = 0, scolon = 0, // counts uncessary use of 'new' keyword variables j, k, l, m, n, o, p, q, and w // are used as various counters for the reporting only. These variables do not // store any tokens and are not used in the algorithm j counts line comments stats = { comma : 0, commentBlock: { chars: 0, token: 0 }, commentLine : { chars: 0, token: 0 }, container : 0, number : { chars: 0, token: 0 }, operator : { chars: 0, token: 0 }, regex : { chars: 0, token: 0 }, semicolon : 0, server : { chars: 0, token: 0 }, space : { newline: 0, other : 0, space : 0, tab : 0 }, string : { chars: 0, quote: 0, token: 0 }, word : { chars: 0, token: 0 } }, result = "", objsortop = false, verticalop = false, originalSize = options.source.length, lf = (options.crlf === true || options.crlf === "true") ? "\r\n" : "\n", extlib = function jspretty__extlib(ops) { var item = (ops === undefined) ? global .prettydiff .markuppretty(ops) : global .prettydiff .markuppretty(options); if (options.nodeasync === true) { if (globalerror === "") { globalerror = item[1]; } return item[0]; } return item; }; (function jspretty__options() { var styleguide = {}, brace_style = {}; if (options.mode === "beautify" || options.mode === "diff" || options.mode === "minify") { objsortop = ( options.objsort === true || options.objsort === "true" || options.objsort === "all" || options.objsort === "js" || options.objsort === "jsonly" ); verticalop = ( options.vertical === true || options.vertical === "true" || options.vertical === "all" || options.vertical === "js" ); } options.source = ( typeof options.source === "string" && options.source.length > 0 ) ? options .source .replace(/\r\n?/g, "\n") : "Error: no source code supplied to jspretty!"; if (options.mode !== "analysis" && options.source.indexOf("Error: no") < 0) { options.source = options.source + " "; } options.titanium = (options.titanium === true || options.titanium === "true") ? (function jspretty__options_titanium() { options.correct = false; options.titanium = true; token.push("x{"); types.push("start"); lines.push(0); depth.push("global"); begin.push(0); return true; }()) : false; styleguide.airbnb = function jspretty__options_styleairbnb() { options.bracepadding = true; options.correct = true; options.endcomma = "always"; options.inchar = " "; options.insize = 2; options.preserve = 1; options.quoteConvert = "single"; options.varword = "each"; options.wrap = 80; }; styleguide.crockford = function jspretty__options_stylecrockford() { options.bracepadding = false; options.correct = true; options.elseline = false; options.endcomma = "never"; options.inchar = " "; options.insize = 4; options.nocaseindent = true; options.nochainindent = false; options.space = true; options.varword = "each"; verticalop = false; }; styleguide.google = function jspretty__options_stylegoogle() { options.correct = true; options.inchar = " "; options.insize = 4; options.preserve = 1; options.quoteConvert = "single"; verticalop = false; options.wrap = -1; }; styleguide.grunt = function jspretty__options_stylegrunt() { options.inchar = " "; options.insize = 2; options.quoteConvert = "single"; options.varword = "each"; }; styleguide.jquery = function jspretty__options_stylejquery() { options.bracepadding = true; options.correct = true; options.inchar = "\u0009"; options.insize = 1; options.quoteConvert = "double"; options.varword = "each"; options.wrap = 80; }; styleguide.jslint = styleguide.crockford; styleguide.mrdoobs = function jspretty__options_stylemrdoobs() { options.braceline = true; options.bracepadding = true; options.correct = true; options.inchar = "\u0009"; options.insize = 1; verticalop = false; }; styleguide.mediawiki = function jspretty__options_stylemediawiki() { options.bracepadding = true; options.correct = true; options.inchar = "\u0009"; options.insize = 1; options.preserve = 1; options.quoteConvert = "single"; options.space = false; options.wrap = 80; }; styleguide.meteor = function jspretty__options_stylemeteor() { options.correct = true; options.inchar = " "; options.insize = 2; options.wrap = 80; }; styleguide.yandex = function jspretty__options_styleyandex() { options.bracepadding = false; options.correct = true; options.quoteConvert = "single"; options.varword = "each"; verticalop = false; }; brace_style.collapse = function jspretty__options_collapse() { options.braceline = false; options.bracepadding = false; options.braces = false; options.formatObject = "indent"; options.neverflatten = true; }; brace_style["collapse-preserve-inline"] = function jspretty__options_collapseInline() { options.braceline = false; options.bracepadding = true; options.braces = false; options.formatObject = "inline"; options.neverflatten = false; }; brace_style.expand = function jspretty__options_expand() { options.braceline = false; options.bracepadding = false; options.braces = true; options.formatObject = "indent"; options.neverflatten = true; }; if (styleguide[options.styleguide] !== undefined) { styleguide[options.styleguide](); } if (brace_style[options.brace_style] !== undefined) { brace_style[options.brace_style](); } if (json === true) { options.wrap = 0; } }()); if (options.source === "Error: no source code supplied to jspretty!") { return options.source; } (function jspretty__tokenize() { var a = 0, b = options.source.length, c = options .source .split(""), ltoke = "", ltype = "", lword = [], brace = [], pword = [], lengtha = 0, lengthb = 0, wordTest = -1, paren = -1, classy = [], depthlist = [ ["global", 0] ], tempstore = [], pdepth = [], //depth and status of templateStrings templateString = [], //identify variable declarations vart = { count: [], index: [], word : [], len : -1 }, //operations for start types: (, [, { start = function jspretty__tokenize_startInit() { return; }, //peek at whats up next nextchar = function jspretty__tokenize_nextchar(len, current) { var cc = 0, dd = "", front = (current === true) ? a : a + 1; if (typeof len !== "number" || len < 1) { len = 1; } if (c[a] === "/") { if (c[a + 1] === "/") { dd = "\n"; } else if (c[a + 1] === "*") { dd = "/"; } } for (cc = front; cc < b; cc = cc + 1) { if ((/\s/).test(c[cc]) === false) { if (c[cc] === "/") { if (dd === "") { if (c[cc + 1] === "/") { dd = "\n"; } else if (c[cc + 1] === "*") { dd = "/"; } } else if (dd === "/" && c[cc - 1] === "*") { dd = ""; } } if (dd === "" && c[cc - 1] + c[cc] !== "*/") { return c .slice(cc, cc + len) .join(""); } } else if (dd === "\n" && c[cc] === "\n") { dd = ""; } } return ""; }, //cleans up improperly applied ASI asifix = function jspretty__tokenize_asifix() { var len = types.length; do { len = len - 1; } while ( len > 0 && (types[len] === "comment" || types[len] === "comment-inline") ); if (token[len] === "from") { len = len - 2; } if (token[len] === "x;") { token.splice(len, 1); types.splice(len, 1); lines.splice(len, 1); depth.splice(len, 1); begin.splice(len, 1); } }, //determine the definition of containment by depth depthPush = function jspretty__tokenize_depthPush() { // * block : if, for, while, catch, function, class, map // * immediates : else, do, try, finally, switch // * paren based: method, expression, paren // * data : array, object var last = 0, aa = 0, wordx = "", wordy = "", bpush = false; lengtha = token.length; last = lengtha - 1; aa = last - 1; wordx = token[aa]; wordy = (depth[aa] === undefined) ? "" : token[begin[aa] - 1]; if (types[aa] === "comment" || types[aa] === "comment-inline") { do { aa = aa - 1; } while (aa > 0 && (types[aa] === "comment" || types[aa] === "comment-inline")); wordx = token[aa]; } if ((token[last] === "{" || token[last] === "x{") && ((wordx === "else" && token[last] !== "if") || wordx === "do" || wordx === "try" || wordx === "finally" || wordx === "switch")) { depth.push(wordx); } else if (token[last] === "{" || token[last] === "x{") { if (lengtha === 1 && options.jsx === true) { depth.push("global"); } else if (classy[classy.length - 1] === 0 && wordx !== "return") { classy.pop(); depth.push("class"); } else if (token[aa - 1] === "class") { depth.push("class"); } else if (token[aa] === "]" && token[aa - 1] === "[") { depth.push("array"); } else if (types[aa] === "word" && (types[aa - 1] === "word" || (token[aa - 1] === "?" && types[aa - 2] === "word")) && token[aa] !== "in" && token[aa - 1] !== "export" && token[aa - 1] !== "import") { depth.push("map"); } else if (depth[aa] === "method" && types[aa] === "end" && types[begin[aa] - 1] === "word" && token[begin[aa] - 2] === "new") { depth.push("initializer"); } else if (token[last] === "{" && (wordx === ")" || wordx === "x)") && (types[begin[aa] - 1] === "word" || token[begin[aa] - 1] === "]")) { if (wordy === "if") { depth.push("if"); } else if (wordy === "for") { depth.push("for"); } else if (wordy === "while") { depth.push("while"); } else if (wordy === "class") { depth.push("class"); } else if (wordy === "switch" || token[begin[aa] - 1] === "switch") { depth.push("switch"); } else if (wordy === "catch") { depth.push("catch"); } else { depth.push("function"); } } else if (token[last] === "{" && (wordx === ";" || wordx === "x;")) { //ES6 block depth.push("block"); } else if (token[last] === "{" && token[aa] === ":" && depth[aa] === "switch") { //ES6 block depth.push("block"); } else if (token[aa - 1] === "import" || token[aa - 2] === "import" || token[aa - 1] === "export" || token[aa - 2] === "export") { depth.push("object"); } else if (wordx === ")" && (pword[0] === "function" || pword[0] === "if" || pword[0] === "for" || pword[0] === "class" || pword[0] === "while" || pword[0] === "switch" || pword[0] === "catch")) { // if preceeded by a paren the prior containment is preceeded by a keyword if // (...) { depth.push(pword[0]); } else if (depth[aa] === "notation") { //if following a TSX array type declaration depth.push("function"); } else if ((types[aa] === "literal" || types[aa] === "word") && types[aa - 1] === "word" && token[begin[aa] - 1] !== "for") { //if preceed by a word and either string or word public class { depth.push("function"); } else if (depthlist.length > 0 && token[aa] !== ":" && depthlist[depthlist.length - 1][0] === "object" && ( token[begin[aa] - 2] === "{" || token[begin[aa] - 2] === "," )) { // if an object wrapped in some containment which is itself preceeded by a curly // brace or comma var a={({b:{cat:"meow"}})}; depth.push("function"); } else if (types[pword[1] - 1] === "markup" && token[pword[1] - 3] === "function") { //checking for TSX function using an angle brace name depth.push("function"); } else if (wordx === "=>") { //checking for fat arrow assignment depth.push("function"); } else if (wordx === ")" && depth[aa] === "method" && types[begin[aa] - 1] === "word") { depth.push("function"); } else if (types[last - 1] === "word" && token[last] === "{" && token[last - 1] !== "return" && token[last - 1] !== "in" && token[last - 1] !== "import" && token[last - 1] !== "const" && token[last - 1] !== "let" && token[last - 1] !== "") { //ES6 block depth.push("block"); } else { depth.push("object"); } } else if (token[last] === "[") { if ((/\s/).test(c[a - 1]) === true && types[aa] === "word" && wordx !== "return" && options.twig === false) { depth.push("notation"); } else { depth.push("array"); } } else if (token[last] === "(" || token[last] === "x(") { if (types[aa] === "generic") { depth.push("method"); } else if (token[aa] === "}" && depth[aa] === "function") { depth.push("method"); } else if (wordx === "if" || wordx === "for" || wordx === "function" || wordx === "class" || wordx === "while" || wordx === "catch" || wordx === "switch" || wordx === "with") { depth.push("expression"); } else if ((types[aa] === "word" && wordx !== "return") || (wordx === "}" && (depth[aa] === "function" || depth[aa] === "class"))) { depth.push("method"); } else { depth.push("paren"); } } else if (ltoke === ":" && types[aa] === "word" && token[aa - 1] === "[") { depth[aa] = "attribute"; depth[aa - 1] = "attribute"; depth.push("attribute"); depthlist[depthlist.length - 1][0] = "attribute"; } else if (depthlist.length === 0) { depth.push("global"); begin.push(0); bpush = true; } else { depth.push(depthlist[depthlist.length - 1][0]); begin.push(depthlist[depthlist.length - 1][1]); bpush = true; } if (bpush === false) { begin.push(last); } }, tokenpop = function jspretty__tokenize_tokenpop() { lengtha = lengtha - 1; lengthb = lengthb - 1; tempstore = [token.pop(), types.pop(), lines.pop(), depth.pop(), begin.pop()]; }, //reinsert the prior popped token temppush = function jspretty__tokenize_temppush() { token.push(tempstore[0]); types.push(tempstore[1]); lines.push(tempstore[2]); depth.push(tempstore[3]); begin.push(tempstore[4]); lengtha = lengtha + 1; }, //populate various parallel arrays tokenpush = function jspretty__tokenize_tokenpush(comma, lin) { if (comma === true) { token.push(","); types.push("separator"); } else { token.push(ltoke); types.push(ltype); } lengtha = token.length; lines.push(lin); depthPush(); }, //inserts ending curly brace blockinsert = function jspretty__tokenize_blockinsert() { var next = nextchar(5, false), g = lengtha - 1; if (json === true) { return; } if (depth[lengtha - 1] === "do" && next === "while" && token[lengtha - 1] === "}") { return; } next = next.slice(0, 4); if (ltoke === ";" && token[g - 1] === "x{") { //to prevent the semicolon from inserting between the braces --> while (x) {}; tokenpop(); ltoke = "x}"; ltype = "end"; tokenpush(false, 0); brace.pop(); pdepth = depthlist.pop(); ltoke = ";"; ltype = "end"; temppush(); return; } ltoke = "x}"; ltype = "end"; if (token[lengtha - 1] === "x}") { return; } if (depth[lengtha - 1] === "if" && (token[lengtha - 1] === ";" || token[lengtha - 1] === "x;") && next === "else") { tokenpush(false, 0); brace.pop(); pdepth = depthlist.pop(); return; } do { tokenpush(false, 0); brace.pop(); pdepth = depthlist.pop(); } while (brace[brace.length - 1] === "x{"); }, //remove "vart" object data vartpop = function jspretty__tokenize_vartpop() { vart .count .pop(); vart .index .pop(); vart .word .pop(); vart.len = vart.len - 1; }, logError = function jspretty__tokenize_logError(message, start) { var f = a, g = types.length; if (error.length > 0) { return; } error.push(message); do { f = f - 1; } while (c[f] !== "\n" && f > 0); error.push(c.slice(f, start).join("")); if (g > 1) { do { g = g - 1; } while (g > 0 && types[g] !== "comment"); } if (g > -1 && g < token.length && token[g].indexOf("//") === 0 && error[1].replace(/^\s+/, "").indexOf(token[g + 1]) === 0 && (token[g].split("\"").length % 2 === 1 || token[g].split("'").length % 2 === 1)) { error = [ message, token[g] + error[1] ]; } else { error = [ message, error[1] ]; } if (globalerror === "") { globalerror = message + ":" + error[1]; } }, //A tokenizer for keywords, reserved words, and variables word = function jspretty__tokenize_word() { var f = wordTest, g = 1, build = [], output = "", nextitem = "", elsefix = function jspretty__tokenize_word_elsefix() { brace.push("x{"); depthlist.push(["else", lengtha]); token.splice(lengtha - 3, 1); types.splice(lengtha - 3, 1); lines.splice(lengtha - 3, 1); depth.splice(lengtha - 3, 1); begin.splice(lengtha - 3, 1); }; do { build.push(c[f]); if (c[f] === "\\") { logError("Illegal escape in JavaScript", a); } f = f + 1; } while (f < a); output = build.join(""); wordTest = -1; if (types.length > 1 && output === "function" && token[lengtha - 1] === "(" && (token[token.length - 2] === "{" || token[token.length - 2] === "x{")) { types[types.length - 1] = "start"; } if (types.length > 2 && output === "function" && ltoke === "(" && (token[token.length - 2] === "}" || token[token.length - 2] === "x}")) { if (token[token.length - 2] === "}") { for (f = token.length - 3; f > -1; f = f - 1) { if (types[f] === "end") { g = g + 1; } else if (types[f] === "start" || types[f] === "end") { g = g - 1; } if (g === 0) { break; } } if (token[f] === "{" && token[f - 1] === ")") { g = 1; for (f = f - 2; f > -1; f = f - 1) { if (types[f] === "end") { g = g + 1; } else if (types[f] === "start" || types[f] === "end") { g = g - 1; } if (g === 0) { break; } } if (token[f - 1] !== "function" && token[f - 2] !== "function") { types[types.length - 1] = "start"; } } } else { types[types.length - 1] = "start"; } } if (options.correct === true && (output === "Object" || output === "Array") && c[a + 1] === "(" && c[a + 2] === ")" && token[lengtha - 2] === "=" && token[lengtha - 1] === "new") { if (output === "Object") { token[lengtha - 1] = "{"; ltoke = "}"; depth[a - 1] = "object"; depthlist[depthlist.length - 1][0] = "object"; } else { token[lengtha - 1] = "["; ltoke = "]"; depth[a - 1] = "array"; depthlist[depthlist.length - 1][0] = "array"; } types[lengtha - 1] = "start"; ltype = "end"; c[a + 1] = ""; c[a + 2] = ""; stats.container = stats.container + 2; a = a + 2; } else { g = types.length - 1; f = g; if (options.varword !== "none" && (output === "var" || output === "let" || output === "const")) { if (types[g] === "comment" || types[g] === "comment-inline") { do { g = g - 1; } while (g > 0 && (types[g] === "comment" || types[g] === "comment-inline")); } if (options.varword === "list" && vart.len > -1 && vart.index[vart.len] === g && output === vart.word[vart.len]) { stats.word.token = stats.word.token + 1; stats.word.chars = stats.word.chars + output.length; ltoke = ","; ltype = "separator"; token[g] = ltoke; types[g] = ltype; vart.count[vart.len] = 0; vart.index[vart.len] = g; vart.word[vart.len] = output; return; } vart.len = vart.len + 1; vart .count .push(0); vart .index .push(g); vart .word .push(output); g = f; } else if (vart.len > -1 && output !== vart.word[vart.len] && token.length === vart.index[vart.len] + 1 && token[vart.index[vart.len]] === ";" && ltoke !== vart.word[vart.len] && options.varword === "list") { vartpop(); } if (output === "else" && (types[g] === "comment" || types[g] === "comment-inline")) { do { f = f - 1; } while (f > -1 && (types[f] === "comment" || types[f] === "comment-inline")); if (token[f] === "x;" && (token[f - 1] === "}" || token[f - 1] === "x}")) { token.splice(f, 1); types.splice(f, 1); lines.splice(f, 1); depth.splice(f, 1); begin.splice(f, 1); g = g - 1; f = f - 1; } do { build = [ token[g], types[g], lines[g], depth[g], begin[g] ]; tokenpop(); token.splice(g - 3, 0, build[0]); types.splice(g - 3, 0, build[1]); lines.splice(g - 3, 0, build[2]); depth.splice(g - 3, 0, build[3]); begin.splice(g - 3, 0, build[4]); f = f + 1; } while (f < g); } if (output === "from" && token[lengtha - 1] === "x;" && token[lengtha - 2] === "}") { asifix(); } if (output === "while" && token[lengtha - 1] === "x;" && token[lengtha - 2] === "}") { (function jspretty__tokenize_word_whilefix() { var d = 0, e = 0; for (e = lengtha - 3; e > -1; e = e - 1) { if (types[e] === "end") { d = d + 1; } else if (types[e] === "start") { d = d - 1; } if (d < 0) { if (token[e] === "{" && token[e - 1] === "do") { asifix(); } return; } } }()); } ltoke = output; ltype = "word"; stats.word.token = stats.word.token + 1; stats.word.chars = stats.word.chars + output.length; if (output === "from" && token[lengtha - 1] === "}") { asifix(); } } tokenpush(false, 0); if (output === "class") { classy.push(0); } if (output === "do") { nextitem = nextchar(1, true); if (nextitem !== "{") { ltoke = "x{"; ltype = "start"; brace.push("x{"); tokenpush(false, 0); depthlist.push([ "do", lengtha - 1 ]); } } if (output === "else") { nextitem = nextchar(2, true); if (nextitem !== "if" && nextitem.charAt(0) !== "{") { ltoke = "x{"; ltype = "start"; brace.push("x{"); tokenpush(false, 0); depthlist.push([ "else", lengtha - 1 ]); } if (token[lengtha - 3] === "x}") { if (token[lengtha - 2] === "else") { if (token[lengtha - 4] === "x}" && pdepth[0] !== "if" && depth[depth.length - 2] === "else") { elsefix(); } else if (token[lengtha - 4] === "}" && depth[lengtha - 4] === "if" && pdepth[0] === "if" && token[pdepth[1] - 1] !== "if" && token[begin[lengtha - 3]] === "x{") { //fixes when "else" is following a block that isn't "if" elsefix(); } } else if (token[lengtha - 2] === "x}" && depth[depth.length - 2] === "if") { elsefix(); } } } if ((output === "for" || output === "if" || output === "switch" || output === "catch") && options.twig === false && token[lengtha - 2] !== ".") { nextitem = nextchar(1, true); if (nextitem !== "(") { paren = lengtha - 1; start("x("); } } }, //sort object properties objSort = function jspretty__tokenize_objSort() { var cc = 0, dd = 0, ee = 0, startlen = token.length - 1, behind = startlen, keys = [], keylen = 0, keyend = 0, front = 0, sort = function jspretty__tokenize_objSort_sort(x, y) { var xx = x[0], yy = y[0]; if (types[xx] === "comment" || types[xx] === "comment-inline") { do { xx = xx + 1; } while ( xx < startlen && (types[xx] === "comment" || types[xx] === "comment-inline") ); } if (types[yy] === "comment" || types[yy] === "comment-inline") { do { yy = yy + 1; } while ( yy < startlen && (types[yy] === "comment" || types[yy] === "comment-inline") ); } if (token[xx].toLowerCase() > token[yy].toLowerCase()) { return 1; } return -1; }, commaTest = true, pairToken = [], pairTypes = [], pairLines = [], pairDepth = [], pairBegin = []; if (token[behind] === "," || types[behind] === "comment") { do { behind = behind - 1; } while (behind > 0 && (token[behind] === "," || types[behind] === "comment")); } for (cc = behind; cc > -1; cc = cc - 1) { if (types[cc] === "end") { dd = dd + 1; } if (types[cc] === "start") { dd = dd - 1; } if (dd === 0) { if (types[cc].indexOf("template") > -1) { return; } if (token[cc] === ",") { commaTest = true; front = cc + 1; } if (commaTest === true && token[cc] === "," && front < behind) { if (token[behind] !== ",") { behind = behind + 1; } if (types[front] === "comment-inline") { front = front + 1; } keys.push([front, behind]); behind = front - 1; } } if (dd < 0 && cc < startlen) { if (keys.length > 0 && keys[keys.length - 1][0] > cc + 1) { ee = keys[keys.length - 1][0]; if (types[ee - 1] !== "comment-inline") { ee = ee - 1; } keys.push([ cc + 1, ee ]); } if (token[cc - 1] === "=" || token[cc - 1] === ":" || token[cc - 1] === "(" || token[cc - 1] === "[" || token[cc - 1] === "," || types[cc - 1] === "word" || cc === 0) { if (keys.length > 1) { keys.sort(sort); keylen = keys.length; commaTest = false; for (dd = 0; dd < keylen; dd = dd + 1) { keyend = keys[dd][1]; if (lines[keys[dd][0] - 1] > 1 && pairLines.length > 0) { pairLines[pairLines.length - 1] = lines[keys[dd][0] - 1]; } for (ee = keys[dd][0]; ee < keyend; ee = ee + 1) { pairToken.push(token[ee]); pairTypes.push(types[ee]); pairLines.push(lines[ee]); pairDepth.push(depth[ee]); pairBegin.push(begin[ee]); //remove extra commas if (token[ee] === ",") { commaTest = true; } else if (token[ee] !== "," && types[ee] !== "comment" && types[ee] !== "comment-inline") { commaTest = false; } } if (commaTest === false) { ee = pairTypes.length - 1; if (pairTypes[ee] === "comment" || pairTypes[ee] === "comment-inline") { do { ee = ee - 1; } while ( ee > 0 && (pairTypes[ee] === "comment" || pairTypes[ee] === "comment-inline") ); } ee = ee + 1; pairToken.splice(ee, 0, ","); pairTypes.splice(ee, 0, "separator"); pairLines.splice(ee, 0, pairLines[ee - 1]); pairDepth.splice(ee, 0, "object"); pairBegin.splice(ee, 0, cc); pairLines[ee - 1] = 0; } } ee = pairTypes.length; do { ee = ee - 1; } while ( ee > 0 && (pairTypes[ee] === "comment" || pairTypes[ee] === "comment-inline") ); if (options.endcomma === "never" || options.endcomma === "multiline") { pairToken.splice(ee, 1); pairTypes.splice(ee, 1); pairLines.splice(ee, 1); pairDepth.splice(ee, 1); pairBegin.splice(ee, 1); } keylen = token.length - (cc + 1); token.splice(cc + 1, keylen); types.splice(cc + 1, keylen); lines.splice(cc + 1, keylen); depth.splice(cc + 1, keylen);