1(function(window, module, undefined) { 2 'use strict'; 3 4 var Defiant = { 5 is_ie: /(msie|trident)/i.test(navigator.userAgent), 6 is_safari: /safari/i.test(navigator.userAgent), 7 env: 'production', 8 xml_decl: '<?xml version="1.0" encoding="utf-8"?>', 9 namespace: 'xmlns:d="defiant-namespace"', 10 tabsize: 4, 11 render: function(template, data) { 12 var processor = new XSLTProcessor(), 13 span = document.createElement('span'), 14 opt = { match: '/' }, 15 tmpltXpath, 16 scripts, 17 temp, 18 sorter; 19 // handle arguments 20 switch (typeof(template)) { 21 case 'object': 22 this.extend(opt, template); 23 if (!opt.data) opt.data = data; 24 break; 25 case 'string': 26 opt.template = template; 27 opt.data = data; 28 break; 29 default: 30 throw 'error'; 31 } 32 opt.data = JSON_FUNCTIONS.toXML(opt.data); 33 tmpltXpath = '//xsl:template[@name="' + opt.template + '"]'; 34 35 if (!this.xsl_template) this.gatherTemplates(); 36 37 if (opt.sorter) { 38 sorter = this.node.selectSingleNode(this.xsl_template, tmpltXpath + '//xsl:for-each//xsl:sort'); 39 if (sorter) { 40 if (opt.sorter.order) sorter.setAttribute('order', opt.sorter.order); 41 if (opt.sorter.select) sorter.setAttribute('select', opt.sorter.select); 42 sorter.setAttribute('data-type', opt.sorter.type || 'text'); 43 } 44 } 45 46 temp = this.node.selectSingleNode(this.xsl_template, tmpltXpath); 47 temp.setAttribute('match', opt.match); 48 processor.importStylesheet(this.xsl_template); 49 span.appendChild(processor.transformToFragment(opt.data, document)); 50 temp.removeAttribute('match'); 51 52 if (this.is_safari) { 53 scripts = span.getElementsByTagName('script'); 54 for (var i = 0, il = scripts.length; i < il; i++) scripts[i].defer = true; 55 } 56 return span.innerHTML; 57 }, 58 gatherTemplates: function() { 59 var scripts = document.getElementsByTagName('script'), 60 str = '', 61 i = 0, 62 il = scripts.length; 63 for (; i < il; i++) { 64 if (scripts[i].type === 'defiant/xsl-template') str += scripts[i].innerHTML; 65 } 66 this.xsl_template = this.xmlFromString('<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ' + this.namespace + '>' + str.replace(/defiant:(\w+)/g, '$1') + '</xsl:stylesheet>'); 67 }, 68 getSnapshot: function(data, callback) { 69 return JSON_FUNCTIONS.toXML(data, callback || true); 70 }, 71 xmlFromString: function(str) { 72 var parser, 73 doc; 74 str = str.replace(/>\s{1,}</g, '><'); 75 if (str.trim().match(/<\?xml/) === null) { 76 str = this.xml_decl + str; 77 } 78 if ('ActiveXObject' in window) { 79 doc = new ActiveXObject('Msxml2.DOMDocument'); 80 doc.loadXML(str); 81 doc.setProperty('SelectionNamespaces', this.namespace); 82 if (str.indexOf('xsl:stylesheet') === -1) { 83 doc.setProperty('SelectionLanguage', 'XPath'); 84 } 85 } else { 86 parser = new DOMParser(); 87 doc = parser.parseFromString(str, 'text/xml'); 88 } 89 return doc; 90 }, 91 extend: function(src, dest) { 92 for (var content in dest) { 93 if (!src[content] || typeof(dest[content]) !== 'object') { 94 src[content] = dest[content]; 95 } else { 96 this.extend(src[content], dest[content]); 97 } 98 } 99 return src; 100 }, 101 node: {} 102 }; 103 104 // Export 105 window.Defiant = module.exports = Defiant; 106 107})( 108 typeof window !== 'undefined' ? window : {}, 109 typeof module !== 'undefined' ? module : {} 110); 111 112// extending STRING 113if (!String.prototype.fill) { 114 String.prototype.fill = function(i, c) { 115 var str = this; 116 c = c || ' '; 117 for (; str.length < i; str += c) {} 118 return str; 119 }; 120} 121 122if (!String.prototype.trim) { 123 String.prototype.trim = function() { 124 return this.replace(/^\s+|\s+$/gm, ''); 125 }; 126} 127 128if (!String.prototype.xTransform) { 129 String.prototype.xTransform = function() { 130 var str = this; 131 if (this.indexOf('translate(') === -1) { 132 str = this.replace(/contains\(([^,]+),([^\\)]+)\)/g, function(c, h, n) { 133 var a = 'abcdefghijklmnopqrstuvwxyz'; 134 return "contains(translate(" + h + ", \"" + a.toUpperCase() + "\", \"" + a + "\")," + n.toLowerCase() + ")"; 135 }); 136 } 137 return str.toString(); 138 }; 139} 140 141if (typeof(XSLTProcessor) === 'undefined') { 142 143 // emulating XSLT Processor (enough to be used in defiant) 144 var XSLTProcessor = function() {}; 145 XSLTProcessor.prototype = { 146 importStylesheet: function(xsldoc) { 147 this.xsldoc = xsldoc; 148 }, 149 transformToFragment: function(data, doc) { 150 var str = data.transformNode(this.xsldoc), 151 span = document.createElement('span'); 152 span.innerHTML = str; 153 return span; 154 } 155 }; 156 157} else if (typeof(XSLTProcessor) !== 'function' && !XSLTProcessor) { 158 159 // throw error 160 throw 'XSLTProcessor transformNode not implemented'; 161 162} 163 164/* jshint ignore:start */ 165if (typeof(JSON) === 'undefined') { 166 window.JSON = { 167 parse: function(sJSON) { return eval("(" + sJSON + ")"); },
168 stringify: function(vContent) { 169 if (vContent instanceof Object) { 170 var sOutput = ""; 171 if (vContent.constructor === Array) { 172 for (var nId = 0; nId < vContent.length; sOutput += this.stringify(vContent[nId]) + ",", nId++); 173 return "[" + sOutput.substr(0, sOutput.length - 1) + "]"; 174 } 175 if (vContent.toString !== Object.prototype.toString) { 176 return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\""; 177 } 178 for (var sProp in vContent) { 179 sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringify(vContent[sProp]) + ","; 180 } 181 return "{" + sOutput.substr(0, sOutput.length - 1) + "}"; 182 } 183 return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent); 184 } 185 }; 186} 187/* jshint ignore:end */ 188JSON_FUNCTIONS = {}; 189 190jsonFunctions = function() { 191 // if (!JSON_FUNCTIONS.search) { 192 JSON_FUNCTIONS.search = function(tree, xpath, single) { 193 'use strict'; 194 195 var isSnapshot = tree.doc && tree.doc.nodeType, 196 doc = isSnapshot ? tree.doc : JSON_FUNCTIONS.toXML(tree), 197 map = isSnapshot ? tree.map : this.search.map, 198 src = isSnapshot ? tree.src : tree, 199 xres = Defiant.node[single ? 'selectSingleNode' : 'selectNodes'](doc, xpath.xTransform()), 200 ret = [], 201 mapIndex, 202 i; 203 204 if (single) xres = [xres]; 205 i = xres.length; 206 207 while (i--) { 208 switch (xres[i].nodeType) { 209 case 2: 210 case 3: 211 ret.unshift(xres[i].nodeValue); 212 break; 213 default: 214 mapIndex = +xres[i].getAttribute('d:mi'); 215 //if (map[mapIndex-1] !== false) { 216 ret.unshift(map[mapIndex - 1]); 217 //} 218 } 219 } 220 221 // if environment = development, add search tracing 222 if (Defiant.env === 'development') { 223 this.trace = JSON_FUNCTIONS.mtrace(src, ret, xres); 224 } 225 226 return ret; 227 }; 228 // } 229 230 // if (!JSON.toXML) { 231 JSON_FUNCTIONS.toXML = function(tree, callback) { 232 'use strict'; 233 234 var interpreter = { 235 map: [], 236 rx_validate_name: /^(?!xml)[a-z_][\w\d.:]*$/i, 237 rx_node: /<(.+?)( .*?)>/, 238 rx_constructor: /<(.+?)( d:contr=".*?")>/, 239 rx_namespace: / xmlns\:d="defiant\-namespace"/, 240 rx_data: /(<.+?>)(.*?)(<\/d:data>)/i, 241 rx_function: /function (\w+)/i, 242 namespace: 'xmlns:d="defiant-namespace"', 243 to_xml_str: function(tree) { 244 return { 245 str: this.hash_to_xml(null, tree), 246 map: this.map 247 }; 248 }, 249 hash_to_xml: function(name, tree, array_child) { 250 var is_array = tree.constructor === Array, 251 self = this, 252 elem = [], 253 attr = [], 254 key, 255 val, 256 val_is_array, 257 type, 258 is_attr, 259 cname, 260 constr, 261 cnName, 262 i, 263 il, 264 fn = function(key, tree) { 265 val = tree[key]; 266 if (val === null || val === undefined || val.toString() === 'NaN') val = null; 267 268 is_attr = key.slice(0, 1) === '@'; 269 cname = array_child ? name : key; 270 if (cname == +cname && tree.constructor !== Object) cname = 'd:item'; 271 if (val === null) { 272 constr = null; 273 cnName = false;
274 } else { 275 constr = val.constructor; 276 cnName = constr.toString().match(self.rx_function)[1]; 277 } 278 279 if (is_attr) { 280 attr.push(cname.slice(1) + '="' + self.escape_xml(val) + '"'); 281 if (cnName !== 'String') attr.push('d:' + cname.slice(1) + '="' + cnName + '"'); 282 } else if (val === null) { 283 elem.push(self.scalar_to_xml(cname, val)); 284 } else { 285 switch (constr) { 286 case Function: 287 // if constructor is function, then it's not a JSON structure 288 throw 'JSON data should not contain functions. Please check your structure.'; 289 /* falls through */ 290 case Object: 291 elem.push(self.hash_to_xml(cname, val)); 292 break; 293 case Array: 294 if (key === cname) { 295 val_is_array = val.constructor === Array; 296 if (val_is_array) { 297 i = val.length; 298 while (i--) { 299 if (val[i] === null || !val[i] || val[i].constructor === Array) val_is_array = true; 300 if (!val_is_array && val[i].constructor === Object) val_is_array = true; 301 } 302 } 303 elem.push(self.scalar_to_xml(cname, val, val_is_array)); 304 break; 305 } 306 /* falls through */ 307 case String: 308 if (typeof(val) === 'string') { 309 val = val.toString().replace(/\&/g, '&') 310 .replace(/\r|\n/g, ' '); 311 } 312 if (cname === '#text') { 313 // prepare map 314 self.map.push(tree); 315 attr.push('d:mi="' + self.map.length + '"'); 316 attr.push('d:constr="' + cnName + '"'); 317 elem.push(self.escape_xml(val)); 318 break; 319 } 320 /* falls through */ 321 case Number: 322 case Boolean: 323 if (cname === '#text' && cnName !== 'String') { 324 // prepare map 325 self.map.push(tree); 326 attr.push('d:mi="' + self.map.length + '"'); 327 attr.push('d:constr="' + cnName + '"'); 328 elem.push(self.escape_xml(val)); 329 break; 330 } 331 elem.push(self.scalar_to_xml(cname, val)); 332 break; 333 } 334 } 335 }; 336 if (tree.constructor === Array) { 337 i = 0; 338 il = tree.length; 339 for (; i < il; i++) { 340 fn(i.toString(), tree); 341 } 342 } else { 343 for (key in tree) { 344 fn(key, tree); 345 } 346 } 347 if (!name) { 348 name = 'd:data'; 349 attr.push(this.namespace); 350 if (is_array) attr.push('d:constr="Array"'); 351 } 352 if (name.match(this.rx_validate_name) === null) { 353 attr.push('d:name="' + name + '"'); 354 name = 'd:name'; 355 } 356 if (array_child) return elem.join(''); 357 // prepare map 358 this.map.push(tree); 359 attr.push('d:mi="' + this.map.length + '"'); 360 361 return '<' + name + (attr.length ? ' ' + attr.join(' ') : '') + (elem.length ? '>' + elem.join('') + '</' + name + '>' : '/>'); 362 }, 363 scalar_to_xml: function(name, val, override) { 364 var attr = '', 365 text, 366 constr, 367 cnName; 368 369 // check whether the nodename is valid 370 if (name.match(this.rx_validate_name) === null) { 371 attr += ' d:name="' + name + '"'; 372 name = 'd:name'; 373 override = false;
374 } 375 if (val === null || val.toString() === 'NaN') val = null; 376 if (val === null) return '<' + name + ' d:constr="null"/>'; 377 if (val.length === 1 && val.constructor === Array && !val[0]) { 378 return '<' + name + ' d:constr="null" d:type="ArrayItem"/>'; 379 } 380 if (val.length === 1 && val[0].constructor === Object) { 381 382 text = this.hash_to_xml(false, val[0]); 383 384 var a1 = text.match(this.rx_node), 385 a2 = text.match(this.rx_constructor); 386 a1 = (a1 !== null) ? a1[2] 387 .replace(this.rx_namespace, '') 388 .replace(/>/, '') 389 .replace(/"\/$/, '"') : ''; 390 a2 = (a2 !== null) ? a2[2] : ''; 391 392 text = text.match(this.rx_data); 393 text = (text !== null) ? text[2] : ''; 394 395 return '<' + name + a1 + ' ' + a2 + ' d:type="ArrayItem">' + text + '</' + name + '>'; 396 } else if (val.length === 0 && val.constructor === Array) { 397 return '<' + name + ' d:constr="Array"/>'; 398 } 399 // else 400 if (override) { 401 return this.hash_to_xml(name, val, true); 402 } 403 404 constr = val.constructor; 405 cnName = constr.toString().match(this.rx_function)[1]; 406 text = (constr === Array) ? this.hash_to_xml('d:item', val, true) : 407 this.escape_xml(val); 408 409 attr += ' d:constr="' + cnName + '"'; 410 // prepare map 411 this.map.push(val); 412 attr += ' d:mi="' + this.map.length + '"'; 413 414 return (name === '#text') ? this.escape_xml(val) : '<' + name + attr + '>
414' + text + '</' + name + '>'; 415 }, 416 escape_xml: function(text) { 417 return String(text).replace(/</g, '<') 418 .replace(/>/g, '>') 419 .replace(/"/g, '"') 420 .replace(/ /g, ' '); 421 } 422 }, 423 processed, 424 doc, 425 task; 426 // depending on request 427 switch (typeof callback) { 428 case 'function': 429 // compile interpreter with 'x10.js' 430 task = x10.compile(interpreter); 431 432 // parse in a dedicated thread 433 task.to_xml_str(tree, function(processed) { 434 // snapshot distinctly improves performance 435 callback({ 436 doc: Defiant.xmlFromString(processed.str), 437 src: tree, 438 map: processed.map 439 }); 440 }); 441 return; 442 case 'boolean': 443 processed = interpreter.to_xml_str.call(interpreter, tree); 444 // return snapshot 445 return { 446 doc: Defiant.xmlFromString(processed.str), 447 src: tree, 448 map: processed.map 449 }; 450 default: 451 processed = interpreter.to_xml_str.call(interpreter, tree); 452 doc = Defiant.xmlFromString(processed.str); 453 454 this.search.map = processed.map; 455 return doc; 456 } 457 }; 458 // } 459 460 // if (!JSON.mtrace) { 461 JSON_FUNCTIONS.mtrace = function(root, hits, xres) { 462 'use strict'; 463 464 var win = window, 465 stringify = JSON.stringify, 466 sroot = stringify(root, null, '\t').replace(/\t/g, ''), 467 trace = [], 468 i = 0, 469 il = xres.length, 470 od = il ? xres[i].ownerDocument.documentElement : false, 471 map = this.search.map, 472 hstr, 473 cConstr, 474 fIndex = 0, 475 mIndex, 476 lStart, 477 lEnd; 478 479 for (; i < il; i++) { 480 switch (xres[i].nodeType) { 481 case 2: 482 cConstr = xres[i].ownerElement ? xres[i].ownerElement.getAttribute('d:' + xres[i].nodeName) : 'String'; 483 hstr = '"@' + xres[i].nodeName + '": ' + win[cConstr](hits[i]); 484 mIndex = sroot.indexOf(hstr); 485 lEnd = 0; 486 break; 487 case 3: 488 cConstr = xres[i].parentNode.getAttribute('d:constr'); 489 hstr = win[cConstr](hits[i]); 490 hstr = '"' + xres[i].parentNode.nodeName + '": ' + (hstr === 'Number' ? hstr : '"' + hstr + '"'); 491 mIndex = sroot.indexOf(hstr); 492 lEnd = 0; 493 break; 494 default: 495 if (xres[i] === od) continue; 496 if (xres[i].getAttribute('d:constr') === 'String' || xres[i].getAttribute('d:constr') === 'Number') { 497 cConstr = xres[i].getAttribute('d:constr'); 498 hstr = win[cConstr](hits[i]); 499 mIndex = sroot.indexOf(hstr, fIndex); 500 hstr = '"' + xres[i].nodeName + '": ' + (cConstr === 'Number' ? hstr : '"' + hstr + '"'); 501 lEnd = 0; 502 fIndex = mIndex + 1; 503 } else { 504 hstr = stringify(hits[i], null, '\t').replace(/\t/g, ''); 505 mIndex = sroot.indexOf(hstr); 506 lEnd = hstr.match(/\n/g).length; 507 } 508 } 509 lStart = sroot.substring(0, mIndex).match(/\n/g).length + 1; 510 trace.push([lStart, lEnd]); 511 } 512 513 return trace; 514 }; 515 // } 516} 517 518jsonFunctions(); 519Defiant.jsonFunctions = jsonFunctions; 520 521Defiant.node.toJSON = function(xnode, stringify) { 522 'use strict'; 523 524 var interpret = function(leaf) { 525 var obj = {}, 526 win = window, 527 attr, 528 type, 529 item, 530 cname, 531 cConstr, 532 cval, 533 text, 534 i, il, a; 535 536 switch (leaf.nodeType) { 537 case 1: 538 cConstr = leaf.getAttribute('d:constr'); 539 if (cConstr === 'Array') obj = []; 540 else if (cConstr === 'String' && leaf.textContent === '') obj = ''; 541 542 attr = leaf.attributes; 543 i = 0; 544 il = attr.length; 545 for (; i < il; i++) { 546 a = attr.item(i); 547 if (a.nodeName.match(/\:d|d\:/g) !== null) continue; 548 549 cConstr = leaf.getAttribute('d:' + a.nodeName); 550 if (cConstr && cConstr !== 'undefined') { 551 if (a.nodeValue === 'null') cval = null; 552 else cval = win[cConstr]((a.nodeValue === 'false') ? '' : a.nodeValue); 553 } else { 554 cval = a.nodeValue; 555 } 556 obj['@' + a.nodeName] = cval; 557 } 558 break; 559 case 3: 560 type = leaf.parentNode.getAttribute('d:type'); 561 cval = (type) ? win[type](leaf.nodeValue === 'false' ? '' : leaf.nodeValue) : leaf.nodeValue; 562 obj = cval; 563 break; 564 } 565 if (leaf.hasChildNodes()) { 566 i = 0; 567 il = leaf.childNodes.length; 568 for (; i < il; i++) { 569 item = leaf.childNodes.item(i); 570 cname = item.nodeName; 571 attr = leaf.attributes; 572 573 if (cname === 'd:name') { 574 cname = item.getAttribute('d:name'); 575 } 576 if (cname === '#text') { 577 cConstr = leaf.getAttribute('d:constr'); 578 if (cConstr === 'undefined') cConstr = undefined; 579 text = item.textContent || item.text; 580 cval = cConstr === 'Boolean' && text === 'false' ? '' : text; 581 582 if (!cConstr && !attr.length) obj = cval; 583 else if (cConstr && il === 1) { 584 obj = win[cConstr](cval); 585 } else if (!leaf.hasChildNodes()) { 586 obj[cname] = (cConstr) ? win[cConstr](cval) : cval; 587 } else { 588 if (attr.length < 3) obj = (cConstr) ? win[cConstr](cval) : cval; 589 else obj[cname] = (cConstr) ? win[cConstr](cval) : cval; 590 } 591 } else { 592 if (item.getAttribute('d:constr') === 'null') { 593 if (obj[cname] && obj[cname].push) obj[cname].push(null); 594 else if (item.getAttribute('d:type') === 'ArrayItem') obj[cname] = [obj[cname]]; 595 else obj[cname] = null; 596 continue; 597 } 598 if (obj[cname]) { 599 if (obj[cname].push) obj[cname].push(interpret(item)); 600 else obj[cname] = [obj[cname], interpret(item)]; 601 continue; 602 } 603 cConstr = item.getAttribute('d:constr'); 604 switch (cConstr) { 605 case 'null': 606 if (obj.push) obj.push(null); 607 else obj[cname] = null; 608 break; 609 case 'Array': 610 //console.log( Defiant.node.prettyPrint(item) ); 611 if (item.parentNode.firstChild === item && cConstr === 'Array' && cname !== 'd:item') { 612 if (cname === 'd:item' || cConstr === 'Array') { 613 cval = interpret(item); 614 obj[cname] = cval.length ? [cval] : cval; 615 } else { 616 obj[cname] = interpret(item); 617 } 618 } else if (obj.push) obj.push(interpret(item)); 619 else obj[cname] = interpret(item); 620 break; 621 case 'String': 622 case 'Number': 623 case 'Boolean': 624 text = item.textContent || item.text; 625 cval = cConstr === 'Boolean' && text === 'false' ? '' : text; 626 627 if (obj.push) obj.push(win[cConstr](cval)); 628 else obj[cname] = interpret(item); 629 break; 630 default: 631 if (obj.push) obj.push(interpret(item)); 632 else obj[cname] = interpret(item); 633 } 634 } 635 } 636 } 637 if (leaf.nodeType === 1 && leaf.getAttribute('d:type') === 'ArrayItem') { 638 obj = [obj]; 639 } 640 return obj; 641 }, 642 node = (xnode.nodeType === 9) ? xnode.documentElement : xnode, 643 ret = interpret(node),
644 rn = ret[node.nodeName]; 645 646 // exclude root, if "this" is root node 647 if (node === node.ownerDocument.documentElement && rn && rn.constructor === Array) { 648 ret = rn; 649 } 650 if (stringify && stringify.toString() === 'true') stringify = '\t'; 651 return stringify ? JSON.stringify(ret, null, stringify) : ret; 652}; 653 654Defiant.node.selectNodes = function(XNode, XPath) { 655 if (XNode.evaluate) { 656 var ns = XNode.createNSResolver(XNode.documentElement), 657 qI = XNode.evaluate(XPath, XNode, ns, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), 658 res = [], 659 i = 0, 660 il = qI.snapshotLength; 661 for (; i < il; i++) { 662 res.push(qI.snapshotItem(i)); 663 } 664 return res; 665 } else { 666 return XNode.selectNodes(XPath); 667 } 668}; 669Defiant.node.selectSingleNode = function(XNode, XPath) { 670 if (XNode.evaluate) { 671 var xI = this.selectNodes(XNode, XPath); 672 return (xI.length > 0) ? xI[0] : null; 673 } else { 674 return XNode.selectSingleNode(XPath); 675 } 676}; 677 678Defiant.node.prettyPrint = function(node) { 679 var root = Defiant, 680 tabs = root.tabsize, 681 decl = root.xml_decl.toLowerCase(), 682 ser, 683 xstr; 684 if (root.is_ie) { 685 xstr = node.xml; 686 } else { 687 ser = new XMLSerializer(); 688 xstr = ser.serializeToString(node); 689 } 690 if (root.env !== 'development') { 691 // if environment is not development, remove defiant related info 692 xstr = xstr.replace(/ \w+\:d=".*?"| d\:\w+=".*?"/g, ''); 693 } 694 var str = xstr.trim().replace(/(>)\s*(<)(\/*)/g, '$1\n$2$3'), 695 lines = str.split('\n'), 696 indent = -1, 697 i = 0, 698 il = lines.length, 699 start, 700 end; 701 for (; i < il; i++) { 702 if (i === 0 && lines[i].toLowerCase() === decl) continue; 703 start = lines[i].match(/<[A-Za-z_\:]+.*?>/g) !== null; 704 //start = lines[i].match(/<[^\/]+>/g) !== null; 705 end = lines[i].match(/<\/[\w\:]+>/g) !== null; 706 if (lines[i].match(/<.*?\/>/g) !== null) start = end = true; 707 if (start) indent++; 708 lines[i] = String().fill(indent, '\t') + lines[i]; 709 if (start && end) indent--; 710 if (!start && end) indent--; 711 } 712 return lines.join('\n').replace(/\t/g, String().fill(tabs, ' ')); 713}; 714 715// check if jQuery is present 716if (typeof(jQuery) !== 'undefined') { 717 (function($) { 718 'use strict'; 719 720 $.fn.defiant = function(template, xpath) { 721 this.html(Defiant.render(template, xpath)); 722 return this; 723 }; 724 725 }(jQuery)); 726}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.