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.

941 lines (936 loc) 260 kB
/*prettydiff.com api.topcoms:true,api.insize:4,api.inchar:" ",api.vertical:true */ /*jshint laxbreak: true*/ /*global __dirname, ace, define, global, module, process, require*/ /*********************************************************************** markuppretty is written by Austin Cheney on 20 Jun 2015. Please see the license.txt file associated with the Pretty Diff application for license information. **********************************************************************/ /* A simple parser for XML, HTML, and a variety of template schemes. It beautifies, minifies, and peforms a series of analysis*/ (function markuppretty_init() { "use strict"; var markuppretty = function markuppretty_(options) { var safeSort = global.prettydiff.safeSort, output = "", stats = { cdata : [ 0, 0 ], comment : [ 0, 0 ], conditional: [ 0, 0 ], content : [ 0, 0 ], end : [ 0, 0 ], ignore : [ 0, 0 ], script : [ 0, 0 ], sgml : [ 0, 0 ], singleton : [ 0, 0 ], space : 0, start : [ 0, 0 ], style : [ 0, 0 ], template : [ 0, 0 ], text : [ 0, 0 ], xml : [0, 0] }, //parallel arrays // * attrs is a list of arrays, each of which contains (if any) parsed // attributes // * begin stores the index of the current token's parent element // * daddy stores the tag name of the parent element // * jscom stores true/false if the current token is a JS comment from JSX // format // * level describes the indentation of a given token level is only used in // beautify and diff modes // * linen stores the input line number on which the token occurs // * lines describes the preceeding space using: 2, 1, or 0 lines is populated // in markuppretty__tokenize_spacer // * presv whether a given token should be preserved as provided // * token stores parsed tokens // * types segments tokens into named groups // * value attribute value if current type is attribute and // options.attributetoken is true attrs = [], jscom = [], level = [], linen = [], lines = [], token = [], types = [], presv = [], daddy = [], begin = [], value = [], reqs = [], ids = [], parseError = [], parent = [ ["none", -1] ], line = 1, wrap = options.wrap, objsortop = false, globalerror = "", lf = (options.crlf === true || options.crlf === "true") ? "\r\n" : "\n", sourceSize = options.source.length, extlib = function markuppretty__extlib(type) { var result = "", newline = options.newline; if (type === "script" && typeof global.prettydiff.jspretty !== "function") { return options.source; } if (type === "style" && typeof global.prettydiff.csspretty !== "function") { return options.source; } options.newline = false; result = (type === "script") ? global .prettydiff .jspretty(options) : global .prettydiff .csspretty(options); options.newline = newline; if (options.nodeasync === true) { if (globalerror === "") { globalerror = result[1]; } if (options.mode === "parse") { if (options.parseFormat === "htmltable") { if (type === "script") { return result[0] .data .replace( "<thead>", "<thead><tr><th colspan=\"6\" class=\"nested\">JavaScript tokens</th></tr>" ); } return result[0] .data .replace( "<thead>", "<thead><tr><th colspan=\"4\" class=\"nested\">CSS tokens</th></tr>" ); } return result[0].data; } return result[0]; } if (options.mode === "parse") { if (options.parseFormat === "htmltable") { if (type === "script") { return result .data .replace( "<thead>", "<thead><tr><th colspan=\"6\" class=\"nested\">JavaScript tokens</th></tr>" ); } return result .data .replace( "<thead>", "<thead><tr><th colspan=\"4\" class=\"nested\">CSS tokens</th></tr>" ); } return result.data; } return result; }, //What is the lowercase tag name of the provided token? tagName = function markuppretty__tagName(el) { var space = el .replace(/^(\{((%-?)|\{-?)\s*)/, "%") .replace(/\s+/, " ") .indexOf(" "), name = (space < 0) ? el .replace(/^(\{((%-?)|\{-?)\s*)/, " ") .slice(1, el.length - 1) .toLowerCase() : el .replace(/^(\{((%-?)|\{-?)\s*)/, " ") .slice(1, space) .toLowerCase(); name = name.replace(/(\}\})$/, ""); if (name.indexOf("(") > 0) { name = name.slice(0, name.indexOf("(")); } return name; }; (function markuppretty__options() { objsortop = ( options.objsort === true || options.objsort === "true" || options.objsort === "all" || options.objsort === "markup" ); options.source = ( typeof options.source === "string" && options.source.length > 0 ) ? options .source .replace(/\r\n?/g, "\n") : "Error: no source code supplied to markuppretty!"; if (options.mode === "analysis") { options.accessibility = true; } }()); //type definitions: // * start end type // * <![CDATA[ ]]> cdata // * <!-- --> comment // * <#-- --> comment // * <%-- --%> comment // * {! !} comment // * <!--[if --> conditional // * text text content // * </ > end // * <pre </pre> ignore (html only) // * text text script // * <! > sgml // * < /> singleton // * < > start // * text text style // * <!--# --> template // * <% %> template // * {{{ }}} template // * {{ }} template // * {% %} template // * [% %] template // * {@ @} template // * {# #} template // * {# /} template // * {? /} template // * {^ /} template // * {@ /} template // * {< /} template // * {+ /} template // * {~ } template // * <? ?> template // * {:else} template_else // * <#else > template_else // * {@}else{@} template_else // * <%}else{%> template_else // * {{ }} template_end // * <%\s*} %> template_end // * [%\s*} %] template_end // * {@\s*} @} template_end // * { } template_end // * {{# }} template_start // * <% {\s*%> template_start // * [% {\s*%] template_start // * {@ {\s*@} template_start // * {# } template_start // * {? } template_start // * {^ } template_start // * {@ } template_start // * {< } template_start // * {+ } template_start // * <?xml ?> xml if (options.mode !== "diff") { options.content = false; } if (options.jsx === true) { options.dustjs = false; } (function markuppretty__tokenize() { var a = 0, b = options .source .split(""), c = b.length, minspace = "", space = "", list = 0, litag = 0, linepreserve = 0, cftransaction = false, sgmlflag = 0, ext = false, //cftags is a list of supported coldfusion tags //* required - means must have a separate matching end tag // * optional - means the tag could have a separate end tag, but is probably a // singleton //* prohibited - means there is not corresponding end tag cftags = { cfabort : "prohibited", cfajaximport : "optional", cfajaxproxy : "optional", cfapplet : "prohibited", cfapplication : "prohibited", cfargument : "prohibited", cfassociate : "prohibited", cfauthenticate : "prohibited", cfbreak : "prohibited", cfcache : "optional", cfcalendar : "optional", cfcase : "required", cfcatch : "required", cfchart : "optional", cfchartdata : "prohibited", cfchartseries : "optional", cfclient : "required", cfclientsettings : "optional", cfcol : "prohibited", cfcollection : "prohibited", cfcomponent : "required", cfcontent : "optional", cfcontinue : "prohibited", cfcookie : "prohibited", cfdbinfo : "prohibited", cfdefaultcase : "required", cfdirectory : "prohibited", cfdiv : "optional", cfdocument : "optional", cfdocumentitem : "optional", cfdocumentsection : "optional", cfdump : "optional", cfelse : "prohibited", cfelseif : "prohibited", cferror : "prohibited", cfexchangecalendar : "optional", cfexchangeconnection : "optional", cfexchangecontact : "optional", cfexchangeconversation: "optional", cfexchangefilter : "optional", cfexchangefolder : "optional", cfexchangemail : "optional", cfexchangetask : "optional", cfexecute : "required", cfexit : "prohibited", cffeed : "prohibited", cffile : "optional", cffileupload : "optional", cffinally : "required", cfflush : "prohibited", cfform : "required", cfformgroup : "required", cfformitem : "optional", cfforward : "prohibited", cfftp : "prohibited", cffunction : "required", cfgraph : "required", cfgraphdata : "prohibited", cfgrid : "required", cfgridcolumn : "optional", cfgridrow : "optional", cfgridupdate : "optional", cfheader : "prohibited", cfhtmlbody : "optional", cfhtmlhead : "optional", cfhtmltopdf : "optional", cfhtmltopdfitem : "optional", cfhttp : "optional", cfhttpparam : "prohibited", cfif : "required", cfimage : "prohibited", cfimap : "prohibited", cfimapfilter : "optional", cfimport : "prohibited", cfinclude : "prohibited", cfindex : "prohibited", cfinput : "prohibited", cfinsert : "prohibited", cfinterface : "required", cfinvoke : "optional", cfinvokeargument : "prohibited", cflayout : "optional", cflayoutarea : "optional", cfldap : "prohibited", cflocation : "prohibited", cflock : "required", cflog : "prohibited", cflogic : "required", cfloginuser : "prohibited", cflogout : "prohibited", cfloop : "required", cfmail : "required", cfmailparam : "prohibited", cfmailpart : "required", cfmap : "optional", cfmapitem : "optional", cfmediaplayer : "optional", cfmenu : "required", cfmenuitem : "optional", cfmessagebox : "optional", cfmodule : "optional", cfNTauthenticate : "optional", cfoauth : "optional", cfobject : "prohibited", cfobjectcache : "prohibited", cfoutput : "required", cfpageencoding : "optional", cfparam : "prohibited", cfpdf : "optional", cfpdfform : "optional", cfpdfformparam : "optional", cfpdfparam : "prohibited", cfpdfsubform : "required", cfpod : "optional", cfpop : "prohibited", cfpresentation : "required", cfpresentationslide : "optional", cfpresenter : "optional", cfprint : "optional", cfprocessingdirective : "optional", cfprocparam : "prohibited", cfprocresult : "prohibited", cfprogressbar : "optional", cfproperty : "prohibited", cfquery : "required", cfqueryparam : "prohibited", cfregistry : "prohibited", cfreport : "optional", cfreportparam : "optional", cfrethrow : "prohibited", cfretry : "prohibited", cfreturn : "prohibited", cfsavecontent : "required", cfschedule : "prohibited", cfscript : "required", cfsearch : "prohibited", cfselect : "required", cfservlet : "prohibited", cfservletparam : "prohibited", cfset : "prohibited", cfsetting : "optional", cfsharepoint : "optional", cfsilent : "required", cfsleep : "prohibited", cfslider : "prohibited", cfspreadsheet : "optional", cfsprydataset : "optional", cfstatic : "required", cfstopwatch : "required", cfstoredproc : "optional", cfswitch : "required", cftable : "required", cftextarea : "optional", cfthread : "optional", cfthrow : "prohibited", cftimer : "required", cftooltip : "required", cftrace : "optional", cftransaction : "required", cftree : "required", cftreeitem : "optional", cftry : "required", cfupdate : "prohibited", cfvideo : "prohibited", cfvideoplayer : "optional", cfwddx : "prohibited", cfwebsocket : "optional", cfwhile : "required", cfwindow : "optional", cfx_ : "prohibited", cfxml : "required", cfzip : "optional", cfzipparam : "prohibited" }, // determine if spaces between nodes are absent, multiline, or merely there 2 - // multiline 1 - space present 0 - no space present spacer = function markuppretty__tokenize_spacer() { var linea = 0; if (space.length > 0) { stats.space = stats.space + space.length; linea = space .split("\n") .length - 1; if (options.preserve > 0 && linea > 1) { if (linea > options.preserve + 1) { lines.push(options.preserve + 1); } else { lines.push(linea); } } else { lines.push(1); } } else { lines.push(0); } minspace = space; space = ""; }, //parses tags, attributes, and template elements tag = function markuppretty__tokenize_tag(end) { var lexer = [], bcount = 0, e = 0, f = 0, igcount = 0, jsxcount = 0, braccount = 0, parncount = 0, quote = "", element = "", lastchar = "", jsxquote = "", tname = "", comment = false, cheat = false, endtag = false, nopush = false, nosort = false, simple = false, preserve = false, stest = false, liend = false, ignoreme = false, quotetest = false, parseFail = false, singleton = false, earlyexit = false, attribute = [], attstore = [], presend = { cfquery: true }, arname = function markuppretty__tokenize_tag_name(x) { var eq = x.indexOf("="); if (eq > 0 && ((eq < x.indexOf("\"") && x.indexOf("\"") > 0) || (eq < x.indexOf("'") && x.indexOf("'") > 0))) { return x.slice(0, eq); } return x; }, slashy = function markuppretty__tokenize_tag_slashy() { var x = a; do { x = x - 1; } while (b[x] === "\\"); x = a - x; if (x % 2 === 1) { return false; } return true; }, attrpush = function markuppretty__tokenize_tag_attrpush(quotes) { var atty = "", name = "", aa = 0, bb = 0; if (quotes === true) { if (quote === "\"" && options.quoteConvert === "single") { atty = attribute .slice(0, attribute.length - 1) .join("") .replace(/'/g, "\"") .replace(/"/, "'") + "'"; } else if (quote === "'" && options.quoteConvert === "double") { atty = attribute .slice(0, attribute.length - 1) .join("") .replace(/"/g, "'") .replace(/'/, "\"") + "\""; } else { atty = attribute.join(""); } name = arname(atty); if (name === "data-prettydiff-ignore") { ignoreme = true; } else if (name === "id") { ids.push(atty.slice(name.length + 2, atty.length - 1)); } else if (name === "schemaLocation") { reqs.push(atty.slice(name.length + 2, atty.length - 1)); } quote = ""; } else { atty = attribute .join("") .replace(/\s+/g, " "); name = arname(atty); if (name === "data-prettydiff-ignore") { ignoreme = true; } else if (name === "id") { ids.push(element.slice(name.length + 1, atty.length)); } if (options.jsx === true && attribute[0] === "{" && attribute[attribute.length - 1] === "}") { jsxcount = 0; } } if (atty.slice(0, 3) === "<%=" || atty.slice(0, 2) === "{%") { nosort = true; } atty = atty .replace(/^\u0020/, "") .replace(/\u0020$/, ""); attribute = atty .replace(/\r\n/g, "\n") .split("\n"); bb = attribute.length; for (aa = 0; aa < bb; aa = aa + 1) { attribute[aa] = attribute[aa].replace(/(\s+)$/, ""); } atty = attribute.join(lf); if (atty === "=") { attstore[attstore.length - 1] = attstore[attstore.length - 1] + "="; } else if (atty.charAt(0) === "=" && attstore.length > 0 && attstore[attstore.length - 1].indexOf("=") < 0) { //if an attribute starts with a `=` then adjoin it to the last attribute attstore[attstore.length - 1] = attstore[attstore.length - 1] + atty; } else if (atty.charAt(0) !== "=" && attstore.length > 0 && attstore[attstore.length - 1].indexOf("=") === attstore[attstore.length - 1].length - 1) { // if an attribute follows an attribute ending with `=` then adjoin it to the // last attribute attstore[attstore.length - 1] = attstore[attstore.length - 1] + atty; } else if (atty !== "" && atty !== " ") { attstore.push(atty); } attribute = []; }; spacer(); jscom.push(false); linen.push(line); value.push(""); ext = false; // this complex series of conditions determines an elements delimiters look to // the types being pushed to quickly reason about the logic no type is pushed // for start tags or singleton tags just yet some types set the `preserve` flag, // which means to preserve internal white space The `nopush` flag is set when // parsed tags are to be ignored and forgotten (function markuppretty__tokenize_types() { if (end === "]>") { end = ">"; sgmlflag = sgmlflag - 1; types.push("template_end"); } else if (end === "---") { preserve = true; types.push("comment"); } else if (b[a] === "<") { if (b[a + 1] === "/") { if (b[a + 2] === "#") { types.push("template_end"); } else { types.push("end"); } end = ">"; } else if (b[a + 1] === "!") { if (b[a + 2] === "-" && b[a + 3] === "-") { if (b[a + 4] === "#") { end = "-->"; types.push("template"); } else if (b[a + 4] === "[" && b[a + 5] === "i" && b[a + 6] === "f" && options.conditional === true) { end = "-->"; types.push("conditional"); } else if (b[a + 4] === "-" && (/<cf[a-z]/i).test(options.source) === true) { preserve = true; comment = true; end = "--->"; types.push("comment"); } else { end = "-->"; if (options.mode === "minify" || options.comments === "nocomment") { nopush = true; comment = true; } else { if (options.preserveComment === true) { preserve = true; } comment = true; if (options.commline === true) { lines[lines.length - 1] = 2; } types.push("comment"); } } } else if (b[a + 2] === "[" && b[a + 3] === "C" && b[a + 4] === "D" && b[a + 5] === "A" && b[a + 6] === "T" && b[a + 7] === "A" && b[a + 8] === "[") { end = "]]>"; preserve = true; comment = true; types.push("cdata"); } else { end = ">"; sgmlflag = sgmlflag + 1; types.push("sgml"); } } else if (b[a + 1] === "?") { end = "?>"; if (b[a + 2] === "x" && b[a + 3] === "m" && b[a + 4] === "l") { types.push("xml"); } else { preserve = true; types.push("template"); } } else if (b[a + 1] === "%") { if (b[a + 2] !== "=") { preserve = true; } if (b[a + 2] === "-" && b[a + 3] === "-") { end = "--%>"; comment = true; if (options.commline === true) { line[line.length - 1] = 2; } types.push("comment"); } else if (b[a + 2] === "#") { end = "%>"; comment = true; if (options.commline === true) { line[line.length - 1] = 2; } types.push("comment"); } else { end = "%>"; types.push("template"); } } else if (b[a + 4] !== undefined && b[a + 1].toLowerCase() === "p" && b[a + 2].toLowerCase() === "r" && b[a + 3].toLowerCase() === "e" && (b[a + 4] === ">" || (/\s/).test(b[a + 4]) === true)) { end = "</pre>"; preserve = true; types.push("ignore"); } else if (b[a + 4] !== undefined && b[a + 1].toLowerCase() === "x" && b[a + 2].toLowerCase() === "s" && b[a + 3].toLowerCase() === "l" && b[a + 4].toLowerCase() === ":" && b[a + 5].toLowerCase() === "t" && b[a + 6].toLowerCase() === "e" && b[a + 7].toLowerCase() === "x" && b[a + 8].toLowerCase() === "t" && (b[a + 9] === ">" || (/\s/).test(b[a + 9]) === true)) { end = "</xsl:text>"; preserve = true; types.push("ignore"); } else if (b[a + 8] !== undefined && b[a + 1].toLowerCase() === "c" && b[a + 2].toLowerCase() === "f" && b[a + 3].toLowerCase() === "q" && b[a + 4].toLowerCase() === "u" && b[a + 5].toLowerCase() === "e" && b[a + 6].toLowerCase() === "r" && b[a + 7].toLowerCase() === "y" && (b[a + 8] === ">" || (/\s/).test(b[a + 8]))) { end = ">"; linepreserve = linepreserve + 1; types.push("linepreserve"); } else if (b[a + 1] === "<") { if (b[a + 2] === "<") { end = ">>>"; } else { end = ">>"; } types.push("template"); } else if (b[a + 1] === "#") { if (b[a + 2] === "e" && b[a + 3] === "l" && b[a + 4] === "s" && b[a + 5] === "e") { end = ">"; types.push("template_else"); } else if (b[a + 2] === "-" && b[a + 3] === "-") { end = "-->"; types.push("comment"); preserve = true; } else { end = ">"; types.push("template_start"); } } else { simple = true; end = ">"; } } else if (b[a] === "{") { preserve = true; if (options.jsx === true) { end = "}"; types.push("script"); } else if (options.dustjs === true) { if (b[a + 1] === ":" && b[a + 2] === "e" && b[a + 3] === "l" && b[a + 4] === "s" && b[a + 5] === "e" && b[a + 6] === "}") { a = a + 6; token.push("{:else}"); presv.push(true); daddy.push(parent[parent.length - 1][0]); begin.push(parent[parent.length - 1][1]); attrs.push({}); stats.template[0] = stats.template[0] + 1; stats.template[1] = stats.template[1] + 7; earlyexit = true; return types.push("template_else"); } if (b[a + 1] === "!") { end = "!}"; comment = true; types.push("comment"); } else if (b[a + 1] === "/") { end = "}"; types.push("template_end"); } else if (b[a + 1] === "~") { end = "}"; types.push("singleton"); } else if (b[a + 1] === ">") { end = "/}"; types.push("singleton"); } else if (b[a + 1] === "#" || b[a + 1] === "?" || b[a + 1] === "^" || b[a + 1] === "@" || b[a + 1] === "<" || b[a + 1] === "+") { end = "}"; types.push("template_start"); } else { end = "}"; types.push("template"); } } else if (b[a + 1] === "{") { if (b[a + 2] === "{") { end = "}}}"; types.push("template"); } else if (b[a + 2] === "#") { end = "}}"; types.push("template_start"); } else if (b[a + 2] === "/") { end = "}}"; types.push("template_end"); } else if (b[a + 2] === "e" && b[a + 3] === "n" && b[a + 4] === "d") { end = "}}"; types.push("template_end"); } else if (b[a + 2] === "e" && b[a + 3] === "l" && b[a + 4] === "s" && b[a + 5] === "e") { end = "}}"; types.push("template_else"); } else { end = "}}"; types.push("template"); } } else if (b[a + 1] === "%") { end = "%}"; types.push("template"); } else if (b[a + 1] === "#") { end = "#}"; types.push("comment"); preserve = true; comment = true; } else { end = b[a + 1] + "}"; types.push("template"); } if (b[a + 1] === "@" && b[a + 2] === "}" && b[a + 3] === "e" && b[a + 4] === "l" && b[a + 5] === "s" && b[a + 6] === "e" && b[a + 7] === "{" && b[a + 8] === "@" && b[a + 9] === "}") { a = a + 9; types[types.length - 1] = "template_else"; presv.push(true); daddy.push(parent[parent.length - 1][0]); begin.push(parent[parent.length - 1][1]); attrs.push({}); stats.template[0] = stats.template[0] + 1; stats.template[1] = stats.template[1] + 10; earlyexit = true; return token.push("{@}else{@}"); } } else if (b[a] === "[" && b[a + 1] === "%") { end = "%]"; types.push("template"); } else if (b[a] === "#" && options.apacheVelocity === true) { if (b[a + 1] === "*") { preserve = true; comment = true; end = "*#"; types.push("comment"); } else if (b[a + 1] === "[" && b[a + 2] === "[") { preserve = true; comment = true; end = "]]#"; types.push("comment"); } else if (b[a + 1] === "#") { preserve = true; comment = true; end = "\n"; types.push("comment"); } else if (b[a + 1] === "e" && b[a + 2] === "l" && b[a + 3] === "s" && b[a + 4] === "e" && (/\s/).test(b[a + 5]) === true) { end = "\n"; types.push("template_else"); } else if (b[a + 1] === "i" && b[a + 2] === "f") { end = "\n"; types.push("template_start"); } else if (b[a + 1] === "f" && b[a + 2] === "o" && b[a + 3] === "r" && b[a + 4] === "e" && b[a + 5] === "a" && b[a + 6] === "c" && b[a + 7] === "h") { end = "\n"; types.push("template_start"); } else if (b[a + 1] === "e" && b[a + 2] === "n" && b[a + 3] === "d") { end = "\n"; types.push("template_end"); } else { end = "\n"; types.push("template"); } } else if (b[a] === "$" && options.apacheVelocity === true) { end = "\n"; types.push("template"); } if (options.unformatted === true) { preserve = true; } }()); if (earlyexit === true) { return; } // This loop is the logic that parses tags and attributes If the attribute // data-prettydiff-ignore is present the `ignore` flag is set The ignore flag is // identical to the preserve flag lastchar = end.charAt(end.length - 1); for (a = a; a < c; a = a + 1) { if (b[a] === "\n") { line = line + 1; } if (preserve === true || (/\s/).test(b[a]) === false) { lexer.push(b[a]); } else if (lexer[lexer.length - 1] !== " ") { lexer.push(" "); } if (comment === true) { quote = ""; //comments must ignore fancy encapsulations and attribute parsing if (b[a] === lastchar && lexer.length > end.length + 1) { //if current character matches the last character of the tag ending sequence f = lexer.length; for (e = end.length - 1; e > -1; e = e - 1) { f = f - 1; if (lexer[f] !== end.charAt(e)) { break; } } if (e < 0) { if (end === "endcomment") { f = f - 1; if ((/\s/).test(lexer[f]) === true) { do { f = f - 1; } while ((/\s/).test(lexer[f]) === true); } if (lexer[f - 1] === "{" && lexer[f] === "%") { end = "%}"; lastchar = "}"; } } else { break; } } } } else { if (quote === "") { if (options.jsx === true) { if (b[a] === "{") { jsxcount = jsxcount + 1; } else if (b[a] === "}") { jsxcount = jsxcount - 1; } } if (types[types.length - 1] === "sgml" && b[a] === "[" && lexer.length > 4) { types[types.length - 1] = "template_start"; break; } if (b[a] === "<" && preserve === false && lexer.length > 1 && end !== ">>" && end !== ">>>" && simple === true) { parseError.push("Parse error on line " + line + " on element: "); parseFail = true; } if (stest === true && (/\s/).test(b[a]) === false && b[a] !== lastchar) { //attribute start stest = false; quote = jsxquote; igcount = 0; lexer.pop(); for (a = a; a < c; a = a + 1) { if (b[a] === "\n") { line = line + 1; } if (options.unformatted === true) { lexer.push(b[a]); } attribute.push(b[a]); if ((b[a] === "<" || b[a] === ">") && (quote === "" || quote === ">") && options.jsx === false) { if (quote === "" && b[a] === "<") { quote = ">"; braccount = 1; } else if (quote === ">") {