angularjs-rails 1.2.0.rc2 → 1.2.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: angularjs-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0.rc2
4
+ version: 1.2.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hirav Gandhi
@@ -9,7 +9,49 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2013-09-06 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: versionomy
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  description: Injects Angular.js into your asset pipeline as well as other Angular
14
56
  modules.
15
57
  email: hgandhi@alumni.stanford.edu
@@ -20,8 +62,6 @@ files:
20
62
  - lib/angularjs-rails/version.rb
21
63
  - lib/angularjs-rails.rb
22
64
  - vendor/assets/javascripts/angular-animate.js
23
- - vendor/assets/javascripts/angular-bootstrap-prettify.js
24
- - vendor/assets/javascripts/angular-bootstrap.js
25
65
  - vendor/assets/javascripts/angular-cookies.js
26
66
  - vendor/assets/javascripts/angular-loader.js
27
67
  - vendor/assets/javascripts/angular-mocks.js
@@ -42,7 +82,8 @@ files:
42
82
  - MIT-LICENSE
43
83
  - README.md
44
84
  homepage: https://github.com/hiravgandhi/angularjs-rails/
45
- licenses: []
85
+ licenses:
86
+ - MIT
46
87
  metadata: {}
47
88
  post_install_message:
48
89
  rdoc_options: []
@@ -60,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
101
  version: 1.3.1
61
102
  requirements: []
62
103
  rubyforge_project:
63
- rubygems_version: 2.0.4
104
+ rubygems_version: 2.0.6
64
105
  signing_key:
65
106
  specification_version: 4
66
107
  summary: Angular.js on Rails
@@ -1,1835 +0,0 @@
1
- /**
2
- * @license AngularJS v1.0.7
3
- * (c) 2010-2012 Google, Inc. http://angularjs.org
4
- * License: MIT
5
- */
6
- (function(window, angular, undefined) {
7
- 'use strict';
8
-
9
- var directive = {};
10
- var service = { value: {} };
11
-
12
- var DEPENDENCIES = {
13
- 'angular.js': 'http://code.angularjs.org/' + angular.version.full + '/angular.min.js',
14
- 'angular-resource.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-resource.min.js',
15
- 'angular-sanitize.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-sanitize.min.js',
16
- 'angular-cookies.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-cookies.min.js'
17
- };
18
-
19
-
20
- function escape(text) {
21
- return text.
22
- replace(/\&/g, '&').
23
- replace(/\</g, '&lt;').
24
- replace(/\>/g, '&gt;').
25
- replace(/"/g, '&quot;');
26
- }
27
-
28
- /**
29
- * http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
30
- * http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
31
- */
32
- function setHtmlIe8SafeWay(element, html) {
33
- var newElement = angular.element('<pre>' + html + '</pre>');
34
-
35
- element.html('');
36
- element.append(newElement.contents());
37
- return element;
38
- }
39
-
40
-
41
- directive.jsFiddle = function(getEmbeddedTemplate, escape, script) {
42
- return {
43
- terminal: true,
44
- link: function(scope, element, attr) {
45
- var name = '',
46
- stylesheet = '<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">\n',
47
- fields = {
48
- html: '',
49
- css: '',
50
- js: ''
51
- };
52
-
53
- angular.forEach(attr.jsFiddle.split(' '), function(file, index) {
54
- var fileType = file.split('.')[1];
55
-
56
- if (fileType == 'html') {
57
- if (index == 0) {
58
- fields[fileType] +=
59
- '<div ng-app' + (attr.module ? '="' + attr.module + '"' : '') + '>\n' +
60
- getEmbeddedTemplate(file, 2);
61
- } else {
62
- fields[fileType] += '\n\n\n <!-- CACHE FILE: ' + file + ' -->\n' +
63
- ' <script type="text/ng-template" id="' + file + '">\n' +
64
- getEmbeddedTemplate(file, 4) +
65
- ' </script>\n';
66
- }
67
- } else {
68
- fields[fileType] += getEmbeddedTemplate(file) + '\n';
69
- }
70
- });
71
-
72
- fields.html += '</div>\n';
73
-
74
- setHtmlIe8SafeWay(element,
75
- '<form class="jsfiddle" method="post" action="http://jsfiddle.net/api/post/library/pure/" target="_blank">' +
76
- hiddenField('title', 'AngularJS Example: ' + name) +
77
- hiddenField('css', '</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> \n' +
78
- stylesheet +
79
- script.angular +
80
- (attr.resource ? script.resource : '') +
81
- '<style>\n' +
82
- fields.css) +
83
- hiddenField('html', fields.html) +
84
- hiddenField('js', fields.js) +
85
- '<button class="btn btn-primary"><i class="icon-white icon-pencil"></i> Edit Me</button>' +
86
- '</form>');
87
-
88
- function hiddenField(name, value) {
89
- return '<input type="hidden" name="' + name + '" value="' + escape(value) + '">';
90
- }
91
- }
92
- }
93
- };
94
-
95
-
96
- directive.code = function() {
97
- return {restrict: 'E', terminal: true};
98
- };
99
-
100
-
101
- directive.prettyprint = ['reindentCode', function(reindentCode) {
102
- return {
103
- restrict: 'C',
104
- terminal: true,
105
- compile: function(element) {
106
- element.html(window.prettyPrintOne(reindentCode(element.html()), undefined, true));
107
- }
108
- };
109
- }];
110
-
111
-
112
- directive.ngSetText = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
113
- return {
114
- restrict: 'CA',
115
- priority: 10,
116
- compile: function(element, attr) {
117
- setHtmlIe8SafeWay(element, escape(getEmbeddedTemplate(attr.ngSetText)));
118
- }
119
- }
120
- }]
121
-
122
-
123
- directive.ngHtmlWrap = ['reindentCode', 'templateMerge', function(reindentCode, templateMerge) {
124
- return {
125
- compile: function(element, attr) {
126
- var properties = {
127
- head: '',
128
- module: '',
129
- body: element.text()
130
- },
131
- html = "<!doctype html>\n<html ng-app{{module}}>\n <head>\n{{head:4}} </head>\n <body>\n{{body:4}} </body>\n</html>";
132
-
133
- angular.forEach((attr.ngHtmlWrap || '').split(' '), function(dep) {
134
- if (!dep) return;
135
- dep = DEPENDENCIES[dep] || dep;
136
-
137
- var ext = dep.split(/\./).pop();
138
-
139
- if (ext == 'css') {
140
- properties.head += '<link rel="stylesheet" href="' + dep + '" type="text/css">\n';
141
- } else if(ext == 'js') {
142
- properties.head += '<script src="' + dep + '"></script>\n';
143
- } else {
144
- properties.module = '="' + dep + '"';
145
- }
146
- });
147
-
148
- setHtmlIe8SafeWay(element, escape(templateMerge(html, properties)));
149
- }
150
- }
151
- }];
152
-
153
-
154
- directive.ngSetHtml = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
155
- return {
156
- restrict: 'CA',
157
- priority: 10,
158
- compile: function(element, attr) {
159
- setHtmlIe8SafeWay(element, getEmbeddedTemplate(attr.ngSetHtml));
160
- }
161
- }
162
- }];
163
-
164
-
165
- directive.ngEvalJavascript = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
166
- return {
167
- compile: function (element, attr) {
168
- var script = getEmbeddedTemplate(attr.ngEvalJavascript);
169
-
170
- try {
171
- if (window.execScript) { // IE
172
- window.execScript(script || '""'); // IE complains when evaling empty string
173
- } else {
174
- window.eval(script);
175
- }
176
- } catch (e) {
177
- if (window.console) {
178
- window.console.log(script, '\n', e);
179
- } else {
180
- window.alert(e);
181
- }
182
- }
183
- }
184
- };
185
- }];
186
-
187
-
188
- directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location', function($templateCache, $browser, docsRootScope, $location) {
189
- return {
190
- terminal: true,
191
- link: function(scope, element, attrs) {
192
- var modules = [];
193
-
194
- modules.push(['$provide', function($provide) {
195
- $provide.value('$templateCache', $templateCache);
196
- $provide.value('$anchorScroll', angular.noop);
197
- $provide.value('$browser', $browser);
198
- $provide.provider('$location', function() {
199
- this.$get = ['$rootScope', function($rootScope) {
200
- docsRootScope.$on('$locationChangeSuccess', function(event, oldUrl, newUrl) {
201
- $rootScope.$broadcast('$locationChangeSuccess', oldUrl, newUrl);
202
- });
203
- return $location;
204
- }];
205
- this.html5Mode = angular.noop;
206
- });
207
- $provide.decorator('$timeout', ['$rootScope', '$delegate', function($rootScope, $delegate) {
208
- return angular.extend(function(fn, delay) {
209
- if (delay && delay > 50) {
210
- return setTimeout(function() {
211
- $rootScope.$apply(fn);
212
- }, delay);
213
- } else {
214
- return $delegate.apply(this, arguments);
215
- }
216
- }, $delegate);
217
- }]);
218
- $provide.decorator('$rootScope', ['$delegate', function(embedRootScope) {
219
- docsRootScope.$watch(function embedRootScopeDigestWatch() {
220
- embedRootScope.$digest();
221
- });
222
- return embedRootScope;
223
- }]);
224
- }]);
225
- if (attrs.ngEmbedApp) modules.push(attrs.ngEmbedApp);
226
-
227
- element.bind('click', function(event) {
228
- if (event.target.attributes.getNamedItem('ng-click')) {
229
- event.preventDefault();
230
- }
231
- });
232
- angular.bootstrap(element, modules);
233
- }
234
- };
235
- }];
236
-
237
- service.reindentCode = function() {
238
- return function (text, spaces) {
239
- if (!text) return text;
240
- var lines = text.split(/\r?\n/);
241
- var prefix = ' '.substr(0, spaces || 0);
242
- var i;
243
-
244
- // remove any leading blank lines
245
- while (lines.length && lines[0].match(/^\s*$/)) lines.shift();
246
- // remove any trailing blank lines
247
- while (lines.length && lines[lines.length - 1].match(/^\s*$/)) lines.pop();
248
- var minIndent = 999;
249
- for (i = 0; i < lines.length; i++) {
250
- var line = lines[0];
251
- var reindentCode = line.match(/^\s*/)[0];
252
- if (reindentCode !== line && reindentCode.length < minIndent) {
253
- minIndent = reindentCode.length;
254
- }
255
- }
256
-
257
- for (i = 0; i < lines.length; i++) {
258
- lines[i] = prefix + lines[i].substring(minIndent);
259
- }
260
- lines.push('');
261
- return lines.join('\n');
262
- }
263
- };
264
-
265
- service.templateMerge = ['reindentCode', function(indentCode) {
266
- return function(template, properties) {
267
- return template.replace(/\{\{(\w+)(?:\:(\d+))?\}\}/g, function(_, key, indent) {
268
- var value = properties[key];
269
-
270
- if (indent) {
271
- value = indentCode(value, indent);
272
- }
273
-
274
- return value == undefined ? '' : value;
275
- });
276
- };
277
- }];
278
-
279
- service.getEmbeddedTemplate = ['reindentCode', function(reindentCode) {
280
- return function (id) {
281
- var element = document.getElementById(id);
282
-
283
- if (!element) {
284
- return null;
285
- }
286
-
287
- return reindentCode(angular.element(element).html(), 0);
288
- }
289
- }];
290
-
291
-
292
- angular.module('bootstrapPrettify', []).directive(directive).factory(service);
293
-
294
- // Copyright (C) 2006 Google Inc.
295
- //
296
- // Licensed under the Apache License, Version 2.0 (the "License");
297
- // you may not use this file except in compliance with the License.
298
- // You may obtain a copy of the License at
299
- //
300
- // http://www.apache.org/licenses/LICENSE-2.0
301
- //
302
- // Unless required by applicable law or agreed to in writing, software
303
- // distributed under the License is distributed on an "AS IS" BASIS,
304
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
305
- // See the License for the specific language governing permissions and
306
- // limitations under the License.
307
-
308
-
309
- /**
310
- * @fileoverview
311
- * some functions for browser-side pretty printing of code contained in html.
312
- *
313
- * <p>
314
- * For a fairly comprehensive set of languages see the
315
- * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a>
316
- * file that came with this source. At a minimum, the lexer should work on a
317
- * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
318
- * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk
319
- * and a subset of Perl, but, because of commenting conventions, doesn't work on
320
- * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
321
- * <p>
322
- * Usage: <ol>
323
- * <li> include this source file in an html page via
324
- * {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
325
- * <li> define style rules. See the example page for examples.
326
- * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
327
- * {@code class=prettyprint.}
328
- * You can also use the (html deprecated) {@code <xmp>} tag, but the pretty
329
- * printer needs to do more substantial DOM manipulations to support that, so
330
- * some css styles may not be preserved.
331
- * </ol>
332
- * That's it. I wanted to keep the API as simple as possible, so there's no
333
- * need to specify which language the code is in, but if you wish, you can add
334
- * another class to the {@code <pre>} or {@code <code>} element to specify the
335
- * language, as in {@code <pre class="prettyprint lang-java">}. Any class that
336
- * starts with "lang-" followed by a file extension, specifies the file type.
337
- * See the "lang-*.js" files in this directory for code that implements
338
- * per-language file handlers.
339
- * <p>
340
- * Change log:<br>
341
- * cbeust, 2006/08/22
342
- * <blockquote>
343
- * Java annotations (start with "@") are now captured as literals ("lit")
344
- * </blockquote>
345
- * @requires console
346
- */
347
-
348
- // JSLint declarations
349
- /*global console, document, navigator, setTimeout, window, define */
350
-
351
- /**
352
- * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
353
- * UI events.
354
- * If set to {@code false}, {@code prettyPrint()} is synchronous.
355
- */
356
- window['PR_SHOULD_USE_CONTINUATION'] = true;
357
-
358
- /**
359
- * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
360
- * {@code class=prettyprint} and prettify them.
361
- *
362
- * @param {Function?} opt_whenDone if specified, called when the last entry
363
- * has been finished.
364
- */
365
- var prettyPrintOne;
366
- /**
367
- * Pretty print a chunk of code.
368
- *
369
- * @param {string} sourceCodeHtml code as html
370
- * @return {string} code as html, but prettier
371
- */
372
- var prettyPrint;
373
-
374
-
375
- (function () {
376
- var win = window;
377
- // Keyword lists for various languages.
378
- // We use things that coerce to strings to make them compact when minified
379
- // and to defeat aggressive optimizers that fold large string constants.
380
- var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
381
- var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," +
382
- "double,enum,extern,float,goto,int,long,register,short,signed,sizeof," +
383
- "static,struct,switch,typedef,union,unsigned,void,volatile"];
384
- var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
385
- "new,operator,private,protected,public,this,throw,true,try,typeof"];
386
- var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
387
- "concept,concept_map,const_cast,constexpr,decltype," +
388
- "dynamic_cast,explicit,export,friend,inline,late_check," +
389
- "mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast," +
390
- "template,typeid,typename,using,virtual,where"];
391
- var JAVA_KEYWORDS = [COMMON_KEYWORDS,
392
- "abstract,boolean,byte,extends,final,finally,implements,import," +
393
- "instanceof,null,native,package,strictfp,super,synchronized,throws," +
394
- "transient"];
395
- var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
396
- "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
397
- "fixed,foreach,from,group,implicit,in,interface,internal,into,is,let," +
398
- "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
399
- "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
400
- "var,virtual,where"];
401
- var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
402
- "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
403
- "throw,true,try,unless,until,when,while,yes";
404
- var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
405
- "debugger,eval,export,function,get,null,set,undefined,var,with," +
406
- "Infinity,NaN"];
407
- var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
408
- "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
409
- "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
410
- var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
411
- "elif,except,exec,finally,from,global,import,in,is,lambda," +
412
- "nonlocal,not,or,pass,print,raise,try,with,yield," +
413
- "False,True,None"];
414
- var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
415
- "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
416
- "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
417
- "BEGIN,END"];
418
- var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
419
- "function,in,local,set,then,until"];
420
- var ALL_KEYWORDS = [
421
- CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS +
422
- PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
423
- var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
424
-
425
- // token style names. correspond to css classes
426
- /**
427
- * token style for a string literal
428
- * @const
429
- */
430
- var PR_STRING = 'str';
431
- /**
432
- * token style for a keyword
433
- * @const
434
- */
435
- var PR_KEYWORD = 'kwd';
436
- /**
437
- * token style for a comment
438
- * @const
439
- */
440
- var PR_COMMENT = 'com';
441
- /**
442
- * token style for a type
443
- * @const
444
- */
445
- var PR_TYPE = 'typ';
446
- /**
447
- * token style for a literal value. e.g. 1, null, true.
448
- * @const
449
- */
450
- var PR_LITERAL = 'lit';
451
- /**
452
- * token style for a punctuation string.
453
- * @const
454
- */
455
- var PR_PUNCTUATION = 'pun';
456
- /**
457
- * token style for plain text.
458
- * @const
459
- */
460
- var PR_PLAIN = 'pln';
461
-
462
- /**
463
- * token style for an sgml tag.
464
- * @const
465
- */
466
- var PR_TAG = 'tag';
467
- /**
468
- * token style for a markup declaration such as a DOCTYPE.
469
- * @const
470
- */
471
- var PR_DECLARATION = 'dec';
472
- /**
473
- * token style for embedded source.
474
- * @const
475
- */
476
- var PR_SOURCE = 'src';
477
- /**
478
- * token style for an sgml attribute name.
479
- * @const
480
- */
481
- var PR_ATTRIB_NAME = 'atn';
482
- /**
483
- * token style for an sgml attribute value.
484
- * @const
485
- */
486
- var PR_ATTRIB_VALUE = 'atv';
487
-
488
- /**
489
- * A class that indicates a section of markup that is not code, e.g. to allow
490
- * embedding of line numbers within code listings.
491
- * @const
492
- */
493
- var PR_NOCODE = 'nocode';
494
-
495
-
496
-
497
- /**
498
- * A set of tokens that can precede a regular expression literal in
499
- * javascript
500
- * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
501
- * has the full list, but I've removed ones that might be problematic when
502
- * seen in languages that don't support regular expression literals.
503
- *
504
- * <p>Specifically, I've removed any keywords that can't precede a regexp
505
- * literal in a syntactically legal javascript program, and I've removed the
506
- * "in" keyword since it's not a keyword in many languages, and might be used
507
- * as a count of inches.
508
- *
509
- * <p>The link above does not accurately describe EcmaScript rules since
510
- * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
511
- * very well in practice.
512
- *
513
- * @private
514
- * @const
515
- */
516
- var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
517
-
518
- // CAVEAT: this does not properly handle the case where a regular
519
- // expression immediately follows another since a regular expression may
520
- // have flags for case-sensitivity and the like. Having regexp tokens
521
- // adjacent is not valid in any language I'm aware of, so I'm punting.
522
- // TODO: maybe style special characters inside a regexp as punctuation.
523
-
524
-
525
- /**
526
- * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
527
- * matches the union of the sets of strings matched by the input RegExp.
528
- * Since it matches globally, if the input strings have a start-of-input
529
- * anchor (/^.../), it is ignored for the purposes of unioning.
530
- * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
531
- * @return {RegExp} a global regex.
532
- */
533
- function combinePrefixPatterns(regexs) {
534
- var capturedGroupIndex = 0;
535
-
536
- var needToFoldCase = false;
537
- var ignoreCase = false;
538
- for (var i = 0, n = regexs.length; i < n; ++i) {
539
- var regex = regexs[i];
540
- if (regex.ignoreCase) {
541
- ignoreCase = true;
542
- } else if (/[a-z]/i.test(regex.source.replace(
543
- /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
544
- needToFoldCase = true;
545
- ignoreCase = false;
546
- break;
547
- }
548
- }
549
-
550
- var escapeCharToCodeUnit = {
551
- 'b': 8,
552
- 't': 9,
553
- 'n': 0xa,
554
- 'v': 0xb,
555
- 'f': 0xc,
556
- 'r': 0xd
557
- };
558
-
559
- function decodeEscape(charsetPart) {
560
- var cc0 = charsetPart.charCodeAt(0);
561
- if (cc0 !== 92 /* \\ */) {
562
- return cc0;
563
- }
564
- var c1 = charsetPart.charAt(1);
565
- cc0 = escapeCharToCodeUnit[c1];
566
- if (cc0) {
567
- return cc0;
568
- } else if ('0' <= c1 && c1 <= '7') {
569
- return parseInt(charsetPart.substring(1), 8);
570
- } else if (c1 === 'u' || c1 === 'x') {
571
- return parseInt(charsetPart.substring(2), 16);
572
- } else {
573
- return charsetPart.charCodeAt(1);
574
- }
575
- }
576
-
577
- function encodeEscape(charCode) {
578
- if (charCode < 0x20) {
579
- return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
580
- }
581
- var ch = String.fromCharCode(charCode);
582
- return (ch === '\\' || ch === '-' || ch === ']' || ch === '^')
583
- ? "\\" + ch : ch;
584
- }
585
-
586
- function caseFoldCharset(charSet) {
587
- var charsetParts = charSet.substring(1, charSet.length - 1).match(
588
- new RegExp(
589
- '\\\\u[0-9A-Fa-f]{4}'
590
- + '|\\\\x[0-9A-Fa-f]{2}'
591
- + '|\\\\[0-3][0-7]{0,2}'
592
- + '|\\\\[0-7]{1,2}'
593
- + '|\\\\[\\s\\S]'
594
- + '|-'
595
- + '|[^-\\\\]',
596
- 'g'));
597
- var ranges = [];
598
- var inverse = charsetParts[0] === '^';
599
-
600
- var out = ['['];
601
- if (inverse) { out.push('^'); }
602
-
603
- for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
604
- var p = charsetParts[i];
605
- if (/\\[bdsw]/i.test(p)) { // Don't muck with named groups.
606
- out.push(p);
607
- } else {
608
- var start = decodeEscape(p);
609
- var end;
610
- if (i + 2 < n && '-' === charsetParts[i + 1]) {
611
- end = decodeEscape(charsetParts[i + 2]);
612
- i += 2;
613
- } else {
614
- end = start;
615
- }
616
- ranges.push([start, end]);
617
- // If the range might intersect letters, then expand it.
618
- // This case handling is too simplistic.
619
- // It does not deal with non-latin case folding.
620
- // It works for latin source code identifiers though.
621
- if (!(end < 65 || start > 122)) {
622
- if (!(end < 65 || start > 90)) {
623
- ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
624
- }
625
- if (!(end < 97 || start > 122)) {
626
- ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
627
- }
628
- }
629
- }
630
- }
631
-
632
- // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
633
- // -> [[1, 12], [14, 14], [16, 17]]
634
- ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); });
635
- var consolidatedRanges = [];
636
- var lastRange = [];
637
- for (var i = 0; i < ranges.length; ++i) {
638
- var range = ranges[i];
639
- if (range[0] <= lastRange[1] + 1) {
640
- lastRange[1] = Math.max(lastRange[1], range[1]);
641
- } else {
642
- consolidatedRanges.push(lastRange = range);
643
- }
644
- }
645
-
646
- for (var i = 0; i < consolidatedRanges.length; ++i) {
647
- var range = consolidatedRanges[i];
648
- out.push(encodeEscape(range[0]));
649
- if (range[1] > range[0]) {
650
- if (range[1] + 1 > range[0]) { out.push('-'); }
651
- out.push(encodeEscape(range[1]));
652
- }
653
- }
654
- out.push(']');
655
- return out.join('');
656
- }
657
-
658
- function allowAnywhereFoldCaseAndRenumberGroups(regex) {
659
- // Split into character sets, escape sequences, punctuation strings
660
- // like ('(', '(?:', ')', '^'), and runs of characters that do not
661
- // include any of the above.
662
- var parts = regex.source.match(
663
- new RegExp(
664
- '(?:'
665
- + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set
666
- + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape
667
- + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape
668
- + '|\\\\[0-9]+' // a back-reference or octal escape
669
- + '|\\\\[^ux0-9]' // other escape sequence
670
- + '|\\(\\?[:!=]' // start of a non-capturing group
671
- + '|[\\(\\)\\^]' // start/end of a group, or line start
672
- + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters
673
- + ')',
674
- 'g'));
675
- var n = parts.length;
676
-
677
- // Maps captured group numbers to the number they will occupy in
678
- // the output or to -1 if that has not been determined, or to
679
- // undefined if they need not be capturing in the output.
680
- var capturedGroups = [];
681
-
682
- // Walk over and identify back references to build the capturedGroups
683
- // mapping.
684
- for (var i = 0, groupIndex = 0; i < n; ++i) {
685
- var p = parts[i];
686
- if (p === '(') {
687
- // groups are 1-indexed, so max group index is count of '('
688
- ++groupIndex;
689
- } else if ('\\' === p.charAt(0)) {
690
- var decimalValue = +p.substring(1);
691
- if (decimalValue) {
692
- if (decimalValue <= groupIndex) {
693
- capturedGroups[decimalValue] = -1;
694
- } else {
695
- // Replace with an unambiguous escape sequence so that
696
- // an octal escape sequence does not turn into a backreference
697
- // to a capturing group from an earlier regex.
698
- parts[i] = encodeEscape(decimalValue);
699
- }
700
- }
701
- }
702
- }
703
-
704
- // Renumber groups and reduce capturing groups to non-capturing groups
705
- // where possible.
706
- for (var i = 1; i < capturedGroups.length; ++i) {
707
- if (-1 === capturedGroups[i]) {
708
- capturedGroups[i] = ++capturedGroupIndex;
709
- }
710
- }
711
- for (var i = 0, groupIndex = 0; i < n; ++i) {
712
- var p = parts[i];
713
- if (p === '(') {
714
- ++groupIndex;
715
- if (!capturedGroups[groupIndex]) {
716
- parts[i] = '(?:';
717
- }
718
- } else if ('\\' === p.charAt(0)) {
719
- var decimalValue = +p.substring(1);
720
- if (decimalValue && decimalValue <= groupIndex) {
721
- parts[i] = '\\' + capturedGroups[decimalValue];
722
- }
723
- }
724
- }
725
-
726
- // Remove any prefix anchors so that the output will match anywhere.
727
- // ^^ really does mean an anchored match though.
728
- for (var i = 0; i < n; ++i) {
729
- if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
730
- }
731
-
732
- // Expand letters to groups to handle mixing of case-sensitive and
733
- // case-insensitive patterns if necessary.
734
- if (regex.ignoreCase && needToFoldCase) {
735
- for (var i = 0; i < n; ++i) {
736
- var p = parts[i];
737
- var ch0 = p.charAt(0);
738
- if (p.length >= 2 && ch0 === '[') {
739
- parts[i] = caseFoldCharset(p);
740
- } else if (ch0 !== '\\') {
741
- // TODO: handle letters in numeric escapes.
742
- parts[i] = p.replace(
743
- /[a-zA-Z]/g,
744
- function (ch) {
745
- var cc = ch.charCodeAt(0);
746
- return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
747
- });
748
- }
749
- }
750
- }
751
-
752
- return parts.join('');
753
- }
754
-
755
- var rewritten = [];
756
- for (var i = 0, n = regexs.length; i < n; ++i) {
757
- var regex = regexs[i];
758
- if (regex.global || regex.multiline) { throw new Error('' + regex); }
759
- rewritten.push(
760
- '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
761
- }
762
-
763
- return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
764
- }
765
-
766
-
767
- /**
768
- * Split markup into a string of source code and an array mapping ranges in
769
- * that string to the text nodes in which they appear.
770
- *
771
- * <p>
772
- * The HTML DOM structure:</p>
773
- * <pre>
774
- * (Element "p"
775
- * (Element "b"
776
- * (Text "print ")) ; #1
777
- * (Text "'Hello '") ; #2
778
- * (Element "br") ; #3
779
- * (Text " + 'World';")) ; #4
780
- * </pre>
781
- * <p>
782
- * corresponds to the HTML
783
- * {@code <p><b>print </b>'Hello '<br> + 'World';</p>}.</p>
784
- *
785
- * <p>
786
- * It will produce the output:</p>
787
- * <pre>
788
- * {
789
- * sourceCode: "print 'Hello '\n + 'World';",
790
- * // 1 2
791
- * // 012345678901234 5678901234567
792
- * spans: [0, #1, 6, #2, 14, #3, 15, #4]
793
- * }
794
- * </pre>
795
- * <p>
796
- * where #1 is a reference to the {@code "print "} text node above, and so
797
- * on for the other text nodes.
798
- * </p>
799
- *
800
- * <p>
801
- * The {@code} spans array is an array of pairs. Even elements are the start
802
- * indices of substrings, and odd elements are the text nodes (or BR elements)
803
- * that contain the text for those substrings.
804
- * Substrings continue until the next index or the end of the source.
805
- * </p>
806
- *
807
- * @param {Node} node an HTML DOM subtree containing source-code.
808
- * @param {boolean} isPreformatted true if white-space in text nodes should
809
- * be considered significant.
810
- * @return {Object} source code and the text nodes in which they occur.
811
- */
812
- function extractSourceSpans(node, isPreformatted) {
813
- var nocode = /(?:^|\s)nocode(?:\s|$)/;
814
-
815
- var chunks = [];
816
- var length = 0;
817
- var spans = [];
818
- var k = 0;
819
-
820
- function walk(node) {
821
- switch (node.nodeType) {
822
- case 1: // Element
823
- if (nocode.test(node.className)) { return; }
824
- for (var child = node.firstChild; child; child = child.nextSibling) {
825
- walk(child);
826
- }
827
- var nodeName = node.nodeName.toLowerCase();
828
- if ('br' === nodeName || 'li' === nodeName) {
829
- chunks[k] = '\n';
830
- spans[k << 1] = length++;
831
- spans[(k++ << 1) | 1] = node;
832
- }
833
- break;
834
- case 3: case 4: // Text
835
- var text = node.nodeValue;
836
- if (text.length) {
837
- if (!isPreformatted) {
838
- text = text.replace(/[ \t\r\n]+/g, ' ');
839
- } else {
840
- text = text.replace(/\r\n?/g, '\n'); // Normalize newlines.
841
- }
842
- // TODO: handle tabs here?
843
- chunks[k] = text;
844
- spans[k << 1] = length;
845
- length += text.length;
846
- spans[(k++ << 1) | 1] = node;
847
- }
848
- break;
849
- }
850
- }
851
-
852
- walk(node);
853
-
854
- return {
855
- sourceCode: chunks.join('').replace(/\n$/, ''),
856
- spans: spans
857
- };
858
- }
859
-
860
-
861
- /**
862
- * Apply the given language handler to sourceCode and add the resulting
863
- * decorations to out.
864
- * @param {number} basePos the index of sourceCode within the chunk of source
865
- * whose decorations are already present on out.
866
- */
867
- function appendDecorations(basePos, sourceCode, langHandler, out) {
868
- if (!sourceCode) { return; }
869
- var job = {
870
- sourceCode: sourceCode,
871
- basePos: basePos
872
- };
873
- langHandler(job);
874
- out.push.apply(out, job.decorations);
875
- }
876
-
877
- var notWs = /\S/;
878
-
879
- /**
880
- * Given an element, if it contains only one child element and any text nodes
881
- * it contains contain only space characters, return the sole child element.
882
- * Otherwise returns undefined.
883
- * <p>
884
- * This is meant to return the CODE element in {@code <pre><code ...>} when
885
- * there is a single child element that contains all the non-space textual
886
- * content, but not to return anything where there are multiple child elements
887
- * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
888
- * is textual content.
889
- */
890
- function childContentWrapper(element) {
891
- var wrapper = undefined;
892
- for (var c = element.firstChild; c; c = c.nextSibling) {
893
- var type = c.nodeType;
894
- wrapper = (type === 1) // Element Node
895
- ? (wrapper ? element : c)
896
- : (type === 3) // Text Node
897
- ? (notWs.test(c.nodeValue) ? element : wrapper)
898
- : wrapper;
899
- }
900
- return wrapper === element ? undefined : wrapper;
901
- }
902
-
903
- /** Given triples of [style, pattern, context] returns a lexing function,
904
- * The lexing function interprets the patterns to find token boundaries and
905
- * returns a decoration list of the form
906
- * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
907
- * where index_n is an index into the sourceCode, and style_n is a style
908
- * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to
909
- * all characters in sourceCode[index_n-1:index_n].
910
- *
911
- * The stylePatterns is a list whose elements have the form
912
- * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
913
- *
914
- * Style is a style constant like PR_PLAIN, or can be a string of the
915
- * form 'lang-FOO', where FOO is a language extension describing the
916
- * language of the portion of the token in $1 after pattern executes.
917
- * E.g., if style is 'lang-lisp', and group 1 contains the text
918
- * '(hello (world))', then that portion of the token will be passed to the
919
- * registered lisp handler for formatting.
920
- * The text before and after group 1 will be restyled using this decorator
921
- * so decorators should take care that this doesn't result in infinite
922
- * recursion. For example, the HTML lexer rule for SCRIPT elements looks
923
- * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match
924
- * '<script>foo()<\/script>', which would cause the current decorator to
925
- * be called with '<script>' which would not match the same rule since
926
- * group 1 must not be empty, so it would be instead styled as PR_TAG by
927
- * the generic tag rule. The handler registered for the 'js' extension would
928
- * then be called with 'foo()', and finally, the current decorator would
929
- * be called with '<\/script>' which would not match the original rule and
930
- * so the generic tag rule would identify it as a tag.
931
- *
932
- * Pattern must only match prefixes, and if it matches a prefix, then that
933
- * match is considered a token with the same style.
934
- *
935
- * Context is applied to the last non-whitespace, non-comment token
936
- * recognized.
937
- *
938
- * Shortcut is an optional string of characters, any of which, if the first
939
- * character, gurantee that this pattern and only this pattern matches.
940
- *
941
- * @param {Array} shortcutStylePatterns patterns that always start with
942
- * a known character. Must have a shortcut string.
943
- * @param {Array} fallthroughStylePatterns patterns that will be tried in
944
- * order if the shortcut ones fail. May have shortcuts.
945
- *
946
- * @return {function (Object)} a
947
- * function that takes source code and returns a list of decorations.
948
- */
949
- function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
950
- var shortcuts = {};
951
- var tokenizer;
952
- (function () {
953
- var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
954
- var allRegexs = [];
955
- var regexKeys = {};
956
- for (var i = 0, n = allPatterns.length; i < n; ++i) {
957
- var patternParts = allPatterns[i];
958
- var shortcutChars = patternParts[3];
959
- if (shortcutChars) {
960
- for (var c = shortcutChars.length; --c >= 0;) {
961
- shortcuts[shortcutChars.charAt(c)] = patternParts;
962
- }
963
- }
964
- var regex = patternParts[1];
965
- var k = '' + regex;
966
- if (!regexKeys.hasOwnProperty(k)) {
967
- allRegexs.push(regex);
968
- regexKeys[k] = null;
969
- }
970
- }
971
- allRegexs.push(/[\0-\uffff]/);
972
- tokenizer = combinePrefixPatterns(allRegexs);
973
- })();
974
-
975
- var nPatterns = fallthroughStylePatterns.length;
976
-
977
- /**
978
- * Lexes job.sourceCode and produces an output array job.decorations of
979
- * style classes preceded by the position at which they start in
980
- * job.sourceCode in order.
981
- *
982
- * @param {Object} job an object like <pre>{
983
- * sourceCode: {string} sourceText plain text,
984
- * basePos: {int} position of job.sourceCode in the larger chunk of
985
- * sourceCode.
986
- * }</pre>
987
- */
988
- var decorate = function (job) {
989
- var sourceCode = job.sourceCode, basePos = job.basePos;
990
- /** Even entries are positions in source in ascending order. Odd enties
991
- * are style markers (e.g., PR_COMMENT) that run from that position until
992
- * the end.
993
- * @type {Array.<number|string>}
994
- */
995
- var decorations = [basePos, PR_PLAIN];
996
- var pos = 0; // index into sourceCode
997
- var tokens = sourceCode.match(tokenizer) || [];
998
- var styleCache = {};
999
-
1000
- for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
1001
- var token = tokens[ti];
1002
- var style = styleCache[token];
1003
- var match = void 0;
1004
-
1005
- var isEmbedded;
1006
- if (typeof style === 'string') {
1007
- isEmbedded = false;
1008
- } else {
1009
- var patternParts = shortcuts[token.charAt(0)];
1010
- if (patternParts) {
1011
- match = token.match(patternParts[1]);
1012
- style = patternParts[0];
1013
- } else {
1014
- for (var i = 0; i < nPatterns; ++i) {
1015
- patternParts = fallthroughStylePatterns[i];
1016
- match = token.match(patternParts[1]);
1017
- if (match) {
1018
- style = patternParts[0];
1019
- break;
1020
- }
1021
- }
1022
-
1023
- if (!match) { // make sure that we make progress
1024
- style = PR_PLAIN;
1025
- }
1026
- }
1027
-
1028
- isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
1029
- if (isEmbedded && !(match && typeof match[1] === 'string')) {
1030
- isEmbedded = false;
1031
- style = PR_SOURCE;
1032
- }
1033
-
1034
- if (!isEmbedded) { styleCache[token] = style; }
1035
- }
1036
-
1037
- var tokenStart = pos;
1038
- pos += token.length;
1039
-
1040
- if (!isEmbedded) {
1041
- decorations.push(basePos + tokenStart, style);
1042
- } else { // Treat group 1 as an embedded block of source code.
1043
- var embeddedSource = match[1];
1044
- var embeddedSourceStart = token.indexOf(embeddedSource);
1045
- var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
1046
- if (match[2]) {
1047
- // If embeddedSource can be blank, then it would match at the
1048
- // beginning which would cause us to infinitely recurse on the
1049
- // entire token, so we catch the right context in match[2].
1050
- embeddedSourceEnd = token.length - match[2].length;
1051
- embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
1052
- }
1053
- var lang = style.substring(5);
1054
- // Decorate the left of the embedded source
1055
- appendDecorations(
1056
- basePos + tokenStart,
1057
- token.substring(0, embeddedSourceStart),
1058
- decorate, decorations);
1059
- // Decorate the embedded source
1060
- appendDecorations(
1061
- basePos + tokenStart + embeddedSourceStart,
1062
- embeddedSource,
1063
- langHandlerForExtension(lang, embeddedSource),
1064
- decorations);
1065
- // Decorate the right of the embedded section
1066
- appendDecorations(
1067
- basePos + tokenStart + embeddedSourceEnd,
1068
- token.substring(embeddedSourceEnd),
1069
- decorate, decorations);
1070
- }
1071
- }
1072
- job.decorations = decorations;
1073
- };
1074
- return decorate;
1075
- }
1076
-
1077
- /** returns a function that produces a list of decorations from source text.
1078
- *
1079
- * This code treats ", ', and ` as string delimiters, and \ as a string
1080
- * escape. It does not recognize perl's qq() style strings.
1081
- * It has no special handling for double delimiter escapes as in basic, or
1082
- * the tripled delimiters used in python, but should work on those regardless
1083
- * although in those cases a single string literal may be broken up into
1084
- * multiple adjacent string literals.
1085
- *
1086
- * It recognizes C, C++, and shell style comments.
1087
- *
1088
- * @param {Object} options a set of optional parameters.
1089
- * @return {function (Object)} a function that examines the source code
1090
- * in the input job and builds the decoration list.
1091
- */
1092
- function sourceDecorator(options) {
1093
- var shortcutStylePatterns = [], fallthroughStylePatterns = [];
1094
- if (options['tripleQuotedStrings']) {
1095
- // '''multi-line-string''', 'single-line-string', and double-quoted
1096
- shortcutStylePatterns.push(
1097
- [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
1098
- null, '\'"']);
1099
- } else if (options['multiLineStrings']) {
1100
- // 'multi-line-string', "multi-line-string"
1101
- shortcutStylePatterns.push(
1102
- [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
1103
- null, '\'"`']);
1104
- } else {
1105
- // 'single-line-string', "single-line-string"
1106
- shortcutStylePatterns.push(
1107
- [PR_STRING,
1108
- /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
1109
- null, '"\'']);
1110
- }
1111
- if (options['verbatimStrings']) {
1112
- // verbatim-string-literal production from the C# grammar. See issue 93.
1113
- fallthroughStylePatterns.push(
1114
- [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
1115
- }
1116
- var hc = options['hashComments'];
1117
- if (hc) {
1118
- if (options['cStyleComments']) {
1119
- if (hc > 1) { // multiline hash comments
1120
- shortcutStylePatterns.push(
1121
- [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
1122
- } else {
1123
- // Stop C preprocessor declarations at an unclosed open comment
1124
- shortcutStylePatterns.push(
1125
- [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,
1126
- null, '#']);
1127
- }
1128
- // #include <stdio.h>
1129
- fallthroughStylePatterns.push(
1130
- [PR_STRING,
1131
- /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
1132
- null]);
1133
- } else {
1134
- shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
1135
- }
1136
- }
1137
- if (options['cStyleComments']) {
1138
- fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
1139
- fallthroughStylePatterns.push(
1140
- [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
1141
- }
1142
- if (options['regexLiterals']) {
1143
- /**
1144
- * @const
1145
- */
1146
- var REGEX_LITERAL = (
1147
- // A regular expression literal starts with a slash that is
1148
- // not followed by * or / so that it is not confused with
1149
- // comments.
1150
- '/(?=[^/*])'
1151
- // and then contains any number of raw characters,
1152
- + '(?:[^/\\x5B\\x5C]'
1153
- // escape sequences (\x5C),
1154
- + '|\\x5C[\\s\\S]'
1155
- // or non-nesting character sets (\x5B\x5D);
1156
- + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
1157
- // finally closed by a /.
1158
- + '/');
1159
- fallthroughStylePatterns.push(
1160
- ['lang-regex',
1161
- new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
1162
- ]);
1163
- }
1164
-
1165
- var types = options['types'];
1166
- if (types) {
1167
- fallthroughStylePatterns.push([PR_TYPE, types]);
1168
- }
1169
-
1170
- var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
1171
- if (keywords.length) {
1172
- fallthroughStylePatterns.push(
1173
- [PR_KEYWORD,
1174
- new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
1175
- null]);
1176
- }
1177
-
1178
- shortcutStylePatterns.push([PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']);
1179
- fallthroughStylePatterns.push(
1180
- // TODO(mikesamuel): recognize non-latin letters and numerals in idents
1181
- [PR_LITERAL, /^@[a-z_$][a-z_$@0-9]*/i, null],
1182
- [PR_TYPE, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
1183
- [PR_PLAIN, /^[a-z_$][a-z_$@0-9]*/i, null],
1184
- [PR_LITERAL,
1185
- new RegExp(
1186
- '^(?:'
1187
- // A hex number
1188
- + '0x[a-f0-9]+'
1189
- // or an octal or decimal number,
1190
- + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
1191
- // possibly in scientific notation
1192
- + '(?:e[+\\-]?\\d+)?'
1193
- + ')'
1194
- // with an optional modifier like UL for unsigned long
1195
- + '[a-z]*', 'i'),
1196
- null, '0123456789'],
1197
- // Don't treat escaped quotes in bash as starting strings. See issue 144.
1198
- [PR_PLAIN, /^\\[\s\S]?/, null],
1199
- [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null]);
1200
-
1201
- return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
1202
- }
1203
-
1204
- var decorateSource = sourceDecorator({
1205
- 'keywords': ALL_KEYWORDS,
1206
- 'hashComments': true,
1207
- 'cStyleComments': true,
1208
- 'multiLineStrings': true,
1209
- 'regexLiterals': true
1210
- });
1211
-
1212
- /**
1213
- * Given a DOM subtree, wraps it in a list, and puts each line into its own
1214
- * list item.
1215
- *
1216
- * @param {Node} node modified in place. Its content is pulled into an
1217
- * HTMLOListElement, and each line is moved into a separate list item.
1218
- * This requires cloning elements, so the input might not have unique
1219
- * IDs after numbering.
1220
- * @param {boolean} isPreformatted true iff white-space in text nodes should
1221
- * be treated as significant.
1222
- */
1223
- function numberLines(node, opt_startLineNum, isPreformatted) {
1224
- var nocode = /(?:^|\s)nocode(?:\s|$)/;
1225
- var lineBreak = /\r\n?|\n/;
1226
-
1227
- var document = node.ownerDocument;
1228
-
1229
- var li = document.createElement('li');
1230
- while (node.firstChild) {
1231
- li.appendChild(node.firstChild);
1232
- }
1233
- // An array of lines. We split below, so this is initialized to one
1234
- // un-split line.
1235
- var listItems = [li];
1236
-
1237
- function walk(node) {
1238
- switch (node.nodeType) {
1239
- case 1: // Element
1240
- if (nocode.test(node.className)) { break; }
1241
- if ('br' === node.nodeName) {
1242
- breakAfter(node);
1243
- // Discard the <BR> since it is now flush against a </LI>.
1244
- if (node.parentNode) {
1245
- node.parentNode.removeChild(node);
1246
- }
1247
- } else {
1248
- for (var child = node.firstChild; child; child = child.nextSibling) {
1249
- walk(child);
1250
- }
1251
- }
1252
- break;
1253
- case 3: case 4: // Text
1254
- if (isPreformatted) {
1255
- var text = node.nodeValue;
1256
- var match = text.match(lineBreak);
1257
- if (match) {
1258
- var firstLine = text.substring(0, match.index);
1259
- node.nodeValue = firstLine;
1260
- var tail = text.substring(match.index + match[0].length);
1261
- if (tail) {
1262
- var parent = node.parentNode;
1263
- parent.insertBefore(
1264
- document.createTextNode(tail), node.nextSibling);
1265
- }
1266
- breakAfter(node);
1267
- if (!firstLine) {
1268
- // Don't leave blank text nodes in the DOM.
1269
- node.parentNode.removeChild(node);
1270
- }
1271
- }
1272
- }
1273
- break;
1274
- }
1275
- }
1276
-
1277
- // Split a line after the given node.
1278
- function breakAfter(lineEndNode) {
1279
- // If there's nothing to the right, then we can skip ending the line
1280
- // here, and move root-wards since splitting just before an end-tag
1281
- // would require us to create a bunch of empty copies.
1282
- while (!lineEndNode.nextSibling) {
1283
- lineEndNode = lineEndNode.parentNode;
1284
- if (!lineEndNode) { return; }
1285
- }
1286
-
1287
- function breakLeftOf(limit, copy) {
1288
- // Clone shallowly if this node needs to be on both sides of the break.
1289
- var rightSide = copy ? limit.cloneNode(false) : limit;
1290
- var parent = limit.parentNode;
1291
- if (parent) {
1292
- // We clone the parent chain.
1293
- // This helps us resurrect important styling elements that cross lines.
1294
- // E.g. in <i>Foo<br>Bar</i>
1295
- // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
1296
- var parentClone = breakLeftOf(parent, 1);
1297
- // Move the clone and everything to the right of the original
1298
- // onto the cloned parent.
1299
- var next = limit.nextSibling;
1300
- parentClone.appendChild(rightSide);
1301
- for (var sibling = next; sibling; sibling = next) {
1302
- next = sibling.nextSibling;
1303
- parentClone.appendChild(sibling);
1304
- }
1305
- }
1306
- return rightSide;
1307
- }
1308
-
1309
- var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
1310
-
1311
- // Walk the parent chain until we reach an unattached LI.
1312
- for (var parent;
1313
- // Check nodeType since IE invents document fragments.
1314
- (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
1315
- copiedListItem = parent;
1316
- }
1317
- // Put it on the list of lines for later processing.
1318
- listItems.push(copiedListItem);
1319
- }
1320
-
1321
- // Split lines while there are lines left to split.
1322
- for (var i = 0; // Number of lines that have been split so far.
1323
- i < listItems.length; // length updated by breakAfter calls.
1324
- ++i) {
1325
- walk(listItems[i]);
1326
- }
1327
-
1328
- // Make sure numeric indices show correctly.
1329
- if (opt_startLineNum === (opt_startLineNum|0)) {
1330
- listItems[0].setAttribute('value', opt_startLineNum);
1331
- }
1332
-
1333
- var ol = document.createElement('ol');
1334
- ol.className = 'linenums';
1335
- var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
1336
- for (var i = 0, n = listItems.length; i < n; ++i) {
1337
- li = listItems[i];
1338
- // Stick a class on the LIs so that stylesheets can
1339
- // color odd/even rows, or any other row pattern that
1340
- // is co-prime with 10.
1341
- li.className = 'L' + ((i + offset) % 10);
1342
- if (!li.firstChild) {
1343
- li.appendChild(document.createTextNode('\xA0'));
1344
- }
1345
- ol.appendChild(li);
1346
- }
1347
-
1348
- node.appendChild(ol);
1349
- }
1350
-
1351
- /**
1352
- * Breaks {@code job.sourceCode} around style boundaries in
1353
- * {@code job.decorations} and modifies {@code job.sourceNode} in place.
1354
- * @param {Object} job like <pre>{
1355
- * sourceCode: {string} source as plain text,
1356
- * spans: {Array.<number|Node>} alternating span start indices into source
1357
- * and the text node or element (e.g. {@code <BR>}) corresponding to that
1358
- * span.
1359
- * decorations: {Array.<number|string} an array of style classes preceded
1360
- * by the position at which they start in job.sourceCode in order
1361
- * }</pre>
1362
- * @private
1363
- */
1364
- function recombineTagsAndDecorations(job) {
1365
- var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent);
1366
- isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;
1367
- var newlineRe = /\n/g;
1368
-
1369
- var source = job.sourceCode;
1370
- var sourceLength = source.length;
1371
- // Index into source after the last code-unit recombined.
1372
- var sourceIndex = 0;
1373
-
1374
- var spans = job.spans;
1375
- var nSpans = spans.length;
1376
- // Index into spans after the last span which ends at or before sourceIndex.
1377
- var spanIndex = 0;
1378
-
1379
- var decorations = job.decorations;
1380
- var nDecorations = decorations.length;
1381
- // Index into decorations after the last decoration which ends at or before
1382
- // sourceIndex.
1383
- var decorationIndex = 0;
1384
-
1385
- // Remove all zero-length decorations.
1386
- decorations[nDecorations] = sourceLength;
1387
- var decPos, i;
1388
- for (i = decPos = 0; i < nDecorations;) {
1389
- if (decorations[i] !== decorations[i + 2]) {
1390
- decorations[decPos++] = decorations[i++];
1391
- decorations[decPos++] = decorations[i++];
1392
- } else {
1393
- i += 2;
1394
- }
1395
- }
1396
- nDecorations = decPos;
1397
-
1398
- // Simplify decorations.
1399
- for (i = decPos = 0; i < nDecorations;) {
1400
- var startPos = decorations[i];
1401
- // Conflate all adjacent decorations that use the same style.
1402
- var startDec = decorations[i + 1];
1403
- var end = i + 2;
1404
- while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
1405
- end += 2;
1406
- }
1407
- decorations[decPos++] = startPos;
1408
- decorations[decPos++] = startDec;
1409
- i = end;
1410
- }
1411
-
1412
- nDecorations = decorations.length = decPos;
1413
-
1414
- var sourceNode = job.sourceNode;
1415
- var oldDisplay;
1416
- if (sourceNode) {
1417
- oldDisplay = sourceNode.style.display;
1418
- sourceNode.style.display = 'none';
1419
- }
1420
- try {
1421
- var decoration = null;
1422
- while (spanIndex < nSpans) {
1423
- var spanStart = spans[spanIndex];
1424
- var spanEnd = spans[spanIndex + 2] || sourceLength;
1425
-
1426
- var decEnd = decorations[decorationIndex + 2] || sourceLength;
1427
-
1428
- var end = Math.min(spanEnd, decEnd);
1429
-
1430
- var textNode = spans[spanIndex + 1];
1431
- var styledText;
1432
- if (textNode.nodeType !== 1 // Don't muck with <BR>s or <LI>s
1433
- // Don't introduce spans around empty text nodes.
1434
- && (styledText = source.substring(sourceIndex, end))) {
1435
- // This may seem bizarre, and it is. Emitting LF on IE causes the
1436
- // code to display with spaces instead of line breaks.
1437
- // Emitting Windows standard issue linebreaks (CRLF) causes a blank
1438
- // space to appear at the beginning of every line but the first.
1439
- // Emitting an old Mac OS 9 line separator makes everything spiffy.
1440
- if (isIE8OrEarlier) {
1441
- styledText = styledText.replace(newlineRe, '\r');
1442
- }
1443
- textNode.nodeValue = styledText;
1444
- var document = textNode.ownerDocument;
1445
- var span = document.createElement('span');
1446
- span.className = decorations[decorationIndex + 1];
1447
- var parentNode = textNode.parentNode;
1448
- parentNode.replaceChild(span, textNode);
1449
- span.appendChild(textNode);
1450
- if (sourceIndex < spanEnd) { // Split off a text node.
1451
- spans[spanIndex + 1] = textNode
1452
- // TODO: Possibly optimize by using '' if there's no flicker.
1453
- = document.createTextNode(source.substring(end, spanEnd));
1454
- parentNode.insertBefore(textNode, span.nextSibling);
1455
- }
1456
- }
1457
-
1458
- sourceIndex = end;
1459
-
1460
- if (sourceIndex >= spanEnd) {
1461
- spanIndex += 2;
1462
- }
1463
- if (sourceIndex >= decEnd) {
1464
- decorationIndex += 2;
1465
- }
1466
- }
1467
- } finally {
1468
- if (sourceNode) {
1469
- sourceNode.style.display = oldDisplay;
1470
- }
1471
- }
1472
- }
1473
-
1474
-
1475
- /** Maps language-specific file extensions to handlers. */
1476
- var langHandlerRegistry = {};
1477
- /** Register a language handler for the given file extensions.
1478
- * @param {function (Object)} handler a function from source code to a list
1479
- * of decorations. Takes a single argument job which describes the
1480
- * state of the computation. The single parameter has the form
1481
- * {@code {
1482
- * sourceCode: {string} as plain text.
1483
- * decorations: {Array.<number|string>} an array of style classes
1484
- * preceded by the position at which they start in
1485
- * job.sourceCode in order.
1486
- * The language handler should assigned this field.
1487
- * basePos: {int} the position of source in the larger source chunk.
1488
- * All positions in the output decorations array are relative
1489
- * to the larger source chunk.
1490
- * } }
1491
- * @param {Array.<string>} fileExtensions
1492
- */
1493
- function registerLangHandler(handler, fileExtensions) {
1494
- for (var i = fileExtensions.length; --i >= 0;) {
1495
- var ext = fileExtensions[i];
1496
- if (!langHandlerRegistry.hasOwnProperty(ext)) {
1497
- langHandlerRegistry[ext] = handler;
1498
- } else if (win['console']) {
1499
- console['warn']('cannot override language handler %s', ext);
1500
- }
1501
- }
1502
- }
1503
- function langHandlerForExtension(extension, source) {
1504
- if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
1505
- // Treat it as markup if the first non whitespace character is a < and
1506
- // the last non-whitespace character is a >.
1507
- extension = /^\s*</.test(source)
1508
- ? 'default-markup'
1509
- : 'default-code';
1510
- }
1511
- return langHandlerRegistry[extension];
1512
- }
1513
- registerLangHandler(decorateSource, ['default-code']);
1514
- registerLangHandler(
1515
- createSimpleLexer(
1516
- [],
1517
- [
1518
- [PR_PLAIN, /^[^<?]+/],
1519
- [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
1520
- [PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/],
1521
- // Unescaped content in an unknown language
1522
- ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/],
1523
- ['lang-', /^<%([\s\S]+?)(?:%>|$)/],
1524
- [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
1525
- ['lang-', /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
1526
- // Unescaped content in javascript. (Or possibly vbscript).
1527
- ['lang-js', /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
1528
- // Contains unescaped stylesheet content
1529
- ['lang-css', /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
1530
- ['lang-in.tag', /^(<\/?[a-z][^<>]*>)/i]
1531
- ]),
1532
- ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
1533
- registerLangHandler(
1534
- createSimpleLexer(
1535
- [
1536
- [PR_PLAIN, /^[\s]+/, null, ' \t\r\n'],
1537
- [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
1538
- ],
1539
- [
1540
- [PR_TAG, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
1541
- [PR_ATTRIB_NAME, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
1542
- ['lang-uq.val', /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
1543
- [PR_PUNCTUATION, /^[=<>\/]+/],
1544
- ['lang-js', /^on\w+\s*=\s*\"([^\"]+)\"/i],
1545
- ['lang-js', /^on\w+\s*=\s*\'([^\']+)\'/i],
1546
- ['lang-js', /^on\w+\s*=\s*([^\"\'>\s]+)/i],
1547
- ['lang-css', /^style\s*=\s*\"([^\"]+)\"/i],
1548
- ['lang-css', /^style\s*=\s*\'([^\']+)\'/i],
1549
- ['lang-css', /^style\s*=\s*([^\"\'>\s]+)/i]
1550
- ]),
1551
- ['in.tag']);
1552
- registerLangHandler(
1553
- createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
1554
- registerLangHandler(sourceDecorator({
1555
- 'keywords': CPP_KEYWORDS,
1556
- 'hashComments': true,
1557
- 'cStyleComments': true,
1558
- 'types': C_TYPES
1559
- }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
1560
- registerLangHandler(sourceDecorator({
1561
- 'keywords': 'null,true,false'
1562
- }), ['json']);
1563
- registerLangHandler(sourceDecorator({
1564
- 'keywords': CSHARP_KEYWORDS,
1565
- 'hashComments': true,
1566
- 'cStyleComments': true,
1567
- 'verbatimStrings': true,
1568
- 'types': C_TYPES
1569
- }), ['cs']);
1570
- registerLangHandler(sourceDecorator({
1571
- 'keywords': JAVA_KEYWORDS,
1572
- 'cStyleComments': true
1573
- }), ['java']);
1574
- registerLangHandler(sourceDecorator({
1575
- 'keywords': SH_KEYWORDS,
1576
- 'hashComments': true,
1577
- 'multiLineStrings': true
1578
- }), ['bsh', 'csh', 'sh']);
1579
- registerLangHandler(sourceDecorator({
1580
- 'keywords': PYTHON_KEYWORDS,
1581
- 'hashComments': true,
1582
- 'multiLineStrings': true,
1583
- 'tripleQuotedStrings': true
1584
- }), ['cv', 'py']);
1585
- registerLangHandler(sourceDecorator({
1586
- 'keywords': PERL_KEYWORDS,
1587
- 'hashComments': true,
1588
- 'multiLineStrings': true,
1589
- 'regexLiterals': true
1590
- }), ['perl', 'pl', 'pm']);
1591
- registerLangHandler(sourceDecorator({
1592
- 'keywords': RUBY_KEYWORDS,
1593
- 'hashComments': true,
1594
- 'multiLineStrings': true,
1595
- 'regexLiterals': true
1596
- }), ['rb']);
1597
- registerLangHandler(sourceDecorator({
1598
- 'keywords': JSCRIPT_KEYWORDS,
1599
- 'cStyleComments': true,
1600
- 'regexLiterals': true
1601
- }), ['js']);
1602
- registerLangHandler(sourceDecorator({
1603
- 'keywords': COFFEE_KEYWORDS,
1604
- 'hashComments': 3, // ### style block comments
1605
- 'cStyleComments': true,
1606
- 'multilineStrings': true,
1607
- 'tripleQuotedStrings': true,
1608
- 'regexLiterals': true
1609
- }), ['coffee']);
1610
- registerLangHandler(
1611
- createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
1612
-
1613
- function applyDecorator(job) {
1614
- var opt_langExtension = job.langExtension;
1615
-
1616
- try {
1617
- // Extract tags, and convert the source code to plain text.
1618
- var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
1619
- /** Plain text. @type {string} */
1620
- var source = sourceAndSpans.sourceCode;
1621
- job.sourceCode = source;
1622
- job.spans = sourceAndSpans.spans;
1623
- job.basePos = 0;
1624
-
1625
- // Apply the appropriate language handler
1626
- langHandlerForExtension(opt_langExtension, source)(job);
1627
-
1628
- // Integrate the decorations and tags back into the source code,
1629
- // modifying the sourceNode in place.
1630
- recombineTagsAndDecorations(job);
1631
- } catch (e) {
1632
- if (win['console']) {
1633
- console['log'](e && e['stack'] ? e['stack'] : e);
1634
- }
1635
- }
1636
- }
1637
-
1638
- /**
1639
- * @param sourceCodeHtml {string} The HTML to pretty print.
1640
- * @param opt_langExtension {string} The language name to use.
1641
- * Typically, a filename extension like 'cpp' or 'java'.
1642
- * @param opt_numberLines {number|boolean} True to number lines,
1643
- * or the 1-indexed number of the first line in sourceCodeHtml.
1644
- */
1645
- function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
1646
- // PATCHED: http://code.google.com/p/google-code-prettify/issues/detail?id=213
1647
- var container = document.createElement('div');
1648
- // This could cause images to load and onload listeners to fire.
1649
- // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
1650
- // We assume that the inner HTML is from a trusted source.
1651
- container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';
1652
- container = container.firstChild;
1653
- if (opt_numberLines) {
1654
- numberLines(container, opt_numberLines, true);
1655
- }
1656
-
1657
- var job = {
1658
- langExtension: opt_langExtension,
1659
- numberLines: opt_numberLines,
1660
- sourceNode: container,
1661
- pre: 1
1662
- };
1663
- applyDecorator(job);
1664
- return container.innerHTML;
1665
- }
1666
-
1667
- function prettyPrint(opt_whenDone) {
1668
- function byTagName(tn) { return document.getElementsByTagName(tn); }
1669
- // fetch a list of nodes to rewrite
1670
- var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
1671
- var elements = [];
1672
- for (var i = 0; i < codeSegments.length; ++i) {
1673
- for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
1674
- elements.push(codeSegments[i][j]);
1675
- }
1676
- }
1677
- codeSegments = null;
1678
-
1679
- var clock = Date;
1680
- if (!clock['now']) {
1681
- clock = { 'now': function () { return +(new Date); } };
1682
- }
1683
-
1684
- // The loop is broken into a series of continuations to make sure that we
1685
- // don't make the browser unresponsive when rewriting a large page.
1686
- var k = 0;
1687
- var prettyPrintingJob;
1688
-
1689
- var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
1690
- var prettyPrintRe = /\bprettyprint\b/;
1691
- var prettyPrintedRe = /\bprettyprinted\b/;
1692
- var preformattedTagNameRe = /pre|xmp/i;
1693
- var codeRe = /^code$/i;
1694
- var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
1695
-
1696
- function doWork() {
1697
- var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
1698
- clock['now']() + 250 /* ms */ :
1699
- Infinity);
1700
- for (; k < elements.length && clock['now']() < endTime; k++) {
1701
- var cs = elements[k];
1702
- var className = cs.className;
1703
- if (prettyPrintRe.test(className)
1704
- // Don't redo this if we've already done it.
1705
- // This allows recalling pretty print to just prettyprint elements
1706
- // that have been added to the page since last call.
1707
- && !prettyPrintedRe.test(className)) {
1708
-
1709
- // make sure this is not nested in an already prettified element
1710
- var nested = false;
1711
- for (var p = cs.parentNode; p; p = p.parentNode) {
1712
- var tn = p.tagName;
1713
- if (preCodeXmpRe.test(tn)
1714
- && p.className && prettyPrintRe.test(p.className)) {
1715
- nested = true;
1716
- break;
1717
- }
1718
- }
1719
- if (!nested) {
1720
- // Mark done. If we fail to prettyprint for whatever reason,
1721
- // we shouldn't try again.
1722
- cs.className += ' prettyprinted';
1723
-
1724
- // If the classes includes a language extensions, use it.
1725
- // Language extensions can be specified like
1726
- // <pre class="prettyprint lang-cpp">
1727
- // the language extension "cpp" is used to find a language handler
1728
- // as passed to PR.registerLangHandler.
1729
- // HTML5 recommends that a language be specified using "language-"
1730
- // as the prefix instead. Google Code Prettify supports both.
1731
- // http://dev.w3.org/html5/spec-author-view/the-code-element.html
1732
- var langExtension = className.match(langExtensionRe);
1733
- // Support <pre class="prettyprint"><code class="language-c">
1734
- var wrapper;
1735
- if (!langExtension && (wrapper = childContentWrapper(cs))
1736
- && codeRe.test(wrapper.tagName)) {
1737
- langExtension = wrapper.className.match(langExtensionRe);
1738
- }
1739
-
1740
- if (langExtension) { langExtension = langExtension[1]; }
1741
-
1742
- var preformatted;
1743
- if (preformattedTagNameRe.test(cs.tagName)) {
1744
- preformatted = 1;
1745
- } else {
1746
- var currentStyle = cs['currentStyle'];
1747
- var whitespace = (
1748
- currentStyle
1749
- ? currentStyle['whiteSpace']
1750
- : (document.defaultView
1751
- && document.defaultView.getComputedStyle)
1752
- ? document.defaultView.getComputedStyle(cs, null)
1753
- .getPropertyValue('white-space')
1754
- : 0);
1755
- preformatted = whitespace
1756
- && 'pre' === whitespace.substring(0, 3);
1757
- }
1758
-
1759
- // Look for a class like linenums or linenums:<n> where <n> is the
1760
- // 1-indexed number of the first line.
1761
- var lineNums = cs.className.match(/\blinenums\b(?::(\d+))?/);
1762
- lineNums = lineNums
1763
- ? lineNums[1] && lineNums[1].length ? +lineNums[1] : true
1764
- : false;
1765
- if (lineNums) { numberLines(cs, lineNums, preformatted); }
1766
-
1767
- // do the pretty printing
1768
- prettyPrintingJob = {
1769
- langExtension: langExtension,
1770
- sourceNode: cs,
1771
- numberLines: lineNums,
1772
- pre: preformatted
1773
- };
1774
- applyDecorator(prettyPrintingJob);
1775
- }
1776
- }
1777
- }
1778
- if (k < elements.length) {
1779
- // finish up in a continuation
1780
- setTimeout(doWork, 250);
1781
- } else if (opt_whenDone) {
1782
- opt_whenDone();
1783
- }
1784
- }
1785
-
1786
- doWork();
1787
- }
1788
-
1789
- /**
1790
- * Contains functions for creating and registering new language handlers.
1791
- * @type {Object}
1792
- */
1793
- var PR = win['PR'] = {
1794
- 'createSimpleLexer': createSimpleLexer,
1795
- 'registerLangHandler': registerLangHandler,
1796
- 'sourceDecorator': sourceDecorator,
1797
- 'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
1798
- 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
1799
- 'PR_COMMENT': PR_COMMENT,
1800
- 'PR_DECLARATION': PR_DECLARATION,
1801
- 'PR_KEYWORD': PR_KEYWORD,
1802
- 'PR_LITERAL': PR_LITERAL,
1803
- 'PR_NOCODE': PR_NOCODE,
1804
- 'PR_PLAIN': PR_PLAIN,
1805
- 'PR_PUNCTUATION': PR_PUNCTUATION,
1806
- 'PR_SOURCE': PR_SOURCE,
1807
- 'PR_STRING': PR_STRING,
1808
- 'PR_TAG': PR_TAG,
1809
- 'PR_TYPE': PR_TYPE,
1810
- 'prettyPrintOne': win['prettyPrintOne'] = prettyPrintOne,
1811
- 'prettyPrint': win['prettyPrint'] = prettyPrint
1812
- };
1813
-
1814
- // Make PR available via the Asynchronous Module Definition (AMD) API.
1815
- // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
1816
- // The Asynchronous Module Definition (AMD) API specifies a
1817
- // mechanism for defining modules such that the module and its
1818
- // dependencies can be asynchronously loaded.
1819
- // ...
1820
- // To allow a clear indicator that a global define function (as
1821
- // needed for script src browser loading) conforms to the AMD API,
1822
- // any global define function SHOULD have a property called "amd"
1823
- // whose value is an object. This helps avoid conflict with any
1824
- // other existing JavaScript code that could have defined a define()
1825
- // function that does not conform to the AMD API.
1826
- if (typeof define === "function" && define['amd']) {
1827
- define("google-code-prettify", [], function () {
1828
- return PR;
1829
- });
1830
- }
1831
- })();
1832
-
1833
-
1834
- })(window, window.angular);
1835
- angular.element(document).find('head').append('<style type="text/css">.com{color:#93a1a1;}.lit{color:#195f91;}.pun,.opn,.clo{color:#93a1a1;}.fun{color:#dc322f;}.str,.atv{color:#D14;}.kwd,.linenums .tag{color:#1e347b;}.typ,.atn,.dec,.var{color:teal;}.pln{color:#48484c;}.prettyprint{padding:8px;background-color:#f7f7f9;border:1px solid #e1e1e8;}.prettyprint.linenums{-webkit-box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;-moz-box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;}ol.linenums{margin:0 0 0 33px;}ol.linenums li{padding-left:12px;color:#bebec5;line-height:18px;text-shadow:0 1px 0 #fff;}</style>');