1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Copyright (C) 2006 Google Inc. 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License"); 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// you may not use this file except in compliance with the License. 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// You may obtain a copy of the License at 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// http://www.apache.org/licenses/LICENSE-2.0 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// Unless required by applicable law or agreed to in writing, software 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS, 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// See the License for the specific language governing permissions and 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// limitations under the License. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @fileoverview 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * some functions for browser-side pretty printing of code contained in html. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The lexer should work on a number of languages including C and friends, 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles. 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It works passably on Ruby, PHP and Awk and a decent subset of Perl, but, 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of commenting conventions, doesn't work on Smalltalk, Lisp-like, or 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * CAML-like languages. 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If there's a language not mentioned here, then I don't know it, and don't 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * know whether it works. If it has a C-like, Bash-like, or XML-like syntax 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then it should work passably. 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Usage: 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1) include this source file in an html page via 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <script type="text/javascript" src="/path/to/prettify.js"></script> 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2) define style rules. See the example page for examples. 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 3) mark the <pre> and <code> tags in your source with class=prettyprint. 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You can also use the (html deprecated) <xmp> tag, but the pretty printer 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * needs to do more substantial DOM manipulations to support that, so some 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * css styles may not be preserved. 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * That's it. I wanted to keep the API as simple as possible, so there's no 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to specify which language the code is in. 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Change log: 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cbeust, 2006/08/22 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Java annotations (start with "@") are now captured as literals ("lit") 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// JSLint declarations 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*global console, document, navigator, setTimeout, window */ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Split {@code prettyPrint} into multiple timeouts so as not to interfere with 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * UI events. 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If set to {@code false}, {@code prettyPrint()} is synchronous. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar PR_SHOULD_USE_CONTINUATION = true; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** the number of characters between tab columns */ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar PR_TAB_WIDTH = 8; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** Walks the DOM returning a properly escaped version of innerHTML. 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Node} node 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array.<string>} out output buffer that receives chunks of HTML. 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar PR_normalizedHtml; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** Contains functions for creating and registering new language handlers. 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @type {Object} 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar PR; 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** Pretty print a chunk of code. 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {string} sourceCodeHtml code as html 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {string} code as html, but prettier 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar prettyPrintOne; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** find all the < pre > and < code > tags in the DOM with class=prettyprint 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and prettify them. 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Function} opt_whenDone if specified, called when the last entry 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has been finished. 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvar prettyPrint; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** browser detection. @extern */ 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfunction _pr_isIE6() { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var isIE6 = navigator && navigator.userAgent && 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /\bMSIE 6\./.test(navigator.userAgent); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project _pr_isIE6 = function () { return isIE6; }; 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return isIE6; 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(function () { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Splits input on space and returns an Object mapping each non-empty part to 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * true. 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function wordSet(words) { 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project words = words.split(/ /g); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var set = {}; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = words.length; --i >= 0;) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var w = words[i]; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (w) { set[w] = null; } 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return set; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Keyword lists for various languages. 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var FLOW_CONTROL_KEYWORDS = 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "break continue do else for if return while "; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "double enum extern float goto int long register short signed sizeof " + 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "static struct switch typedef union unsigned void volatile "; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "new operator private protected public this throw true try "; 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "concept concept_map const_cast constexpr decltype " + 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "dynamic_cast explicit export friend inline late_check " + 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "mutable namespace nullptr reinterpret_cast static_assert static_cast " + 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "template typeid typename typeof using virtual wchar_t where "; 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var JAVA_KEYWORDS = COMMON_KEYWORDS + 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "boolean byte extends final finally implements import instanceof null " + 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "native package strictfp super synchronized throws transient "; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var CSHARP_KEYWORDS = JAVA_KEYWORDS + 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "as base by checked decimal delegate descending event " + 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "fixed foreach from group implicit in interface internal into is lock " + 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "object out override orderby params readonly ref sbyte sealed " + 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "stackalloc string select uint ulong unchecked unsafe ushort var "; 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "debugger eval export function get null set undefined var with " + 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "Infinity NaN "; 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "goto if import last local my next no our print package redo require " + 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "sub undef unless until use wantarray while BEGIN END "; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "elif except exec finally from global import in is lambda " + 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "nonlocal not or pass print raise try with yield " + 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "False True None "; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " defined elsif end ensure false in module next nil not or redo rescue " + 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "retry self super then true undef unless until when yield BEGIN END "; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "function in local set then until "; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var ALL_KEYWORDS = ( 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // token style names. correspond to css classes 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a string literal */ 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_STRING = 'str'; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a keyword */ 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_KEYWORD = 'kwd'; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a comment */ 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_COMMENT = 'com'; 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a type */ 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_TYPE = 'typ'; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a literal value. e.g. 1, null, true. */ 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_LITERAL = 'lit'; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a punctuation string. */ 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_PUNCTUATION = 'pun'; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a punctuation string. */ 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_PLAIN = 'pln'; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for an sgml tag. */ 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_TAG = 'tag'; 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for a markup declaration such as a DOCTYPE. */ 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_DECLARATION = 'dec'; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for embedded source. */ 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_SOURCE = 'src'; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for an sgml attribute name. */ 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_ATTRIB_NAME = 'atn'; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** token style for an sgml attribute value. */ 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_ATTRIB_VALUE = 'atv'; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A class that indicates a section of markup that is not code, e.g. to allow 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * embedding of line numbers within code listings. 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_NOCODE = 'nocode'; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function isWordChar(ch) { 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Splice one array into another. 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like the python <code> 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * container[containerPosition:containerPosition + countReplaced] = inserted 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </code> 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array} inserted 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array} container modified in place 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Number} containerPosition 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Number} countReplaced 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function spliceArrayInto( 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project inserted, container, containerPosition, countReplaced) { 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project inserted.unshift(containerPosition, countReplaced || 0); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project container.splice.apply(container, inserted); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } finally { 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project inserted.splice(0, 2); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** A set of tokens that can precede a regular expression literal in 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * javascript. 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list, but I've removed ones that might be problematic when seen in 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * languages that don't support regular expression literals. 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>Specifically, I've removed any keywords that can't precede a regexp 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * literal in a syntactically legal javascript program, and I've removed the 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "in" keyword since it's not a keyword in many languages, and might be used 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as a count of inches. 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var REGEXP_PRECEDER_PATTERN = function () { 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var preceders = [ 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=", 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";", 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "<", "<<", "<<=", "<=", "=", "==", "===", ">", 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "^", "^=", "^^", "^^=", "{", "|", "|=", "||", 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "||=", "~" /* handles =~ and !~ */, 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "break", "case", "continue", "delete", 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "do", "else", "finally", "instanceof", 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "return", "throw", "try", "typeof" 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ]; 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pattern = '(?:' + 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project '(?:(?:^|[^0-9.])\\.{1,3})|' + // a dot that's not part of a number 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project '(?:(?:^|[^\\+])\\+)|' + // allow + but not ++ 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project '(?:(?:^|[^\\-])-)'; // allow - but not -- 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < preceders.length; ++i) { 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var preceder = preceders[i]; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isWordChar(preceder.charAt(0))) { 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pattern += '|\\b' + preceder; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pattern += '|^)\\s*$'; // matches at end, and matches empty string 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new RegExp(pattern); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // CAVEAT: this does not properly handle the case where a regular 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // expression immediately follows another since a regular expression may 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // have flags for case-sensitivity and the like. Having regexp tokens 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // adjacent is not 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // valid in any language I'm aware of, so I'm punting. 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // TODO: maybe style special characters inside a regexp as punctuation. 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }(); 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Define regexps here so that the interpreter doesn't have to create an 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // object each time the function containing them is called. 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The language spec requires a new object created even if you don't access 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the $1 members. 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_amp = /&/g; 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_lt = /</g; 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_gt = />/g; 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_quot = /\"/g; 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** like textToHtml but escapes double quotes to be attribute safe. */ 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function attribToHtml(str) { 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return str.replace(pr_amp, '&') 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_lt, '<') 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_gt, '>') 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_quot, '"'); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** escapest html special characters to html. */ 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function textToHtml(str) { 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return str.replace(pr_amp, '&') 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_lt, '<') 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_gt, '>'); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_ltEnt = /</g; 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_gtEnt = />/g; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_aposEnt = /'/g; 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_quotEnt = /"/g; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_ampEnt = /&/g; 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_nbspEnt = / /g; 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** unescapes html to plain text. */ 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function htmlToText(html) { 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pos = html.indexOf('&'); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pos < 0) { return html; } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Handle numeric entities specially. We can't use functional substitution 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // since that doesn't work in older versions of Safari. 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // These should be rare since most browsers convert them to normal chars. 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0;) { 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var end = html.indexOf(';', pos); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (end >= 0) { 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var num = html.substring(pos + 3, end); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var radix = 10; 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (num && num.charAt(0) === 'x') { 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project num = num.substring(1); 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project radix = 16; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var codePoint = parseInt(num, radix); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!isNaN(codePoint)) { 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html = (html.substring(0, pos) + String.fromCharCode(codePoint) + 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.substring(end + 1)); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return html.replace(pr_ltEnt, '<') 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_gtEnt, '>') 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_aposEnt, "'") 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_quotEnt, '"') 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_ampEnt, '&') 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(pr_nbspEnt, ' '); 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** is the given node's innerHTML normally unescaped? */ 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function isRawContent(node) { 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 'XMP' === node.tagName; 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function normalizedHtml(node, out) { 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (node.nodeType) { 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 1: // an element 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var name = node.tagName.toLowerCase(); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push('<', name); 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < node.attributes.length; ++i) { 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attr = node.attributes[i]; 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!attr.specified) { continue; } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(' '); 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project normalizedHtml(attr, out); 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push('>'); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var child = node.firstChild; child; child = child.nextSibling) { 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project normalizedHtml(child, out); 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push('<\/', name, '>'); 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 2: // an attribute 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 3: case 4: // text 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(textToHtml(node.nodeValue)); 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_innerHtmlWorks = null; 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function getInnerHtml(node) { 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // inner html is hopelessly broken in Safari 2.0.4 when the content is 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // an html description of well formed XML and the containing tag is a PRE 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // tag, so we detect that case and emulate innerHTML. 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (null === PR_innerHtmlWorks) { 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var testNode = document.createElement('PRE'); 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project testNode.appendChild( 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project PR_innerHtmlWorks = !/</.test(testNode.innerHTML); 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (PR_innerHtmlWorks) { 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var content = node.innerHTML; 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // XMP tags contain unescaped entities so require special handling. 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isRawContent(node)) { 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project content = textToHtml(content); 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return content; 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var out = []; 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var child = node.firstChild; child; child = child.nextSibling) { 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project normalizedHtml(child, out); 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return out.join(''); 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** returns a function that expand tabs to spaces. This function can be fed 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * successive chunks of text, and will maintain its own internal state to 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * keep track of how tabs are expanded. 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {function (string) : string} a function that takes 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plain text and return the text with tabs expanded. 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function makeTabExpander(tabWidth) { 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var SPACES = ' '; 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var charInLine = 0; 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return function (plainText) { 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // walk over each character looking for tabs and newlines. 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // On tabs, expand them. On newlines, reset charInLine. 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Otherwise increment charInLine 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var out = null; 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pos = 0; 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0, n = plainText.length; i < n; ++i) { 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var ch = plainText.charAt(i); 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (ch) { 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '\t': 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!out) { out = []; } 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(plainText.substring(pos, i)); 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // calculate how much space we need in front of this part 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // nSpaces is the amount of padding -- the number of spaces needed 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // to move us to the next column, where columns occur at factors of 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // tabWidth. 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var nSpaces = tabWidth - (charInLine % tabWidth); 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project charInLine += nSpaces; 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (; nSpaces >= 0; nSpaces -= SPACES.length) { 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(SPACES.substring(0, nSpaces)); 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pos = i + 1; 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '\n': 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project charInLine = 0; 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ++charInLine; 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!out) { return plainText; } 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.push(plainText.substring(pos)); 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return out.join(''); 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The below pattern matches one of the following 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (1) /[^<]+/ : A run of characters other than '<' 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (2) /<!--.*?-->/: an HTML comment 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (3) /<!\[CDATA\[.*?\]\]>/: a cdata section 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (3) /<\/?[a-zA-Z][^>]*>/ : A probably tag that should not be highlighted 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (4) /</ : A '<' that does not begin a larger chunk. Treated as 1 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_chunkPattern = 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_commentPrefix = /^<!--/; 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_cdataPrefix = /^<\[CDATA\[/; 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_brPrefix = /^<br\b/i; 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** split markup into chunks of html tags (style null) and 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * plain text (style {@link #PR_PLAIN}), converting tags which are 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * significant for tokenization (<br>) into their textual equivalent. 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {string} s html where whitespace is considered significant. 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {Object} source code and extracted tags. 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function extractTags(s) { 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // since the pattern has the 'g' modifier and defines no capturing groups, 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // this will return a list of all chunks which we then classify and wrap as 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // PR_Tokens 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var matches = s.match(pr_chunkPattern); 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var sourceBuf = []; 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var sourceBufLen = 0; 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var extractedTags = []; 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (matches) { 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0, n = matches.length; i < n; ++i) { 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var match = matches[i]; 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (match.length > 1 && match.charAt(0) === '<') { 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pr_commentPrefix.test(match)) { continue; } 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pr_cdataPrefix.test(match)) { 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // strip CDATA prefix and suffix. Don't unescape since it's CDATA 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBuf.push(match.substring(9, match.length - 3)); 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBufLen += match.length - 12; 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (pr_brPrefix.test(match)) { 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // <br> tags are lexically significant so convert them to text. 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This is undone later. 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBuf.push('\n'); 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ++sourceBufLen; 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A <span class="nocode"> will start a section that should be 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ignored. Continue walking the list until we see a matching end 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // tag. 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var name = match.match(pr_tagNameRe)[2]; 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var depth = 1; 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end_tag_loop: 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = i + 1; j < n; ++j) { 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var name2 = matches[j].match(pr_tagNameRe); 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (name2 && name2[2] === name) { 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (name2[1] === '/') { 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (--depth === 0) { break end_tag_loop; } 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ++depth; 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (j < n) { 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extractedTags.push( 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBufLen, matches.slice(i, j + 1).join('')); 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i = j; 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { // Ignore unclosed sections. 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extractedTags.push(sourceBufLen, match); 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extractedTags.push(sourceBufLen, match); 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var literalText = htmlToText(match); 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBuf.push(literalText); 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceBufLen += literalText.length; 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return { source: sourceBuf.join(''), tags: extractedTags }; 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** True if the given tag contains a class attribute with the nocode class. */ 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function isNoCodeTag(tag) { 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return !!tag 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // First canonicalize the representation of attributes 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ' $1="$2$3$4"') 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Then look for the attribute we want. 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Given triples of [style, pattern, context] returns a lexing function, 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The lexing function interprets the patterns to find token boundaries and 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns a decoration list of the form 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [index_0, style_0, index_1, style_1, ..., index_n, style_n] 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * where index_n is an index into the sourceCode, and style_n is a style 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * all characters in sourceCode[index_n-1:index_n]. 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The stylePatterns is a list whose elements have the form 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [style : string, pattern : RegExp, context : RegExp, shortcut : string]. 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project & 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Style is a style constant like PR_PLAIN. 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pattern must only match prefixes, and if it matches a prefix and context 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is null or matches the last non-comment token parsed, then that match is 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * considered a token with the same style. 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Context is applied to the last non-whitespace, non-comment token 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * recognized. 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shortcut is an optional string of characters, any of which, if the first 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * character, gurantee that this pattern and only this pattern matches. 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array} shortcutStylePatterns patterns that always start with 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a known character. Must have a shortcut string. 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array} fallthroughStylePatterns patterns that will be tried in 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * order if the shortcut ones fail. May have shortcuts. 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {function (string, number?) : Array.<number|string>} a 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * function that takes source code and returns a list of decorations. 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function createSimpleLexer(shortcutStylePatterns, 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fallthroughStylePatterns) { 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var shortcuts = {}; 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (function () { 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = allPatterns.length; --i >= 0;) { 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var patternParts = allPatterns[i]; 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var shortcutChars = patternParts[3]; 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (shortcutChars) { 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var c = shortcutChars.length; --c >= 0;) { 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcuts[shortcutChars.charAt(c)] = patternParts; 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project })(); 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var nPatterns = fallthroughStylePatterns.length; 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var notWs = /\S/; 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return function (sourceCode, opt_basePos) { 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opt_basePos = opt_basePos || 0; 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorations = [opt_basePos, PR_PLAIN]; 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var lastToken = ''; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pos = 0; // index into sourceCode 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var tail = sourceCode; 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (tail.length) { 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var style; 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var token = null; 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var match; 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var patternParts = shortcuts[tail.charAt(0)]; 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (patternParts) { 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project match = tail.match(patternParts[1]); 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project token = match[0]; 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project style = patternParts[0]; 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < nPatterns; ++i) { 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project patternParts = fallthroughStylePatterns[i]; 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var contextPattern = patternParts[2]; 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (contextPattern && !contextPattern.test(lastToken)) { 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // rule can't be used 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project match = tail.match(patternParts[1]); 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (match) { 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project token = match[0]; 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project style = patternParts[0]; 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!token) { // make sure that we make progress 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project style = PR_PLAIN; 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project token = tail.substring(0, 1); 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations.push(opt_basePos + pos, style); 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pos += token.length; 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project tail = tail.substring(token.length); 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_MARKUP_LEXER = createSimpleLexer([], [ 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PLAIN, /^[^<]+/, null], 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_SOURCE, 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Tags whose content is not escaped, and which contain source code. 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_TAG, /^<\/?\w[^<>]*>/, null] 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ]); 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Splits any of the source|style|xmp entries above into a start tag, 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // source content, and end tag. 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** split markup on tags, comments, application directives, and other top 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * level constructs. Tags are returned as a single token - attributes are 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not yet broken out. 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function tokenizeMarkup(source) { 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorations = PR_MARKUP_LEXER(source); 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < decorations.length; i += 2) { 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (decorations[i + 1] === PR_SOURCE) { 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var start, end; 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Split out start and end script tags as actual tags, and leave the 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // body with style SCRIPT. 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var sourceChunk = source.substring(start, end); 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (match) { 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations.splice( 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i, 2, 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start, PR_TAG, // the open chunk 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start + match[1].length, PR_SOURCE, 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start + match[1].length + (match[2] || '').length, PR_TAG); 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var PR_TAG_LEXER = createSimpleLexer([ 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/='] 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ], [ 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_TAG, /^[\w:\-]+/, /^</], 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_ATTRIB_NAME, /^[\w:\-]+/, null], 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PLAIN, /^\s+/, null, ' \t\r\n'] 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ]); 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** split tags attributes and their values out from the tag name, and 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * recursively lex source chunks. 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function splitTagAttributes(source, decorations) { 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < decorations.length; i += 2) { 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var style = decorations[i + 1]; 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (style === PR_TAG) { 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var start, end; 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var chunk = source.substring(start, end); 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var subDecorations = PR_TAG_LEXER(chunk, start); 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spliceArrayInto(subDecorations, decorations, i, 2); 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i += subDecorations.length - 2; 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** returns a function that produces a list of decorations from source text. 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This code treats ", ', and ` as string delimiters, and \ as a string 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * escape. It does not recognize perl's qq() style strings. 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It has no special handling for double delimiter escapes as in basic, or 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the tripled delimiters used in python, but should work on those regardless 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * although in those cases a single string literal may be broken up into 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * multiple adjacent string literals. 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It recognizes C, C++, and shell style comments. 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Object} options a set of optional parameters. 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {function (string) : Array.<string|number>} a 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * decorator that takes sourceCode as plain text and that returns a 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * decoration list 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function sourceDecorator(options) { 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var shortcutStylePatterns = [], fallthroughStylePatterns = []; 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (options.tripleQuotedStrings) { 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // '''multi-line-string''', 'single-line-string', and double-quoted 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcutStylePatterns.push( 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project null, '\'"']); 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (options.multiLineStrings) { 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 'multi-line-string', "multi-line-string" 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcutStylePatterns.push( 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project null, '\'"`']); 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 'single-line-string', "single-line-string" 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcutStylePatterns.push( 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_STRING, 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project null, '"\'']); 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fallthroughStylePatterns.push( 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (options.hashComments) { 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (options.cStyleComments) { 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fallthroughStylePatterns.push( 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (options.regexLiterals) { 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var REGEX_LITERAL = ( 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A regular expression literal starts with a slash that is 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // not followed by * or / so that it is not confused with 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // comments. 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project '^/(?=[^/*])' 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // and then contains any number of raw characters, 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + '(?:[^/\\x5B\\x5C]' 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // escape sequences (\x5C), 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + '|\\x5C[\\s\\S]' 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // or non-nesting character sets (\x5B\x5D); 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // finally closed by a /. 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + '(?:/|$)'); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fallthroughStylePatterns.push( 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var keywords = wordSet(options.keywords); 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project options = null; 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** splits the given string into comment, string, and "other" tokens. 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {string} sourceCode as plain text 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {Array.<number|string>} a decoration list. 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var splitStringAndCommentTokens = createSimpleLexer( 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project shortcutStylePatterns, fallthroughStylePatterns); 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [ 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PLAIN, /^\s+/, null, ' \r\n'], 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // TODO(mikesamuel): recognize non-latin letters and numerals in idents 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A hex number 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // An octal or decimal number, possibly in scientific notation 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_LITERAL, 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project null, '123456789'], 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null] 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Fallback will handle decimal points not adjacent to a digit 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ]); 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** splits plain text tokens into more specific tokens, and then tries to 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * recognize keywords, and types. 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function splitNonStringNonCommentTokens(source, decorations) { 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < decorations.length; i += 2) { 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var style = decorations[i + 1]; 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (style === PR_PLAIN) { 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var start, end, chunk, subDecs; 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project chunk = source.substring(start, end); 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = 0, m = subDecs.length; j < m; j += 2) { 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var subStyle = subDecs[j + 1]; 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (subStyle === PR_PLAIN) { 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var subStart = subDecs[j]; 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var token = source.substring(subStart, subEnd); 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (token === '.') { 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subDecs[j + 1] = PR_PUNCTUATION; 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (token in keywords) { 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subDecs[j + 1] = PR_KEYWORD; 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // classify types and annotations using Java's style conventions 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spliceArrayInto(subDecs, decorations, i, 2); 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i += subDecs.length - 2; 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return function (sourceCode) { 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Split into strings, comments, and other. 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // We do this because strings and comments are easily recognizable and can 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // contain stuff that looks like other tokens, so we want to mark those 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // early so we don't recurse into them. 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorations = splitStringAndCommentTokens(sourceCode); 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Split non comment|string tokens on whitespace and word boundaries 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations = splitNonStringNonCommentTokens(sourceCode, decorations); 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorateSource = sourceDecorator({ 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: ALL_KEYWORDS, 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cStyleComments: true, 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project multiLineStrings: true, 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regexLiterals: true 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }); 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** identify regions of markup that are really source code, and recursivley 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lex them. 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function splitSourceNodes(source, decorations) { 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < decorations.length; i += 2) { 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var style = decorations[i + 1]; 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (style === PR_SOURCE) { 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Recurse using the non-markup lexer 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var start, end; 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var subDecorations = decorateSource(source.substring(start, end)); 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = 0, m = subDecorations.length; j < m; j += 2) { 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project subDecorations[j] += start; 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spliceArrayInto(subDecorations, decorations, i, 2); 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i += subDecorations.length - 2; 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** identify attribute values that really contain source code and recursively 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lex them. 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function splitSourceAttributes(source, decorations) { 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var nextValueIsSource = false; 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < decorations.length; i += 2) { 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var style = decorations[i + 1]; 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var start, end; 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (style === PR_ATTRIB_NAME) { 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (style === PR_ATTRIB_VALUE) { 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (nextValueIsSource) { 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = decorations[i]; 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project end = i + 2 < decorations.length ? decorations[i + 2] : source.length; 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribValue = source.substring(start, end); 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribLen = attribValue.length; 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var quoted = 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (attribLen >= 2 && /^[\"\']/.test(attribValue) && 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribSource; 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribSourceStart; 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribSourceEnd; 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (quoted) { 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceStart = start + 1; 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceEnd = end - 1; 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSource = attribValue; 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceStart = start + 1; 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceEnd = end - 1; 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSource = attribValue.substring(1, attribValue.length - 1); 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var attribSourceDecorations = decorateSource(attribSource); 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceDecorations[j] += attribSourceStart; 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (quoted) { 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project spliceArrayInto(attribSourceDecorations, decorations, i, 2); 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nextValueIsSource = false; 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** returns a decoration list given a string of markup. 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This code recognizes a number of constructs. 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <!-- ... --> comment 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <!\w ... > declaration 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <\w ... > tag 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </\w ... > tag 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <?...?> embedded source 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <%...%> embedded source 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * &[#\w]...; entity 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It does not recognizes %foo; doctype entities from . 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It will recurse into any <style>, <script>, and on* attributes using 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * PR_lexSource. 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function decorateMarkup(sourceCode) { 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This function works as follows: 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 1) Start by splitting the markup into text and tag chunks 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Input: string s 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Output: List<PR_Token> where style in (PR_PLAIN, null) 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 2) Then split the text chunks further into comments, declarations, 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // tags, etc. 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // After each split, consider whether the token is the start of an 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // embedded source section, i.e. is an open <script> tag. If it is, find 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the corresponding close token, and don't bother to lex in between. 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Input: List<string> 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Output: List<PR_Token> with style in 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (PR_TAG, PR_PLAIN, PR_SOURCE, null) 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 3) Finally go over each tag token and split out attribute names and 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // values. 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Input: List<PR_Token> 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Output: List<PR_Token> where style in 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // (PR_TAG, PR_PLAIN, PR_SOURCE, NAME, VALUE, null) 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorations = tokenizeMarkup(sourceCode); 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations = splitTagAttributes(sourceCode, decorations); 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations = splitSourceNodes(sourceCode, decorations); 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decorations = splitSourceAttributes(sourceCode, decorations); 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return decorations; 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {string} sourceText plain text 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array.<number|string>} extractedTags chunks of raw html preceded 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by their position in sourceText in order. 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array.<number|string>} decorations style classes preceded by their 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * position in sourceText in order. 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {string} html 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @private 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var html = []; 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // index past the last char in sourceText written to html 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var outputIdx = 0; 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var openDecoration = null; 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var currentDecoration = null; 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var tagPos = 0; // index into extractedTags 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decPos = 0; // index into decorations 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var tabExpander = makeTabExpander(PR_TAB_WIDTH); 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var adjacentSpaceRe = /([\r\n ]) /g; 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var startOrSpaceRe = /(^| ) /gm; 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var newlineRe = /\r\n?|\n/g; 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var trailingSpaceRe = /[ \r\n]$/; 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var lastWasSpace = true; // the last text chunk emitted ended with a space. 972de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A helper function that is responsible for opening sections of decoration 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // and outputing properly escaped chunks of source 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function emitTextUpTo(sourceIdx) { 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sourceIdx > outputIdx) { 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (openDecoration && openDecoration !== currentDecoration) { 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Close the current decoration 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push('</span>'); 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project openDecoration = null; 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!openDecoration && currentDecoration) { 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project openDecoration = currentDecoration; 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push('<span class="', openDecoration, '">'); 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This interacts badly with some wikis which introduces paragraph tags 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // into pre blocks for some strange reason. 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // It's necessary for IE though which seems to lose the preformattedness 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // of <pre> tags when their innerHTML is assigned. 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // and it serves to undo the conversion of <br>s to newlines done in 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // chunkify. 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var htmlChunk = textToHtml( 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project tabExpander(sourceText.substring(outputIdx, sourceIdx))) 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .replace(lastWasSpace 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ? startOrSpaceRe 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project : adjacentSpaceRe, '$1 '); 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Keep track of whether we need to escape space at the beginning of the 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // next chunk. 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastWasSpace = trailingSpaceRe.test(htmlChunk); 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push(htmlChunk.replace(newlineRe, '<br />')); 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outputIdx = sourceIdx; 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Determine if we're going to consume a tag this time around. Otherwise 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // we consume a decoration or exit. 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var outputTag; 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (tagPos < extractedTags.length) { 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (decPos < decorations.length) { 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Pick one giving preference to extractedTags since we shouldn't open 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a new style that we're going to have to immediately close in order 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // to output a tag. 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outputTag = extractedTags[tagPos] <= decorations[decPos]; 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outputTag = true; 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project outputTag = false; 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Consume either a decoration or a tag or exit. 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (outputTag) { 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project emitTextUpTo(extractedTags[tagPos]); 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (openDecoration) { 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Close the current decoration 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push('</span>'); 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project openDecoration = null; 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push(extractedTags[tagPos + 1]); 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project tagPos += 2; 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (decPos < decorations.length) { 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project emitTextUpTo(decorations[decPos]); 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentDecoration = decorations[decPos + 1]; 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project decPos += 2; 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project emitTextUpTo(sourceText.length); 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (openDecoration) { 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project html.push('</span>'); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return html.join(''); 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Maps language-specific file extensions to handlers. */ 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var langHandlerRegistry = {}; 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Register a language handler for the given file extensions. 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {function (string) : Array.<number|string>} handler 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a function from source code to a list of decorations. 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param {Array.<string>} fileExtensions 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function registerLangHandler(handler, fileExtensions) { 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = fileExtensions.length; --i >= 0;) { 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var ext = fileExtensions[i]; 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!langHandlerRegistry.hasOwnProperty(ext)) { 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project langHandlerRegistry[ext] = handler; 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if ('console' in window) { 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project console.log('cannot override language handler %s', ext); 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(decorateSource, ['default-code']); 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(decorateMarkup, 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: CPP_KEYWORDS, 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cStyleComments: true 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['c', 'cc', 'cpp', 'cxx', 'cyc']); 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: CSHARP_KEYWORDS, 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cStyleComments: true 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['cs']); 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: JAVA_KEYWORDS, 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cStyleComments: true 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['java']); 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: SH_KEYWORDS, 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project multiLineStrings: true 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['bsh', 'csh', 'sh']); 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: PYTHON_KEYWORDS, 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project multiLineStrings: true, 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project tripleQuotedStrings: true 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['cv', 'py']); 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: PERL_KEYWORDS, 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project multiLineStrings: true, 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regexLiterals: true 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['perl', 'pl', 'pm']); 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: RUBY_KEYWORDS, 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashComments: true, 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project multiLineStrings: true, 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regexLiterals: true 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['rb']); 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project registerLangHandler(sourceDecorator({ 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keywords: JSCRIPT_KEYWORDS, 1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cStyleComments: true, 1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project regexLiterals: true 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }), ['js']); 1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function prettyPrintOne(sourceCodeHtml, opt_langExtension) { 1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Extract tags, and convert the source code to plain text. 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var sourceAndExtractedTags = extractTags(sourceCodeHtml); 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Plain text. @type {string} */ 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var source = sourceAndExtractedTags.source; 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Even entries are positions in source in ascending order. Odd entries 1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are tags that were extracted at that position. 1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @type {Array.<number|string>} 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var extractedTags = sourceAndExtractedTags.tags; 1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Pick a lexer and apply it. 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { 1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Treat it as markup if the first non whitespace character is a < and 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the last non-whitespace character is a >. 1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opt_langExtension = 1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /^\s*</.test(source) ? 'default-markup' : 'default-code'; 1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** Even entries are positions in source in ascending order. Odd enties 1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are style markers (e.g., PR_COMMENT) that run from that position until 1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the end. 1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @type {Array.<number|string>} 1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var decorations = langHandlerRegistry[opt_langExtension].call({}, source); 1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Integrate the decorations and tags back into the source code to produce 1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a decorated html string. 1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return recombineTagsAndDecorations(source, extractedTags, decorations); 1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (e) { 1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ('console' in window) { 1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project console.log(e); 1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project console.trace(); 1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return sourceCodeHtml; 1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function prettyPrint(opt_whenDone) { 1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var isIE6 = _pr_isIE6(); 1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // fetch a list of nodes to rewrite 1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var codeSegments = [ 1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project document.getElementsByTagName('pre'), 1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project document.getElementsByTagName('code'), 1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project document.getElementsByTagName('xmp') ]; 1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var elements = []; 1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < codeSegments.length; ++i) { 1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = 0; j < codeSegments[i].length; ++j) { 1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project elements.push(codeSegments[i][j]); 1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project codeSegments = null; 1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the loop is broken into a series of continuations to make sure that we 1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // don't make the browser unresponsive when rewriting a large page. 1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var k = 0; 1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project function doWork() { 1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var endTime = (PR_SHOULD_USE_CONTINUATION ? 1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new Date().getTime() + 250 /* ms */ : 1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Infinity); 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (; k < elements.length && new Date().getTime() < endTime; k++) { 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var cs = elements[k]; 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cs.className && cs.className.indexOf('prettyprint') >= 0) { 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // If the classes includes a language extensions, use it. 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Language extensions can be specified like 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // <pre class="prettyprint lang-cpp"> 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the language extension "cpp" is used to find a language handler as 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // passed to PR_registerLangHandler. 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var langExtension = cs.className.match(/\blang-(\w+)\b/); 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (langExtension) { langExtension = langExtension[1]; } 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // make sure this is not nested in an already prettified element 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var nested = false; 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var p = cs.parentNode; p; p = p.parentNode) { 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((p.tagName === 'pre' || p.tagName === 'code' || 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project p.tagName === 'xmp') && 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project p.className && p.className.indexOf('prettyprint') >= 0) { 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nested = true; 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!nested) { 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // fetch the content as a snippet of properly escaped HTML. 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Firefox adds newlines at the end. 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var content = getInnerHtml(cs); 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project content = content.replace(/(?:\r\n?|\n)$/, ''); 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // do the pretty printing 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var newContent = prettyPrintOne(content, langExtension); 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // push the prettified html back into the tag. 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!isRawContent(cs)) { 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // just replace the old html with the new 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cs.innerHTML = newContent; 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // we need to change the tag to a <pre> since <xmp>s do not allow 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // embedded tags such as the span tags used to attach styles to 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // sections of source code. 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var pre = document.createElement('PRE'); 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var i = 0; i < cs.attributes.length; ++i) { 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var a = cs.attributes[i]; 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (a.specified) { 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var aname = a.name.toLowerCase(); 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (aname === 'class') { 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pre.className = a.value; // For IE 6 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pre.setAttribute(a.name, a.value); 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pre.innerHTML = newContent; 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // remove the old 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cs.parentNode.replaceChild(pre, cs); 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cs = pre; 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Replace <br>s with line-feeds so that copying and pasting works 1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // on IE 6. 1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Doing this on other browsers breaks lots of stuff since \r\n is 1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // treated as two newlines on Firefox, and doing this also slows 1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // down rendering. 1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isIE6 && cs.tagName === 'PRE') { 1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var lineBreaks = cs.getElementsByTagName('br'); 1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (var j = lineBreaks.length; --j >= 0;) { 1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project var lineBreak = lineBreaks[j]; 1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineBreak.parentNode.replaceChild( 1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project document.createTextNode('\r\n'), lineBreak); 1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (k < elements.length) { 1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // finish up in a continuation 1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setTimeout(doWork, 250); 1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (opt_whenDone) { 1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opt_whenDone(); 1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project doWork(); 1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project window['PR_normalizedHtml'] = normalizedHtml; 1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project window['prettyPrintOne'] = prettyPrintOne; 1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project window['prettyPrint'] = prettyPrint; 1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project window['PR'] = { 1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'createSimpleLexer': createSimpleLexer, 1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'registerLangHandler': registerLangHandler, 1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'sourceDecorator': sourceDecorator, 1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_COMMENT': PR_COMMENT, 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_DECLARATION': PR_DECLARATION, 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_KEYWORD': PR_KEYWORD, 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_LITERAL': PR_LITERAL, 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_NOCODE': PR_NOCODE, 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_PLAIN': PR_PLAIN, 1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_PUNCTUATION': PR_PUNCTUATION, 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_SOURCE': PR_SOURCE, 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_STRING': PR_STRING, 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_TAG': PR_TAG, 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 'PR_TYPE': PR_TYPE 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project})(); 1281