├── src ├── prettify.css ├── lang-proto.js ├── lang-lua.js ├── lang-ml.js ├── lang-sql.js ├── lang-lisp.js └── prettify.js ├── CHANGES.html ├── README.html ├── COPYING └── tests └── prettify_test.html /src/prettify.css: -------------------------------------------------------------------------------- 1 | /* Pretty printing styles. Used with prettify.js. */ 2 | 3 | .str { color: #080; } 4 | .kwd { color: #008; } 5 | .com { color: #800; } 6 | .typ { color: #606; } 7 | .lit { color: #066; } 8 | .pun { color: #660; } 9 | .pln { color: #000; } 10 | .tag { color: #008; } 11 | .atn { color: #606; } 12 | .atv { color: #080; } 13 | .dec { color: #606; } 14 | pre.prettyprint { padding: 2px; border: 1px solid #888; } 15 | 16 | @media print { 17 | .str { color: #060; } 18 | .kwd { color: #006; font-weight: bold; } 19 | .com { color: #600; font-style: italic; } 20 | .typ { color: #404; font-weight: bold; } 21 | .lit { color: #044; } 22 | .pun { color: #440; } 23 | .pln { color: #000; } 24 | .tag { color: #006; font-weight: bold; } 25 | .atn { color: #404; } 26 | .atv { color: #060; } 27 | } 28 | -------------------------------------------------------------------------------- /src/lang-proto.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2006 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview 18 | * Registers a language handler for Protocol Buffers as described at 19 | * http://code.google.com/p/protobuf/. 20 | * 21 | * Based on the lexical grammar at 22 | * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 23 | * 24 | * @author mikesamuel@gmail.com 25 | */ 26 | 27 | PR.registerLangHandler(PR.sourceDecorator({ 28 | keywords: ( 29 | 'bool bytes default double enum extend extensions false fixed32 ' 30 | + 'fixed64 float group import int32 int64 max message option ' 31 | + 'optional package repeated required returns rpc service ' 32 | + 'sfixed32 sfixed64 sint32 sint64 string syntax to true uint32 ' 33 | + 'uint64'), 34 | cStyleComments: true 35 | }), ['proto']); 36 | -------------------------------------------------------------------------------- /src/lang-lua.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for LUA. 20 | * 21 | * 22 | * To use, include prettify.js and this file in your HTML page. 23 | * Then put your code in an HTML tag like 24 | *
(my LUA code)25 | * 26 | * 27 | * I used http://www.lua.org/manual/5.1/manual.html#2.1 28 | * Because of the long-bracket concept used in strings and comments, LUA does 29 | * not have a regular lexical grammar, but luckily it fits within the space 30 | * of irregular grammars supported by javascript regular expressions. 31 | * 32 | * @author mikesamuel@gmail.com 33 | */ 34 | 35 | PR.registerLangHandler( 36 | PR.createSimpleLexer( 37 | [ 38 | // Whitespace 39 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 40 | // A double or single quoted, possibly multi-line, string. 41 | [PR.PR_STRING, /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] 42 | ], 43 | [ 44 | // A comment is either a line comment that starts with two dashes, or 45 | // two dashes preceding a long bracketed block. 46 | [PR.PR_COMMENT, /^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/], 47 | // A long bracketed block not preceded by -- is a string. 48 | [PR.PR_STRING, /^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/], 49 | [PR.PR_KEYWORD, /^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/, null], 50 | // A number is a hex integer literal, a decimal real literal, or in 51 | // scientific notation. 52 | [PR.PR_LITERAL, 53 | /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], 54 | // An identifier 55 | [PR.PR_PLAIN, /^[a-z_]\w*/i], 56 | // A run of punctuation 57 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0]+/] 58 | ]), 59 | ['lua']); 60 | -------------------------------------------------------------------------------- /CHANGES.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
prettyPrintOne was not halting. This was not
18 | reachable through the normal entry point.
19 | 30 |34 | is no longer applicable. 35 |Caveats: please properly escape less-thans. x<y 31 | instead of x<y, and use " instead of 32 | " for string delimiters.
33 |
lang-<language-file-extension>'''string'''
46 | / in regex [charsets] should not end regex
47 | nocode spans to allow embedding of line
56 | numbers and code annotations which should not be styled or otherwise
57 | affect the tokenization of prettified code.
58 | See the issue 22 testcase.
59 | (my SQL code)25 | * 26 | * 27 | * http://savage.net.au/SQL/sql-99.bnf.html is the basis for the grammar, and 28 | * http://msdn.microsoft.com/en-us/library/aa238507(SQL.80).aspx as the basis 29 | * for the keyword list. 30 | * 31 | * @author mikesamuel@gmail.com 32 | */ 33 | 34 | PR.registerLangHandler( 35 | PR.createSimpleLexer( 36 | [ 37 | // Whitespace 38 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 39 | // A double or single quoted, possibly multi-line, string. 40 | [PR.PR_STRING, /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null, 41 | '"\''] 42 | ], 43 | [ 44 | // A comment is either a line comment that starts with two dashes, or 45 | // two dashes preceding a long bracketed block. 46 | [PR.PR_COMMENT, /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/], 47 | [PR.PR_KEYWORD, /^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LIMIT|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i, null], 48 | // A number is a hex integer literal, a decimal real literal, or in 49 | // scientific notation. 50 | [PR.PR_LITERAL, 51 | /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], 52 | // An identifier 53 | [PR.PR_PLAIN, /^[a-z_][\w-]*/i], 54 | // A run of punctuation 55 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0]+/] 56 | ]), 57 | ['sql']); 58 | -------------------------------------------------------------------------------- /src/lang-lisp.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for Common Lisp and related languages. 20 | * 21 | * 22 | * To use, include prettify.js and this file in your HTML page. 23 | * Then put your code in an HTML tag like 24 | *
(my lisp code)25 | * The lang-cl class identifies the language as common lisp. 26 | * This file supports the following language extensions: 27 | * lang-cl - Common Lisp 28 | * lang-el - Emacs Lisp 29 | * lang-lisp - Lisp 30 | * lang-scm - Scheme 31 | * 32 | * 33 | * I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm 34 | * as the basis, but added line comments that start with ; and changed the atom 35 | * production to disallow unquoted semicolons. 36 | * 37 | * "Name" = 'LISP' 38 | * "Author" = 'John McCarthy' 39 | * "Version" = 'Minimal' 40 | * "About" = 'LISP is an abstract language that organizes ALL' 41 | * | 'data around "lists".' 42 | * 43 | * "Start Symbol" = [s-Expression] 44 | * 45 | * {Atom Char} = {Printable} - {Whitespace} - [()"\''] 46 | * 47 | * Atom = ( {Atom Char} | '\'{Printable} )+ 48 | * 49 | * [s-Expression] ::= [Quote] Atom 50 | * | [Quote] '(' [Series] ')' 51 | * | [Quote] '(' [s-Expression] '.' [s-Expression] ')' 52 | * 53 | * [Series] ::= [s-Expression] [Series] 54 | * | 55 | * 56 | * [Quote] ::= '' !Quote = do not evaluate 57 | * | 58 | * 59 | * 60 | * I used Practical Common Lisp as 61 | * the basis for the reserved word list. 62 | * 63 | * 64 | * @author mikesamuel@gmail.com 65 | */ 66 | 67 | PR.registerLangHandler( 68 | PR.createSimpleLexer( 69 | [ 70 | ['opn', /^\(/, null, '('], 71 | ['clo', /^\)/, null, ')'], 72 | // A line comment that starts with ; 73 | [PR.PR_COMMENT, /^;[^\r\n]*/, null, ';'], 74 | // Whitespace 75 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 76 | // A double quoted, possibly multi-line, string. 77 | [PR.PR_STRING, /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] 78 | ], 79 | [ 80 | [PR.PR_KEYWORD, /^(?:block|c[ad]+r|catch|cons|defun|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null], 81 | [PR.PR_LITERAL, 82 | /^[+\-]?(?:\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[eEdD][+\-]?\d+)?)/], 83 | // A single quote possibly followed by a word that optionally ends with 84 | // = ! or ?. 85 | [PR.PR_LITERAL, 86 | /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], 87 | // A word that optionally ends with = ! or ?. 88 | [PR.PR_PLAIN, 89 | /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], 90 | // A printable non-space non-special character 91 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0()\"\\\';]+/] 92 | ]), 93 | ['cl', 'el', 'lisp', 'scm']); 94 | -------------------------------------------------------------------------------- /README.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 |
28 | <link href="prettify.css" type="text/css" rel="stylesheet" /> 29 | <script type="text/javascript" src="prettify.js"></script>30 |
onload="prettyPrint()" to your
31 | document's body tag.
32 | Put code snippets in 37 | <pre class="prettyprint">...</pre> 38 | or <code class="prettyprint">...</code> 39 | and it will automatically be pretty printed. 40 | 41 |
| The original 44 | | Prettier 45 | |
|---|---|
class Voila { 48 | public: 49 | // Voila 50 | static const string VOILA = "Voila"; 51 | 52 | // will not interfere with embedded tags. 53 | }54 | 55 | | class Voila { 56 | public: 57 | // Voila 58 | static const string VOILA = "Voila"; 59 | 60 | // will not interfere with embedded tags. 61 | }62 | |
The comments in prettify.js are authoritative but the lexer 67 | should work on a number of languages including C and friends, 68 | Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles. 69 | It works passably on Ruby, PHP and Awk and a decent subset of Perl, but, 70 | because of commenting conventions, doesn't work on Smalltalk, or 71 | CAML-like languages.
72 | 73 |LISPy languages are supported via an extension:
74 | lang-lisp.js.
And similarly for LUA, OCAML, SML, F#,
79 | SQL, and
81 | Protocol Buffers.
83 |
84 |
If you'd like to add an extension for your favorite language, please 85 | look at lang-lisp.js and file an 86 | issue including your language extension, and a testcase.
88 | 89 |You don't need to specify the language since prettyprint()
91 | will guess. You can specify a language by specifying the language extension
92 | along with the prettyprint class like so:
<pre class="prettyprint lang-html"> 95 | The lang-* class specifies the language file extensions. 96 | Supported file extensions include 97 | "c", "cc", "cpp", "cs", "cyc", "java", "bsh", "csh", "sh", 98 | "cv", "py", "perl", "pl", "pm", "rb", "js", 99 | "html", "html", "xhtml", "xml", "xsl". 100 | </pre>101 | 102 |
Yes. Prettifying obfuscated code is like putting lipstick on a pig 104 | — i.e. outside the scope of this tool.
105 | 106 |It's been tested with IE 6, Firefox 1.5 & 2, and Safari 2.0.4. 108 | Look at the test page to see if it 109 | works in your browser.
110 | 111 |See the change log
113 | 114 |Apparently wordpress does "smart quoting" which changes close quotes. 116 | This causes end quotes to not match up with open quotes. 117 |
This breaks prettifying as well as copying and pasting of code samples. 118 | See 119 | WordPress's help center for info on how to stop smart quoting of code 121 | snippets.
122 | 123 |You can use the nocode class to identify a span of markup
125 | that is not code.
126 |
<pre class=prettyprint>
127 | <span class="nocode">1:</span> /* This is line 1 of my code
128 | <span class="nocode">2:</span> * and here's line 2 */
129 | <span class="nocode">3:</span> print("I'm line number 3");
130 | </pre>
131 | produces
132 | 133 | 1: /* This is line 1 of my code 134 | 2: * and here's line 2 */ 135 | 3: print("I'm line number 3"); 136 |137 | 138 |
For a more complete example see the issue22 139 | testcase.
140 | 141 | and tags in your source with class=prettyprint.
35 | * You can also use the (html deprecated) tag, but the pretty printer
36 | * needs to do more substantial DOM manipulations to support that, so some
37 | * css styles may not be preserved.
38 | * That's it. I wanted to keep the API as simple as possible, so there's no
39 | * need to specify which language the code is in.
40 | *
41 | * Change log:
42 | * cbeust, 2006/08/22
43 | * Java annotations (start with "@") are now captured as literals ("lit")
44 | */
45 |
46 | // JSLint declarations
47 | /*global console, document, navigator, setTimeout, window */
48 |
49 | /**
50 | * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
51 | * UI events.
52 | * If set to {@code false}, {@code prettyPrint()} is synchronous.
53 | */
54 | var PR_SHOULD_USE_CONTINUATION = true;
55 |
56 | /** the number of characters between tab columns */
57 | var PR_TAB_WIDTH = 8;
58 |
59 | /** Walks the DOM returning a properly escaped version of innerHTML.
60 | * @param {Node} node
61 | * @param {Array.} out output buffer that receives chunks of HTML.
62 | */
63 | var PR_normalizedHtml;
64 |
65 | /** Contains functions for creating and registering new language handlers.
66 | * @type {Object}
67 | */
68 | var PR;
69 |
70 | /** Pretty print a chunk of code.
71 | *
72 | * @param {string} sourceCodeHtml code as html
73 | * @return {string} code as html, but prettier
74 | */
75 | var prettyPrintOne;
76 | /** find all the < pre > and < code > tags in the DOM with class=prettyprint
77 | * and prettify them.
78 | * @param {Function} opt_whenDone if specified, called when the last entry
79 | * has been finished.
80 | */
81 | var prettyPrint;
82 |
83 | /** browser detection. @extern */
84 | function _pr_isIE6() {
85 | var isIE6 = navigator && navigator.userAgent &&
86 | /\bMSIE 6\./.test(navigator.userAgent);
87 | _pr_isIE6 = function () { return isIE6; };
88 | return isIE6;
89 | }
90 |
91 |
92 | (function () {
93 | /** Splits input on space and returns an Object mapping each non-empty part to
94 | * true.
95 | */
96 | function wordSet(words) {
97 | words = words.split(/ /g);
98 | var set = {};
99 | for (var i = words.length; --i >= 0;) {
100 | var w = words[i];
101 | if (w) { set[w] = null; }
102 | }
103 | return set;
104 | }
105 |
106 | // Keyword lists for various languages.
107 | var FLOW_CONTROL_KEYWORDS =
108 | "break continue do else for if return while ";
109 | var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " +
110 | "double enum extern float goto int long register short signed sizeof " +
111 | "static struct switch typedef union unsigned void volatile ";
112 | var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " +
113 | "new operator private protected public this throw true try ";
114 | var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " +
115 | "concept concept_map const_cast constexpr decltype " +
116 | "dynamic_cast explicit export friend inline late_check " +
117 | "mutable namespace nullptr reinterpret_cast static_assert static_cast " +
118 | "template typeid typename typeof using virtual wchar_t where ";
119 | var JAVA_KEYWORDS = COMMON_KEYWORDS +
120 | "boolean byte extends final finally implements import instanceof null " +
121 | "native package strictfp super synchronized throws transient ";
122 | var CSHARP_KEYWORDS = JAVA_KEYWORDS +
123 | "as base by checked decimal delegate descending event " +
124 | "fixed foreach from group implicit in interface internal into is lock " +
125 | "object out override orderby params readonly ref sbyte sealed " +
126 | "stackalloc string select uint ulong unchecked unsafe ushort var ";
127 | var JSCRIPT_KEYWORDS = COMMON_KEYWORDS +
128 | "debugger eval export function get null set undefined var with " +
129 | "Infinity NaN ";
130 | var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " +
131 | "goto if import last local my next no our print package redo require " +
132 | "sub undef unless until use wantarray while BEGIN END ";
133 | var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " +
134 | "elif except exec finally from global import in is lambda " +
135 | "nonlocal not or pass print raise try with yield " +
136 | "False True None ";
137 | var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" +
138 | " defined elsif end ensure false in module next nil not or redo rescue " +
139 | "retry self super then true undef unless until when yield BEGIN END ";
140 | var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " +
141 | "function in local set then until ";
142 | var ALL_KEYWORDS = (
143 | CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS +
144 | PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS);
145 |
146 | // token style names. correspond to css classes
147 | /** token style for a string literal */
148 | var PR_STRING = 'str';
149 | /** token style for a keyword */
150 | var PR_KEYWORD = 'kwd';
151 | /** token style for a comment */
152 | var PR_COMMENT = 'com';
153 | /** token style for a type */
154 | var PR_TYPE = 'typ';
155 | /** token style for a literal value. e.g. 1, null, true. */
156 | var PR_LITERAL = 'lit';
157 | /** token style for a punctuation string. */
158 | var PR_PUNCTUATION = 'pun';
159 | /** token style for a punctuation string. */
160 | var PR_PLAIN = 'pln';
161 |
162 | /** token style for an sgml tag. */
163 | var PR_TAG = 'tag';
164 | /** token style for a markup declaration such as a DOCTYPE. */
165 | var PR_DECLARATION = 'dec';
166 | /** token style for embedded source. */
167 | var PR_SOURCE = 'src';
168 | /** token style for an sgml attribute name. */
169 | var PR_ATTRIB_NAME = 'atn';
170 | /** token style for an sgml attribute value. */
171 | var PR_ATTRIB_VALUE = 'atv';
172 |
173 | /**
174 | * A class that indicates a section of markup that is not code, e.g. to allow
175 | * embedding of line numbers within code listings.
176 | */
177 | var PR_NOCODE = 'nocode';
178 |
179 | function isWordChar(ch) {
180 | return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
181 | }
182 |
183 | /** Splice one array into another.
184 | * Like the python
185 | * container[containerPosition:containerPosition + countReplaced] = inserted
186 | *
187 | * @param {Array} inserted
188 | * @param {Array} container modified in place
189 | * @param {Number} containerPosition
190 | * @param {Number} countReplaced
191 | */
192 | function spliceArrayInto(
193 | inserted, container, containerPosition, countReplaced) {
194 | inserted.unshift(containerPosition, countReplaced || 0);
195 | try {
196 | container.splice.apply(container, inserted);
197 | } finally {
198 | inserted.splice(0, 2);
199 | }
200 | }
201 |
202 | /** A set of tokens that can precede a regular expression literal in
203 | * javascript.
204 | * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full
205 | * list, but I've removed ones that might be problematic when seen in
206 | * languages that don't support regular expression literals.
207 | *
208 | * Specifically, I've removed any keywords that can't precede a regexp
209 | * literal in a syntactically legal javascript program, and I've removed the
210 | * "in" keyword since it's not a keyword in many languages, and might be used
211 | * as a count of inches.
212 | * @private
213 | */
214 | var REGEXP_PRECEDER_PATTERN = function () {
215 | var preceders = [
216 | "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=",
217 | "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=",
218 | "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";",
219 | "<", "<<", "<<=", "<=", "=", "==", "===", ">",
220 | ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[",
221 | "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
222 | "||=", "~" /* handles =~ and !~ */,
223 | "break", "case", "continue", "delete",
224 | "do", "else", "finally", "instanceof",
225 | "return", "throw", "try", "typeof"
226 | ];
227 | var pattern = '(?:' +
228 | '(?:(?:^|[^0-9.])\\.{1,3})|' + // a dot that's not part of a number
229 | '(?:(?:^|[^\\+])\\+)|' + // allow + but not ++
230 | '(?:(?:^|[^\\-])-)'; // allow - but not --
231 | for (var i = 0; i < preceders.length; ++i) {
232 | var preceder = preceders[i];
233 | if (isWordChar(preceder.charAt(0))) {
234 | pattern += '|\\b' + preceder;
235 | } else {
236 | pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1');
237 | }
238 | }
239 | pattern += '|^)\\s*$'; // matches at end, and matches empty string
240 | return new RegExp(pattern);
241 | // CAVEAT: this does not properly handle the case where a regular
242 | // expression immediately follows another since a regular expression may
243 | // have flags for case-sensitivity and the like. Having regexp tokens
244 | // adjacent is not
245 | // valid in any language I'm aware of, so I'm punting.
246 | // TODO: maybe style special characters inside a regexp as punctuation.
247 | }();
248 |
249 | // Define regexps here so that the interpreter doesn't have to create an
250 | // object each time the function containing them is called.
251 | // The language spec requires a new object created even if you don't access
252 | // the $1 members.
253 | var pr_amp = /&/g;
254 | var pr_lt = //g;
256 | var pr_quot = /\"/g;
257 | /** like textToHtml but escapes double quotes to be attribute safe. */
258 | function attribToHtml(str) {
259 | return str.replace(pr_amp, '&')
260 | .replace(pr_lt, '<')
261 | .replace(pr_gt, '>')
262 | .replace(pr_quot, '"');
263 | }
264 |
265 | /** escapest html special characters to html. */
266 | function textToHtml(str) {
267 | return str.replace(pr_amp, '&')
268 | .replace(pr_lt, '<')
269 | .replace(pr_gt, '>');
270 | }
271 |
272 |
273 | var pr_ltEnt = /</g;
274 | var pr_gtEnt = />/g;
275 | var pr_aposEnt = /'/g;
276 | var pr_quotEnt = /"/g;
277 | var pr_ampEnt = /&/g;
278 | var pr_nbspEnt = / /g;
279 | /** unescapes html to plain text. */
280 | function htmlToText(html) {
281 | var pos = html.indexOf('&');
282 | if (pos < 0) { return html; }
283 | // Handle numeric entities specially. We can't use functional substitution
284 | // since that doesn't work in older versions of Safari.
285 | // These should be rare since most browsers convert them to normal chars.
286 | for (--pos; (pos = html.indexOf('', pos + 1)) >= 0;) {
287 | var end = html.indexOf(';', pos);
288 | if (end >= 0) {
289 | var num = html.substring(pos + 3, end);
290 | var radix = 10;
291 | if (num && num.charAt(0) === 'x') {
292 | num = num.substring(1);
293 | radix = 16;
294 | }
295 | var codePoint = parseInt(num, radix);
296 | if (!isNaN(codePoint)) {
297 | html = (html.substring(0, pos) + String.fromCharCode(codePoint) +
298 | html.substring(end + 1));
299 | }
300 | }
301 | }
302 |
303 | return html.replace(pr_ltEnt, '<')
304 | .replace(pr_gtEnt, '>')
305 | .replace(pr_aposEnt, "'")
306 | .replace(pr_quotEnt, '"')
307 | .replace(pr_ampEnt, '&')
308 | .replace(pr_nbspEnt, ' ');
309 | }
310 |
311 | /** is the given node's innerHTML normally unescaped? */
312 | function isRawContent(node) {
313 | return 'XMP' === node.tagName;
314 | }
315 |
316 | function normalizedHtml(node, out) {
317 | switch (node.nodeType) {
318 | case 1: // an element
319 | var name = node.tagName.toLowerCase();
320 | out.push('<', name);
321 | for (var i = 0; i < node.attributes.length; ++i) {
322 | var attr = node.attributes[i];
323 | if (!attr.specified) { continue; }
324 | out.push(' ');
325 | normalizedHtml(attr, out);
326 | }
327 | out.push('>');
328 | for (var child = node.firstChild; child; child = child.nextSibling) {
329 | normalizedHtml(child, out);
330 | }
331 | if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
332 | out.push('<\/', name, '>');
333 | }
334 | break;
335 | case 2: // an attribute
336 | out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"');
337 | break;
338 | case 3: case 4: // text
339 | out.push(textToHtml(node.nodeValue));
340 | break;
341 | }
342 | }
343 |
344 | var PR_innerHtmlWorks = null;
345 | function getInnerHtml(node) {
346 | // inner html is hopelessly broken in Safari 2.0.4 when the content is
347 | // an html description of well formed XML and the containing tag is a PRE
348 | // tag, so we detect that case and emulate innerHTML.
349 | if (null === PR_innerHtmlWorks) {
350 | var testNode = document.createElement('PRE');
351 | testNode.appendChild(
352 | document.createTextNode('\n '));
353 | PR_innerHtmlWorks = !/= 0; nSpaces -= SPACES.length) {
403 | out.push(SPACES.substring(0, nSpaces));
404 | }
405 | pos = i + 1;
406 | break;
407 | case '\n':
408 | charInLine = 0;
409 | break;
410 | default:
411 | ++charInLine;
412 | }
413 | }
414 | if (!out) { return plainText; }
415 | out.push(plainText.substring(pos));
416 | return out.join('');
417 | };
418 | }
419 |
420 | // The below pattern matches one of the following
421 | // (1) /[^<]+/ : A run of characters other than '<'
422 | // (2) //: an HTML comment
423 | // (3) //: a cdata section
424 | // (3) /<\/?[a-zA-Z][^>]*>/ : A probably tag that should not be highlighted
425 | // (4) / : A '<' that does not begin a larger chunk. Treated as 1
426 | var pr_chunkPattern =
427 | /(?:[^<]+|||<\/?[a-zA-Z][^>]*>|<)/g;
428 | var pr_commentPrefix = /^|$)/, null],
614 | [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null],
615 | [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null],
616 | [PR_SOURCE,
617 | // Tags whose content is not escaped, and which contain source code.
618 | /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null],
619 | [PR_TAG, /^<\/?\w[^<>]*>/, null]
620 | ]);
621 | // Splits any of the source|style|xmp entries above into a start tag,
622 | // source content, and end tag.
623 | var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/;
624 | /** split markup on tags, comments, application directives, and other top
625 | * level constructs. Tags are returned as a single token - attributes are
626 | * not yet broken out.
627 | * @private
628 | */
629 | function tokenizeMarkup(source) {
630 | var decorations = PR_MARKUP_LEXER(source);
631 | for (var i = 0; i < decorations.length; i += 2) {
632 | if (decorations[i + 1] === PR_SOURCE) {
633 | var start, end;
634 | start = decorations[i];
635 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
636 | // Split out start and end script tags as actual tags, and leave the
637 | // body with style SCRIPT.
638 | var sourceChunk = source.substring(start, end);
639 | var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS);
640 | if (match) {
641 | decorations.splice(
642 | i, 2,
643 | start, PR_TAG, // the open chunk
644 | start + match[1].length, PR_SOURCE,
645 | start + match[1].length + (match[2] || '').length, PR_TAG);
646 | }
647 | }
648 | }
649 | return decorations;
650 | }
651 |
652 | var PR_TAG_LEXER = createSimpleLexer([
653 | [PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"],
654 | [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'],
655 | [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']
656 | ], [
657 | [PR_TAG, /^[\w:\-]+/, /^],
658 | [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/],
659 | [PR_ATTRIB_NAME, /^[\w:\-]+/, null],
660 | [PR_PLAIN, /^\s+/, null, ' \t\r\n']
661 | ]);
662 | /** split tags attributes and their values out from the tag name, and
663 | * recursively lex source chunks.
664 | * @private
665 | */
666 | function splitTagAttributes(source, decorations) {
667 | for (var i = 0; i < decorations.length; i += 2) {
668 | var style = decorations[i + 1];
669 | if (style === PR_TAG) {
670 | var start, end;
671 | start = decorations[i];
672 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
673 | var chunk = source.substring(start, end);
674 | var subDecorations = PR_TAG_LEXER(chunk, start);
675 | spliceArrayInto(subDecorations, decorations, i, 2);
676 | i += subDecorations.length - 2;
677 | }
678 | }
679 | return decorations;
680 | }
681 |
682 | /** returns a function that produces a list of decorations from source text.
683 | *
684 | * This code treats ", ', and ` as string delimiters, and \ as a string
685 | * escape. It does not recognize perl's qq() style strings.
686 | * It has no special handling for double delimiter escapes as in basic, or
687 | * the tripled delimiters used in python, but should work on those regardless
688 | * although in those cases a single string literal may be broken up into
689 | * multiple adjacent string literals.
690 | *
691 | * It recognizes C, C++, and shell style comments.
692 | *
693 | * @param {Object} options a set of optional parameters.
694 | * @return {function (string) : Array.} a
695 | * decorator that takes sourceCode as plain text and that returns a
696 | * decoration list
697 | */
698 | function sourceDecorator(options) {
699 | var shortcutStylePatterns = [], fallthroughStylePatterns = [];
700 | if (options.tripleQuotedStrings) {
701 | // '''multi-line-string''', 'single-line-string', and double-quoted
702 | shortcutStylePatterns.push(
703 | [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
704 | null, '\'"']);
705 | } else if (options.multiLineStrings) {
706 | // 'multi-line-string', "multi-line-string"
707 | shortcutStylePatterns.push(
708 | [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
709 | null, '\'"`']);
710 | } else {
711 | // 'single-line-string', "single-line-string"
712 | shortcutStylePatterns.push(
713 | [PR_STRING,
714 | /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
715 | null, '"\'']);
716 | }
717 | fallthroughStylePatterns.push(
718 | [PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']);
719 | if (options.hashComments) {
720 | shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
721 | }
722 | if (options.cStyleComments) {
723 | fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
724 | fallthroughStylePatterns.push(
725 | [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
726 | }
727 | if (options.regexLiterals) {
728 | var REGEX_LITERAL = (
729 | // A regular expression literal starts with a slash that is
730 | // not followed by * or / so that it is not confused with
731 | // comments.
732 | '^/(?=[^/*])'
733 | // and then contains any number of raw characters,
734 | + '(?:[^/\\x5B\\x5C]'
735 | // escape sequences (\x5C),
736 | + '|\\x5C[\\s\\S]'
737 | // or non-nesting character sets (\x5B\x5D);
738 | + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
739 | // finally closed by a /.
740 | + '(?:/|$)');
741 | fallthroughStylePatterns.push(
742 | [PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]);
743 | }
744 |
745 | var keywords = wordSet(options.keywords);
746 |
747 | options = null;
748 |
749 | /** splits the given string into comment, string, and "other" tokens.
750 | * @param {string} sourceCode as plain text
751 | * @return {Array.} a decoration list.
752 | * @private
753 | */
754 | var splitStringAndCommentTokens = createSimpleLexer(
755 | shortcutStylePatterns, fallthroughStylePatterns);
756 |
757 | var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [
758 | [PR_PLAIN, /^\s+/, null, ' \r\n'],
759 | // TODO(mikesamuel): recognize non-latin letters and numerals in idents
760 | [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null],
761 | // A hex number
762 | [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null],
763 | // An octal or decimal number, possibly in scientific notation
764 | [PR_LITERAL,
765 | /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i,
766 | null, '123456789'],
767 | [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]
768 | // Fallback will handle decimal points not adjacent to a digit
769 | ]);
770 |
771 | /** splits plain text tokens into more specific tokens, and then tries to
772 | * recognize keywords, and types.
773 | * @private
774 | */
775 | function splitNonStringNonCommentTokens(source, decorations) {
776 | for (var i = 0; i < decorations.length; i += 2) {
777 | var style = decorations[i + 1];
778 | if (style === PR_PLAIN) {
779 | var start, end, chunk, subDecs;
780 | start = decorations[i];
781 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
782 | chunk = source.substring(start, end);
783 | subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start);
784 | for (var j = 0, m = subDecs.length; j < m; j += 2) {
785 | var subStyle = subDecs[j + 1];
786 | if (subStyle === PR_PLAIN) {
787 | var subStart = subDecs[j];
788 | var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length;
789 | var token = source.substring(subStart, subEnd);
790 | if (token === '.') {
791 | subDecs[j + 1] = PR_PUNCTUATION;
792 | } else if (token in keywords) {
793 | subDecs[j + 1] = PR_KEYWORD;
794 | } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) {
795 | // classify types and annotations using Java's style conventions
796 | subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE;
797 | }
798 | }
799 | }
800 | spliceArrayInto(subDecs, decorations, i, 2);
801 | i += subDecs.length - 2;
802 | }
803 | }
804 | return decorations;
805 | }
806 |
807 | return function (sourceCode) {
808 | // Split into strings, comments, and other.
809 | // We do this because strings and comments are easily recognizable and can
810 | // contain stuff that looks like other tokens, so we want to mark those
811 | // early so we don't recurse into them.
812 | var decorations = splitStringAndCommentTokens(sourceCode);
813 |
814 | // Split non comment|string tokens on whitespace and word boundaries
815 | decorations = splitNonStringNonCommentTokens(sourceCode, decorations);
816 |
817 | return decorations;
818 | };
819 | }
820 |
821 | var decorateSource = sourceDecorator({
822 | keywords: ALL_KEYWORDS,
823 | hashComments: true,
824 | cStyleComments: true,
825 | multiLineStrings: true,
826 | regexLiterals: true
827 | });
828 |
829 | /** identify regions of markup that are really source code, and recursivley
830 | * lex them.
831 | * @private
832 | */
833 | function splitSourceNodes(source, decorations) {
834 | for (var i = 0; i < decorations.length; i += 2) {
835 | var style = decorations[i + 1];
836 | if (style === PR_SOURCE) {
837 | // Recurse using the non-markup lexer
838 | var start, end;
839 | start = decorations[i];
840 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
841 | var subDecorations = decorateSource(source.substring(start, end));
842 | for (var j = 0, m = subDecorations.length; j < m; j += 2) {
843 | subDecorations[j] += start;
844 | }
845 | spliceArrayInto(subDecorations, decorations, i, 2);
846 | i += subDecorations.length - 2;
847 | }
848 | }
849 | return decorations;
850 | }
851 |
852 | /** identify attribute values that really contain source code and recursively
853 | * lex them.
854 | * @private
855 | */
856 | function splitSourceAttributes(source, decorations) {
857 | var nextValueIsSource = false;
858 | for (var i = 0; i < decorations.length; i += 2) {
859 | var style = decorations[i + 1];
860 | var start, end;
861 | if (style === PR_ATTRIB_NAME) {
862 | start = decorations[i];
863 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
864 | nextValueIsSource = /^on|^style$/i.test(source.substring(start, end));
865 | } else if (style === PR_ATTRIB_VALUE) {
866 | if (nextValueIsSource) {
867 | start = decorations[i];
868 | end = i + 2 < decorations.length ? decorations[i + 2] : source.length;
869 | var attribValue = source.substring(start, end);
870 | var attribLen = attribValue.length;
871 | var quoted =
872 | (attribLen >= 2 && /^[\"\']/.test(attribValue) &&
873 | attribValue.charAt(0) === attribValue.charAt(attribLen - 1));
874 |
875 | var attribSource;
876 | var attribSourceStart;
877 | var attribSourceEnd;
878 | if (quoted) {
879 | attribSourceStart = start + 1;
880 | attribSourceEnd = end - 1;
881 | attribSource = attribValue;
882 | } else {
883 | attribSourceStart = start + 1;
884 | attribSourceEnd = end - 1;
885 | attribSource = attribValue.substring(1, attribValue.length - 1);
886 | }
887 |
888 | var attribSourceDecorations = decorateSource(attribSource);
889 | for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) {
890 | attribSourceDecorations[j] += attribSourceStart;
891 | }
892 |
893 | if (quoted) {
894 | attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE);
895 | spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0);
896 | } else {
897 | spliceArrayInto(attribSourceDecorations, decorations, i, 2);
898 | }
899 | }
900 | nextValueIsSource = false;
901 | }
902 | }
903 | return decorations;
904 | }
905 |
906 | /** returns a decoration list given a string of markup.
907 | *
908 | * This code recognizes a number of constructs.
909 | * comment
910 | * declaration
911 | * <\w ... > tag
912 | * \w ... > tag
913 | * ...?> embedded source
914 | * <%...%> embedded source
915 | * &[#\w]...; entity
916 | *
917 | * It does not recognizes %foo; doctype entities from .
918 | *
919 | * It will recurse into any
29 |
30 |
31 |
34 |
35 |
36 |
37 | Bash
38 | #!/bin/bash
39 |
40 | # Fibonacci numbers
41 | # Writes an infinite series to stdout, one entry per line
42 | function fib() {
43 | local a=1
44 | local b=1
45 | while true ; do
46 | echo $a
47 | local tmp=$a
48 | a=$(( $a + $b ))
49 | b=$tmp
50 | done
51 | }
52 |
53 | # output the 10th element of the series and halt
54 | fib | head -10 | tail -1
55 |
56 |
57 | Bash w/ language specified
58 | #!/bin/bash
59 |
60 | # Fibonacci numbers
61 | # Writes an infinite series to stdout, one entry per line
62 | function fib() {
63 | local a=1
64 | local b=1
65 | while true ; do
66 | echo $a
67 | local tmp=$a
68 | a=$(( $a + $b ))
69 | b=$tmp
70 | done
71 | }
72 |
73 | # output the 10th element of the series and halt
74 | fib | /usr/bin/*head -10 | tail -1
75 |
76 |
77 | C
78 |
79 |
80 | #include <stdio.h>
81 |
82 | /* the n-th fibonacci number.
83 | */
84 | unsigned int fib(unsigned int n) {
85 | unsigned int a = 1, b = 1;
86 | unsigned int tmp;
87 | while (--n >= 0) {
88 | tmp = a;
89 | a += b;
90 | b = tmp;
91 | }
92 | return a;
93 | }
94 |
95 | main() {
96 | printf("%u", fib(10));
97 | }
98 |
99 |
100 | C w/ language specified
101 |
102 |
103 | #include <stdio.h>
104 |
105 | /* the nth fibonacci number. */
106 | unsigned int fib(unsigned int n) {
107 | unsigned int a = 1, b = 1;
108 | unsigned int tmp;
109 | while (--n >= 0) {
110 | tmp = a;
111 | a += b;
112 | b = tmp;
113 | }
114 | return a;
115 | }
116 |
117 | void main() {
118 | printf("%u", fib(10));
119 | }
120 |
121 |
122 | C++
123 |
124 | #include <iostream>
125 |
126 | using namespace std;
127 |
128 | //! fibonacci numbers with gratuitous use of templates.
129 | //! \param n an index into the fibonacci series
130 | //! \param fib0 element 0 of the series
131 | //! \return the nth element of the fibonacci series
132 | template <class T>
133 | T fib(unsigned int n, const T& fib0) {
134 | T a(fib0), b(fib0);
135 | for (; n; --n) {
136 | T tmp(a);
137 | a += b;
138 | b = tmp;
139 | }
140 | return a;
141 | }
142 |
143 | int main(int argc, char **argv) {
144 | cout << fib(10, 1U);
145 | }
146 |
147 |
148 | C++ w/ language specified
149 |
150 | #include <iostream>
151 |
152 | using namespace std;
153 |
154 | //! fibonacci numbers with gratuitous use of templates.
155 | //! \param n an index into the fibonacci series
156 | //! \param fib0 element 0 of the series
157 | //! \return the nth element of the fibonacci series
158 | template <class T>
159 | T fib(int n, const T& fib0) {
160 | T a(fib0), b(fib0);
161 | while (--n >= 0) {
162 | T tmp(a);
163 | a += b;
164 | b = tmp;
165 | }
166 | return a;
167 | }
168 |
169 | int main(int argc, char **argv) {
170 | cout << fib(10, 1U);
171 | }
172 |
173 |
174 | Java
175 |
176 | package foo;
177 |
178 | import java.util.Iterator;
179 |
180 | /**
181 | * the fibonacci series implemented as an Iterable.
182 | */
183 | public final class Fibonacci implements Iterable<Integer> {
184 | /** the next and previous members of the series. */
185 | private int a = 1, b = 1;
186 |
187 | @Override
188 | public Iterator<Integer> iterator() {
189 | return new Iterator<Integer>() {
190 | /** the series is infinite. */
191 | public boolean hasNext() { return true; }
192 | public Integer next() {
193 | int tmp = a;
194 | a += b;
195 | b = tmp;
196 | return a;
197 | }
198 | public void remove() { throw new UnsupportedOperationException(); }
199 | };
200 | }
201 |
202 | /**
203 | * the n<sup>th</sup> element of the given series.
204 | * @throws NoSuchElementException if there are less than n elements in the
205 | * given Iterable's {@link Iterable#iterator iterator}.
206 | */
207 | public static <T>
208 | T nth(int n, Iterable<T> iterable) {
209 | Iterator<? extends T> it = iterable.iterator();
210 | while (--n > 0) {
211 | it.next();
212 | }
213 | return it.next();
214 | }
215 |
216 | public static void main(String[] args) {
217 | System.out.print(nth(10, new Fibonacci()));
218 | }
219 | }
220 |
221 |
222 | Java w/ language specified
223 |
224 | package foo;
225 |
226 | import java.util.Iterator;
227 |
228 | /**
229 | * the fibonacci series implemented as an Iterable.
230 | */
231 | public final class Fibonacci implements Iterable<Integer> {
232 | /** the next and previous members of the series. */
233 | private int a = 1, b = 1;
234 |
235 | @Override
236 | public Iterator<Integer> iterator() {
237 | return new Iterator<Integer>() {
238 | /** the series is infinite. */
239 | public boolean hasNext() { return true; }
240 | public Integer next() {
241 | int tmp = a;
242 | a += b;
243 | b = tmp;
244 | return a;
245 | }
246 | public void remove() { throw new UnsupportedOperationException(); }
247 | };
248 | }
249 |
250 | /**
251 | * the n<sup>th</sup> element of the given series.
252 | * @throws NoSuchElementException if there are less than n elements in the
253 | * given Iterable's {@link Iterable#iterator iterator}.
254 | */
255 | public static <T>
256 | T nth(int n, Iterable<T> iterable) {
257 | Iterator<? extends T> in = iterable.iterator();
258 | while (--n > 0) {
259 | in.next();
260 | }
261 | return in.next();
262 | }
263 |
264 | public static void main(String[] args) {
265 | System.out.print(nth(10, new Fibonacci()));
266 | }
267 | }
268 |
269 | # not a java comment
270 | # not keywords: static_cast and namespace
271 |
272 |
273 | Javascript
274 |
275 | /**
276 | * nth element in the fibonacci series.
277 | * @param n >= 0
278 | * @return the nth element, >= 0.
279 | */
280 | function fib(n) {
281 | var a = 1, b = 1;
282 | var tmp;
283 | while (--n >= 0) {
284 | tmp = a;
285 | a += b;
286 | b = tmp;
287 | }
288 | return a;
289 | }
290 |
291 | document.write(fib(10));
292 |
293 |
294 | Issue 12 - Javascript Regular Expressions
295 |
296 | /foo/; // a slash starting a line treated as a regexp beginning
297 | "foo".match(/fo+$/);
298 | // this line comment not treated as a regular expressions
299 | "foo /bar/".test(/"baz"/); // test string and regexp boundaries
300 | var division = /\b\d+\/\d+/g; // test char sets and escaping of specials
301 | var allSpecials = /([^\(\)\[\]\{\}\-\?\+\*\.\^\$\/]+)\\/;
302 | var slashInCharset = /[^/]/g, notCloseSq = /[^\]]/;
303 |
304 | // test that slash used in numeric context treated as an operator
305 | 1 / 2;
306 | 1. / x;
307 | x / y;
308 | (x) / y;
309 | 1 /* foo */ / 2;
310 | 1 /* foo *// 2;
311 | 1/2;
312 | 1./x;
313 | x/y;
314 | (x)/y;
315 |
316 | // test split over two lines. line comment should not fool it
317 | 1//
318 | /2;
319 |
320 | x++/y;
321 | x--/y;
322 | x[y] / z;
323 | f() / n;
324 |
325 | // test that slash after non postfix operator is start of regexp
326 | log('matches = ' + /foo/.test(foo));
327 |
328 | // test keyword preceders
329 | return /a regexp/;
330 | division = notreturn / not_a_regexp / 2; // keyword suffix does not match
331 |
332 | // & not used as prefix operator in javascript but this should still work
333 | &/foo/;
334 |
335 | extends = /extends/;
336 |
337 |
338 | Issue 12 - Javascript Regular Expressions w/ language specified
339 |
340 | /foo/; // a slash starting a line treated as a regexp beginning
341 | "foo".match(/fo+$/);
342 | // this line comment not treated as a regular expressions
343 | "foo /bar/".test(/"baz"/); // test string and regexp boundaries
344 | var division = /\b\d+\/\d+/g; // test char sets and escaping of specials
345 | var allSpecials = /([^\(\)\[\]\{\}\-\?\+\*\.\^\$\/]+)\\/;
346 | var slashInCharset = /[^/]/g, notCloseSq = /[^\]]/;
347 |
348 | // test that slash used in numeric context treated as an operator
349 | 1 / 2;
350 | 1. / x;
351 | x / y;
352 | (x) / y;
353 | 1 /* foo */ / 2;
354 | 1 /* foo *// 2;
355 | 1/2;
356 | 1./x;
357 | x/y;
358 | (x)/y;
359 |
360 | // test split over two lines. line comment should not fool it
361 | 1//
362 | /2;
363 |
364 | x++/y;
365 | x--/y;
366 | x[y] / z;
367 | f() / n;
368 |
369 | // test that slash after non postfix operator is start of regexp
370 | log('matches = ' + /foo/.test(foo));
371 |
372 | // test keyword preceders
373 | return /a regexp/;
374 | division = notreturn / not_a_regexp / 2; // keyword suffix does not match
375 |
376 | // & not used as prefix operator in javascript but this should still work
377 | &/foo/;
378 |
379 | extends = /extends/;
380 |
381 |
382 | Perl
383 |
384 | #!/usr/bin/perl
385 |
386 | use strict;
387 | use integer;
388 |
389 | # the nth element of the fibonacci series
390 | # param n - an int >= 0
391 | # return an int >= 0
392 | sub fib($) {
393 | my $n = shift, $a = 1, $b = 1;
394 | ($a, $b) = ($a + $b, $a) until (--$n < 0);
395 | return $a;
396 | }
397 |
398 | print fib(10);
399 |
400 |
401 | Python
402 |
403 | #!/usr/bin/python2.4
404 |
405 | def fib():
406 | '''
407 | a generator that produces the elements of the fibonacci series
408 | '''
409 |
410 | a = 1
411 | b = 1
412 | while True:
413 | a, b = a + b, a
414 | yield a
415 |
416 | def nth(series, n):
417 | '''
418 | returns the nth element of a series,
419 | consuming the earlier elements of the series
420 | '''
421 |
422 | for x in series:
423 | n = n - 1
424 | if n <= 0: return x
425 |
426 | print nth(fib(), 10)
427 |
428 |
429 | Python w/ language specified
430 |
431 | #!/usr/bin/python2.4
432 |
433 | def fib():
434 | '''
435 | a generator that produces the fibonacci series's elements
436 | '''
437 |
438 | a = 1
439 | b = 1
440 | while True:
441 | a, b = a + b, a
442 | yield a
443 |
444 | def nth(series, n):
445 | '''
446 | returns the nth element of a series,
447 | consuming the earlier elements of the series
448 | '''
449 |
450 | for x in series:
451 | n -= 1
452 | if n <= 0: return x
453 |
454 | print nth(fib(), 10)
455 |
456 | /* not a comment and not keywords: null char true */
457 |
458 |
459 | SQL w/ language specified
460 |
461 | /* A multi-line
462 | * comment */
463 | 'Another string /* Isn\'t a comment',
464 | "A string */"
465 | -- A line comment
466 | SELECT * FROM users WHERE id IN (1, 2.0, +30e-1);
467 | -- keywords are case-insensitive.
468 | -- Note: user-table is a single identifier, not a pair of keywords
469 | select * from user-table where id in (x, y, z);
470 |
471 |
472 | XML
473 |
474 | <!DOCTYPE series PUBLIC "fibonacci numbers">
475 |
476 | <series base="1" step="s(n-2) + s(n-1)">
477 | <element i="0">1</element>
478 | <element i="1">1</element>
479 | <element i="2">2</element>
480 | <element i="3">3</element>
481 | <element i="4">5</element>
482 | <element i="5">8</element>
483 | ...
484 | </series>
485 |
486 |
487 | HTML
488 |
489 | <html>
490 | <head>
491 | <title>Fibonacci number</title>
492 | </head>
493 | <body>
494 | <noscript>
495 | <dl>
496 | <dt>Fibonacci numbers</dt>
497 | <dd>1</dd>
498 | <dd>1</dd>
499 | <dd>2</dd>
500 | <dd>3</dd>
501 | <dd>5</dd>
502 | <dd>8</dd>
503 | …
504 | </dl>
505 | </noscript>
506 |
507 | <script type="text/javascript"><!--
508 | function fib(n) {
509 | var a = 1, b = 1;
510 | var tmp;
511 | while (--n >= 0) {
512 | tmp = a;
513 | a += b;
514 | b = tmp;
515 | }
516 | return a;
517 | }
518 |
519 | document.writeln(fib(10));
520 | // -->
521 | </script>
522 | </body>
523 | </html>
524 |
525 |
526 | HTML w/ language specified
527 |
528 | Fibonacci Numbers
529 |
530 | <noscript>
531 | <dl>
532 | <dt>Fibonacci numbers</dt>
533 | <dd>1</dd>
534 | <dd>1</dd>
535 | <dd>2</dd>
536 | <dd>3</dd>
537 | <dd>5</dd>
538 | <dd>8</dd>
539 | …
540 | </dl>
541 | </noscript>
542 |
543 | <script type="text/javascript"><!--
544 | function fib(n) {
545 | var a = 1, b = 1;
546 | var tmp;
547 | while (--n >= 0) {
548 | tmp = a;
549 | a += b;
550 | b = tmp;
551 | }
552 | return a;
553 | }
554 |
555 | document.writeln(fib(10));
556 | // -->
557 | </script>
558 |
559 |
560 |
561 | HTML using XMP
562 |
564 |
565 | Fibonacci number
566 |
567 |
568 |
580 |
581 |
596 |
597 |
598 |
599 |
600 | XHTML
601 | <xhtml>
603 | <head>
604 | <title>Fibonacci number</title>
605 | </head>
606 | <body>
607 | <script type="text/javascript"><![CDATA[
608 | function fib(n) {
609 | var a = 1, b = 1;
610 | var tmp;
611 | while (--n >= 0) {
612 | tmp = a;
613 | a += b;
614 | b = tmp;
615 | }
616 | return a;
617 | }
618 |
619 | document.writeln(fib(10));
620 | ]]>
621 | </script>
622 | </body>
623 | </xhtml>
624 |
625 |
626 | PHP
627 |
628 | <html>
629 | <head>
630 | <title><?= 'Fibonacci numbers' ?></title>
631 |
632 | <?php
633 | // PHP has a plethora of comment types
634 | /* What is a
635 | "plethora"? */
636 | function fib($n) {
637 | # I don't know.
638 | $a = 1;
639 | $b = 1;
640 | while (--$n >= 0) {
641 | echo "$a\n";
642 | $tmp = $a;
643 | $a += $b;
644 | $b = $tmp;
645 | }
646 | }
647 | ?>
648 | </head>
649 | <body>
650 | <?= fib(10) ?>
651 | </body>
652 | </html>
653 |
654 |
655 | XSL (Issue 19)
656 |
657 | <!-- Test elements and attributes with namespaces -->
658 |
659 | <xsl:stylesheet xml:lang="en">
660 | <xsl:template match=".">
661 | <xsl:text>Hello World</xsl:text>
662 | </xsl:template>
663 | </xsl:stylesheet>
664 |
665 |
666 | Whitespace
667 |
668 |
669 | Misc
670 | // ends with line comment token
671 | //
672 |
673 | User submitted testcase for Bug 4
674 |
675 | Javascript Snippets wrapped in HTML SCRIPT tags hides/destroys inner content
676 |
677 |
678 | <script type="text/javascript">
679 | var savedTarget=null; // The target layer (effectively vidPane)
680 | var orgCursor=null; // The original mouse style so we can restore it
681 | var dragOK=false; // True if we're allowed to move the element under mouse
682 | var dragXoffset=0; // How much we've moved the element on the horozontal
683 | var dragYoffset=0; // How much we've moved the element on the verticle
684 | vidPaneID = document.getElementById('vidPane'); // Our movable layer
685 | vidPaneID.style.top='75px'; // Starting location horozontal
686 | vidPaneID.style.left='75px'; // Starting location verticle
687 | <script>
688 |
689 | The fact that the script tag was not closed properly was causing
690 | PR_splitSourceNodes to end without emitting the script contents.
691 |
692 | Bug 8 - tabs mangled
693 | If tabs are used to indent code inside <pre> IE6 and 7 won't honor them
694 | after the script runs.
695 |
696 | Code indented with tabs will be shown aligned to the left margin instead of
697 | the proper indenting shown in Firefox.
698 |
699 | I'm using Revision 20 of prettify.js, IE 6.0.29.00 in English and IE
700 | 7.0.5730.11 in Spanish.
701 |
702 |
703 | one Two three Four five |
704 | Six seven Eight nine Ten |
705 | eleven Twelve thirteen Fourteen fifteen |
706 |
707 |
708 | Bug 14a - does not recognize <br> as newline
709 | //comment
int main(int argc, char **argv)
711 | {}
712 |
713 | Bug 14b - comments not ignored
714 | <!-- There's an HTML comment in my comment -->
716 | <p>And another one inside the end tag</p>
717 |
718 |
719 | Bug 20 - missing blank lines
720 | <html>
722 |
723 | <head>
724 |
725 | Bug 21 - code doesn't copy and paste well in IE
726 | <html>
728 | <head>
729 | <title>Test</title>
730 | </head>
731 | </html>
732 | To test this bug, disable overriding of _pr_isIE6 above, and copy and paste
733 | the above into Notepad.
734 |
735 | Bug 22 - Line numbers and other non-code spans in code
736 | 01: // This is a line of code
738 | 02: /* Multiline comments can
739 | 03: * span over and around
740 | 04: * line markers
741 | And can even be interrupted
742 | by inline code annotations
743 | 05: */
744 | 06: class MyClass extends Foo {
745 | 07: public static void main(String... argv) {
746 | 08: System.out.print("Hello World");
747 | 09: }
748 | 10: }
749 |
750 | Bug 24 - LUA Syntax Highlighting
751 |
753 | -- Examples from the language reference
754 | a = 'alo\n123"'
755 | a = "alo\n123\""
756 | a = '\97lo\10\04923"'
757 | a = [[alo
758 | 123"]]
759 | a = [==[
760 | alo
761 | 123"]==]
762 |
763 | 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
764 |
765 | -- Some comments that demonstrate long brackets
766 | double_quoted = "Not a long bracket [=["
767 | --[=[ quoting out
768 | [[ foo ]]
769 | [==[does not end comment either]==]
770 | ]=]
771 | past_end_of_comment
772 | --]=]
773 |
774 | -- Example code courtesy Joseph Harmbruster
775 | #
776 | do
777 | local function ssgeneral(t, n, before)
778 | for _, h in ipairs(incs) do
779 | for i = h + 1, n do
780 | local v = t[i]
781 | for j = i - h, 1, -h do
782 | local testval = t[j]
783 | if not before(v, testval) then break end
784 | t[i] = testval; i = j
785 | end
786 | t[i] = v
787 | end
788 | end
789 | return t
790 | end
791 |
792 | function shellsort(t, before, n)
793 | n = n or #t
794 | if not before or before == "<" then return ssup(t, n)
795 | elseif before == ">" then return ssdown(t, n)
796 | else return ssgeneral(t, n, before)
797 | end
798 | end
799 | return shellsort
800 | end
801 |
802 | Bug 42 - Lisp Syntax Highlighting
803 | ; -*- mode: lisp -*-
805 |
806 | (defun back-six-lines () (interactive) (forward-line -6))
807 | (defun forward-six-lines () (interactive) (forward-line 6))
808 |
809 | (global-set-key "\M-l" 'goto-line)
810 | (global-set-key "\C-z" 'advertised-undo)
811 | (global-set-key [C-insert] 'clipboard-kill-ring-save)
812 | (global-set-key [S-insert] 'clipboard-yank)
813 | (global-set-key [C-up] 'back-six-lines)
814 | (global-set-key [C-down] 'forward-six-lines)
815 |
816 | (setq visible-bell t)
817 | (setq user-mail-address "foo@bar.com")
818 | (setq default-major-mode 'text-mode)
819 |
820 | (setenv "TERM" "emacs")
821 | (c-set-offset 'case-label 2)
822 | (setq c-basic-offset 2)
823 | (setq perl-indent-level 2)
824 | (setq delete-key-deletes-forward t)
825 | (setq indent-tabs-mode nil)
826 |
827 | ;; Text mode
828 | (add-hook 'text-mode-hook
829 | '(lambda ()
830 | (turn-on-auto-fill)
831 | )
832 | )
833 |
834 | ;; Fundamental mode
835 | (add-hook 'fundamental-mode-hook
836 | '(lambda ()
837 | (turn-on-auto-fill)
838 | )
839 | )
840 |
841 |
842 | Bug 33 - OCaml and F#
843 |
844 | (*
845 | * Print the 10th fibonacci number
846 | *)
847 |
848 | //// A line comment
849 | "A string";;
850 | (0, 125, 0xa0, -1.0, 1e6, 1.2e-3);; // number literals
851 |
852 | #if fibby
853 | let
854 | rec fib = function (0, a, _) -> a
855 | | (n, a, b) -> fib(n - 1, a + b, a)
856 | in
857 | print_int(fib(10, 1, 1));;
858 | #endif
859 |
860 | Still TODO: handle nested (* (* comments *) *) properly.
861 |
862 | Bug 45 - Square brackets in strings
863 |
864 | throw new RuntimeException("Element [" + element.getName() +
865 | "] missing attribute.");
866 | variable++;
867 |
868 |
869 | Protocol Buffers
870 | message SearchRequest {
872 | required string query = 1;
873 | optional int32 page_number = 2;
874 | optional int32 result_per_page = 3 [default = 10];
875 | enum Corpus {
876 | UNIVERSAL = 0;
877 | WEB = 1;
878 | IMAGES = 2;
879 | LOCAL = 3;
880 | NEWS = 4;
881 | PRODUCTS = 5;
882 | VIDEO = 6;
883 | }
884 | optional Corpus corpus = 4 [default = UNIVERSAL];
885 | }
886 |
887 |
888 |
889 |
2160 |
2161 |