// get accurate timing. // This file must be loaded after prettify.js for this to work. PR_SHOULD_USE_CONTINUATION = false; var attribToHtml, textToHtml; var getInnerHtml; (function () { /** is the given node's innerHTML normally unescaped? */ function isRawContent(node) { return 'XMP' === node.tagName; } var newlineRe = /[\r\n]/g; /** * Are newlines and adjacent spaces significant in the given node's innerHTML? */ function isPreformatted(node, content) { // PRE means preformatted, and is a very common case, so don't create // unnecessary computed style objects. if ('PRE' === node.tagName) { return true; } if (!newlineRe.test(content)) { return true; } // Don't care var whitespace = ''; // For disconnected nodes, IE has no currentStyle. if (node.currentStyle) { whitespace = node.currentStyle.whiteSpace; } else if (window.getComputedStyle) { // Firefox makes a best guess if node is disconnected whereas Safari // returns the empty string. whitespace = window.getComputedStyle(node, null).whiteSpace; } return !whitespace || whitespace === 'pre'; } // Define regexps here so that the interpreter doesn't have to create an // object each time the function containing them is called. // The language spec requires a new object created even if you don't access // the $1 members. var pr_amp = /&/g; var pr_lt = //g; var pr_quot = /\"/g; /** escapest html special characters to html. */ textToHtml = function (str) { return str.replace(pr_amp, '&') .replace(pr_lt, '<') .replace(pr_gt, '>'); }; /** like textToHtml but escapes double quotes to be attribute safe. */ attribToHtml = function (str) { return str.replace(pr_amp, '&') .replace(pr_lt, '<') .replace(pr_gt, '>') .replace(pr_quot, '"'); }; var PR_innerHtmlWorks = null; getInnerHtml = function (node) { // inner html is hopelessly broken in Safari 2.0.4 when the content is // an html description of well formed XML and the containing tag is a PRE // tag, so we detect that case and emulate innerHTML. if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild( document.createTextNode('\n')); PR_innerHtmlWorks = !/)[\r\n]+/g, '$1') .replace(/(?:[\r\n]+[ \t]*)+/g, ' '); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); }; })(); function normalizedHtml(node, out, opt_sortAttrs) { switch (node.nodeType) { case 1: // an element var name = node.tagName.toLowerCase(); out.push('<', name); var attrs = node.attributes; var n = attrs.length; if (n) { if (opt_sortAttrs) { var sortedAttrs = []; for (var i = n; --i >= 0;) { sortedAttrs[i] = attrs[i]; } sortedAttrs.sort(function (a, b) { return (a.name < b.name) ? -1 : a.name === b.name ? 0 : 1; }); attrs = sortedAttrs; } for (var i = 0; i < n; ++i) { var attr = attrs[i]; if (!attr.specified) { continue; } out.push(' ', attr.name.toLowerCase(), '="', attribToHtml(attr.value), '"'); } } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out, opt_sortAttrs); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 3: case 4: // text out.push(textToHtml(node.nodeValue)); break; } } /** * @param golden a mapping from IDs of prettyprinted chunks to an abbreviated * form of the expected output. See "var goldens" in prettify_test.html * for an example. */ function go(goldens) { startClock(); prettyPrint(function () { stopClock(); runTests(goldens); }); } function runTests(goldens) { /** number of characters in common at the end up to max. */ function commonPrefix(a, b) { var n = Math.min(a.length, b.length); var i; for (i = 0; i < n; ++i) { if (a.charAt(i) !== b.charAt(i)) { break; } } return i; } /** number of characters in common at the end up to max. */ function commonSuffix(a, b, max) { var n = Math.min(a.length - max, b.length - max); var i; for (i = 0; i < n; ++i) { if (a.charAt(a.length - i - 1) !== b.charAt(b.length - i - 1)) { break; } } return i; } /** convert a plain text string to html by escaping html special chars. */ function html(plainText) { return attribToHtml(plainText).replace(/\xa0/g, ' '); } /** * get normalized markup. innerHTML varies enough across browsers that we * can't use it. */ function normalizedInnerHtml(node) { var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out, true); } out = out.join(''); // more normalization to work around problems with non-ascii chars in // regexps in Safari for (var i = 0; (i = out.indexOf('\xa0')) >= 0;) { out = out.substring(0, i) + ' ' + out.substring(i + 1); } return out.replace(/\r\n?/g, '\n'); } var htmlOut = []; var failures = 0; document.getElementById('errorReport').innerHTML = '

Running tests…<\/h1>'; htmlOut.push('

Test results<\/h1>'); for (var lang in goldens) { var container = document.getElementById(lang); // Convert abbreviations that start with `. var golden = goldens[lang].replace(/`([A-Z]{3})/g, function (_, lbl) { return (lbl == 'END' ? '<\/span>' : ''); }) // Line numbers .replace(/`#(?![0-9])/, '
  • ') .replace(/`#([0-9])/g, '
  • '); var actual = normalizedInnerHtml(container); if (golden !== actual) { // test failed // write out var pre = commonPrefix(golden, actual); var post = commonSuffix(golden, actual, pre); ++failures; htmlOut.push( '

    ' + html(lang) + '<\/a> Failed<\/h2>'); htmlOut.push( '' + html(golden.substring(0, pre)) + '»' + html(golden.substring(pre, golden.length - post)) + '<\/span>«' + html(golden.substring(golden.length - post)) + '
    !==
    ' + html(actual.substring(0, pre)) + '»' + html(actual.substring(pre, actual.length - post)) + '<\/span>«' + html(actual.substring(actual.length - post)) + '<\/tt>'); } else { htmlOut.push( '

    ' + html(lang) + '<\/a> OK<\/h2>'); } } var summary = ( failures ? (failures + ' test' + (failures === 1 ? '' : 's') + ' failed') : 'Tests Passed'); var summaryStr = '

    ' + summary + '<\/h2>'; htmlOut.push(summaryStr); htmlOut.splice(0, 0, summaryStr); document.title += ' \u2014 ' + summary; document.getElementById('errorReport').innerHTML = htmlOut.join('').replace(/<br>/g, '<br>\n'); } var startTime = null; function startClock() { startTime = (new Date).getTime(); } function stopClock() { var delta = (new Date).getTime() - startTime; startTime = null; document.getElementById('timing').innerHTML = 'Took ' + delta + ' ms'; }