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
JavaScript
/*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);