rubyception 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -6
- data/app/assets/images/rubyception/entry_collapse.png +0 -0
- data/app/assets/images/rubyception/entry_expand.png +0 -0
- data/app/assets/javascripts/rubyception/application.coffee +1 -3
- data/app/assets/javascripts/rubyception/routers/log.coffee +4 -2
- data/app/assets/javascripts/rubyception/syntax_highlighting.js +543 -0
- data/app/assets/javascripts/rubyception/views/backtrace_lines/index.coffee +0 -1
- data/app/assets/javascripts/rubyception/views/entries/entry.coffee +30 -11
- data/app/assets/stylesheets/rubyception/application.sass +1 -2
- data/app/assets/stylesheets/rubyception/entries.sass +54 -5
- data/app/assets/stylesheets/rubyception/lines.sass +10 -7
- data/app/assets/stylesheets/rubyception/syntax_highlighting.css +138 -0
- data/app/controllers/rubyception/templates_controller.rb +12 -0
- data/app/helpers/rubyception/application_helper.rb +19 -0
- data/app/models/rubyception/entry.rb +37 -2
- data/app/views/layouts/rubyception/application.haml +1 -0
- data/app/views/rubyception/entries/_entry.haml +14 -7
- data/app/views/rubyception/lines/action_view/_render_partial.haml +2 -2
- data/app/views/rubyception/lines/action_view/_render_template.haml +2 -2
- data/app/views/rubyception/lines/active_record/_identity.haml +2 -2
- data/app/views/rubyception/lines/active_record/_sql.haml +3 -3
- data/app/views/rubyception/templates/index.js.erb +4 -0
- data/config/initializers/sass.rb +1 -2
- data/config/initializers/templates.rb +5 -0
- data/config/routes.rb +1 -0
- data/config/{templating.yml → templates.yml} +7 -7
- data/lib/rubyception/engine.rb +27 -0
- data/lib/rubyception/version.rb +1 -1
- metadata +10 -13
- data/app/assets/javascripts/rubyception/shBrushSql.js +0 -66
- data/app/assets/javascripts/rubyception/shCore.js +0 -17
- data/app/assets/javascripts/rubyception/template.js +0 -1
- data/app/assets/stylesheets/rubyception/shCore.css +0 -226
- data/app/assets/stylesheets/rubyception/shThemeDefault.css +0 -117
- data/app/controllers/rubyception/templating_controller.rb +0 -22
- data/config/initializers/websocket_server.rb +0 -22
- data/lib/rubyception/templating.rb +0 -48
- data/lib/tasks/rubyception_tasks.rake +0 -4
- data/lib/tasks/templates.rake +0 -7
data/README.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
A realtime log viewer for Rails (released under the MIT license)
|
4
4
|
|
5
|
+
--------------------
|
6
|
+
|
7
|
+
This shows a normal log entry
|
8
|
+
![screenshot 1](https://s3.amazonaws.com/tye/rubyception1.png)
|
9
|
+
|
10
|
+
This entry has an exception. The backtrace file names are clickable and will open in MacVim. Soon support for TextMate & other editors will be added.
|
11
|
+
![screenshot 2](https://s3.amazonaws.com/tye/rubyception2.png)
|
12
|
+
|
5
13
|
## Features
|
6
14
|
|
7
15
|
* Real-time updating of the log file using Websocket
|
@@ -9,27 +17,39 @@ A realtime log viewer for Rails (released under the MIT license)
|
|
9
17
|
|
10
18
|
## Installation
|
11
19
|
|
12
|
-
Add to your gemfile
|
20
|
+
Add to your gemfile **in the development group**:
|
13
21
|
```ruby
|
14
|
-
|
22
|
+
group :development do
|
23
|
+
gem 'rubyception'
|
24
|
+
end
|
15
25
|
```
|
16
26
|
Run:
|
17
27
|
```
|
18
28
|
bundle install
|
19
29
|
```
|
20
|
-
|
30
|
+
|
31
|
+
Add to your `config/routes.rb`:
|
21
32
|
```ruby
|
22
|
-
|
33
|
+
mount Rubyception::Engine => '/rubyception'
|
23
34
|
```
|
24
|
-
|
35
|
+
Run your rails server and go to:<br>
|
25
36
|
`http://localhost:3000/rubyception`<br>
|
26
37
|
Your log entries will appear on the rubyception page in realtime. You
|
27
38
|
must be using a browser that supports Websockets.
|
28
39
|
|
40
|
+
## Using in Production
|
41
|
+
Rubyception is not intended to be used in a production environment. If
|
42
|
+
you need exception handling in production I recommend
|
43
|
+
[Airbrake](http://airbrake.io/pages/home),
|
44
|
+
[Exceptional](http://www.exceptional.io/) or
|
45
|
+
[NewRelic](https://newrelic.com/).
|
46
|
+
|
29
47
|
## Hotkeys
|
30
48
|
`up` or `k` Move selection up<br>
|
31
49
|
`down` or `j` Move selection down<br>
|
32
50
|
`enter` Expand selected entry<br>
|
33
51
|
`G` Go to last entry<br>
|
34
52
|
`gg` Go to first entry<br>
|
35
|
-
`42gg` or `42G` Go to 42nd entry<br>
|
53
|
+
`42gg` or `42G` Go to 42nd entry<br>
|
54
|
+
`p` Toggles between inline and nested parameters view if you have a log
|
55
|
+
entry open<br>
|
Binary file
|
Binary file
|
@@ -5,12 +5,10 @@
|
|
5
5
|
#= require rubyception/lib/inflections
|
6
6
|
#= require rubyception/lib/jenny
|
7
7
|
#= require rubyception/lib/mousetrap
|
8
|
-
#= require rubyception/template
|
9
8
|
#= require rubyception/init
|
10
9
|
#= require_tree ./routers
|
11
10
|
#= require_tree ./views
|
12
11
|
#= require_tree ./collections
|
13
12
|
#= require_tree ./models
|
14
13
|
#= require rubyception/app
|
15
|
-
#= require rubyception/
|
16
|
-
#= require rubyception/shBrushSql
|
14
|
+
#= require rubyception/syntax_highlighting
|
@@ -28,10 +28,12 @@ class App.Routers.Log extends Backbone.Router
|
|
28
28
|
@collection.add data
|
29
29
|
default: ->
|
30
30
|
@index()
|
31
|
+
toggle_params: =>
|
32
|
+
expanded_entry = $('.entry.selected.open')
|
33
|
+
if expanded_entry.length > 0
|
34
|
+
expanded_entry.find('.params').toggleClass 'nested'
|
31
35
|
toggle_side: =>
|
32
36
|
$('.wrapper').toggleClass 'filter'
|
33
|
-
toggle_params: =>
|
34
|
-
$('body').toggleClass 'pretty_params'
|
35
37
|
hotkeys: =>
|
36
38
|
m = Mousetrap
|
37
39
|
m.bind '\\ n' , @toggle_side
|
@@ -0,0 +1,543 @@
|
|
1
|
+
/*
|
2
|
+
SHJS - Syntax Highlighting in JavaScript
|
3
|
+
Copyright (C) 2007, 2008 gnombat@users.sourceforge.net
|
4
|
+
License: http://shjs.sourceforge.net/doc/gplv3.html
|
5
|
+
*/
|
6
|
+
|
7
|
+
if (! this.sh_languages) {
|
8
|
+
this.sh_languages = {};
|
9
|
+
}
|
10
|
+
var sh_requests = {};
|
11
|
+
|
12
|
+
function sh_isEmailAddress(url) {
|
13
|
+
if (/^mailto:/.test(url)) {
|
14
|
+
return false;
|
15
|
+
}
|
16
|
+
return url.indexOf('@') !== -1;
|
17
|
+
}
|
18
|
+
|
19
|
+
function sh_setHref(tags, numTags, inputString) {
|
20
|
+
var url = inputString.substring(tags[numTags - 2].pos, tags[numTags - 1].pos);
|
21
|
+
if (url.length >= 2 && url.charAt(0) === '<' && url.charAt(url.length - 1) === '>') {
|
22
|
+
url = url.substr(1, url.length - 2);
|
23
|
+
}
|
24
|
+
if (sh_isEmailAddress(url)) {
|
25
|
+
url = 'mailto:' + url;
|
26
|
+
}
|
27
|
+
tags[numTags - 2].node.href = url;
|
28
|
+
}
|
29
|
+
|
30
|
+
/*
|
31
|
+
Konqueror has a bug where the regular expression /$/g will not match at the end
|
32
|
+
of a line more than once:
|
33
|
+
|
34
|
+
var regex = /$/g;
|
35
|
+
var match;
|
36
|
+
|
37
|
+
var line = '1234567890';
|
38
|
+
regex.lastIndex = 10;
|
39
|
+
match = regex.exec(line);
|
40
|
+
|
41
|
+
var line2 = 'abcde';
|
42
|
+
regex.lastIndex = 5;
|
43
|
+
match = regex.exec(line2); // fails
|
44
|
+
*/
|
45
|
+
function sh_konquerorExec(s) {
|
46
|
+
var result = [''];
|
47
|
+
result.index = s.length;
|
48
|
+
result.input = s;
|
49
|
+
return result;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
Highlights all elements containing source code in a text string. The return
|
54
|
+
value is an array of objects, each representing an HTML start or end tag. Each
|
55
|
+
object has a property named pos, which is an integer representing the text
|
56
|
+
offset of the tag. Every start tag also has a property named node, which is the
|
57
|
+
DOM element started by the tag. End tags do not have this property.
|
58
|
+
@param inputString a text string
|
59
|
+
@param language a language definition object
|
60
|
+
@return an array of tag objects
|
61
|
+
*/
|
62
|
+
function sh_highlightString(inputString, language) {
|
63
|
+
if (/Konqueror/.test(navigator.userAgent)) {
|
64
|
+
if (! language.konquered) {
|
65
|
+
for (var s = 0; s < language.length; s++) {
|
66
|
+
for (var p = 0; p < language[s].length; p++) {
|
67
|
+
var r = language[s][p][0];
|
68
|
+
if (r.source === '$') {
|
69
|
+
r.exec = sh_konquerorExec;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
language.konquered = true;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
var a = document.createElement('a');
|
78
|
+
var span = document.createElement('span');
|
79
|
+
|
80
|
+
// the result
|
81
|
+
var tags = [];
|
82
|
+
var numTags = 0;
|
83
|
+
|
84
|
+
// each element is a pattern object from language
|
85
|
+
var patternStack = [];
|
86
|
+
|
87
|
+
// the current position within inputString
|
88
|
+
var pos = 0;
|
89
|
+
|
90
|
+
// the name of the current style, or null if there is no current style
|
91
|
+
var currentStyle = null;
|
92
|
+
|
93
|
+
var output = function(s, style) {
|
94
|
+
var length = s.length;
|
95
|
+
// this is more than just an optimization - we don't want to output empty <span></span> elements
|
96
|
+
if (length === 0) {
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
if (! style) {
|
100
|
+
var stackLength = patternStack.length;
|
101
|
+
if (stackLength !== 0) {
|
102
|
+
var pattern = patternStack[stackLength - 1];
|
103
|
+
// check whether this is a state or an environment
|
104
|
+
if (! pattern[3]) {
|
105
|
+
// it's not a state - it's an environment; use the style for this environment
|
106
|
+
style = pattern[1];
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
if (currentStyle !== style) {
|
111
|
+
if (currentStyle) {
|
112
|
+
tags[numTags++] = {pos: pos};
|
113
|
+
if (currentStyle === 'sh_url') {
|
114
|
+
sh_setHref(tags, numTags, inputString);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
if (style) {
|
118
|
+
var clone;
|
119
|
+
if (style === 'sh_url') {
|
120
|
+
clone = a.cloneNode(false);
|
121
|
+
}
|
122
|
+
else {
|
123
|
+
clone = span.cloneNode(false);
|
124
|
+
}
|
125
|
+
clone.className = style;
|
126
|
+
tags[numTags++] = {node: clone, pos: pos};
|
127
|
+
}
|
128
|
+
}
|
129
|
+
pos += length;
|
130
|
+
currentStyle = style;
|
131
|
+
};
|
132
|
+
|
133
|
+
var endOfLinePattern = /\r\n|\r|\n/g;
|
134
|
+
endOfLinePattern.lastIndex = 0;
|
135
|
+
var inputStringLength = inputString.length;
|
136
|
+
while (pos < inputStringLength) {
|
137
|
+
var start = pos;
|
138
|
+
var end;
|
139
|
+
var startOfNextLine;
|
140
|
+
var endOfLineMatch = endOfLinePattern.exec(inputString);
|
141
|
+
if (endOfLineMatch === null) {
|
142
|
+
end = inputStringLength;
|
143
|
+
startOfNextLine = inputStringLength;
|
144
|
+
}
|
145
|
+
else {
|
146
|
+
end = endOfLineMatch.index;
|
147
|
+
startOfNextLine = endOfLinePattern.lastIndex;
|
148
|
+
}
|
149
|
+
|
150
|
+
var line = inputString.substring(start, end);
|
151
|
+
|
152
|
+
var matchCache = [];
|
153
|
+
for (;;) {
|
154
|
+
var posWithinLine = pos - start;
|
155
|
+
|
156
|
+
var stateIndex;
|
157
|
+
var stackLength = patternStack.length;
|
158
|
+
if (stackLength === 0) {
|
159
|
+
stateIndex = 0;
|
160
|
+
}
|
161
|
+
else {
|
162
|
+
// get the next state
|
163
|
+
stateIndex = patternStack[stackLength - 1][2];
|
164
|
+
}
|
165
|
+
|
166
|
+
var state = language[stateIndex];
|
167
|
+
var numPatterns = state.length;
|
168
|
+
var mc = matchCache[stateIndex];
|
169
|
+
if (! mc) {
|
170
|
+
mc = matchCache[stateIndex] = [];
|
171
|
+
}
|
172
|
+
var bestMatch = null;
|
173
|
+
var bestPatternIndex = -1;
|
174
|
+
for (var i = 0; i < numPatterns; i++) {
|
175
|
+
var match;
|
176
|
+
if (i < mc.length && (mc[i] === null || posWithinLine <= mc[i].index)) {
|
177
|
+
match = mc[i];
|
178
|
+
}
|
179
|
+
else {
|
180
|
+
var regex = state[i][0];
|
181
|
+
regex.lastIndex = posWithinLine;
|
182
|
+
match = regex.exec(line);
|
183
|
+
mc[i] = match;
|
184
|
+
}
|
185
|
+
if (match !== null && (bestMatch === null || match.index < bestMatch.index)) {
|
186
|
+
bestMatch = match;
|
187
|
+
bestPatternIndex = i;
|
188
|
+
if (match.index === posWithinLine) {
|
189
|
+
break;
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
if (bestMatch === null) {
|
195
|
+
output(line.substring(posWithinLine), null);
|
196
|
+
break;
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
// got a match
|
200
|
+
if (bestMatch.index > posWithinLine) {
|
201
|
+
output(line.substring(posWithinLine, bestMatch.index), null);
|
202
|
+
}
|
203
|
+
|
204
|
+
var pattern = state[bestPatternIndex];
|
205
|
+
|
206
|
+
var newStyle = pattern[1];
|
207
|
+
var matchedString;
|
208
|
+
if (newStyle instanceof Array) {
|
209
|
+
for (var subexpression = 0; subexpression < newStyle.length; subexpression++) {
|
210
|
+
matchedString = bestMatch[subexpression + 1];
|
211
|
+
output(matchedString, newStyle[subexpression]);
|
212
|
+
}
|
213
|
+
}
|
214
|
+
else {
|
215
|
+
matchedString = bestMatch[0];
|
216
|
+
output(matchedString, newStyle);
|
217
|
+
}
|
218
|
+
|
219
|
+
switch (pattern[2]) {
|
220
|
+
case -1:
|
221
|
+
// do nothing
|
222
|
+
break;
|
223
|
+
case -2:
|
224
|
+
// exit
|
225
|
+
patternStack.pop();
|
226
|
+
break;
|
227
|
+
case -3:
|
228
|
+
// exitall
|
229
|
+
patternStack.length = 0;
|
230
|
+
break;
|
231
|
+
default:
|
232
|
+
// this was the start of a delimited pattern or a state/environment
|
233
|
+
patternStack.push(pattern);
|
234
|
+
break;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
// end of the line
|
240
|
+
if (currentStyle) {
|
241
|
+
tags[numTags++] = {pos: pos};
|
242
|
+
if (currentStyle === 'sh_url') {
|
243
|
+
sh_setHref(tags, numTags, inputString);
|
244
|
+
}
|
245
|
+
currentStyle = null;
|
246
|
+
}
|
247
|
+
pos = startOfNextLine;
|
248
|
+
}
|
249
|
+
|
250
|
+
return tags;
|
251
|
+
}
|
252
|
+
|
253
|
+
////////////////////////////////////////////////////////////////////////////////
|
254
|
+
// DOM-dependent functions
|
255
|
+
|
256
|
+
function sh_getClasses(element) {
|
257
|
+
var result = [];
|
258
|
+
var htmlClass = element.className;
|
259
|
+
if (htmlClass && htmlClass.length > 0) {
|
260
|
+
var htmlClasses = htmlClass.split(' ');
|
261
|
+
for (var i = 0; i < htmlClasses.length; i++) {
|
262
|
+
if (htmlClasses[i].length > 0) {
|
263
|
+
result.push(htmlClasses[i]);
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
return result;
|
268
|
+
}
|
269
|
+
|
270
|
+
function sh_addClass(element, name) {
|
271
|
+
var htmlClasses = sh_getClasses(element);
|
272
|
+
for (var i = 0; i < htmlClasses.length; i++) {
|
273
|
+
if (name.toLowerCase() === htmlClasses[i].toLowerCase()) {
|
274
|
+
return;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
htmlClasses.push(name);
|
278
|
+
element.className = htmlClasses.join(' ');
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
Extracts the tags from an HTML DOM NodeList.
|
283
|
+
@param nodeList a DOM NodeList
|
284
|
+
@param result an object with text, tags and pos properties
|
285
|
+
*/
|
286
|
+
function sh_extractTagsFromNodeList(nodeList, result) {
|
287
|
+
var length = nodeList.length;
|
288
|
+
for (var i = 0; i < length; i++) {
|
289
|
+
var node = nodeList.item(i);
|
290
|
+
switch (node.nodeType) {
|
291
|
+
case 1:
|
292
|
+
if (node.nodeName.toLowerCase() === 'br') {
|
293
|
+
var terminator;
|
294
|
+
if (/MSIE/.test(navigator.userAgent)) {
|
295
|
+
terminator = '\r';
|
296
|
+
}
|
297
|
+
else {
|
298
|
+
terminator = '\n';
|
299
|
+
}
|
300
|
+
result.text.push(terminator);
|
301
|
+
result.pos++;
|
302
|
+
}
|
303
|
+
else {
|
304
|
+
result.tags.push({node: node.cloneNode(false), pos: result.pos});
|
305
|
+
sh_extractTagsFromNodeList(node.childNodes, result);
|
306
|
+
result.tags.push({pos: result.pos});
|
307
|
+
}
|
308
|
+
break;
|
309
|
+
case 3:
|
310
|
+
case 4:
|
311
|
+
result.text.push(node.data);
|
312
|
+
result.pos += node.length;
|
313
|
+
break;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
/**
|
319
|
+
Extracts the tags from the text of an HTML element. The extracted tags will be
|
320
|
+
returned as an array of tag objects. See sh_highlightString for the format of
|
321
|
+
the tag objects.
|
322
|
+
@param element a DOM element
|
323
|
+
@param tags an empty array; the extracted tag objects will be returned in it
|
324
|
+
@return the text of the element
|
325
|
+
@see sh_highlightString
|
326
|
+
*/
|
327
|
+
function sh_extractTags(element, tags) {
|
328
|
+
var result = {};
|
329
|
+
result.text = [];
|
330
|
+
result.tags = tags;
|
331
|
+
result.pos = 0;
|
332
|
+
sh_extractTagsFromNodeList(element.childNodes, result);
|
333
|
+
return result.text.join('');
|
334
|
+
}
|
335
|
+
|
336
|
+
/**
|
337
|
+
Merges the original tags from an element with the tags produced by highlighting.
|
338
|
+
@param originalTags an array containing the original tags
|
339
|
+
@param highlightTags an array containing the highlighting tags - these must not overlap
|
340
|
+
@result an array containing the merged tags
|
341
|
+
*/
|
342
|
+
function sh_mergeTags(originalTags, highlightTags) {
|
343
|
+
var numOriginalTags = originalTags.length;
|
344
|
+
if (numOriginalTags === 0) {
|
345
|
+
return highlightTags;
|
346
|
+
}
|
347
|
+
|
348
|
+
var numHighlightTags = highlightTags.length;
|
349
|
+
if (numHighlightTags === 0) {
|
350
|
+
return originalTags;
|
351
|
+
}
|
352
|
+
|
353
|
+
var result = [];
|
354
|
+
var originalIndex = 0;
|
355
|
+
var highlightIndex = 0;
|
356
|
+
|
357
|
+
while (originalIndex < numOriginalTags && highlightIndex < numHighlightTags) {
|
358
|
+
var originalTag = originalTags[originalIndex];
|
359
|
+
var highlightTag = highlightTags[highlightIndex];
|
360
|
+
|
361
|
+
if (originalTag.pos <= highlightTag.pos) {
|
362
|
+
result.push(originalTag);
|
363
|
+
originalIndex++;
|
364
|
+
}
|
365
|
+
else {
|
366
|
+
result.push(highlightTag);
|
367
|
+
if (highlightTags[highlightIndex + 1].pos <= originalTag.pos) {
|
368
|
+
highlightIndex++;
|
369
|
+
result.push(highlightTags[highlightIndex]);
|
370
|
+
highlightIndex++;
|
371
|
+
}
|
372
|
+
else {
|
373
|
+
// new end tag
|
374
|
+
result.push({pos: originalTag.pos});
|
375
|
+
|
376
|
+
// new start tag
|
377
|
+
highlightTags[highlightIndex] = {node: highlightTag.node.cloneNode(false), pos: originalTag.pos};
|
378
|
+
}
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
while (originalIndex < numOriginalTags) {
|
383
|
+
result.push(originalTags[originalIndex]);
|
384
|
+
originalIndex++;
|
385
|
+
}
|
386
|
+
|
387
|
+
while (highlightIndex < numHighlightTags) {
|
388
|
+
result.push(highlightTags[highlightIndex]);
|
389
|
+
highlightIndex++;
|
390
|
+
}
|
391
|
+
|
392
|
+
return result;
|
393
|
+
}
|
394
|
+
|
395
|
+
/**
|
396
|
+
Inserts tags into text.
|
397
|
+
@param tags an array of tag objects
|
398
|
+
@param text a string representing the text
|
399
|
+
@return a DOM DocumentFragment representing the resulting HTML
|
400
|
+
*/
|
401
|
+
function sh_insertTags(tags, text) {
|
402
|
+
var doc = document;
|
403
|
+
|
404
|
+
var result = document.createDocumentFragment();
|
405
|
+
var tagIndex = 0;
|
406
|
+
var numTags = tags.length;
|
407
|
+
var textPos = 0;
|
408
|
+
var textLength = text.length;
|
409
|
+
var currentNode = result;
|
410
|
+
|
411
|
+
// output one tag or text node every iteration
|
412
|
+
while (textPos < textLength || tagIndex < numTags) {
|
413
|
+
var tag;
|
414
|
+
var tagPos;
|
415
|
+
if (tagIndex < numTags) {
|
416
|
+
tag = tags[tagIndex];
|
417
|
+
tagPos = tag.pos;
|
418
|
+
}
|
419
|
+
else {
|
420
|
+
tagPos = textLength;
|
421
|
+
}
|
422
|
+
|
423
|
+
if (tagPos <= textPos) {
|
424
|
+
// output the tag
|
425
|
+
if (tag.node) {
|
426
|
+
// start tag
|
427
|
+
var newNode = tag.node;
|
428
|
+
currentNode.appendChild(newNode);
|
429
|
+
currentNode = newNode;
|
430
|
+
}
|
431
|
+
else {
|
432
|
+
// end tag
|
433
|
+
currentNode = currentNode.parentNode;
|
434
|
+
}
|
435
|
+
tagIndex++;
|
436
|
+
}
|
437
|
+
else {
|
438
|
+
// output text
|
439
|
+
currentNode.appendChild(doc.createTextNode(text.substring(textPos, tagPos)));
|
440
|
+
textPos = tagPos;
|
441
|
+
}
|
442
|
+
}
|
443
|
+
|
444
|
+
return result;
|
445
|
+
}
|
446
|
+
|
447
|
+
/**
|
448
|
+
Highlights an element containing source code. Upon completion of this function,
|
449
|
+
the element will have been placed in the "sh_sourceCode" class.
|
450
|
+
@param element a DOM <pre> element containing the source code to be highlighted
|
451
|
+
@param language a language definition object
|
452
|
+
*/
|
453
|
+
function sh_highlightElement(element, language) {
|
454
|
+
sh_addClass(element, 'sh_sourceCode');
|
455
|
+
var originalTags = [];
|
456
|
+
var inputString = sh_extractTags(element, originalTags);
|
457
|
+
var highlightTags = sh_highlightString(inputString, language);
|
458
|
+
var tags = sh_mergeTags(originalTags, highlightTags);
|
459
|
+
var documentFragment = sh_insertTags(tags, inputString);
|
460
|
+
while (element.hasChildNodes()) {
|
461
|
+
element.removeChild(element.firstChild);
|
462
|
+
}
|
463
|
+
element.appendChild(documentFragment);
|
464
|
+
}
|
465
|
+
|
466
|
+
function sh_getXMLHttpRequest() {
|
467
|
+
if (window.ActiveXObject) {
|
468
|
+
return new ActiveXObject('Msxml2.XMLHTTP');
|
469
|
+
}
|
470
|
+
else if (window.XMLHttpRequest) {
|
471
|
+
return new XMLHttpRequest();
|
472
|
+
}
|
473
|
+
throw 'No XMLHttpRequest implementation available';
|
474
|
+
}
|
475
|
+
|
476
|
+
function sh_load(language, element, prefix, suffix) {
|
477
|
+
if (language in sh_requests) {
|
478
|
+
sh_requests[language].push(element);
|
479
|
+
return;
|
480
|
+
}
|
481
|
+
sh_requests[language] = [element];
|
482
|
+
var request = sh_getXMLHttpRequest();
|
483
|
+
var url = prefix + 'sh_' + language + suffix;
|
484
|
+
request.open('GET', url, true);
|
485
|
+
request.onreadystatechange = function () {
|
486
|
+
if (request.readyState === 4) {
|
487
|
+
try {
|
488
|
+
if (! request.status || request.status === 200) {
|
489
|
+
eval(request.responseText);
|
490
|
+
var elements = sh_requests[language];
|
491
|
+
for (var i = 0; i < elements.length; i++) {
|
492
|
+
sh_highlightElement(elements[i], sh_languages[language]);
|
493
|
+
}
|
494
|
+
}
|
495
|
+
else {
|
496
|
+
throw 'HTTP error: status ' + request.status;
|
497
|
+
}
|
498
|
+
}
|
499
|
+
finally {
|
500
|
+
request = null;
|
501
|
+
}
|
502
|
+
}
|
503
|
+
};
|
504
|
+
request.send(null);
|
505
|
+
}
|
506
|
+
|
507
|
+
/**
|
508
|
+
Highlights all elements containing source code on the current page. Elements
|
509
|
+
containing source code must be "pre" elements with a "class" attribute of
|
510
|
+
"sh_LANGUAGE", where LANGUAGE is a valid language identifier; e.g., "sh_java"
|
511
|
+
identifies the element as containing "java" language source code.
|
512
|
+
*/
|
513
|
+
function sh_highlightDocument(prefix, suffix) {
|
514
|
+
var nodeList = document.getElementsByTagName('pre');
|
515
|
+
for (var i = 0; i < nodeList.length; i++) {
|
516
|
+
var element = nodeList.item(i);
|
517
|
+
var htmlClasses = sh_getClasses(element);
|
518
|
+
if (_.include(htmlClasses, 'sh_sourceCode')) {
|
519
|
+
continue;
|
520
|
+
}
|
521
|
+
for (var j = 0; j < htmlClasses.length; j++) {
|
522
|
+
var htmlClass = htmlClasses[j].toLowerCase();
|
523
|
+
if (htmlClass === 'sh_sourcecode') {
|
524
|
+
continue;
|
525
|
+
}
|
526
|
+
if (htmlClass.substr(0, 3) === 'sh_') {
|
527
|
+
var language = htmlClass.substring(3);
|
528
|
+
if (language in sh_languages) {
|
529
|
+
sh_highlightElement(element, sh_languages[language]);
|
530
|
+
}
|
531
|
+
else if (typeof(prefix) === 'string' && typeof(suffix) === 'string') {
|
532
|
+
sh_load(language, element, prefix, suffix);
|
533
|
+
}
|
534
|
+
else {
|
535
|
+
throw 'Found <pre> element with class="' + htmlClass + '", but no such language exists';
|
536
|
+
}
|
537
|
+
break;
|
538
|
+
}
|
539
|
+
}
|
540
|
+
}
|
541
|
+
}
|
542
|
+
|
543
|
+
if(!this.sh_languages){this.sh_languages={}}sh_languages.sql=[[[/\b(?:VARCHAR|TINYINT|TEXT|DATE|SMALLINT|MEDIUMINT|INT|BIGINT|FLOAT|DOUBLE|DECIMAL|DATETIME|TIMESTAMP|TIME|YEAR|UNSIGNED|CHAR|TINYBLOB|TINYTEXT|BLOB|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT|ENUM|BOOL|BINARY|VARBINARY)\b/gi,"sh_type",-1],[/\b(?:ALL|ASC|AS|ALTER|AND|ADD|AUTO_INCREMENT|BETWEEN|BINARY|BOTH|BY|BOOLEAN|CHANGE|CHECK|COLUMNS|COLUMN|CROSS|CREATE|DATABASES|DATABASE|DATA|DELAYED|DESCRIBE|DESC|DISTINCT|DELETE|DROP|DEFAULT|ENCLOSED|ESCAPED|EXISTS|EXPLAIN|FIELDS|FIELD|FLUSH|FOR|FOREIGN|FUNCTION|FROM|GROUP|GRANT|HAVING|IGNORE|INDEX|INFILE|INSERT|INNER|INTO|IDENTIFIED|IN|IS|IF|JOIN|KEYS|KILL|KEY|LEADING|LIKE|LIMIT|LINES|LOAD|LOCAL|LOCK|LOW_PRIORITY|LEFT|LANGUAGE|MODIFY|NATURAL|NOT|NULL|NEXTVAL|OPTIMIZE|OPTION|OPTIONALLY|ORDER|OUTFILE|OR|OUTER|ON|PROCEDURE|PROCEDURAL|PRIMARY|READ|REFERENCES|REGEXP|RENAME|REPLACE|RETURN|REVOKE|RLIKE|RIGHT|SHOW|SONAME|STATUS|STRAIGHT_JOIN|SELECT|SETVAL|SET|TABLES|TERMINATED|TO|TRAILING|TRUNCATE|TABLE|TEMPORARY|TRIGGER|TRUSTED|UNIQUE|UNLOCK|USE|USING|UPDATE|VALUES|VARIABLES|VIEW|WITH|WRITE|WHERE|ZEROFILL|TYPE|XOR)\b/gi,"sh_keyword",-1],[/"/g,"sh_string",1],[/'/g,"sh_string",2],[/`/g,"sh_string",3],[/#/g,"sh_comment",4],[/\/\/\//g,"sh_comment",5],[/\/\//g,"sh_comment",4],[/\/\*\*/g,"sh_comment",11],[/\/\*/g,"sh_comment",12],[/--/g,"sh_comment",4],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1]],[[/"/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/'/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/`/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/$/g,null,-2]],[[/$/g,null,-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",6,1],[/<!DOCTYPE/g,"sh_preproc",8,1],[/<!--/g,"sh_comment",9],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",10,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",10,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",9]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",6,1],[/<!DOCTYPE/g,"sh_preproc",8,1],[/<!--/g,"sh_comment",9],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",10,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",10,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)|(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]]];
|