moovui 0.0.1

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.
Files changed (116) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +17 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +1 -0
  7. data/Rakefile +1 -0
  8. data/bourbon/_bourbon-deprecated-upcoming.scss +13 -0
  9. data/bourbon/_bourbon.scss +59 -0
  10. data/bourbon/addons/_button.scss +273 -0
  11. data/bourbon/addons/_clearfix.scss +29 -0
  12. data/bourbon/addons/_font-family.scss +5 -0
  13. data/bourbon/addons/_hide-text.scss +5 -0
  14. data/bourbon/addons/_html5-input-types.scss +56 -0
  15. data/bourbon/addons/_position.scss +42 -0
  16. data/bourbon/addons/_prefixer.scss +49 -0
  17. data/bourbon/addons/_retina-image.scss +32 -0
  18. data/bourbon/addons/_size.scss +44 -0
  19. data/bourbon/addons/_timing-functions.scss +32 -0
  20. data/bourbon/addons/_triangle.scss +45 -0
  21. data/bourbon/css3/_animation.scss +52 -0
  22. data/bourbon/css3/_appearance.scss +3 -0
  23. data/bourbon/css3/_backface-visibility.scss +6 -0
  24. data/bourbon/css3/_background-image.scss +48 -0
  25. data/bourbon/css3/_background.scss +103 -0
  26. data/bourbon/css3/_border-image.scss +55 -0
  27. data/bourbon/css3/_border-radius.scss +22 -0
  28. data/bourbon/css3/_box-sizing.scss +4 -0
  29. data/bourbon/css3/_columns.scss +47 -0
  30. data/bourbon/css3/_flex-box.scss +52 -0
  31. data/bourbon/css3/_font-face.scss +23 -0
  32. data/bourbon/css3/_hidpi-media-query.scss +10 -0
  33. data/bourbon/css3/_image-rendering.scss +13 -0
  34. data/bourbon/css3/_inline-block.scss +8 -0
  35. data/bourbon/css3/_keyframes.scss +43 -0
  36. data/bourbon/css3/_linear-gradient.scss +41 -0
  37. data/bourbon/css3/_perspective.scss +8 -0
  38. data/bourbon/css3/_placeholder.scss +29 -0
  39. data/bourbon/css3/_radial-gradient.scss +44 -0
  40. data/bourbon/css3/_transform.scss +15 -0
  41. data/bourbon/css3/_transition.scss +34 -0
  42. data/bourbon/css3/_user-select.scss +3 -0
  43. data/bourbon/functions/_compact.scss +11 -0
  44. data/bourbon/functions/_flex-grid.scss +39 -0
  45. data/bourbon/functions/_grid-width.scss +13 -0
  46. data/bourbon/functions/_linear-gradient.scss +13 -0
  47. data/bourbon/functions/_modular-scale.scss +40 -0
  48. data/bourbon/functions/_px-to-em.scss +8 -0
  49. data/bourbon/functions/_radial-gradient.scss +23 -0
  50. data/bourbon/functions/_tint-shade.scss +9 -0
  51. data/bourbon/functions/_transition-property-name.scss +22 -0
  52. data/bourbon/helpers/_deprecated-webkit-gradient.scss +39 -0
  53. data/bourbon/helpers/_gradient-positions-parser.scss +13 -0
  54. data/bourbon/helpers/_linear-positions-parser.scss +61 -0
  55. data/bourbon/helpers/_radial-arg-parser.scss +69 -0
  56. data/bourbon/helpers/_radial-positions-parser.scss +18 -0
  57. data/bourbon/helpers/_render-gradients.scss +26 -0
  58. data/bourbon/helpers/_shape-size-stripper.scss +10 -0
  59. data/chosen.jquery.js +1166 -0
  60. data/custom.modernizr.js +4 -0
  61. data/fonts/TSTARPRO-BoldWeb.eot +0 -0
  62. data/fonts/TSTARPRO-BoldWeb.woff +0 -0
  63. data/fonts/entypo.eot +0 -0
  64. data/fonts/entypo.svg +235 -0
  65. data/fonts/entypo.ttf +0 -0
  66. data/fonts/entypo.woff +0 -0
  67. data/foundation.alerts.js +52 -0
  68. data/foundation.dropdown.js +177 -0
  69. data/foundation.js +440 -0
  70. data/foundation.reveal.js +330 -0
  71. data/foundation.section.js +400 -0
  72. data/foundation.tooltips.custom.js +222 -0
  73. data/globals/_base.scss +41 -0
  74. data/globals/_entypo.scss +711 -0
  75. data/globals/_footer.scss +29 -0
  76. data/globals/_header.scss +64 -0
  77. data/globals/_mixins.scss +69 -0
  78. data/globals/_normalize.scss +405 -0
  79. data/globals/_vars.scss +67 -0
  80. data/index.html +1254 -0
  81. data/lib/moovui/version.rb +3 -0
  82. data/lib/moovui.rb +4 -0
  83. data/modules/_accordion.scss +51 -0
  84. data/modules/_btn.scss +130 -0
  85. data/modules/_btnbar.scss +56 -0
  86. data/modules/_code.scss +55 -0
  87. data/modules/_copy.scss +99 -0
  88. data/modules/_definition.scss +34 -0
  89. data/modules/_docs.scss +127 -0
  90. data/modules/_dropdown.scss +32 -0
  91. data/modules/_flex.scss +300 -0
  92. data/modules/_grid.scss +72 -0
  93. data/modules/_input.scss +59 -0
  94. data/modules/_label.scss +6 -0
  95. data/modules/_list.scss +57 -0
  96. data/modules/_media.scss +17 -0
  97. data/modules/_modal.scss +71 -0
  98. data/modules/_notice.scss +111 -0
  99. data/modules/_pane.scss +25 -0
  100. data/modules/_resp.scss +71 -0
  101. data/modules/_select.scss +94 -0
  102. data/modules/_sidebar.scss +117 -0
  103. data/modules/_syntax-highlighter.scss +100 -0
  104. data/modules/_table.scss +63 -0
  105. data/modules/_tooltip.scss +59 -0
  106. data/moovui.gemspec +21 -0
  107. data/moovui.scss +43 -0
  108. data/shBrushBash.js +59 -0
  109. data/shBrushJScript.js +52 -0
  110. data/shBrushNull.js +35 -0
  111. data/shBrushSass.js +90 -0
  112. data/shBrushTritium.js +46 -0
  113. data/shBrushXml.js +69 -0
  114. data/shCore.custom.js +2399 -0
  115. data/shInit.js +14 -0
  116. metadata +187 -0
data/shCore.custom.js ADDED
@@ -0,0 +1,2399 @@
1
+ // XRegExp 1.5.1
2
+ // (c) 2007-2012 Steven Levithan
3
+ // MIT License
4
+ // <http://xregexp.com>
5
+ // Provides an augmented, extensible, cross-browser implementation of regular expressions,
6
+ // including support for additional syntax, flags, and methods
7
+
8
+ var XRegExp;
9
+
10
+ if (XRegExp) {
11
+ // Avoid running twice, since that would break references to native globals
12
+ throw Error("can't load XRegExp twice in the same frame");
13
+ }
14
+
15
+ // Run within an anonymous function to protect variables and avoid new globals
16
+ (function (undefined) {
17
+
18
+ //---------------------------------
19
+ // Constructor
20
+ //---------------------------------
21
+
22
+ // Accepts a pattern and flags; returns a new, extended `RegExp` object. Differs from a native
23
+ // regular expression in that additional syntax and flags are supported and cross-browser
24
+ // syntax inconsistencies are ameliorated. `XRegExp(/regex/)` clones an existing regex and
25
+ // converts to type XRegExp
26
+ XRegExp = function (pattern, flags) {
27
+ var output = [],
28
+ currScope = XRegExp.OUTSIDE_CLASS,
29
+ pos = 0,
30
+ context, tokenResult, match, chr, regex;
31
+
32
+ if (XRegExp.isRegExp(pattern)) {
33
+ if (flags !== undefined)
34
+ throw TypeError("can't supply flags when constructing one RegExp from another");
35
+ return clone(pattern);
36
+ }
37
+ // Tokens become part of the regex construction process, so protect against infinite
38
+ // recursion when an XRegExp is constructed within a token handler or trigger
39
+ if (isInsideConstructor)
40
+ throw Error("can't call the XRegExp constructor within token definition functions");
41
+
42
+ flags = flags || "";
43
+ context = { // `this` object for custom tokens
44
+ hasNamedCapture: false,
45
+ captureNames: [],
46
+ hasFlag: function (flag) {return flags.indexOf(flag) > -1;},
47
+ setFlag: function (flag) {flags += flag;}
48
+ };
49
+
50
+ while (pos < pattern.length) {
51
+ // Check for custom tokens at the current position
52
+ tokenResult = runTokens(pattern, pos, currScope, context);
53
+
54
+ if (tokenResult) {
55
+ output.push(tokenResult.output);
56
+ pos += (tokenResult.match[0].length || 1);
57
+ } else {
58
+ // Check for native multicharacter metasequences (excluding character classes) at
59
+ // the current position
60
+ if (match = nativ.exec.call(nativeTokens[currScope], pattern.slice(pos))) {
61
+ output.push(match[0]);
62
+ pos += match[0].length;
63
+ } else {
64
+ chr = pattern.charAt(pos);
65
+ if (chr === "[")
66
+ currScope = XRegExp.INSIDE_CLASS;
67
+ else if (chr === "]")
68
+ currScope = XRegExp.OUTSIDE_CLASS;
69
+ // Advance position one character
70
+ output.push(chr);
71
+ pos++;
72
+ }
73
+ }
74
+ }
75
+
76
+ regex = RegExp(output.join(""), nativ.replace.call(flags, flagClip, ""));
77
+ regex._xregexp = {
78
+ source: pattern,
79
+ captureNames: context.hasNamedCapture ? context.captureNames : null
80
+ };
81
+ return regex;
82
+ };
83
+
84
+
85
+ //---------------------------------
86
+ // Public properties
87
+ //---------------------------------
88
+
89
+ XRegExp.version = "1.5.1";
90
+
91
+ // Token scope bitflags
92
+ XRegExp.INSIDE_CLASS = 1;
93
+ XRegExp.OUTSIDE_CLASS = 2;
94
+
95
+
96
+ //---------------------------------
97
+ // Private variables
98
+ //---------------------------------
99
+
100
+ var replacementToken = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g,
101
+ flagClip = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, // Nonnative and duplicate flags
102
+ quantifier = /^(?:[?*+]|{\d+(?:,\d*)?})\??/,
103
+ isInsideConstructor = false,
104
+ tokens = [],
105
+ // Copy native globals for reference ("native" is an ES3 reserved keyword)
106
+ nativ = {
107
+ exec: RegExp.prototype.exec,
108
+ test: RegExp.prototype.test,
109
+ match: String.prototype.match,
110
+ replace: String.prototype.replace,
111
+ split: String.prototype.split
112
+ },
113
+ compliantExecNpcg = nativ.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
114
+ compliantLastIndexIncrement = function () {
115
+ var x = /^/g;
116
+ nativ.test.call(x, "");
117
+ return !x.lastIndex;
118
+ }(),
119
+ hasNativeY = RegExp.prototype.sticky !== undefined,
120
+ nativeTokens = {};
121
+
122
+ // `nativeTokens` match native multicharacter metasequences only (including deprecated octals,
123
+ // excluding character classes)
124
+ nativeTokens[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/;
125
+ nativeTokens[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/;
126
+
127
+
128
+ //---------------------------------
129
+ // Public methods
130
+ //---------------------------------
131
+
132
+ // Lets you extend or change XRegExp syntax and create custom flags. This is used internally by
133
+ // the XRegExp library and can be used to create XRegExp plugins. This function is intended for
134
+ // users with advanced knowledge of JavaScript's regular expression syntax and behavior. It can
135
+ // be disabled by `XRegExp.freezeTokens`
136
+ XRegExp.addToken = function (regex, handler, scope, trigger) {
137
+ tokens.push({
138
+ pattern: clone(regex, "g" + (hasNativeY ? "y" : "")),
139
+ handler: handler,
140
+ scope: scope || XRegExp.OUTSIDE_CLASS,
141
+ trigger: trigger || null
142
+ });
143
+ };
144
+
145
+ // Accepts a pattern and flags; returns an extended `RegExp` object. If the pattern and flag
146
+ // combination has previously been cached, the cached copy is returned; otherwise the newly
147
+ // created regex is cached
148
+ XRegExp.cache = function (pattern, flags) {
149
+ var key = pattern + "/" + (flags || "");
150
+ return XRegExp.cache[key] || (XRegExp.cache[key] = XRegExp(pattern, flags));
151
+ };
152
+
153
+ // Accepts a `RegExp` instance; returns a copy with the `/g` flag set. The copy has a fresh
154
+ // `lastIndex` (set to zero). If you want to copy a regex without forcing the `global`
155
+ // property, use `XRegExp(regex)`. Do not use `RegExp(regex)` because it will not preserve
156
+ // special properties required for named capture
157
+ XRegExp.copyAsGlobal = function (regex) {
158
+ return clone(regex, "g");
159
+ };
160
+
161
+ // Accepts a string; returns the string with regex metacharacters escaped. The returned string
162
+ // can safely be used at any point within a regex to match the provided literal string. Escaped
163
+ // characters are [ ] { } ( ) * + ? - . , \ ^ $ | # and whitespace
164
+ XRegExp.escape = function (str) {
165
+ return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
166
+ };
167
+
168
+ // Accepts a string to search, regex to search with, position to start the search within the
169
+ // string (default: 0), and an optional Boolean indicating whether matches must start at-or-
170
+ // after the position or at the specified position only. This function ignores the `lastIndex`
171
+ // of the provided regex in its own handling, but updates the property for compatibility
172
+ XRegExp.execAt = function (str, regex, pos, anchored) {
173
+ var r2 = clone(regex, "g" + ((anchored && hasNativeY) ? "y" : "")),
174
+ match;
175
+ r2.lastIndex = pos = pos || 0;
176
+ match = r2.exec(str); // Run the altered `exec` (required for `lastIndex` fix, etc.)
177
+ if (anchored && match && match.index !== pos)
178
+ match = null;
179
+ if (regex.global)
180
+ regex.lastIndex = match ? r2.lastIndex : 0;
181
+ return match;
182
+ };
183
+
184
+ // Breaks the unrestorable link to XRegExp's private list of tokens, thereby preventing
185
+ // syntax and flag changes. Should be run after XRegExp and any plugins are loaded
186
+ XRegExp.freezeTokens = function () {
187
+ XRegExp.addToken = function () {
188
+ throw Error("can't run addToken after freezeTokens");
189
+ };
190
+ };
191
+
192
+ // Accepts any value; returns a Boolean indicating whether the argument is a `RegExp` object.
193
+ // Note that this is also `true` for regex literals and regexes created by the `XRegExp`
194
+ // constructor. This works correctly for variables created in another frame, when `instanceof`
195
+ // and `constructor` checks would fail to work as intended
196
+ XRegExp.isRegExp = function (o) {
197
+ return Object.prototype.toString.call(o) === "[object RegExp]";
198
+ };
199
+
200
+ // Executes `callback` once per match within `str`. Provides a simpler and cleaner way to
201
+ // iterate over regex matches compared to the traditional approaches of subverting
202
+ // `String.prototype.replace` or repeatedly calling `exec` within a `while` loop
203
+ XRegExp.iterate = function (str, regex, callback, context) {
204
+ var r2 = clone(regex, "g"),
205
+ i = -1, match;
206
+ while (match = r2.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.)
207
+ if (regex.global)
208
+ regex.lastIndex = r2.lastIndex; // Doing this to follow expectations if `lastIndex` is checked within `callback`
209
+ callback.call(context, match, ++i, str, regex);
210
+ if (r2.lastIndex === match.index)
211
+ r2.lastIndex++;
212
+ }
213
+ if (regex.global)
214
+ regex.lastIndex = 0;
215
+ };
216
+
217
+ // Accepts a string and an array of regexes; returns the result of using each successive regex
218
+ // to search within the matches of the previous regex. The array of regexes can also contain
219
+ // objects with `regex` and `backref` properties, in which case the named or numbered back-
220
+ // references specified are passed forward to the next regex or returned. E.g.:
221
+ // var xregexpImgFileNames = XRegExp.matchChain(html, [
222
+ // {regex: /<img\b([^>]+)>/i, backref: 1}, // <img> tag attributes
223
+ // {regex: XRegExp('(?ix) \\s src=" (?<src> [^"]+ )'), backref: "src"}, // src attribute values
224
+ // {regex: XRegExp("^http://xregexp\\.com(/[^#?]+)", "i"), backref: 1}, // xregexp.com paths
225
+ // /[^\/]+$/ // filenames (strip directory paths)
226
+ // ]);
227
+ XRegExp.matchChain = function (str, chain) {
228
+ return function recurseChain (values, level) {
229
+ var item = chain[level].regex ? chain[level] : {regex: chain[level]},
230
+ regex = clone(item.regex, "g"),
231
+ matches = [], i;
232
+ for (i = 0; i < values.length; i++) {
233
+ XRegExp.iterate(values[i], regex, function (match) {
234
+ matches.push(item.backref ? (match[item.backref] || "") : match[0]);
235
+ });
236
+ }
237
+ return ((level === chain.length - 1) || !matches.length) ?
238
+ matches : recurseChain(matches, level + 1);
239
+ }([str], 0);
240
+ };
241
+
242
+
243
+ //---------------------------------
244
+ // New RegExp prototype methods
245
+ //---------------------------------
246
+
247
+ // Accepts a context object and arguments array; returns the result of calling `exec` with the
248
+ // first value in the arguments array. the context is ignored but is accepted for congruity
249
+ // with `Function.prototype.apply`
250
+ RegExp.prototype.apply = function (context, args) {
251
+ return this.exec(args[0]);
252
+ };
253
+
254
+ // Accepts a context object and string; returns the result of calling `exec` with the provided
255
+ // string. the context is ignored but is accepted for congruity with `Function.prototype.call`
256
+ RegExp.prototype.call = function (context, str) {
257
+ return this.exec(str);
258
+ };
259
+
260
+
261
+ //---------------------------------
262
+ // Overriden native methods
263
+ //---------------------------------
264
+
265
+ // Adds named capture support (with backreferences returned as `result.name`), and fixes two
266
+ // cross-browser issues per ES3:
267
+ // - Captured values for nonparticipating capturing groups should be returned as `undefined`,
268
+ // rather than the empty string.
269
+ // - `lastIndex` should not be incremented after zero-length matches.
270
+ RegExp.prototype.exec = function (str) {
271
+ var match, name, r2, origLastIndex;
272
+ if (!this.global)
273
+ origLastIndex = this.lastIndex;
274
+ match = nativ.exec.apply(this, arguments);
275
+ if (match) {
276
+ // Fix browsers whose `exec` methods don't consistently return `undefined` for
277
+ // nonparticipating capturing groups
278
+ if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
279
+ r2 = RegExp(this.source, nativ.replace.call(getNativeFlags(this), "g", ""));
280
+ // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
281
+ // matching due to characters outside the match
282
+ nativ.replace.call((str + "").slice(match.index), r2, function () {
283
+ for (var i = 1; i < arguments.length - 2; i++) {
284
+ if (arguments[i] === undefined)
285
+ match[i] = undefined;
286
+ }
287
+ });
288
+ }
289
+ // Attach named capture properties
290
+ if (this._xregexp && this._xregexp.captureNames) {
291
+ for (var i = 1; i < match.length; i++) {
292
+ name = this._xregexp.captureNames[i - 1];
293
+ if (name)
294
+ match[name] = match[i];
295
+ }
296
+ }
297
+ // Fix browsers that increment `lastIndex` after zero-length matches
298
+ if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
299
+ this.lastIndex--;
300
+ }
301
+ if (!this.global)
302
+ this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
303
+ return match;
304
+ };
305
+
306
+ // Fix browser bugs in native method
307
+ RegExp.prototype.test = function (str) {
308
+ // Use the native `exec` to skip some processing overhead, even though the altered
309
+ // `exec` would take care of the `lastIndex` fixes
310
+ var match, origLastIndex;
311
+ if (!this.global)
312
+ origLastIndex = this.lastIndex;
313
+ match = nativ.exec.call(this, str);
314
+ // Fix browsers that increment `lastIndex` after zero-length matches
315
+ if (match && !compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
316
+ this.lastIndex--;
317
+ if (!this.global)
318
+ this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
319
+ return !!match;
320
+ };
321
+
322
+ // Adds named capture support and fixes browser bugs in native method
323
+ String.prototype.match = function (regex) {
324
+ if (!XRegExp.isRegExp(regex))
325
+ regex = RegExp(regex); // Native `RegExp`
326
+ if (regex.global) {
327
+ var result = nativ.match.apply(this, arguments);
328
+ regex.lastIndex = 0; // Fix IE bug
329
+ return result;
330
+ }
331
+ return regex.exec(this); // Run the altered `exec`
332
+ };
333
+
334
+ // Adds support for `${n}` tokens for named and numbered backreferences in replacement text,
335
+ // and provides named backreferences to replacement functions as `arguments[0].name`. Also
336
+ // fixes cross-browser differences in replacement text syntax when performing a replacement
337
+ // using a nonregex search value, and the value of replacement regexes' `lastIndex` property
338
+ // during replacement iterations. Note that this doesn't support SpiderMonkey's proprietary
339
+ // third (`flags`) parameter
340
+ String.prototype.replace = function (search, replacement) {
341
+ var isRegex = XRegExp.isRegExp(search),
342
+ captureNames, result, str, origLastIndex;
343
+
344
+ // There are too many combinations of search/replacement types/values and browser bugs that
345
+ // preclude passing to native `replace`, so don't try
346
+ //if (...)
347
+ // return nativ.replace.apply(this, arguments);
348
+
349
+ if (isRegex) {
350
+ if (search._xregexp)
351
+ captureNames = search._xregexp.captureNames; // Array or `null`
352
+ if (!search.global)
353
+ origLastIndex = search.lastIndex;
354
+ } else {
355
+ search = search + ""; // Type conversion
356
+ }
357
+
358
+ if (Object.prototype.toString.call(replacement) === "[object Function]") {
359
+ result = nativ.replace.call(this + "", search, function () {
360
+ if (captureNames) {
361
+ // Change the `arguments[0]` string primitive to a String object which can store properties
362
+ arguments[0] = new String(arguments[0]);
363
+ // Store named backreferences on `arguments[0]`
364
+ for (var i = 0; i < captureNames.length; i++) {
365
+ if (captureNames[i])
366
+ arguments[0][captureNames[i]] = arguments[i + 1];
367
+ }
368
+ }
369
+ // Update `lastIndex` before calling `replacement` (fix browsers)
370
+ if (isRegex && search.global)
371
+ search.lastIndex = arguments[arguments.length - 2] + arguments[0].length;
372
+ return replacement.apply(null, arguments);
373
+ });
374
+ } else {
375
+ str = this + ""; // Type conversion, so `args[args.length - 1]` will be a string (given nonstring `this`)
376
+ result = nativ.replace.call(str, search, function () {
377
+ var args = arguments; // Keep this function's `arguments` available through closure
378
+ return nativ.replace.call(replacement + "", replacementToken, function ($0, $1, $2) {
379
+ // Numbered backreference (without delimiters) or special variable
380
+ if ($1) {
381
+ switch ($1) {
382
+ case "$": return "$";
383
+ case "&": return args[0];
384
+ case "`": return args[args.length - 1].slice(0, args[args.length - 2]);
385
+ case "'": return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
386
+ // Numbered backreference
387
+ default:
388
+ // What does "$10" mean?
389
+ // - Backreference 10, if 10 or more capturing groups exist
390
+ // - Backreference 1 followed by "0", if 1-9 capturing groups exist
391
+ // - Otherwise, it's the string "$10"
392
+ // Also note:
393
+ // - Backreferences cannot be more than two digits (enforced by `replacementToken`)
394
+ // - "$01" is equivalent to "$1" if a capturing group exists, otherwise it's the string "$01"
395
+ // - There is no "$0" token ("$&" is the entire match)
396
+ var literalNumbers = "";
397
+ $1 = +$1; // Type conversion; drop leading zero
398
+ if (!$1) // `$1` was "0" or "00"
399
+ return $0;
400
+ while ($1 > args.length - 3) {
401
+ literalNumbers = String.prototype.slice.call($1, -1) + literalNumbers;
402
+ $1 = Math.floor($1 / 10); // Drop the last digit
403
+ }
404
+ return ($1 ? args[$1] || "" : "$") + literalNumbers;
405
+ }
406
+ // Named backreference or delimited numbered backreference
407
+ } else {
408
+ // What does "${n}" mean?
409
+ // - Backreference to numbered capture n. Two differences from "$n":
410
+ // - n can be more than two digits
411
+ // - Backreference 0 is allowed, and is the entire match
412
+ // - Backreference to named capture n, if it exists and is not a number overridden by numbered capture
413
+ // - Otherwise, it's the string "${n}"
414
+ var n = +$2; // Type conversion; drop leading zeros
415
+ if (n <= args.length - 3)
416
+ return args[n];
417
+ n = captureNames ? indexOf(captureNames, $2) : -1;
418
+ return n > -1 ? args[n + 1] : $0;
419
+ }
420
+ });
421
+ });
422
+ }
423
+
424
+ if (isRegex) {
425
+ if (search.global)
426
+ search.lastIndex = 0; // Fix IE, Safari bug (last tested IE 9.0.5, Safari 5.1.2 on Windows)
427
+ else
428
+ search.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
429
+ }
430
+
431
+ return result;
432
+ };
433
+
434
+ // A consistent cross-browser, ES3 compliant `split`
435
+ String.prototype.split = function (s /* separator */, limit) {
436
+ // If separator `s` is not a regex, use the native `split`
437
+ if (!XRegExp.isRegExp(s))
438
+ return nativ.split.apply(this, arguments);
439
+
440
+ var str = this + "", // Type conversion
441
+ output = [],
442
+ lastLastIndex = 0,
443
+ match, lastLength;
444
+
445
+ // Behavior for `limit`: if it's...
446
+ // - `undefined`: No limit
447
+ // - `NaN` or zero: Return an empty array
448
+ // - A positive number: Use `Math.floor(limit)`
449
+ // - A negative number: No limit
450
+ // - Other: Type-convert, then use the above rules
451
+ if (limit === undefined || +limit < 0) {
452
+ limit = Infinity;
453
+ } else {
454
+ limit = Math.floor(+limit);
455
+ if (!limit)
456
+ return [];
457
+ }
458
+
459
+ // This is required if not `s.global`, and it avoids needing to set `s.lastIndex` to zero
460
+ // and restore it to its original value when we're done using the regex
461
+ s = XRegExp.copyAsGlobal(s);
462
+
463
+ while (match = s.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.)
464
+ if (s.lastIndex > lastLastIndex) {
465
+ output.push(str.slice(lastLastIndex, match.index));
466
+
467
+ if (match.length > 1 && match.index < str.length)
468
+ Array.prototype.push.apply(output, match.slice(1));
469
+
470
+ lastLength = match[0].length;
471
+ lastLastIndex = s.lastIndex;
472
+
473
+ if (output.length >= limit)
474
+ break;
475
+ }
476
+
477
+ if (s.lastIndex === match.index)
478
+ s.lastIndex++;
479
+ }
480
+
481
+ if (lastLastIndex === str.length) {
482
+ if (!nativ.test.call(s, "") || lastLength)
483
+ output.push("");
484
+ } else {
485
+ output.push(str.slice(lastLastIndex));
486
+ }
487
+
488
+ return output.length > limit ? output.slice(0, limit) : output;
489
+ };
490
+
491
+
492
+ //---------------------------------
493
+ // Private helper functions
494
+ //---------------------------------
495
+
496
+ // Supporting function for `XRegExp`, `XRegExp.copyAsGlobal`, etc. Returns a copy of a `RegExp`
497
+ // instance with a fresh `lastIndex` (set to zero), preserving properties required for named
498
+ // capture. Also allows adding new flags in the process of copying the regex
499
+ function clone (regex, additionalFlags) {
500
+ if (!XRegExp.isRegExp(regex))
501
+ throw TypeError("type RegExp expected");
502
+ var x = regex._xregexp;
503
+ regex = XRegExp(regex.source, getNativeFlags(regex) + (additionalFlags || ""));
504
+ if (x) {
505
+ regex._xregexp = {
506
+ source: x.source,
507
+ captureNames: x.captureNames ? x.captureNames.slice(0) : null
508
+ };
509
+ }
510
+ return regex;
511
+ }
512
+
513
+ function getNativeFlags (regex) {
514
+ return (regex.global ? "g" : "") +
515
+ (regex.ignoreCase ? "i" : "") +
516
+ (regex.multiline ? "m" : "") +
517
+ (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3
518
+ (regex.sticky ? "y" : "");
519
+ }
520
+
521
+ function runTokens (pattern, index, scope, context) {
522
+ var i = tokens.length,
523
+ result, match, t;
524
+ // Protect against constructing XRegExps within token handler and trigger functions
525
+ isInsideConstructor = true;
526
+ // Must reset `isInsideConstructor`, even if a `trigger` or `handler` throws
527
+ try {
528
+ while (i--) { // Run in reverse order
529
+ t = tokens[i];
530
+ if ((scope & t.scope) && (!t.trigger || t.trigger.call(context))) {
531
+ t.pattern.lastIndex = index;
532
+ match = t.pattern.exec(pattern); // Running the altered `exec` here allows use of named backreferences, etc.
533
+ if (match && match.index === index) {
534
+ result = {
535
+ output: t.handler.call(context, match, scope),
536
+ match: match
537
+ };
538
+ break;
539
+ }
540
+ }
541
+ }
542
+ } catch (err) {
543
+ throw err;
544
+ } finally {
545
+ isInsideConstructor = false;
546
+ }
547
+ return result;
548
+ }
549
+
550
+ function indexOf (array, item, from) {
551
+ if (Array.prototype.indexOf) // Use the native array method if available
552
+ return array.indexOf(item, from);
553
+ for (var i = from || 0; i < array.length; i++) {
554
+ if (array[i] === item)
555
+ return i;
556
+ }
557
+ return -1;
558
+ }
559
+
560
+
561
+ //---------------------------------
562
+ // Built-in tokens
563
+ //---------------------------------
564
+
565
+ // Augment XRegExp's regular expression syntax and flags. Note that when adding tokens, the
566
+ // third (`scope`) argument defaults to `XRegExp.OUTSIDE_CLASS`
567
+
568
+ // Comment pattern: (?# )
569
+ XRegExp.addToken(
570
+ /\(\?#[^)]*\)/,
571
+ function (match) {
572
+ // Keep tokens separated unless the following token is a quantifier
573
+ return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)";
574
+ }
575
+ );
576
+
577
+ // Capturing group (match the opening parenthesis only).
578
+ // Required for support of named capturing groups
579
+ XRegExp.addToken(
580
+ /\((?!\?)/,
581
+ function () {
582
+ this.captureNames.push(null);
583
+ return "(";
584
+ }
585
+ );
586
+
587
+ // Named capturing group (match the opening delimiter only): (?<name>
588
+ XRegExp.addToken(
589
+ /\(\?<([$\w]+)>/,
590
+ function (match) {
591
+ this.captureNames.push(match[1]);
592
+ this.hasNamedCapture = true;
593
+ return "(";
594
+ }
595
+ );
596
+
597
+ // Named backreference: \k<name>
598
+ XRegExp.addToken(
599
+ /\\k<([\w$]+)>/,
600
+ function (match) {
601
+ var index = indexOf(this.captureNames, match[1]);
602
+ // Keep backreferences separate from subsequent literal numbers. Preserve back-
603
+ // references to named groups that are undefined at this point as literal strings
604
+ return index > -1 ?
605
+ "\\" + (index + 1) + (isNaN(match.input.charAt(match.index + match[0].length)) ? "" : "(?:)") :
606
+ match[0];
607
+ }
608
+ );
609
+
610
+ // Empty character class: [] or [^]
611
+ XRegExp.addToken(
612
+ /\[\^?]/,
613
+ function (match) {
614
+ // For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
615
+ // (?!) should work like \b\B, but is unreliable in Firefox
616
+ return match[0] === "[]" ? "\\b\\B" : "[\\s\\S]";
617
+ }
618
+ );
619
+
620
+ // Mode modifier at the start of the pattern only, with any combination of flags imsx: (?imsx)
621
+ // Does not support x(?i), (?-i), (?i-m), (?i: ), (?i)(?m), etc.
622
+ XRegExp.addToken(
623
+ /^\(\?([imsx]+)\)/,
624
+ function (match) {
625
+ this.setFlag(match[1]);
626
+ return "";
627
+ }
628
+ );
629
+
630
+ // Whitespace and comments, in free-spacing (aka extended) mode only
631
+ XRegExp.addToken(
632
+ /(?:\s+|#.*)+/,
633
+ function (match) {
634
+ // Keep tokens separated unless the following token is a quantifier
635
+ return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)";
636
+ },
637
+ XRegExp.OUTSIDE_CLASS,
638
+ function () {return this.hasFlag("x");}
639
+ );
640
+
641
+ // Dot, in dotall (aka singleline) mode only
642
+ XRegExp.addToken(
643
+ /\./,
644
+ function () {return "[\\s\\S]";},
645
+ XRegExp.OUTSIDE_CLASS,
646
+ function () {return this.hasFlag("s");}
647
+ );
648
+
649
+
650
+ //---------------------------------
651
+ // Backward compatibility
652
+ //---------------------------------
653
+
654
+ // Uncomment the following block for compatibility with XRegExp 1.0-1.2:
655
+ /*
656
+ XRegExp.matchWithinChain = XRegExp.matchChain;
657
+ RegExp.prototype.addFlags = function (s) {return clone(this, s);};
658
+ RegExp.prototype.execAll = function (s) {var r = []; XRegExp.iterate(s, this, function (m) {r.push(m);}); return r;};
659
+ RegExp.prototype.forEachExec = function (s, f, c) {return XRegExp.iterate(s, this, f, c);};
660
+ RegExp.prototype.validate = function (s) {var r = RegExp("^(?:" + this.source + ")$(?!\\s)", getNativeFlags(this)); if (this.global) this.lastIndex = 0; return s.search(r) === 0;};
661
+ */
662
+
663
+ })();
664
+
665
+ /**
666
+ * SyntaxHighlighter
667
+ * http://alexgorbatchev.com/SyntaxHighlighter
668
+ *
669
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
670
+ * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
671
+ *
672
+ * @version
673
+ * 3.0.83 (July 02 2010)
674
+ *
675
+ * @copyright
676
+ * Copyright (C) 2004-2010 Alex Gorbatchev.
677
+ *
678
+ * @license
679
+ * Dual licensed under the MIT and GPL licenses.
680
+ */
681
+ //
682
+ // Begin anonymous function. This is used to contain local scope variables without polutting global scope.
683
+ //
684
+ var SyntaxHighlighter = function() {
685
+
686
+ // CommonJS
687
+ if (typeof(require) != 'undefined' && typeof(XRegExp) == 'undefined')
688
+ {
689
+ XRegExp = require('XRegExp').XRegExp;
690
+ }
691
+
692
+ // Shortcut object which will be assigned to the SyntaxHighlighter variable.
693
+ // This is a shorthand for local reference in order to avoid long namespace
694
+ // references to SyntaxHighlighter.whatever...
695
+ var sh = {
696
+ defaults : {
697
+ /** Additional CSS class names to be added to highlighter elements. */
698
+ 'class-name' : '',
699
+
700
+ /** First line number. */
701
+ 'first-line' : 1,
702
+
703
+ /**
704
+ * Pads line numbers. Possible values are:
705
+ *
706
+ * false - don't pad line numbers.
707
+ * true - automaticaly pad numbers with minimum required number of leading zeroes.
708
+ * [int] - length up to which pad line numbers.
709
+ */
710
+ 'pad-line-numbers' : false,
711
+
712
+ /** Lines to highlight. */
713
+ 'highlight' : null,
714
+
715
+ /** Title to be displayed above the code block. */
716
+ 'title' : null,
717
+
718
+ /** Enables or disables smart tabs. */
719
+ 'smart-tabs' : true,
720
+
721
+ /** Gets or sets tab size. */
722
+ 'tab-size' : 4,
723
+
724
+ /** Enables or disables gutter. */
725
+ 'gutter' : true,
726
+
727
+ /** Enables or disables toolbar. */
728
+ 'toolbar' : true,
729
+
730
+ /** Enables quick code copy and paste from double click. */
731
+ 'quick-code' : true,
732
+
733
+ /** Forces code view to be collapsed. */
734
+ 'collapse' : false,
735
+
736
+ /** Enables or disables automatic links. */
737
+ 'auto-links' : true,
738
+
739
+ /** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */
740
+ 'light' : false,
741
+
742
+ 'html-script' : false
743
+ },
744
+
745
+ config : {
746
+ space : '&nbsp;',
747
+
748
+ /** Enables use of <SCRIPT type="syntaxhighlighter" /> tags. */
749
+ useScriptTags : true,
750
+
751
+ /** Blogger mode flag. */
752
+ bloggerMode : false,
753
+
754
+ stripBrs : false,
755
+
756
+ /** Name of the tag that SyntaxHighlighter will automatically look for. */
757
+ tagName : 'pre',
758
+
759
+ strings : {
760
+ expandSource : 'expand source',
761
+ help : '?',
762
+ alert: 'SyntaxHighlighter\n\n',
763
+ noBrush : 'Can\'t find brush for: ',
764
+ brushNotHtmlScript : 'Brush wasn\'t configured for html-script option: ',
765
+
766
+ // this is populated by the build script
767
+ aboutDialog : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>About SyntaxHighlighter</title></head><body style="font-family:Geneva,Arial,Helvetica,sans-serif;background-color:#fff;color:#000;font-size:1em;text-align:center;"><div style="text-align:center;margin-top:1.5em;"><div style="font-size:xx-large;">SyntaxHighlighter</div><div style="font-size:.75em;margin-bottom:3em;"><div>version 3.0.83 (July 02 2010)</div><div><a href="http://alexgorbatchev.com/SyntaxHighlighter" target="_blank" style="color:#005896">http://alexgorbatchev.com/SyntaxHighlighter</a></div><div>JavaScript code syntax highlighter.</div><div>Copyright 2004-2010 Alex Gorbatchev.</div></div><div>If you like this script, please <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2930402" style="color:#005896">donate</a> to <br/>keep development active!</div></div></body></html>'
768
+ }
769
+ },
770
+
771
+ /** Internal 'global' variables. */
772
+ vars : {
773
+ discoveredBrushes : null,
774
+ highlighters : {}
775
+ },
776
+
777
+ /** This object is populated by user included external brush files. */
778
+ brushes : {},
779
+
780
+ /** Common regular expressions. */
781
+ regexLib : {
782
+ multiLineCComments : /\/\*[\s\S]*?\*\//gm,
783
+ singleLineCComments : /\/\/.*$/gm,
784
+ singleLinePerlComments : /#.*$/gm,
785
+ doubleQuotedString : /"([^\\"\n]|\\.)*"/g,
786
+ singleQuotedString : /'([^\\'\n]|\\.)*'/g,
787
+ multiLineDoubleQuotedString : new XRegExp('"([^\\\\"]|\\\\.)*"', 'gs'),
788
+ multiLineSingleQuotedString : new XRegExp("'([^\\\\']|\\\\.)*'", 'gs'),
789
+ xmlComments : /(&lt;|<)!--[\s\S]*?--(&gt;|>)/gm,
790
+ url : /\w+:\/\/[\w-.\/?%&=:@;]*/g,
791
+
792
+ /** <?= ?> tags. */
793
+ phpScriptTags : { left: /(&lt;|<)\?=?/g, right: /\?(&gt;|>)/g },
794
+
795
+ /** <%= %> tags. */
796
+ aspScriptTags : { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
797
+
798
+ /** <script></script> tags. */
799
+ scriptScriptTags : { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
800
+ },
801
+
802
+ toolbar: {
803
+ /**
804
+ * Generates HTML markup for the toolbar.
805
+ * @param {Highlighter} highlighter Highlighter instance.
806
+ * @return {String} Returns HTML markup.
807
+ */
808
+ getHtml: function(highlighter)
809
+ {
810
+ var html = '<div class="toolbar">',
811
+ items = sh.toolbar.items,
812
+ list = items.list
813
+ ;
814
+
815
+ function defaultGetHtml(highlighter, name)
816
+ {
817
+ return sh.toolbar.getButtonHtml(highlighter, name, sh.config.strings[name]);
818
+ };
819
+
820
+ for (var i = 0; i < list.length; i++)
821
+ html += (items[list[i]].getHtml || defaultGetHtml)(highlighter, list[i]);
822
+
823
+ html += '</div>';
824
+
825
+ return html;
826
+ },
827
+
828
+ /**
829
+ * Generates HTML markup for a regular button in the toolbar.
830
+ * @param {Highlighter} highlighter Highlighter instance.
831
+ * @param {String} commandName Command name that would be executed.
832
+ * @param {String} label Label text to display.
833
+ * @return {String} Returns HTML markup.
834
+ */
835
+ getButtonHtml: function(highlighter, commandName, label)
836
+ {
837
+ return '<span><a href="#" class="toolbar_item'
838
+ + ' command_' + commandName
839
+ + ' ' + commandName
840
+ + '">' + label + '</a></span>'
841
+ ;
842
+ },
843
+
844
+ /**
845
+ * Event handler for a toolbar anchor.
846
+ */
847
+ handler: function(e)
848
+ {
849
+ var target = e.target,
850
+ className = target.className || ''
851
+ ;
852
+
853
+ function getValue(name)
854
+ {
855
+ var r = new RegExp(name + '_(\\w+)'),
856
+ match = r.exec(className)
857
+ ;
858
+
859
+ return match ? match[1] : null;
860
+ };
861
+
862
+ var highlighter = getHighlighterById(findParentElement(target, '.syntaxhighlighter').id),
863
+ commandName = getValue('command')
864
+ ;
865
+
866
+ // execute the toolbar command
867
+ if (highlighter && commandName)
868
+ sh.toolbar.items[commandName].execute(highlighter);
869
+
870
+ // disable default A click behaviour
871
+ e.preventDefault();
872
+ },
873
+
874
+ /** Collection of toolbar items. */
875
+ items : {
876
+ // Ordered lis of items in the toolbar. Can't expect `for (var n in items)` to be consistent.
877
+ list: ['expandSource', 'help'],
878
+
879
+ expandSource: {
880
+ getHtml: function(highlighter)
881
+ {
882
+ if (highlighter.getParam('collapse') != true)
883
+ return '';
884
+
885
+ var title = highlighter.getParam('title');
886
+ return sh.toolbar.getButtonHtml(highlighter, 'expandSource', title ? title : sh.config.strings.expandSource);
887
+ },
888
+
889
+ execute: function(highlighter)
890
+ {
891
+ var div = getHighlighterDivById(highlighter.id);
892
+ removeClass(div, 'collapsed');
893
+ }
894
+ },
895
+
896
+ /** Command to display the about dialog window. */
897
+ help: {
898
+ execute: function(highlighter)
899
+ {
900
+ var wnd = popup('', '_blank', 500, 250, 'scrollbars=0'),
901
+ doc = wnd.document
902
+ ;
903
+
904
+ doc.write(sh.config.strings.aboutDialog);
905
+ doc.close();
906
+ wnd.focus();
907
+ }
908
+ }
909
+ }
910
+ },
911
+
912
+ /**
913
+ * Finds all elements on the page which should be processes by SyntaxHighlighter.
914
+ *
915
+ * @param {Object} globalParams Optional parameters which override element's
916
+ * parameters. Only used if element is specified.
917
+ *
918
+ * @param {Object} element Optional element to highlight. If none is
919
+ * provided, all elements in the current document
920
+ * are returned which qualify.
921
+ *
922
+ * @return {Array} Returns list of <code>{ target: DOMElement, params: Object }</code> objects.
923
+ */
924
+ findElements: function(globalParams, element)
925
+ {
926
+ var elements = element ? [element] : toArray(document.getElementsByTagName(sh.config.tagName)),
927
+ conf = sh.config,
928
+ result = []
929
+ ;
930
+
931
+ // support for <SCRIPT TYPE="syntaxhighlighter" /> feature
932
+ if (conf.useScriptTags)
933
+ elements = elements.concat(getSyntaxHighlighterScriptTags());
934
+
935
+ if (elements.length === 0)
936
+ return result;
937
+
938
+ for (var i = 0; i < elements.length; i++)
939
+ {
940
+ var item = {
941
+ target: elements[i],
942
+ // local params take precedence over globals
943
+ params: merge(globalParams, parseParams(elements[i].className))
944
+ };
945
+
946
+ if (item.params['brush'] == null)
947
+ continue;
948
+
949
+ result.push(item);
950
+ }
951
+
952
+ return result;
953
+ },
954
+
955
+ /**
956
+ * Shorthand to highlight all elements on the page that are marked as
957
+ * SyntaxHighlighter source code.
958
+ *
959
+ * @param {Object} globalParams Optional parameters which override element's
960
+ * parameters. Only used if element is specified.
961
+ *
962
+ * @param {Object} element Optional element to highlight. If none is
963
+ * provided, all elements in the current document
964
+ * are highlighted.
965
+ */
966
+ highlight: function(globalParams, element)
967
+ {
968
+ var elements = this.findElements(globalParams, element),
969
+ propertyName = 'innerHTML',
970
+ highlighter = null,
971
+ conf = sh.config
972
+ ;
973
+
974
+ if (elements.length === 0)
975
+ return;
976
+
977
+ for (var i = 0; i < elements.length; i++)
978
+ {
979
+ var element = elements[i],
980
+ target = element.target,
981
+ params = element.params,
982
+ brushName = params.brush,
983
+ code
984
+ ;
985
+
986
+ if (brushName == null)
987
+ continue;
988
+
989
+ // Instantiate a brush
990
+ if (params['html-script'] == 'true' || sh.defaults['html-script'] == true)
991
+ {
992
+ highlighter = new sh.HtmlScript(brushName);
993
+ brushName = 'htmlscript';
994
+ }
995
+ else
996
+ {
997
+ var brush = findBrush(brushName);
998
+
999
+ if (brush)
1000
+ highlighter = new brush();
1001
+ else
1002
+ continue;
1003
+ }
1004
+
1005
+ code = target[propertyName];
1006
+
1007
+ // remove CDATA from <SCRIPT/> tags if it's present
1008
+ if (conf.useScriptTags)
1009
+ code = stripCData(code);
1010
+
1011
+ // Inject title if the attribute is present
1012
+ if ((target.title || '') != '')
1013
+ params.title = target.title;
1014
+
1015
+ params['brush'] = brushName;
1016
+ highlighter.init(params);
1017
+ element = highlighter.getDiv(code);
1018
+
1019
+ // carry over ID
1020
+ if ((target.id || '') != '')
1021
+ element.id = target.id;
1022
+
1023
+ target.parentNode.replaceChild(element, target);
1024
+ }
1025
+ },
1026
+
1027
+ /**
1028
+ * Main entry point for the SyntaxHighlighter.
1029
+ * @param {Object} params Optional params to apply to all highlighted elements.
1030
+ */
1031
+ all: function(params)
1032
+ {
1033
+ attachEvent(
1034
+ window,
1035
+ 'load',
1036
+ function() { sh.highlight(params); }
1037
+ );
1038
+ }
1039
+ }; // end of sh
1040
+
1041
+ sh['all'] = sh.all;
1042
+ sh['highlight'] = sh.highlight;
1043
+
1044
+ /**
1045
+ * Checks if target DOM elements has specified CSS class.
1046
+ * @param {DOMElement} target Target DOM element to check.
1047
+ * @param {String} className Name of the CSS class to check for.
1048
+ * @return {Boolean} Returns true if class name is present, false otherwise.
1049
+ */
1050
+ function hasClass(target, className)
1051
+ {
1052
+ return target.className.indexOf(className) != -1;
1053
+ };
1054
+
1055
+ /**
1056
+ * Adds CSS class name to the target DOM element.
1057
+ * @param {DOMElement} target Target DOM element.
1058
+ * @param {String} className New CSS class to add.
1059
+ */
1060
+ function addClass(target, className)
1061
+ {
1062
+ if (!hasClass(target, className))
1063
+ target.className += ' ' + className;
1064
+ };
1065
+
1066
+ /**
1067
+ * Removes CSS class name from the target DOM element.
1068
+ * @param {DOMElement} target Target DOM element.
1069
+ * @param {String} className CSS class to remove.
1070
+ */
1071
+ function removeClass(target, className)
1072
+ {
1073
+ target.className = target.className.replace(className, '');
1074
+ };
1075
+
1076
+ /**
1077
+ * Converts the source to array object. Mostly used for function arguments and
1078
+ * lists returned by getElementsByTagName() which aren't Array objects.
1079
+ * @param {List} source Source list.
1080
+ * @return {Array} Returns array.
1081
+ */
1082
+ function toArray(source)
1083
+ {
1084
+ var result = [];
1085
+
1086
+ for (var i = 0; i < source.length; i++)
1087
+ result.push(source[i]);
1088
+
1089
+ return result;
1090
+ };
1091
+
1092
+ /**
1093
+ * Splits block of text into lines.
1094
+ * @param {String} block Block of text.
1095
+ * @return {Array} Returns array of lines.
1096
+ */
1097
+ function splitLines(block)
1098
+ {
1099
+ return block.split('\n');
1100
+ }
1101
+
1102
+ /**
1103
+ * Generates HTML ID for the highlighter.
1104
+ * @param {String} highlighterId Highlighter ID.
1105
+ * @return {String} Returns HTML ID.
1106
+ */
1107
+ function getHighlighterId(id)
1108
+ {
1109
+ var prefix = 'highlighter_';
1110
+ return id.indexOf(prefix) == 0 ? id : prefix + id;
1111
+ };
1112
+
1113
+ /**
1114
+ * Finds Highlighter instance by ID.
1115
+ * @param {String} highlighterId Highlighter ID.
1116
+ * @return {Highlighter} Returns instance of the highlighter.
1117
+ */
1118
+ function getHighlighterById(id)
1119
+ {
1120
+ return sh.vars.highlighters[getHighlighterId(id)];
1121
+ };
1122
+
1123
+ /**
1124
+ * Finds highlighter's DIV container.
1125
+ * @param {String} highlighterId Highlighter ID.
1126
+ * @return {Element} Returns highlighter's DIV element.
1127
+ */
1128
+ function getHighlighterDivById(id)
1129
+ {
1130
+ return document.getElementById(getHighlighterId(id));
1131
+ };
1132
+
1133
+ /**
1134
+ * Stores highlighter so that getHighlighterById() can do its thing. Each
1135
+ * highlighter must call this method to preserve itself.
1136
+ * @param {Highilghter} highlighter Highlighter instance.
1137
+ */
1138
+ function storeHighlighter(highlighter)
1139
+ {
1140
+ sh.vars.highlighters[getHighlighterId(highlighter.id)] = highlighter;
1141
+ };
1142
+
1143
+ /**
1144
+ * Looks for a child or parent node which has specified classname.
1145
+ * Equivalent to jQuery's $(container).find(".className")
1146
+ * @param {Element} target Target element.
1147
+ * @param {String} search Class name or node name to look for.
1148
+ * @param {Boolean} reverse If set to true, will go up the node tree instead of down.
1149
+ * @return {Element} Returns found child or parent element on null.
1150
+ */
1151
+ function findElement(target, search, reverse /* optional */)
1152
+ {
1153
+ if (target == null)
1154
+ return null;
1155
+
1156
+ var nodes = reverse != true ? target.childNodes : [ target.parentNode ],
1157
+ propertyToFind = { '#' : 'id', '.' : 'className' }[search.substr(0, 1)] || 'nodeName',
1158
+ expectedValue,
1159
+ found
1160
+ ;
1161
+
1162
+ expectedValue = propertyToFind != 'nodeName'
1163
+ ? search.substr(1)
1164
+ : search.toUpperCase()
1165
+ ;
1166
+
1167
+ // main return of the found node
1168
+ if ((target[propertyToFind] || '').indexOf(expectedValue) != -1)
1169
+ return target;
1170
+
1171
+ for (var i = 0; nodes && i < nodes.length && found == null; i++)
1172
+ found = findElement(nodes[i], search, reverse);
1173
+
1174
+ return found;
1175
+ };
1176
+
1177
+ /**
1178
+ * Looks for a parent node which has specified classname.
1179
+ * This is an alias to <code>findElement(container, className, true)</code>.
1180
+ * @param {Element} target Target element.
1181
+ * @param {String} className Class name to look for.
1182
+ * @return {Element} Returns found parent element on null.
1183
+ */
1184
+ function findParentElement(target, className)
1185
+ {
1186
+ return findElement(target, className, true);
1187
+ };
1188
+
1189
+ /**
1190
+ * Finds an index of element in the array.
1191
+ * @ignore
1192
+ * @param {Object} searchElement
1193
+ * @param {Number} fromIndex
1194
+ * @return {Number} Returns index of element if found; -1 otherwise.
1195
+ */
1196
+ function indexOf(array, searchElement, fromIndex)
1197
+ {
1198
+ fromIndex = Math.max(fromIndex || 0, 0);
1199
+
1200
+ for (var i = fromIndex; i < array.length; i++)
1201
+ if(array[i] == searchElement)
1202
+ return i;
1203
+
1204
+ return -1;
1205
+ };
1206
+
1207
+ /**
1208
+ * Generates a unique element ID.
1209
+ */
1210
+ function guid(prefix)
1211
+ {
1212
+ return (prefix || '') + Math.round(Math.random() * 1000000).toString();
1213
+ };
1214
+
1215
+ /**
1216
+ * Merges two objects. Values from obj2 override values in obj1.
1217
+ * Function is NOT recursive and works only for one dimensional objects.
1218
+ * @param {Object} obj1 First object.
1219
+ * @param {Object} obj2 Second object.
1220
+ * @return {Object} Returns combination of both objects.
1221
+ */
1222
+ function merge(obj1, obj2)
1223
+ {
1224
+ var result = {}, name;
1225
+
1226
+ for (name in obj1)
1227
+ result[name] = obj1[name];
1228
+
1229
+ for (name in obj2)
1230
+ result[name] = obj2[name];
1231
+
1232
+ return result;
1233
+ };
1234
+
1235
+ /**
1236
+ * Attempts to convert string to boolean.
1237
+ * @param {String} value Input string.
1238
+ * @return {Boolean} Returns true if input was "true", false if input was "false" and value otherwise.
1239
+ */
1240
+ function toBoolean(value)
1241
+ {
1242
+ var result = { "true" : true, "false" : false }[value];
1243
+ return result == null ? value : result;
1244
+ };
1245
+
1246
+ /**
1247
+ * Opens up a centered popup window.
1248
+ * @param {String} url URL to open in the window.
1249
+ * @param {String} name Popup name.
1250
+ * @param {int} width Popup width.
1251
+ * @param {int} height Popup height.
1252
+ * @param {String} options window.open() options.
1253
+ * @return {Window} Returns window instance.
1254
+ */
1255
+ function popup(url, name, width, height, options)
1256
+ {
1257
+ var x = (screen.width - width) / 2,
1258
+ y = (screen.height - height) / 2
1259
+ ;
1260
+
1261
+ options += ', left=' + x +
1262
+ ', top=' + y +
1263
+ ', width=' + width +
1264
+ ', height=' + height
1265
+ ;
1266
+ options = options.replace(/^,/, '');
1267
+
1268
+ var win = window.open(url, name, options);
1269
+ win.focus();
1270
+ return win;
1271
+ };
1272
+
1273
+ /**
1274
+ * Adds event handler to the target object.
1275
+ * @param {Object} obj Target object.
1276
+ * @param {String} type Name of the event.
1277
+ * @param {Function} func Handling function.
1278
+ */
1279
+ function attachEvent(obj, type, func, scope)
1280
+ {
1281
+ function handler(e)
1282
+ {
1283
+ e = e || window.event;
1284
+
1285
+ if (!e.target)
1286
+ {
1287
+ e.target = e.srcElement;
1288
+ e.preventDefault = function()
1289
+ {
1290
+ this.returnValue = false;
1291
+ };
1292
+ }
1293
+
1294
+ func.call(scope || window, e);
1295
+ };
1296
+
1297
+ if (obj.attachEvent)
1298
+ {
1299
+ obj.attachEvent('on' + type, handler);
1300
+ }
1301
+ else
1302
+ {
1303
+ obj.addEventListener(type, handler, false);
1304
+ }
1305
+ };
1306
+
1307
+ /**
1308
+ * Displays an alert.
1309
+ * @param {String} str String to display.
1310
+ */
1311
+ function alert(str)
1312
+ {
1313
+ window.alert(sh.config.strings.alert + str);
1314
+ };
1315
+
1316
+ /**
1317
+ * Finds a brush by its alias.
1318
+ *
1319
+ * @param {String} alias Brush alias.
1320
+ * @param {Boolean} showAlert Suppresses the alert if false.
1321
+ * @return {Brush} Returns bursh constructor if found, null otherwise.
1322
+ */
1323
+ function findBrush(alias, showAlert)
1324
+ {
1325
+ var brushes = sh.vars.discoveredBrushes,
1326
+ result = null
1327
+ ;
1328
+
1329
+ if (brushes == null)
1330
+ {
1331
+ brushes = {};
1332
+
1333
+ // Find all brushes
1334
+ for (var brush in sh.brushes)
1335
+ {
1336
+ var info = sh.brushes[brush],
1337
+ aliases = info.aliases
1338
+ ;
1339
+
1340
+ if (aliases == null)
1341
+ continue;
1342
+
1343
+ // keep the brush name
1344
+ info.brushName = brush.toLowerCase();
1345
+
1346
+ for (var i = 0; i < aliases.length; i++)
1347
+ brushes[aliases[i]] = brush;
1348
+ }
1349
+
1350
+ sh.vars.discoveredBrushes = brushes;
1351
+ }
1352
+
1353
+ // PATCH to pass through unrecognized languages
1354
+ result = sh.brushes[brushes[alias] || "Null"];
1355
+
1356
+ if (brushes[alias] == null && showAlert != false)
1357
+ console.log(sh.config.strings.noBrush + alias);
1358
+
1359
+ return result;
1360
+ };
1361
+
1362
+ /**
1363
+ * Executes a callback on each line and replaces each line with result from the callback.
1364
+ * @param {Object} str Input string.
1365
+ * @param {Object} callback Callback function taking one string argument and returning a string.
1366
+ */
1367
+ function eachLine(str, callback)
1368
+ {
1369
+ var lines = splitLines(str);
1370
+
1371
+ for (var i = 0; i < lines.length; i++)
1372
+ lines[i] = callback(lines[i], i);
1373
+
1374
+ return lines.join('\n');
1375
+ };
1376
+
1377
+ /**
1378
+ * This is a special trim which only removes first and last empty lines
1379
+ * and doesn't affect valid leading space on the first line.
1380
+ *
1381
+ * @param {String} str Input string
1382
+ * @return {String} Returns string without empty first and last lines.
1383
+ */
1384
+ function trimFirstAndLastLines(str)
1385
+ {
1386
+ return str.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, '');
1387
+ };
1388
+
1389
+ /**
1390
+ * Parses key/value pairs into hash object.
1391
+ *
1392
+ * Understands the following formats:
1393
+ * - name: word;
1394
+ * - name: [word, word];
1395
+ * - name: "string";
1396
+ * - name: 'string';
1397
+ *
1398
+ * For example:
1399
+ * name1: value; name2: [value, value]; name3: 'value'
1400
+ *
1401
+ * @param {String} str Input string.
1402
+ * @return {Object} Returns deserialized object.
1403
+ */
1404
+ function parseParams(str)
1405
+ {
1406
+ var match,
1407
+ result = {},
1408
+ arrayRegex = new XRegExp("^\\[(?<values>(.*?))\\]$"),
1409
+ regex = new XRegExp(
1410
+ "(?<name>[\\w-]+)" +
1411
+ "\\s*:\\s*" +
1412
+ "(?<value>" +
1413
+ "[\\w-%#]+|" + // word
1414
+ "\\[.*?\\]|" + // [] array
1415
+ '".*?"|' + // "" string
1416
+ "'.*?'" + // '' string
1417
+ ")\\s*;?",
1418
+ "g"
1419
+ )
1420
+ ;
1421
+
1422
+ while ((match = regex.exec(str)) != null)
1423
+ {
1424
+ var value = match.value
1425
+ .replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
1426
+ ;
1427
+
1428
+ // try to parse array value
1429
+ if (value != null && arrayRegex.test(value))
1430
+ {
1431
+ var m = arrayRegex.exec(value);
1432
+ value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
1433
+ }
1434
+
1435
+ result[match.name] = value;
1436
+ }
1437
+
1438
+ return result;
1439
+ };
1440
+
1441
+ /**
1442
+ * Wraps each line of the string into <code/> tag with given style applied to it.
1443
+ *
1444
+ * @param {String} str Input string.
1445
+ * @param {String} css Style name to apply to the string.
1446
+ * @return {String} Returns input string with each line surrounded by <span/> tag.
1447
+ */
1448
+ function wrapLinesWithCode(str, css)
1449
+ {
1450
+ if (str == null || str.length == 0 || str == '\n')
1451
+ return str;
1452
+
1453
+ str = str.replace(/</g, '&lt;');
1454
+
1455
+ // Replace two or more sequential spaces with &nbsp; leaving last space untouched.
1456
+ str = str.replace(/ {2,}/g, function(m)
1457
+ {
1458
+ var spaces = '';
1459
+
1460
+ for (var i = 0; i < m.length - 1; i++)
1461
+ spaces += sh.config.space;
1462
+
1463
+ return spaces + ' ';
1464
+ });
1465
+
1466
+ // Split each line and apply <span class="...">...</span> to them so that
1467
+ // leading spaces aren't included.
1468
+ if (css != null)
1469
+ str = eachLine(str, function(line)
1470
+ {
1471
+ if (line.length == 0)
1472
+ return '';
1473
+
1474
+ var spaces = '';
1475
+
1476
+ line = line.replace(/^(&nbsp;| )+/, function(s)
1477
+ {
1478
+ spaces = s;
1479
+ return '';
1480
+ });
1481
+
1482
+ if (line.length == 0)
1483
+ return spaces;
1484
+
1485
+ return spaces + '<code class="' + css + '">' + line + '</code>';
1486
+ });
1487
+
1488
+ return str;
1489
+ };
1490
+
1491
+ /**
1492
+ * Pads number with zeros until it's length is the same as given length.
1493
+ *
1494
+ * @param {Number} number Number to pad.
1495
+ * @param {Number} length Max string length with.
1496
+ * @return {String} Returns a string padded with proper amount of '0'.
1497
+ */
1498
+ function padNumber(number, length)
1499
+ {
1500
+ var result = number.toString();
1501
+
1502
+ while (result.length < length)
1503
+ result = '0' + result;
1504
+
1505
+ return result;
1506
+ };
1507
+
1508
+ /**
1509
+ * Replaces tabs with spaces.
1510
+ *
1511
+ * @param {String} code Source code.
1512
+ * @param {Number} tabSize Size of the tab.
1513
+ * @return {String} Returns code with all tabs replaces by spaces.
1514
+ */
1515
+ function processTabs(code, tabSize)
1516
+ {
1517
+ var tab = '';
1518
+
1519
+ for (var i = 0; i < tabSize; i++)
1520
+ tab += ' ';
1521
+
1522
+ return code.replace(/\t/g, tab);
1523
+ };
1524
+
1525
+ /**
1526
+ * Replaces tabs with smart spaces.
1527
+ *
1528
+ * @param {String} code Code to fix the tabs in.
1529
+ * @param {Number} tabSize Number of spaces in a column.
1530
+ * @return {String} Returns code with all tabs replaces with roper amount of spaces.
1531
+ */
1532
+ function processSmartTabs(code, tabSize)
1533
+ {
1534
+ var lines = splitLines(code),
1535
+ tab = '\t',
1536
+ spaces = ''
1537
+ ;
1538
+
1539
+ // Create a string with 1000 spaces to copy spaces from...
1540
+ // It's assumed that there would be no indentation longer than that.
1541
+ for (var i = 0; i < 50; i++)
1542
+ spaces += ' '; // 20 spaces * 50
1543
+
1544
+ // This function inserts specified amount of spaces in the string
1545
+ // where a tab is while removing that given tab.
1546
+ function insertSpaces(line, pos, count)
1547
+ {
1548
+ return line.substr(0, pos)
1549
+ + spaces.substr(0, count)
1550
+ + line.substr(pos + 1, line.length) // pos + 1 will get rid of the tab
1551
+ ;
1552
+ };
1553
+
1554
+ // Go through all the lines and do the 'smart tabs' magic.
1555
+ code = eachLine(code, function(line)
1556
+ {
1557
+ if (line.indexOf(tab) == -1)
1558
+ return line;
1559
+
1560
+ var pos = 0;
1561
+
1562
+ while ((pos = line.indexOf(tab)) != -1)
1563
+ {
1564
+ // This is pretty much all there is to the 'smart tabs' logic.
1565
+ // Based on the position within the line and size of a tab,
1566
+ // calculate the amount of spaces we need to insert.
1567
+ var spaces = tabSize - pos % tabSize;
1568
+ line = insertSpaces(line, pos, spaces);
1569
+ }
1570
+
1571
+ return line;
1572
+ });
1573
+
1574
+ return code;
1575
+ };
1576
+
1577
+ /**
1578
+ * Performs various string fixes based on configuration.
1579
+ */
1580
+ function fixInputString(str)
1581
+ {
1582
+ var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
1583
+
1584
+ if (sh.config.bloggerMode == true)
1585
+ str = str.replace(br, '\n');
1586
+
1587
+ if (sh.config.stripBrs == true)
1588
+ str = str.replace(br, '');
1589
+
1590
+ return str;
1591
+ };
1592
+
1593
+ /**
1594
+ * Removes all white space at the begining and end of a string.
1595
+ *
1596
+ * @param {String} str String to trim.
1597
+ * @return {String} Returns string without leading and following white space characters.
1598
+ */
1599
+ function trim(str)
1600
+ {
1601
+ return str.replace(/^\s+|\s+$/g, '');
1602
+ };
1603
+
1604
+ /**
1605
+ * Unindents a block of text by the lowest common indent amount.
1606
+ * @param {String} str Text to unindent.
1607
+ * @return {String} Returns unindented text block.
1608
+ */
1609
+ function unindent(str)
1610
+ {
1611
+ var lines = splitLines(fixInputString(str)),
1612
+ indents = new Array(),
1613
+ regex = /^\s*/,
1614
+ min = 1000
1615
+ ;
1616
+
1617
+ // go through every line and check for common number of indents
1618
+ for (var i = 0; i < lines.length && min > 0; i++)
1619
+ {
1620
+ var line = lines[i];
1621
+
1622
+ if (trim(line).length == 0)
1623
+ continue;
1624
+
1625
+ var matches = regex.exec(line);
1626
+
1627
+ // In the event that just one line doesn't have leading white space
1628
+ // we can't unindent anything, so bail completely.
1629
+ if (matches == null)
1630
+ return str;
1631
+
1632
+ min = Math.min(matches[0].length, min);
1633
+ }
1634
+
1635
+ // trim minimum common number of white space from the begining of every line
1636
+ if (min > 0)
1637
+ for (var i = 0; i < lines.length; i++)
1638
+ lines[i] = lines[i].substr(min);
1639
+
1640
+ return lines.join('\n');
1641
+ };
1642
+
1643
+ /**
1644
+ * Callback method for Array.sort() which sorts matches by
1645
+ * index position and then by length.
1646
+ *
1647
+ * @param {Match} m1 Left object.
1648
+ * @param {Match} m2 Right object.
1649
+ * @return {Number} Returns -1, 0 or -1 as a comparison result.
1650
+ */
1651
+ function matchesSortCallback(m1, m2)
1652
+ {
1653
+ // sort matches by index first
1654
+ if(m1.index < m2.index)
1655
+ return -1;
1656
+ else if(m1.index > m2.index)
1657
+ return 1;
1658
+ else
1659
+ {
1660
+ // if index is the same, sort by length
1661
+ if(m1.length < m2.length)
1662
+ return -1;
1663
+ else if(m1.length > m2.length)
1664
+ return 1;
1665
+ }
1666
+
1667
+ return 0;
1668
+ };
1669
+
1670
+ /**
1671
+ * Executes given regular expression on provided code and returns all
1672
+ * matches that are found.
1673
+ *
1674
+ * @param {String} code Code to execute regular expression on.
1675
+ * @param {Object} regex Regular expression item info from <code>regexList</code> collection.
1676
+ * @return {Array} Returns a list of Match objects.
1677
+ */
1678
+ function getMatches(code, regexInfo)
1679
+ {
1680
+ function defaultAdd(match, regexInfo)
1681
+ {
1682
+ return match[0];
1683
+ };
1684
+
1685
+ var index = 0,
1686
+ match = null,
1687
+ matches = [],
1688
+ func = regexInfo.func ? regexInfo.func : defaultAdd
1689
+ ;
1690
+
1691
+ while((match = regexInfo.regex.exec(code)) != null)
1692
+ {
1693
+ var resultMatch = func(match, regexInfo);
1694
+
1695
+ if (typeof(resultMatch) == 'string')
1696
+ resultMatch = [new sh.Match(resultMatch, match.index, regexInfo.css)];
1697
+
1698
+ matches = matches.concat(resultMatch);
1699
+ }
1700
+
1701
+ return matches;
1702
+ };
1703
+
1704
+ /**
1705
+ * Turns all URLs in the code into <a/> tags.
1706
+ * @param {String} code Input code.
1707
+ * @return {String} Returns code with </a> tags.
1708
+ */
1709
+ function processUrls(code)
1710
+ {
1711
+ var gt = /(.*)((&gt;|&lt;).*)/;
1712
+
1713
+ return code.replace(sh.regexLib.url, function(m)
1714
+ {
1715
+ var suffix = '',
1716
+ match = null
1717
+ ;
1718
+
1719
+ // We include &lt; and &gt; in the URL for the common cases like <http://google.com>
1720
+ // The problem is that they get transformed into &lt;http://google.com&gt;
1721
+ // Where as &gt; easily looks like part of the URL string.
1722
+
1723
+ if (match = gt.exec(m))
1724
+ {
1725
+ m = match[1];
1726
+ suffix = match[2];
1727
+ }
1728
+
1729
+ return '<a href="' + m + '" target="_blank">' + m + '</a>' + suffix;
1730
+ });
1731
+ };
1732
+
1733
+ /**
1734
+ * Finds all <SCRIPT TYPE="syntaxhighlighter" /> elementss.
1735
+ * @return {Array} Returns array of all found SyntaxHighlighter tags.
1736
+ */
1737
+ function getSyntaxHighlighterScriptTags()
1738
+ {
1739
+ var tags = document.getElementsByTagName('script'),
1740
+ result = []
1741
+ ;
1742
+
1743
+ for (var i = 0; i < tags.length; i++)
1744
+ if (tags[i].type == 'syntaxhighlighter')
1745
+ result.push(tags[i]);
1746
+
1747
+ return result;
1748
+ };
1749
+
1750
+ /**
1751
+ * Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
1752
+ * there in most cases for XHTML compliance.
1753
+ * @param {String} original Input code.
1754
+ * @return {String} Returns code without leading <![CDATA[]]> tags.
1755
+ */
1756
+ function stripCData(original)
1757
+ {
1758
+ var left = '<![CDATA[',
1759
+ right = ']]>',
1760
+ // for some reason IE inserts some leading blanks here
1761
+ copy = trim(original),
1762
+ changed = false,
1763
+ leftLength = left.length,
1764
+ rightLength = right.length
1765
+ ;
1766
+
1767
+ if (copy.indexOf(left) == 0)
1768
+ {
1769
+ copy = copy.substring(leftLength);
1770
+ changed = true;
1771
+ }
1772
+
1773
+ var copyLength = copy.length;
1774
+
1775
+ if (copy.indexOf(right) == copyLength - rightLength)
1776
+ {
1777
+ copy = copy.substring(0, copyLength - rightLength);
1778
+ changed = true;
1779
+ }
1780
+
1781
+ return changed ? copy : original;
1782
+ };
1783
+
1784
+
1785
+ /**
1786
+ * Quick code mouse double click handler.
1787
+ */
1788
+ function quickCodeHandler(e)
1789
+ {
1790
+ var target = e.target,
1791
+ highlighterDiv = findParentElement(target, '.syntaxhighlighter'),
1792
+ container = findParentElement(target, '.container'),
1793
+ textarea = document.createElement('textarea'),
1794
+ highlighter
1795
+ ;
1796
+
1797
+ if (!container || !highlighterDiv || findElement(container, 'textarea'))
1798
+ return;
1799
+
1800
+ highlighter = getHighlighterById(highlighterDiv.id);
1801
+
1802
+ // add source class name
1803
+ addClass(highlighterDiv, 'source');
1804
+
1805
+ // Have to go over each line and grab it's text, can't just do it on the
1806
+ // container because Firefox loses all \n where as Webkit doesn't.
1807
+ var lines = container.childNodes,
1808
+ code = []
1809
+ ;
1810
+
1811
+ for (var i = 0; i < lines.length; i++)
1812
+ code.push(lines[i].innerText || lines[i].textContent);
1813
+
1814
+ // using \r instead of \r or \r\n makes this work equally well on IE, FF and Webkit
1815
+ code = code.join('\r');
1816
+
1817
+ // inject <textarea/> tag
1818
+ textarea.appendChild(document.createTextNode(code));
1819
+ container.appendChild(textarea);
1820
+
1821
+ // preselect all text
1822
+ textarea.focus();
1823
+ textarea.select();
1824
+
1825
+ // set up handler for lost focus
1826
+ attachEvent(textarea, 'blur', function(e)
1827
+ {
1828
+ textarea.parentNode.removeChild(textarea);
1829
+ removeClass(highlighterDiv, 'source');
1830
+ });
1831
+ };
1832
+
1833
+ /**
1834
+ * Match object.
1835
+ */
1836
+ sh.Match = function(value, index, css)
1837
+ {
1838
+ this.value = value;
1839
+ this.index = index;
1840
+ this.length = value.length;
1841
+ this.css = css;
1842
+ this.brushName = null;
1843
+ };
1844
+
1845
+ sh.Match.prototype.toString = function()
1846
+ {
1847
+ return this.value;
1848
+ };
1849
+
1850
+ /**
1851
+ * Simulates HTML code with a scripting language embedded.
1852
+ *
1853
+ * @param {String} scriptBrushName Brush name of the scripting language.
1854
+ */
1855
+ sh.HtmlScript = function(scriptBrushName)
1856
+ {
1857
+ var brushClass = findBrush(scriptBrushName),
1858
+ scriptBrush,
1859
+ xmlBrush = new sh.brushes.Xml(),
1860
+ bracketsRegex = null,
1861
+ ref = this,
1862
+ methodsToExpose = 'getDiv getHtml init'.split(' ')
1863
+ ;
1864
+
1865
+ if (brushClass == null)
1866
+ return;
1867
+
1868
+ scriptBrush = new brushClass();
1869
+
1870
+ for(var i = 0; i < methodsToExpose.length; i++)
1871
+ // make a closure so we don't lose the name after i changes
1872
+ (function() {
1873
+ var name = methodsToExpose[i];
1874
+
1875
+ ref[name] = function()
1876
+ {
1877
+ return xmlBrush[name].apply(xmlBrush, arguments);
1878
+ };
1879
+ })();
1880
+
1881
+ if (scriptBrush.htmlScript == null)
1882
+ {
1883
+ alert(sh.config.strings.brushNotHtmlScript + scriptBrushName);
1884
+ return;
1885
+ }
1886
+
1887
+ xmlBrush.regexList.push(
1888
+ { regex: scriptBrush.htmlScript.code, func: process }
1889
+ );
1890
+
1891
+ function offsetMatches(matches, offset)
1892
+ {
1893
+ for (var j = 0; j < matches.length; j++)
1894
+ matches[j].index += offset;
1895
+ }
1896
+
1897
+ function process(match, info)
1898
+ {
1899
+ var code = match.code,
1900
+ matches = [],
1901
+ regexList = scriptBrush.regexList,
1902
+ offset = match.index + match.left.length,
1903
+ htmlScript = scriptBrush.htmlScript,
1904
+ result
1905
+ ;
1906
+
1907
+ // add all matches from the code
1908
+ for (var i = 0; i < regexList.length; i++)
1909
+ {
1910
+ result = getMatches(code, regexList[i]);
1911
+ offsetMatches(result, offset);
1912
+ matches = matches.concat(result);
1913
+ }
1914
+
1915
+ // add left script bracket
1916
+ if (htmlScript.left != null && match.left != null)
1917
+ {
1918
+ result = getMatches(match.left, htmlScript.left);
1919
+ offsetMatches(result, match.index);
1920
+ matches = matches.concat(result);
1921
+ }
1922
+
1923
+ // add right script bracket
1924
+ if (htmlScript.right != null && match.right != null)
1925
+ {
1926
+ result = getMatches(match.right, htmlScript.right);
1927
+ offsetMatches(result, match.index + match[0].lastIndexOf(match.right));
1928
+ matches = matches.concat(result);
1929
+ }
1930
+
1931
+ for (var j = 0; j < matches.length; j++)
1932
+ matches[j].brushName = brushClass.brushName;
1933
+
1934
+ return matches;
1935
+ }
1936
+ };
1937
+
1938
+ /**
1939
+ * Main Highlither class.
1940
+ * @constructor
1941
+ */
1942
+ sh.Highlighter = function()
1943
+ {
1944
+ // not putting any code in here because of the prototype inheritance
1945
+ };
1946
+
1947
+ sh.Highlighter.prototype = {
1948
+ /**
1949
+ * Returns value of the parameter passed to the highlighter.
1950
+ * @param {String} name Name of the parameter.
1951
+ * @param {Object} defaultValue Default value.
1952
+ * @return {Object} Returns found value or default value otherwise.
1953
+ */
1954
+ getParam: function(name, defaultValue)
1955
+ {
1956
+ var result = this.params[name];
1957
+ return toBoolean(result == null ? defaultValue : result);
1958
+ },
1959
+
1960
+ /**
1961
+ * Shortcut to document.createElement().
1962
+ * @param {String} name Name of the element to create (DIV, A, etc).
1963
+ * @return {HTMLElement} Returns new HTML element.
1964
+ */
1965
+ create: function(name)
1966
+ {
1967
+ return document.createElement(name);
1968
+ },
1969
+
1970
+ /**
1971
+ * Applies all regular expression to the code and stores all found
1972
+ * matches in the `this.matches` array.
1973
+ * @param {Array} regexList List of regular expressions.
1974
+ * @param {String} code Source code.
1975
+ * @return {Array} Returns list of matches.
1976
+ */
1977
+ findMatches: function(regexList, code)
1978
+ {
1979
+ var result = [];
1980
+
1981
+ if (regexList != null)
1982
+ for (var i = 0; i < regexList.length; i++)
1983
+ // BUG: length returns len+1 for array if methods added to prototype chain (oising@gmail.com)
1984
+ if (typeof (regexList[i]) == "object")
1985
+ result = result.concat(getMatches(code, regexList[i]));
1986
+
1987
+ // sort and remove nested the matches
1988
+ return this.removeNestedMatches(result.sort(matchesSortCallback));
1989
+ },
1990
+
1991
+ /**
1992
+ * Checks to see if any of the matches are inside of other matches.
1993
+ * This process would get rid of highligted strings inside comments,
1994
+ * keywords inside strings and so on.
1995
+ */
1996
+ removeNestedMatches: function(matches)
1997
+ {
1998
+ // Optimized by Jose Prado (http://joseprado.com)
1999
+ for (var i = 0; i < matches.length; i++)
2000
+ {
2001
+ if (matches[i] === null)
2002
+ continue;
2003
+
2004
+ var itemI = matches[i],
2005
+ itemIEndPos = itemI.index + itemI.length
2006
+ ;
2007
+
2008
+ for (var j = i + 1; j < matches.length && matches[i] !== null; j++)
2009
+ {
2010
+ var itemJ = matches[j];
2011
+
2012
+ if (itemJ === null)
2013
+ continue;
2014
+ else if (itemJ.index > itemIEndPos)
2015
+ break;
2016
+ else if (itemJ.index == itemI.index && itemJ.length > itemI.length)
2017
+ matches[i] = null;
2018
+ else if (itemJ.index >= itemI.index && itemJ.index < itemIEndPos)
2019
+ matches[j] = null;
2020
+ }
2021
+ }
2022
+
2023
+ return matches;
2024
+ },
2025
+
2026
+ /**
2027
+ * Creates an array containing integer line numbers starting from the 'first-line' param.
2028
+ * @return {Array} Returns array of integers.
2029
+ */
2030
+ figureOutLineNumbers: function(code)
2031
+ {
2032
+ var lines = [],
2033
+ firstLine = parseInt(this.getParam('first-line'))
2034
+ ;
2035
+
2036
+ eachLine(code, function(line, index)
2037
+ {
2038
+ lines.push(index + firstLine);
2039
+ });
2040
+
2041
+ return lines;
2042
+ },
2043
+
2044
+ /**
2045
+ * Determines if specified line number is in the highlighted list.
2046
+ */
2047
+ isLineHighlighted: function(lineNumber)
2048
+ {
2049
+ var list = this.getParam('highlight', []);
2050
+
2051
+ if (typeof(list) != 'object' && list.push == null)
2052
+ list = [ list ];
2053
+
2054
+ return indexOf(list, lineNumber.toString()) != -1;
2055
+ },
2056
+
2057
+ /**
2058
+ * Generates HTML markup for a single line of code while determining alternating line style.
2059
+ * @param {Integer} lineNumber Line number.
2060
+ * @param {String} code Line HTML markup.
2061
+ * @return {String} Returns HTML markup.
2062
+ */
2063
+ getLineHtml: function(lineIndex, lineNumber, code)
2064
+ {
2065
+ var classes = [
2066
+ 'line',
2067
+ 'number' + lineNumber,
2068
+ 'index' + lineIndex,
2069
+ 'alt' + (lineNumber % 2 == 0 ? 1 : 2).toString()
2070
+ ];
2071
+
2072
+ if (this.isLineHighlighted(lineNumber))
2073
+ classes.push('highlighted');
2074
+
2075
+ if (lineNumber == 0)
2076
+ classes.push('break');
2077
+
2078
+ return '<div class="' + classes.join(' ') + '">' + code + '</div>';
2079
+ },
2080
+
2081
+ /**
2082
+ * Generates HTML markup for line number column.
2083
+ * @param {String} code Complete code HTML markup.
2084
+ * @param {Array} lineNumbers Calculated line numbers.
2085
+ * @return {String} Returns HTML markup.
2086
+ */
2087
+ getLineNumbersHtml: function(code, lineNumbers)
2088
+ {
2089
+ var html = '',
2090
+ count = splitLines(code).length,
2091
+ firstLine = parseInt(this.getParam('first-line')),
2092
+ pad = this.getParam('pad-line-numbers')
2093
+ ;
2094
+
2095
+ if (pad == true)
2096
+ pad = (firstLine + count - 1).toString().length;
2097
+ else if (isNaN(pad) == true)
2098
+ pad = 0;
2099
+
2100
+ for (var i = 0; i < count; i++)
2101
+ {
2102
+ var lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i,
2103
+ code = lineNumber == 0 ? sh.config.space : padNumber(lineNumber, pad)
2104
+ ;
2105
+
2106
+ html += this.getLineHtml(i, lineNumber, code);
2107
+ }
2108
+
2109
+ return html;
2110
+ },
2111
+
2112
+ /**
2113
+ * Splits block of text into individual DIV lines.
2114
+ * @param {String} code Code to highlight.
2115
+ * @param {Array} lineNumbers Calculated line numbers.
2116
+ * @return {String} Returns highlighted code in HTML form.
2117
+ */
2118
+ getCodeLinesHtml: function(html, lineNumbers)
2119
+ {
2120
+ html = trim(html);
2121
+
2122
+ var lines = splitLines(html),
2123
+ padLength = this.getParam('pad-line-numbers'),
2124
+ firstLine = parseInt(this.getParam('first-line')),
2125
+ html = '',
2126
+ brushName = this.getParam('brush')
2127
+ ;
2128
+
2129
+ for (var i = 0; i < lines.length; i++)
2130
+ {
2131
+ var line = lines[i],
2132
+ indent = /^(&nbsp;|\s)+/.exec(line),
2133
+ spaces = null,
2134
+ lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i;
2135
+ ;
2136
+
2137
+ if (indent != null)
2138
+ {
2139
+ spaces = indent[0].toString();
2140
+ line = line.substr(spaces.length);
2141
+ spaces = spaces.replace(' ', sh.config.space);
2142
+ }
2143
+
2144
+ line = trim(line);
2145
+
2146
+ if (line.length == 0)
2147
+ line = sh.config.space;
2148
+
2149
+ html += this.getLineHtml(
2150
+ i,
2151
+ lineNumber,
2152
+ (spaces != null ? '<code class="' + brushName + ' spaces">' + spaces + '</code>' : '') + line
2153
+ );
2154
+ }
2155
+
2156
+ return html;
2157
+ },
2158
+
2159
+ /**
2160
+ * Returns HTML for the table title or empty string if title is null.
2161
+ */
2162
+ getTitleHtml: function(title)
2163
+ {
2164
+ return title ? '<caption>' + title + '</caption>' : '';
2165
+ },
2166
+
2167
+ /**
2168
+ * Finds all matches in the source code.
2169
+ * @param {String} code Source code to process matches in.
2170
+ * @param {Array} matches Discovered regex matches.
2171
+ * @return {String} Returns formatted HTML with processed mathes.
2172
+ */
2173
+ getMatchesHtml: function(code, matches)
2174
+ {
2175
+ var pos = 0,
2176
+ result = '',
2177
+ brushName = this.getParam('brush', '')
2178
+ ;
2179
+
2180
+ function getBrushNameCss(match)
2181
+ {
2182
+ var result = match ? (match.brushName || brushName) : brushName;
2183
+ return result ? result + ' ' : '';
2184
+ };
2185
+
2186
+ // Finally, go through the final list of matches and pull the all
2187
+ // together adding everything in between that isn't a match.
2188
+ for (var i = 0; i < matches.length; i++)
2189
+ {
2190
+ var match = matches[i],
2191
+ matchBrushName
2192
+ ;
2193
+
2194
+ if (match === null || match.length === 0)
2195
+ continue;
2196
+
2197
+ matchBrushName = getBrushNameCss(match);
2198
+
2199
+ result += wrapLinesWithCode(code.substr(pos, match.index - pos), matchBrushName + 'plain')
2200
+ + wrapLinesWithCode(match.value, matchBrushName + match.css)
2201
+ ;
2202
+
2203
+ pos = match.index + match.length + (match.offset || 0);
2204
+ }
2205
+
2206
+ // don't forget to add whatever's remaining in the string
2207
+ result += wrapLinesWithCode(code.substr(pos), getBrushNameCss() + 'plain');
2208
+
2209
+ return result;
2210
+ },
2211
+
2212
+ /**
2213
+ * Generates HTML markup for the whole syntax highlighter.
2214
+ * @param {String} code Source code.
2215
+ * @return {String} Returns HTML markup.
2216
+ */
2217
+ getHtml: function(code)
2218
+ {
2219
+ var html = '',
2220
+ classes = [ 'syntaxhighlighter' ],
2221
+ tabSize,
2222
+ matches,
2223
+ lineNumbers
2224
+ ;
2225
+
2226
+ // process light mode
2227
+ if (this.getParam('light') == true)
2228
+ this.params.toolbar = this.params.gutter = false;
2229
+
2230
+ className = 'syntaxhighlighter';
2231
+
2232
+ if (this.getParam('collapse') == true)
2233
+ classes.push('collapsed');
2234
+
2235
+ if ((gutter = this.getParam('gutter')) == false)
2236
+ classes.push('nogutter');
2237
+
2238
+ // add custom user style name
2239
+ classes.push(this.getParam('class-name'));
2240
+
2241
+ // add brush alias to the class name for custom CSS
2242
+ classes.push(this.getParam('brush'));
2243
+
2244
+ code = trimFirstAndLastLines(code)
2245
+ .replace(/\r/g, ' ') // IE lets these buggers through
2246
+ ;
2247
+
2248
+ tabSize = this.getParam('tab-size');
2249
+
2250
+ // replace tabs with spaces
2251
+ code = this.getParam('smart-tabs') == true
2252
+ ? processSmartTabs(code, tabSize)
2253
+ : processTabs(code, tabSize)
2254
+ ;
2255
+
2256
+ // unindent code by the common indentation
2257
+ code = unindent(code);
2258
+
2259
+ if (gutter)
2260
+ lineNumbers = this.figureOutLineNumbers(code);
2261
+
2262
+ // PATCH to allow embedded html
2263
+ var tags = [], c = 0;
2264
+ code = code.replace(/<(.*?)>/mg, function(m, p1) {
2265
+ tags[c] = p1;
2266
+ return String.fromCharCode(c++ + 5000);
2267
+ });
2268
+
2269
+ // find matches in the code using brushes regex list
2270
+ matches = this.findMatches(this.regexList, code);
2271
+ // processes found matches into the html
2272
+ html = this.getMatchesHtml(code, matches);
2273
+ // finally, split all lines so that they wrap well
2274
+ html = this.getCodeLinesHtml(html, lineNumbers);
2275
+
2276
+ // finally, process the links
2277
+ if (this.getParam('auto-links'))
2278
+ html = processUrls(html);
2279
+
2280
+ // PATCH to allow embedded html
2281
+ for (var i = 0; i < tags.length; i++)
2282
+ html = html.replace(String.fromCharCode(i + 5000), "<" + tags[i] + ">");
2283
+
2284
+ if (typeof(navigator) != 'undefined' && navigator.userAgent && navigator.userAgent.match(/MSIE/))
2285
+ classes.push('ie');
2286
+
2287
+ var brush = this.getParam('brush');
2288
+
2289
+ html =
2290
+ '<div class="syntaxhighlighter-wrapper"><div id="' + getHighlighterId(this.id) + '" class="' + classes.join(' ') + (brush ? '" data-lang="' + brush : '') + '">'
2291
+ + (this.getParam('toolbar') ? sh.toolbar.getHtml(this) : '')
2292
+ + '<table border="0" cellpadding="0" cellspacing="0">'
2293
+ + this.getTitleHtml(this.getParam('title'))
2294
+ + '<tbody>'
2295
+ + '<tr>'
2296
+ + (gutter ? '<td class="gutter">' + this.getLineNumbersHtml(code) + '</td>' : '')
2297
+ + '<td class="code">'
2298
+ + '<div class="container">'
2299
+ + html
2300
+ + '</div>'
2301
+ + '</td>'
2302
+ + '</tr>'
2303
+ + '</tbody>'
2304
+ + '</table>'
2305
+ + '</div></div>'
2306
+ ;
2307
+
2308
+ return html;
2309
+ },
2310
+
2311
+ /**
2312
+ * Highlights the code and returns complete HTML.
2313
+ * @param {String} code Code to highlight.
2314
+ * @return {Element} Returns container DIV element with all markup.
2315
+ */
2316
+ getDiv: function(code)
2317
+ {
2318
+ if (code === null)
2319
+ code = '';
2320
+
2321
+ this.code = code;
2322
+
2323
+ var div = this.create('div');
2324
+
2325
+ // create main HTML
2326
+ div.innerHTML = this.getHtml(code);
2327
+
2328
+ // set up click handlers
2329
+ if (this.getParam('toolbar'))
2330
+ attachEvent(findElement(div, '.toolbar'), 'click', sh.toolbar.handler);
2331
+
2332
+ if (this.getParam('quick-code'))
2333
+ attachEvent(findElement(div, '.code'), 'dblclick', quickCodeHandler);
2334
+
2335
+ return div;
2336
+ },
2337
+
2338
+ /**
2339
+ * Initializes the highlighter/brush.
2340
+ *
2341
+ * Constructor isn't used for initialization so that nothing executes during necessary
2342
+ * `new SyntaxHighlighter.Highlighter()` call when setting up brush inheritence.
2343
+ *
2344
+ * @param {Hash} params Highlighter parameters.
2345
+ */
2346
+ init: function(params)
2347
+ {
2348
+ this.id = guid();
2349
+
2350
+ // register this instance in the highlighters list
2351
+ storeHighlighter(this);
2352
+
2353
+ // local params take precedence over defaults
2354
+ this.params = merge(sh.defaults, params || {})
2355
+
2356
+ // process light mode
2357
+ if (this.getParam('light') == true)
2358
+ this.params.toolbar = this.params.gutter = false;
2359
+ },
2360
+
2361
+ /**
2362
+ * Converts space separated list of keywords into a regular expression string.
2363
+ * @param {String} str Space separated keywords.
2364
+ * @return {String} Returns regular expression string.
2365
+ */
2366
+ getKeywords: function(str)
2367
+ {
2368
+ str = str
2369
+ .replace(/^\s+|\s+$/g, '')
2370
+ .replace(/\s+/g, '|')
2371
+ ;
2372
+
2373
+ return '\\b(?:' + str + ')\\b';
2374
+ },
2375
+
2376
+ /**
2377
+ * Makes a brush compatible with the `html-script` functionality.
2378
+ * @param {Object} regexGroup Object containing `left` and `right` regular expressions.
2379
+ */
2380
+ forHtmlScript: function(regexGroup)
2381
+ {
2382
+ this.htmlScript = {
2383
+ left : { regex: regexGroup.left, css: 'script' },
2384
+ right : { regex: regexGroup.right, css: 'script' },
2385
+ code : new XRegExp(
2386
+ "(?<left>" + regexGroup.left.source + ")" +
2387
+ "(?<code>.*?)" +
2388
+ "(?<right>" + regexGroup.right.source + ")",
2389
+ "sgi"
2390
+ )
2391
+ };
2392
+ }
2393
+ }; // end of Highlighter
2394
+
2395
+ return sh;
2396
+ }(); // end of anonymous function
2397
+
2398
+ // CommonJS
2399
+ typeof(exports) != 'undefined' ? exports['SyntaxHighlighter'] = SyntaxHighlighter : null;