From 4f9408a68f5510c1c953a61d373c6e17951a458b Mon Sep 17 00:00:00 2001 From: Benjamin Southall Date: Fri, 3 Mar 2017 15:09:52 +0900 Subject: [PATCH] Update included version of prettify.js, despite the fact we use highlight.js for code highlighting now --- js/prettify.js | 259 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 172 insertions(+), 87 deletions(-) diff --git a/js/prettify.js b/js/prettify.js index fccf4f52..97651ea5 100644 --- a/js/prettify.js +++ b/js/prettify.js @@ -1,17 +1,19 @@ -// Copyright (C) 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +/** + * @license + * Copyright (C) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** * @fileoverview @@ -19,7 +21,7 @@ * *

* For a fairly comprehensive set of languages see the - * README + * README * file that came with this source. At a minimum, the lexer should work on a * number of languages including C and friends, Java, Python, Bash, SQL, HTML, * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk @@ -55,8 +57,82 @@ // JSLint declarations /*global console, document, navigator, setTimeout, window, define */ + +/** + * {@type !{ + * 'createSimpleLexer': function (Array, Array): (function (JobT)), + * 'registerLangHandler': function (function (JobT), Array.), + * 'PR_ATTRIB_NAME': string, + * 'PR_ATTRIB_NAME': string, + * 'PR_ATTRIB_VALUE': string, + * 'PR_COMMENT': string, + * 'PR_DECLARATION': string, + * 'PR_KEYWORD': string, + * 'PR_LITERAL': string, + * 'PR_NOCODE': string, + * 'PR_PLAIN': string, + * 'PR_PUNCTUATION': string, + * 'PR_SOURCE': string, + * 'PR_STRING': string, + * 'PR_TAG': string, + * 'PR_TYPE': string, + * 'prettyPrintOne': function (string, string, number|boolean), + * 'prettyPrint': function (?function, ?(HTMLElement|HTMLDocument)) + * }} + * @const + */ +/** +* @typedef {!Array.} +* Alternating indices and the decorations that should be inserted there. +* The indices are monotonically increasing. +*/ +var DecorationsT; + +/** +* @typedef {!{ +* sourceNode: !Element, +* pre: !(number|boolean), +* langExtension: ?string, +* numberLines: ?(number|boolean), +* sourceCode: ?string, +* spans: ?(Array.), +* basePos: ?number, +* decorations: ?DecorationsT +* }} +*

+*
sourceNode
the element containing the source +*
sourceCode
source as plain text +*
pre
truthy if white-space in text nodes +* should be considered significant. +*
spans
alternating span start indices into source +* and the text node or element (e.g. {@code
}) corresponding to that +* span. +*
decorations
an array of style classes preceded +* by the position at which they start in job.sourceCode in order +*
basePos
integer position of this.sourceCode in the larger chunk of +* source. +*
+*/ +var JobT; + +/** +* @typedef {!{ +* sourceCode: string, +* spans: !(Array.) +* }} +*
+*
sourceCode
source as plain text +*
spans
alternating span start indices into source +* and the text node or element (e.g. {@code
}) corresponding to that +* span. +*
+*/ +var SourceSpansT; + /** @define {boolean} */ -var IN_GLOBAL_SCOPE = true; +var IN_GLOBAL_SCOPE = false; + +var PR; /** * Split {@code prettyPrint} into multiple timeouts so as not to interfere with @@ -93,7 +169,7 @@ var prettyPrint; // We use things that coerce to strings to make them compact when minified // and to defeat aggressive optimizers that fold large string constants. var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"]; - var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + + var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + "double,enum,extern,float,goto,inline,int,long,register,short,signed," + "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"]; var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," + @@ -104,7 +180,7 @@ var prettyPrint; "mutable,namespace,nullptr,property,reinterpret_cast,static_assert," + "static_cast,template,typeid,typename,using,virtual,where"]; var JAVA_KEYWORDS = [COMMON_KEYWORDS, - "abstract,assert,boolean,byte,extends,final,finally,implements,import," + + "abstract,assert,boolean,byte,extends,finally,final,implements,import," + "instanceof,interface,null,native,package,strictfp,super,synchronized," + "throws,transient"]; var CSHARP_KEYWORDS = [COMMON_KEYWORDS, @@ -117,8 +193,9 @@ var prettyPrint; "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," + "throw,true,try,unless,until,when,while,yes"; var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS, - "debugger,eval,export,function,get,null,set,undefined,var,with," + - "Infinity,NaN"]; + "abstract,async,await,constructor,debugger,enum,eval,export,function," + + "get,implements,instanceof,interface,let,null,set,undefined,var,with," + + "yield,Infinity,NaN"]; var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," + "goto,if,import,last,local,my,next,no,our,print,package,redo,require," + "sub,undef,unless,until,use,wantarray,while,BEGIN,END"; @@ -130,14 +207,11 @@ var prettyPrint; "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," + "rescue,retry,self,super,then,true,undef,unless,until,when,yield," + "BEGIN,END"]; - var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "as,assert,const,copy,drop," + - "enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv," + - "pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"]; var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," + "function,in,local,set,then,until"]; var ALL_KEYWORDS = [ - CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS, - PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS]; + CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, JSCRIPT_KEYWORDS, + PERL_KEYWORDS, PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS]; var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/; // token style names. correspond to css classes @@ -521,9 +595,9 @@ var prettyPrint; *

* * @param {Node} node an HTML DOM subtree containing source-code. - * @param {boolean} isPreformatted true if white-space in text nodes should - * be considered significant. - * @return {Object} source code and the text nodes in which they occur. + * @param {boolean|number} isPreformatted truthy if white-space in + * text nodes should be considered significant. + * @return {SourceSpansT} source code and the nodes in which they occur. */ function extractSourceSpans(node, isPreformatted) { var nocode = /(?:^|\s)nocode(?:\s|$)/; @@ -574,14 +648,26 @@ var prettyPrint; /** * Apply the given language handler to sourceCode and add the resulting * decorations to out. + * @param {!Element} sourceNode * @param {number} basePos the index of sourceCode within the chunk of source * whose decorations are already present on out. + * @param {string} sourceCode + * @param {function(JobT)} langHandler + * @param {DecorationsT} out */ - function appendDecorations(basePos, sourceCode, langHandler, out) { + function appendDecorations( + sourceNode, basePos, sourceCode, langHandler, out) { if (!sourceCode) { return; } + /** @type {JobT} */ var job = { + sourceNode: sourceNode, + pre: 1, + langExtension: null, + numberLines: null, sourceCode: sourceCode, - basePos: basePos + spans: null, + basePos: basePos, + decorations: null }; langHandler(job); out.push.apply(out, job.decorations); @@ -656,8 +742,8 @@ var prettyPrint; * @param {Array} fallthroughStylePatterns patterns that will be tried in * order if the shortcut ones fail. May have shortcuts. * - * @return {function (Object)} a - * function that takes source code and returns a list of decorations. + * @return {function (JobT)} a function that takes an undecorated job and + * attaches a list of decorations. */ function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; @@ -688,22 +774,19 @@ var prettyPrint; var nPatterns = fallthroughStylePatterns.length; /** - * Lexes job.sourceCode and produces an output array job.decorations of + * Lexes job.sourceCode and attaches an output array job.decorations of * style classes preceded by the position at which they start in * job.sourceCode in order. * - * @param {Object} job an object like
{
-     *    sourceCode: {string} sourceText plain text,
-     *    basePos: {int} position of job.sourceCode in the larger chunk of
-     *        sourceCode.
-     * }
+ * @type{function (JobT)} */ var decorate = function (job) { var sourceCode = job.sourceCode, basePos = job.basePos; + var sourceNode = job.sourceNode; /** Even entries are positions in source in ascending order. Odd enties * are style markers (e.g., PR_COMMENT) that run from that position until * the end. - * @type {Array.} + * @type {DecorationsT} */ var decorations = [basePos, PR_PLAIN]; var pos = 0; // index into sourceCode @@ -766,17 +849,20 @@ var prettyPrint; var lang = style.substring(5); // Decorate the left of the embedded source appendDecorations( + sourceNode, basePos + tokenStart, token.substring(0, embeddedSourceStart), decorate, decorations); // Decorate the embedded source appendDecorations( + sourceNode, basePos + tokenStart + embeddedSourceStart, embeddedSource, langHandlerForExtension(lang, embeddedSource), decorations); // Decorate the right of the embedded section appendDecorations( + sourceNode, basePos + tokenStart + embeddedSourceEnd, token.substring(embeddedSourceEnd), decorate, decorations); @@ -799,8 +885,9 @@ var prettyPrint; * It recognizes C, C++, and shell style comments. * * @param {Object} options a set of optional parameters. - * @return {function (Object)} a function that examines the source code - * in the input job and builds the decoration list. + * @return {function (JobT)} a function that examines the source code + * in the input job and builds a decoration list which it attaches to + * the job. */ function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; @@ -910,7 +997,7 @@ var prettyPrint; // which are the following plus space, tab, and newline: { } // | & $ ; < > // ... - + // A word beginning with # causes that word and all remaining // characters on that line to be ignored. @@ -985,10 +1072,14 @@ var prettyPrint; * HTMLOListElement, and each line is moved into a separate list item. * This requires cloning elements, so the input might not have unique * IDs after numbering. + * @param {number|null|boolean} startLineNum + * If truthy, coerced to an integer which is the 1-indexed line number + * of the first line of code. The number of the first line will be + * attached to the list. * @param {boolean} isPreformatted true iff white-space in text nodes should * be treated as significant. */ - function numberLines(node, opt_startLineNum, isPreformatted) { + function numberLines(node, startLineNum, isPreformatted) { var nocode = /(?:^|\s)nocode(?:\s|$)/; var lineBreak = /\r\n?|\n/; @@ -1089,13 +1180,13 @@ var prettyPrint; } // Make sure numeric indices show correctly. - if (opt_startLineNum === (opt_startLineNum|0)) { - listItems[0].setAttribute('value', opt_startLineNum); + if (startLineNum === (startLineNum|0)) { + listItems[0].setAttribute('value', startLineNum); } var ol = document.createElement('ol'); ol.className = 'linenums'; - var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0; + var offset = Math.max(0, ((startLineNum - 1 /* zero index */)) | 0) || 0; for (var i = 0, n = listItems.length; i < n; ++i) { li = listItems[i]; // Stick a class on the LIs so that stylesheets can @@ -1110,18 +1201,11 @@ var prettyPrint; node.appendChild(ol); } + /** * Breaks {@code job.sourceCode} around style boundaries in * {@code job.decorations} and modifies {@code job.sourceNode} in place. - * @param {Object} job like
{
-   *    sourceCode: {string} source as plain text,
-   *    sourceNode: {HTMLElement} the element containing the source,
-   *    spans: {Array.} alternating span start indices into source
-   *       and the text node or element (e.g. {@code 
}) corresponding to that - * span. - * decorations: {Array. + * @param {JobT} job * @private */ function recombineTagsAndDecorations(job) { @@ -1175,7 +1259,7 @@ var prettyPrint; nDecorations = decorations.length = decPos; var sourceNode = job.sourceNode; - var oldDisplay; + var oldDisplay = ""; if (sourceNode) { oldDisplay = sourceNode.style.display; sourceNode.style.display = 'none'; @@ -1184,13 +1268,14 @@ var prettyPrint; var decoration = null; while (spanIndex < nSpans) { var spanStart = spans[spanIndex]; - var spanEnd = spans[spanIndex + 2] || sourceLength; + var spanEnd = /** @type{number} */ (spans[spanIndex + 2]) + || sourceLength; var decEnd = decorations[decorationIndex + 2] || sourceLength; var end = Math.min(spanEnd, decEnd); - var textNode = spans[spanIndex + 1]; + var textNode = /** @type{Node} */ (spans[spanIndex + 1]); var styledText; if (textNode.nodeType !== 1 // Don't muck with
s or
  • s // Don't introduce spans around empty text nodes. @@ -1237,19 +1322,9 @@ var prettyPrint; /** Maps language-specific file extensions to handlers. */ var langHandlerRegistry = {}; /** Register a language handler for the given file extensions. - * @param {function (Object)} handler a function from source code to a list + * @param {function (JobT)} handler a function from source code to a list * of decorations. Takes a single argument job which describes the - * state of the computation. The single parameter has the form - * {@code { - * sourceCode: {string} as plain text. - * decorations: {Array.} an array of style classes - * preceded by the position at which they start in - * job.sourceCode in order. - * The language handler should assigned this field. - * basePos: {int} the position of source in the larger source chunk. - * All positions in the output decorations array are relative - * to the larger source chunk. - * } } + * state of the computation and attaches the decorations to it. * @param {Array.} fileExtensions */ function registerLangHandler(handler, fileExtensions) { @@ -1360,7 +1435,7 @@ var prettyPrint; 'keywords': JSCRIPT_KEYWORDS, 'cStyleComments': true, 'regexLiterals': true - }), ['javascript', 'js']); + }), ['javascript', 'js', 'ts', 'typescript']); registerLangHandler(sourceDecorator({ 'keywords': COFFEE_KEYWORDS, 'hashComments': 3, // ### style block comments @@ -1369,14 +1444,10 @@ var prettyPrint; 'tripleQuotedStrings': true, 'regexLiterals': true }), ['coffee']); - registerLangHandler(sourceDecorator({ - 'keywords': RUST_KEYWORDS, - 'cStyleComments': true, - 'multilineStrings': true - }), ['rc', 'rs', 'rust']); registerLangHandler( createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']); + /** @param {JobT} job */ function applyDecorator(job) { var opt_langExtension = job.langExtension; @@ -1411,6 +1482,11 @@ var prettyPrint; * or the 1-indexed number of the first line in sourceCodeHtml. */ function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) { + /** @type{number|boolean} */ + var nl = opt_numberLines || false; + /** @type{string|null} */ + var langExtension = opt_langExtension || null; + /** @type{!Element} */ var container = document.createElement('div'); // This could cause images to load and onload listeners to fire. // E.g. . @@ -1420,16 +1496,21 @@ var prettyPrint; // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript container.innerHTML = '
    ' + sourceCodeHtml + '
    '; - container = container.firstChild; - if (opt_numberLines) { - numberLines(container, opt_numberLines, true); + container = /** @type{!Element} */(container.firstChild); + if (nl) { + numberLines(container, nl, true); } + /** @type{JobT} */ var job = { - langExtension: opt_langExtension, - numberLines: opt_numberLines, + langExtension: langExtension, + numberLines: nl, sourceNode: container, - pre: 1 + pre: 1, + sourceCode: null, + basePos: null, + spans: null, + decorations: null }; applyDecorator(job); return container.innerHTML; @@ -1466,7 +1547,6 @@ var prettyPrint; // The loop is broken into a series of continuations to make sure that we // don't make the browser unresponsive when rewriting a large page. var k = 0; - var prettyPrintingJob; var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/; var prettyPrintRe = /\bprettyprint\b/; @@ -1583,11 +1663,15 @@ var prettyPrint; if (lineNums) { numberLines(cs, lineNums, preformatted); } // do the pretty printing - prettyPrintingJob = { + var prettyPrintingJob = { langExtension: langExtension, sourceNode: cs, numberLines: lineNums, - pre: preformatted + pre: preformatted, + sourceCode: null, + basePos: null, + spans: null, + decorations: null }; applyDecorator(prettyPrintingJob); } @@ -1595,7 +1679,7 @@ var prettyPrint; } if (k < elements.length) { // finish up in a continuation - setTimeout(doWork, 250); + win.setTimeout(doWork, 250); } else if ('function' === typeof opt_whenDone) { opt_whenDone(); } @@ -1647,9 +1731,10 @@ var prettyPrint; // whose value is an object. This helps avoid conflict with any // other existing JavaScript code that could have defined a define() // function that does not conform to the AMD API. + var define = win['define']; if (typeof define === "function" && define['amd']) { define("google-code-prettify", [], function () { - return PR; + return PR; }); } })();