better_errors 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of better_errors might be problematic. Click here for more details.

data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails in any Rack app as Rack middleware.
4
4
 
5
- ![image](http://i.imgur.com/urVDW.png)
5
+ ![image](http://i.imgur.com/zYOXF.png)
6
6
 
7
7
  ## Features
8
8
 
@@ -23,7 +23,7 @@ module BetterErrors
23
23
  end
24
24
 
25
25
  def source_unavailable
26
- "<p>Source unavailable</p>"
26
+ "<p class='unavailable'>Source unavailable</p>"
27
27
  end
28
28
 
29
29
  def coderay_scanner
@@ -4,7 +4,7 @@ module BetterErrors
4
4
  idx_offset = 0
5
5
  list = exception.backtrace.each_with_index.map do |frame, idx|
6
6
  frame_binding = exception.__better_errors_bindings_stack[idx - idx_offset]
7
- md = /\A(?<file>.*):(?<line>\d*):in `(?<name>.*)'\z/.match(frame)
7
+ md = /\A(?<file>.*):(?<line>\d*)(:in `(?<name>.*)')?\z/.match(frame)
8
8
 
9
9
  # prevent mismatching frames in the backtrace with the binding stack
10
10
  if frame_binding and frame_binding.eval("__FILE__") != md[:file]
@@ -53,6 +53,14 @@ module BetterErrors
53
53
  end
54
54
  end
55
55
  end
56
+
57
+ def class_name
58
+ @class_name
59
+ end
60
+
61
+ def method_name
62
+ @method_name || @name
63
+ end
56
64
 
57
65
  def context
58
66
  if application?
@@ -99,12 +107,14 @@ module BetterErrors
99
107
  def set_pretty_method_name
100
108
  name =~ /\A(block (\([^)]+\) )?in )?/
101
109
  recv = frame_binding.eval("self")
102
- return unless method = frame_binding.eval("__method__")
103
- @name = if recv.is_a? Module
104
- "#{$1}#{recv}.#{method}"
105
- else
106
- "#{$1}#{recv.class}##{method}"
107
- end
110
+ return unless method_name = frame_binding.eval("__method__")
111
+ if recv.is_a? Module
112
+ @class_name = "#{$1}#{recv}"
113
+ @method_name = ".#{method_name}"
114
+ else
115
+ @class_name = "#{$1}#{recv.class}"
116
+ @method_name = "##{method_name}"
117
+ end
108
118
  end
109
119
 
110
120
  def starts_with?(haystack, needle)
@@ -3,264 +3,722 @@
3
3
  <head>
4
4
  <title><%= exception.class %> at <%= request_path %></title>
5
5
  <style>
6
+ /* Basic reset */
6
7
  * {
7
- margin:0;
8
- padding:0;
8
+ margin: 0;
9
+ padding: 0;
9
10
  }
11
+
12
+ table {
13
+ width: 100%;
14
+ border-collapse: collapse;
15
+ }
16
+
17
+ th, td {
18
+ vertical-align: top;
19
+ text-align: left;
20
+ }
21
+
22
+ textarea {
23
+ resize: none;
24
+ }
25
+
10
26
  body {
11
- font-family:Verdana, sans-serif;
12
- margin:0;
13
- font-size:13px;
14
- }
15
- header {
16
- padding:32px 32px;
17
- border-bottom:1px solid #e64c38;
18
- background-color: #ffe5e7;
19
- background-image: -webkit-gradient(linear, left top, left bottom, from(#ffe5e7), to(#ffb2b8)); /* Safari 4+, Chrome */
20
- background-image: -webkit-linear-gradient(top, #ffe5e7, #ffb2b8); /* Chrome 10+, Safari 5.1+, iOS 5+ */
21
- background-image: -moz-linear-gradient(top, #ffe5e7, #ffb2b8); /* Firefox 3.6-15 */
22
- background-image: -o-linear-gradient(top, #ffe5e7, #ffb2b8); /* Opera 11.10-12.00 */
23
- background-image: linear-gradient(to bottom, #ffe5e7, #ffb2b8); /* Firefox 16+, IE10, Opera 12.50+ */
24
- }
25
- h2 {
26
- font-weight:normal;
27
- margin:0;
28
- margin-bottom:16px;
29
- }
30
- h2 span {
31
- color:#666666;
32
- }
33
- header table {
34
- border-collapse:collapse;
35
- }
36
- header table th {
37
- text-align:right;
38
- font-weight:bold;
39
- padding-right:12px;
40
- }
41
- header table th, header table td {
42
- padding:4px 6px;
43
- }
44
- nav {
45
- display:block;
46
- padding:12px 12px;
47
- border-bottom:1px solid #000000;
48
- background-color: #444444;
49
- background-image: -webkit-gradient(linear, left top, left bottom, from(#444444), to(#222222)); /* Safari 4+, Chrome */
50
- background-image: -webkit-linear-gradient(top, #444444, #222222); /* Chrome 10+, Safari 5.1+, iOS 5+ */
51
- background-image: -moz-linear-gradient(top, #444444, #222222); /* Firefox 3.6-15 */
52
- background-image: -o-linear-gradient(top, #444444, #222222); /* Opera 11.10-12.00 */
53
- background-image: linear-gradient(to bottom, #444444, #222222); /* Firefox 16+, IE10, Opera 12.50+ */
54
- }
55
- nav a {
56
- color:#ffffff;
57
- text-decoration:none;
58
- padding:4px 16px;
59
- border-radius:16px;
60
- }
61
- nav a:hover {
62
- background-color: #666666;
63
- background-image: -webkit-gradient(linear, left top, left bottom, from(#666666), to(#444444)); /* Safari 4+, Chrome */
64
- background-image: -webkit-linear-gradient(top, #666666, #444444); /* Chrome 10+, Safari 5.1+, iOS 5+ */
65
- background-image: -moz-linear-gradient(top, #666666, #444444); /* Firefox 3.6-15 */
66
- background-image: -o-linear-gradient(top, #666666, #444444); /* Opera 11.10-12.00 */
67
- background-image: linear-gradient(to bottom, #666666, #444444); /* Firefox 16+, IE10, Opera 12.50+ */
68
- }
69
- nav a.selected {
70
- color:#000000;
71
- background-color: #efefef;
72
- background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#cfcfcf)); /* Safari 4+, Chrome */
73
- background-image: -webkit-linear-gradient(top, #efefef, #cfcfcf); /* Chrome 10+, Safari 5.1+, iOS 5+ */
74
- background-image: -moz-linear-gradient(top, #efefef, #cfcfcf); /* Firefox 3.6-15 */
75
- background-image: -o-linear-gradient(top, #efefef, #cfcfcf); /* Opera 11.10-12.00 */
76
- background-image: linear-gradient(to bottom, #efefef, #cfcfcf); /* Firefox 16+, IE10, Opera 12.50+ */
77
- }
78
- .frames {
79
- width:50%;
80
- float:left;
81
- }
82
- .frames li {
83
- list-style:none;
84
- display:block;
85
- padding:12px;
86
- overflow:hidden;
87
- cursor:pointer;
88
- background-color: #f4f7ff;
89
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f4f7ff), to(#e4ebfe)); /* Safari 4+, Chrome */
90
- background-image: -webkit-linear-gradient(top, #f4f7ff, #e4ebfe); /* Chrome 10+, Safari 5.1+, iOS 5+ */
91
- background-image: -moz-linear-gradient(top, #f4f7ff, #e4ebfe); /* Firefox 3.6-15 */
92
- background-image: -o-linear-gradient(top, #f4f7ff, #e4ebfe); /* Opera 11.10-12.00 */
93
- background-image: linear-gradient(to bottom, #f4f7ff, #e4ebfe); /* Firefox 16+, IE10, Opera 12.50+ */
94
- border-bottom:1px solid #cccccc;
95
- }
96
- .frames li:hover, .frames li.selected {
97
- background-color: #e4ebfe;
98
- background-image: -webkit-gradient(linear, left top, left bottom, from(#e4ebfe), to(#c2d3fe)); /* Safari 4+, Chrome */
99
- background-image: -webkit-linear-gradient(top, #e4ebfe, #c2d3fe); /* Chrome 10+, Safari 5.1+, iOS 5+ */
100
- background-image: -moz-linear-gradient(top, #e4ebfe, #c2d3fe); /* Firefox 3.6-15 */
101
- background-image: -o-linear-gradient(top, #e4ebfe, #c2d3fe); /* Opera 11.10-12.00 */
102
- background-image: linear-gradient(to bottom, #e4ebfe, #c2d3fe); /* Firefox 16+, IE10, Opera 12.50+ */
103
- }
104
- .frames .name, .frame_info h2.name {
105
- font-family:Monaco, Incosolata, Consolas, monospace;
106
- font-size:14px;
107
- margin-bottom:4px;
108
- word-wrap:break-word;
109
- }
110
- .location {
111
- color:#888888;
112
- }
113
- .location .filename, .location .line {
114
- color:#333333;
115
- }
116
- .frame_info {
117
- background-color:#efefef;
118
- border-bottom:1px solid #cccccc;
119
- float:left;
120
- width:50%;
121
- }
122
- .frame_info > * {
123
- margin:16px;
124
- }
125
- .frame_info h2 {
126
- font-family:Monaco, Incosolata, Consolas, monospace;
127
- }
128
- .frame_info .code {
129
- font-family:Monaco, Incosolata, Consolas, monospace;
130
- background-color:#ffffff;
131
- border:1px solid #cccccc;
132
- border-collapse:collapse;
133
- overflow:auto;
134
- }
135
- .frame_info .code pre:nth-child(2n+1) {
136
- background-color:#f9f9f9;
137
- }
138
- .frame_info .code pre:nth-child(2n) {
139
- background-color:#f3f3f3;
140
- }
141
- .frame_info .code pre.highlight {
142
- background-color:#ffeaaa;
143
- }
144
- .frame_info .code .line {
145
- text-align:right;
146
- padding-right:12px;
147
- padding-left:0px;
148
- }
149
- code {
150
- background-color:#f0f0f0;
151
- padding:2px 4px;
152
- border:1px solid #d0d0d0;
153
- }
154
- h3 {
155
- font-weight:normal;
156
- border-top:1px solid #cccccc;
157
- padding-top:16px;
158
- margin-bottom:16px;
159
- }
160
- .var_table {
161
- border-collapse:collapse;
162
- }
163
- .var_table td {
164
- padding:8px;
165
- }
166
- .var_table td.name {
167
- font-style:italic;
168
- }
169
- .var_table tr {
170
- border-bottom:1px solid #cccccc;
171
- }
172
- .repl .console {
173
- background-color:#ffffff;
174
- padding:2px 4px;
175
- border:1px solid #d0d0d0;
176
- margin-bottom:8px;
177
- font-family:monospace;
178
- }
179
- .repl pre {
180
- font-size:12px;
181
- white-space:pre-wrap;
182
- max-height:400px;
183
- overflow:auto;
184
- }
185
- .repl .prompt {
186
- font-size:12px;
187
- position:relative;
188
- }
189
- .repl input {
190
- font-size:12px;
191
- border:none;
192
- font-family:monospace;
193
- outline:none;
194
- padding:0px;
195
- position:absolute;
196
- left:20px;
197
- right:0px;
27
+ font-size: 10pt;
28
+ }
29
+
30
+ body, td, input, textarea {
31
+ font-family: helvetica neue, lucida grande, sans-serif;
32
+ line-height: 1.5;
33
+ color: #333;
34
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
35
+ }
36
+
37
+ html {
38
+ background: #f0f0f5;
39
+ }
40
+
41
+ /* ---------------------------------------------------------------------
42
+ * Basic layout
43
+ * --------------------------------------------------------------------- */
44
+
45
+ /* Small */
46
+ @media screen and (max-width: 1100px) {
47
+ html {
48
+ overflow-y: scroll;
49
+ }
50
+
51
+ body {
52
+ margin: 0 20px;
53
+ }
54
+
55
+ header.exception {
56
+ margin: 0 -20px;
57
+ }
58
+
59
+ nav.sidebar {
60
+ padding: 0;
61
+ margin: 20px 0;
62
+ }
63
+
64
+ ul.frames {
65
+ max-height: 200px;
66
+ overflow: auto;
67
+ }
68
+ }
69
+
70
+ /* Wide */
71
+ @media screen and (min-width: 1100px) {
72
+ header.exception {
73
+ position: fixed;
74
+ top: 0;
75
+ left: 0;
76
+ right: 0;
77
+ }
78
+
79
+ nav.sidebar,
80
+ .frame_info {
81
+ position: fixed;
82
+ top: 95px;
83
+ bottom: 0;
84
+
85
+ box-sizing: border-box;
86
+
87
+ overflow-y: auto;
88
+ overflow-x: hidden;
89
+ }
90
+
91
+ nav.sidebar {
92
+ width: 40%;
93
+ left: 20px;
94
+ top: 115px;
95
+ bottom: 20px;
96
+ }
97
+
98
+ .frame_info {
99
+ right: 0;
100
+ left: 40%;
101
+
102
+ padding: 20px;
103
+ padding-left: 10px;
104
+ margin-left: 30px;
105
+ }
106
+ }
107
+
108
+ nav.sidebar {
109
+ background: #d3d3da;
110
+ border-top: solid 3px #a33;
111
+ border-bottom: solid 3px #a33;
112
+ border-radius: 4px;
113
+ box-shadow: 0 0 6px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
114
+ }
115
+
116
+ /* ---------------------------------------------------------------------
117
+ * Header
118
+ * --------------------------------------------------------------------- */
119
+
120
+ header.exception {
121
+ padding: 18px 20px;
122
+
123
+ height: 59px;
124
+ min-height: 59px;
125
+
126
+ overflow: hidden;
127
+
128
+ background-color: #20202a;
129
+ color: #aaa;
130
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
131
+ font-weight: 200;
132
+ box-shadow: inset 0 -5px 3px -3px rgba(0, 0, 0, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
133
+
134
+ -webkit-text-smoothing: antialiased;
135
+ }
136
+
137
+ /* Heading */
138
+ header.exception h2 {
139
+ font-weight: 200;
140
+ font-size: 11pt;
141
+ }
142
+
143
+ header.exception h2,
144
+ header.exception p {
145
+ line-height: 1.4em;
146
+ height: 1.4em;
147
+ overflow: hidden;
148
+ white-space: pre;
149
+ text-overflow: ellipsis;
150
+ }
151
+
152
+ header.exception h2 strong {
153
+ font-weight: 700;
154
+ color: #d55;
155
+ }
156
+
157
+ header.exception p {
158
+ font-weight: 200;
159
+ font-size: 20pt;
160
+ color: white;
161
+ }
162
+
163
+ header.exception:hover {
164
+ height: auto;
165
+ z-index: 2;
166
+ }
167
+
168
+ header.exception:hover h2,
169
+ header.exception:hover p {
170
+ padding-right: 20px;
171
+ overflow-y: auto;
172
+ word-wrap: break-word;
173
+ height: auto;
174
+ max-height: 7em;
175
+ }
176
+
177
+ @media screen and (max-width: 1100px) {
178
+ header.exception {
179
+ height: auto;
180
+ }
181
+
182
+ header.exception h2,
183
+ header.exception p {
184
+ padding-right: 20px;
185
+ overflow-y: auto;
186
+ word-wrap: break-word;
187
+ height: auto;
188
+ max-height: 7em;
189
+ }
190
+ }
191
+
192
+ <%#
193
+ /* Light theme */
194
+ header.exception {
195
+ text-shadow: 0 1px 0 rgba(250, 250, 250, 0.6);
196
+ background: rgba(200,100,50,0.10);
197
+ color: #977;
198
+ }
199
+ header.exception h2 strong {
200
+ color: #533;
201
+ }
202
+ header.exception p {
203
+ color: #744;
204
+ }
205
+ %>
206
+
207
+ /* ---------------------------------------------------------------------
208
+ * Navigation
209
+ * --------------------------------------------------------------------- */
210
+
211
+ nav.tabs {
212
+ border-bottom: solid 1px #ddd;
213
+
214
+ background-color: #eee;
215
+ text-align: center;
216
+
217
+ padding: 6px;
218
+
219
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
220
+ }
221
+
222
+ nav.tabs a {
223
+ display: inline-block;
224
+
225
+ height: 22px;
226
+ line-height: 22px;
227
+ padding: 0 10px;
228
+
229
+ text-decoration: none;
230
+ font-size: 8pt;
231
+ font-weight: bold;
232
+
233
+ color: #999;
234
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
235
+ }
236
+
237
+ nav.tabs a.selected {
238
+ color: white;
239
+ background: rgba(0, 0, 0, 0.5);
240
+ border-radius: 16px;
241
+ box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.1);
242
+ text-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.4);
243
+ }
244
+
245
+ /* ---------------------------------------------------------------------
246
+ * Sidebar
247
+ * --------------------------------------------------------------------- */
248
+
249
+ ul.frames {
250
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
251
+ }
252
+
253
+ /* Each item */
254
+ ul.frames li {
255
+ background-color: #f8f8f8;
256
+ background: -webkit-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
257
+ background: -moz-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
258
+ background: linear-gradient(top, #f8f8f8 80%, #f0f0f0);
259
+ box-shadow: inset 0 -1px 0 #e2e2e2;
260
+ padding: 7px 20px;
261
+
262
+ cursor: pointer;
263
+ overflow: hidden;
264
+ }
265
+
266
+ ul.frames .name,
267
+ ul.frames .location {
268
+ overflow: hidden;
269
+ height: 1.5em;
270
+
271
+ white-space: nowrap;
272
+ word-wrap: none;
273
+ text-overflow: ellipsis;
274
+ }
275
+
276
+ ul.frames .method {
277
+ color: #966;
278
+ }
279
+
280
+ ul.frames .location {
281
+ font-size: 0.85em;
282
+ font-weight: 400;
283
+ color: #999;
284
+ }
285
+
286
+ ul.frames .line {
287
+ font-weight: bold;
288
+ }
289
+
290
+ /* Selected frame */
291
+ ul.frames li.selected {
292
+ background: #38a;
293
+ box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), inset 0 2px 0 rgba(255, 255, 255, 0.01), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
294
+ }
295
+
296
+ ul.frames li.selected .name,
297
+ ul.frames li.selected .method,
298
+ ul.frames li.selected .location {
299
+ color: white;
300
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
301
+ }
302
+
303
+ ul.frames li.selected .location {
304
+ opacity: 0.6;
305
+ }
306
+
307
+ /* Iconography */
308
+ ul.frames li {
309
+ padding-left: 60px;
310
+ position: relative;
311
+ }
312
+
313
+ ul.frames li .icon {
314
+ display: block;
315
+ width: 20px;
316
+ height: 20px;
317
+ line-height: 20px;
318
+ border-radius: 15px;
319
+
320
+ text-align: center;
321
+
322
+ background: white;
323
+ border: solid 2px #ccc;
324
+
325
+ font-size: 9pt;
326
+ font-weight: 200;
327
+ font-style: normal;
328
+
329
+ position: absolute;
330
+ top: 14px;
331
+ left: 20px;
332
+ }
333
+
334
+ ul.frames .icon.application {
335
+ background: #808090;
336
+ border-color: #555;
337
+ }
338
+
339
+ ul.frames .icon.application:before {
340
+ content: 'A';
341
+ color: white;
342
+ text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
198
343
  }
344
+
345
+ /* Responsiveness -- flow to single-line mode */
346
+ @media screen and (max-width: 1100px) {
347
+ ul.frames li {
348
+ padding-top: 6px;
349
+ padding-bottom: 6px;
350
+ padding-left: 36px;
351
+ line-height: 1.3;
352
+ }
353
+
354
+ ul.frames li .icon {
355
+ width: 11px;
356
+ height: 11px;
357
+ line-height: 11px;
358
+
359
+ top: 7px;
360
+ left: 10px;
361
+ font-size: 5pt;
362
+ }
363
+
364
+ ul.frames .name,
365
+ ul.frames .location {
366
+ display: inline-block;
367
+ line-height: 1.3;
368
+ height: 1.3em;
369
+ }
370
+
371
+ ul.frames .name {
372
+ margin-right: 10px;
373
+ }
374
+ }
375
+
376
+ /* ---------------------------------------------------------------------
377
+ * Monospace
378
+ * --------------------------------------------------------------------- */
379
+
380
+ pre, code, .repl input, .repl .prompt span, textarea {
381
+ font-family: menlo, lucida console, monospace;
382
+ font-size: 8pt;
383
+ }
384
+
385
+ /* ---------------------------------------------------------------------
386
+ * Display area
387
+ * --------------------------------------------------------------------- */
388
+
389
+ .trace_info {
390
+ background: #fff;
391
+ padding: 6px;
392
+ border-radius: 3px;
393
+ margin-bottom: 2px;
394
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.03), 1px 1px 0 rgba(0, 0, 0, 0.05), -1px 1px 0 rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(0, 0, 0, 0.04);
395
+ }
396
+
397
+ /* Titlebar */
398
+ .trace_info .title {
399
+ background: #f1f1f1;
400
+
401
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
402
+ overflow: hidden;
403
+ padding: 6px 10px;
404
+
405
+ border: solid 1px #ccc;
406
+ border-bottom: 0;
407
+
408
+ border-top-left-radius: 2px;
409
+ border-top-right-radius: 2px;
410
+ }
411
+
412
+ .trace_info .title .name,
413
+ .trace_info .title .location {
414
+ font-size: 9pt;
415
+ line-height: 26px;
416
+ height: 26px;
417
+ overflow: hidden;
418
+ }
419
+
420
+ .trace_info .title .location {
421
+ float: left;
422
+ font-weight: bold;
423
+ font-size: 10pt;
424
+ }
425
+
426
+ .trace_info .title .name {
427
+ float: right;
428
+ font-weight: 200;
429
+ }
430
+
431
+ .code, .console, .unavailable {
432
+ background: #fff;
433
+ padding: 5px;
434
+
435
+ box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
436
+ }
437
+
438
+ .code {
439
+ margin-bottom: -1px;
440
+ }
441
+
442
+ .code {
443
+ padding: 10px 0;
444
+ overflow: auto;
445
+ }
446
+
447
+ /* Source unavailable */
448
+ p.unavailable {
449
+ padding: 20px 0 40px 0;
450
+ text-align: center;
451
+ color: #b99;
452
+ font-weight: bold;
453
+ }
454
+
455
+ p.unavailable:before {
456
+ content: '\00d7';
457
+ display: block;
458
+
459
+ color: #daa;
460
+
461
+ text-align: center;
462
+ font-size: 40pt;
463
+ font-weight: normal;
464
+ margin-bottom: -10px;
465
+ }
466
+
467
+ @-webkit-keyframes highlight {
468
+ 0% { background: rgba(220, 30, 30, 0.3); }
469
+ 100% { background: rgba(220, 30, 30, 0.1); }
470
+ }
471
+ @-moz-keyframes highlight {
472
+ 0% { background: rgba(220, 30, 30, 0.3); }
473
+ 100% { background: rgba(220, 30, 30, 0.1); }
474
+ }
475
+ @keyframes highlight {
476
+ 0% { background: rgba(220, 30, 30, 0.3); }
477
+ 100% { background: rgba(220, 30, 30, 0.1); }
478
+ }
479
+
480
+ .code .highlight {
481
+ background: rgba(220, 30, 30, 0.1);
482
+ -webkit-animation: highlight 400ms linear 1;
483
+ -moz-animation: highlight 400ms linear 1;
484
+ animation: highlight 400ms linear 1;
485
+ }
486
+
487
+ /* REPL shell */
488
+ .console {
489
+ padding: 0 1px 10px 1px;
490
+ border-bottom-left-radius: 2px;
491
+ border-bottom-right-radius: 2px;
492
+ }
493
+
494
+ .console pre {
495
+ padding: 10px 10px 0 10px;
496
+ max-height: 200px;
497
+ overflow-x: none;
498
+ overflow-y: auto;
499
+ margin-bottom: -3px;
500
+ word-wrap: break-word;
501
+ white-space: pre-wrap;
502
+ }
503
+
504
+ /* .prompt > span + input */
505
+ .console .prompt {
506
+ display: table;
507
+ width: 100%;
508
+ }
509
+
510
+ .console .prompt span,
511
+ .console .prompt input {
512
+ display: table-cell;
513
+ }
514
+
515
+ .console .prompt span {
516
+ width: 1%;
517
+ padding-right: 5px;
518
+ padding-left: 10px;
519
+ }
520
+
521
+ .console .prompt input {
522
+ width: 99%;
523
+ }
524
+
525
+ /* Input box */
526
+ .console input,
527
+ .console input:focus {
528
+ outline: 0;
529
+ border: 0;
530
+ padding: 0;
531
+ background: transparent;
532
+ margin: 0;
533
+ }
534
+
535
+ /* Hint text */
536
+ .hint {
537
+ margin: 15px 0 20px 0;
538
+ font-size: 8pt;
539
+ color: #8080a0;
540
+ padding-left: 20px;
541
+ }
542
+
543
+ .hint:before {
544
+ content: '\25b2';
545
+ margin-right: 5px;
546
+ opacity: 0.5;
547
+ }
548
+
549
+ /* ---------------------------------------------------------------------
550
+ * Variable infos
551
+ * --------------------------------------------------------------------- */
552
+
553
+ .sub {
554
+ padding: 10px 0;
555
+ margin: 10px 0;
556
+ }
557
+
558
+ .sub:before {
559
+ content: '';
560
+ display: block;
561
+ width: 100%;
562
+ height: 4px;
563
+
564
+ border-radius: 2px;
565
+ background: rgba(0, 150, 200, 0.05);
566
+ box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04), inset 2px 2px 2px rgba(0, 0, 0, 0.07);
567
+ }
568
+
569
+ .sub h3 {
570
+ color: #39a;
571
+ font-size: 1.1em;
572
+ margin: 10px 0;
573
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
574
+
575
+ -webkit-font-smoothing: antialiased;
576
+ }
577
+
578
+ .sub .inset {
579
+ overflow-y: auto;
580
+ }
581
+
582
+ .sub table {
583
+ table-layout: fixed;
584
+ }
585
+
586
+ .sub table td {
587
+ border-top: dotted 1px #ddd;
588
+ padding: 7px 1px;
589
+ }
590
+
591
+ .sub table td.name {
592
+ width: 150px;
593
+
594
+ font-weight: bold;
595
+ font-size: 0.8em;
596
+ padding-right: 20px;
597
+ }
598
+
599
+ .sub table td pre {
600
+ max-height: 15em;
601
+ overflow-y: auto;
602
+ }
603
+
604
+ .sub table td pre {
605
+ width: 100%;
606
+
607
+ word-wrap: break-word;
608
+ white-space: normal;
609
+ }
610
+
611
+ /* ---------------------------------------------------------------------
612
+ * Scrollbar
613
+ * --------------------------------------------------------------------- */
614
+
615
+ nav.sidebar::-webkit-scrollbar,
616
+ .inset pre::-webkit-scrollbar,
617
+ .console pre::-webkit-scrollbar,
618
+ .code::-webkit-scrollbar {
619
+ width: 10px;
620
+ height: 10px;
621
+ }
622
+
623
+ .inset pre::-webkit-scrollbar-thumb,
624
+ .console pre::-webkit-scrollbar-thumb,
625
+ .code::-webkit-scrollbar-thumb {
626
+ background: #ccc;
627
+ border-radius: 5px;
628
+ }
629
+
630
+ nav.sidebar::-webkit-scrollbar-thumb {
631
+ background: rgba(0, 0, 0, 0.0);
632
+ border-radius: 5px;
633
+ }
634
+
635
+ nav.sidebar:hover::-webkit-scrollbar-thumb {
636
+ background-color: #999;
637
+ background: -webkit-linear-gradient(left, #aaa, #999);
638
+ }
639
+
640
+ .console pre:hover::-webkit-scrollbar-thumb,
641
+ .inset pre:hover::-webkit-scrollbar-thumb,
642
+ .code:hover::-webkit-scrollbar-thumb {
643
+ background: #888;
644
+ }
645
+
646
+
199
647
  </style>
200
648
  </head>
201
649
  <body>
202
- <header>
203
- <h2><%= exception.class %> <span>at <%= request_path %></span></h2>
204
- <table>
205
- <tr>
206
- <th>Message</th>
207
- <td><%= exception_message %></td>
208
- </tr>
209
- <% if backtrace_frames.any? %>
210
- <tr>
211
- <th>File</th>
212
- <td><%= backtrace_frames.first.filename %></td>
213
- </tr>
214
- <tr>
215
- <th>Line</th>
216
- <td><%= backtrace_frames.first.line %></td>
217
- </tr>
218
- <% end %>
219
- </table>
220
- </header>
221
- <nav>
222
- <a href="#" id="application_frames">Application Frames</a>
223
- <a href="#" id="all_frames">All Frames</a>
224
- </nav>
650
+ <div class='top'>
651
+ <header class="exception">
652
+ <h2><strong><%= exception.class %></strong> <span>at <%= request_path %></span></h2>
653
+ <p><%= exception_message %></p>
654
+ </header>
655
+ </div>
656
+
225
657
  <section class="backtrace">
226
- <ul class="frames">
227
- <% backtrace_frames.each_with_index do |frame, index| %>
228
- <li
229
- data-context="<%= frame.context %>"
230
- data-full-filename="<%= frame.filename %>"
231
- data-filename="<%= frame.pretty_path %>"
232
- data-line="<%= frame.line %>"
233
- data-name="<%= frame.name %>"
234
- data-index="<%= index %>"
235
- >
236
- <div class="name"><%= frame.name %></div>
237
- <div class="location"><span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span></div>
238
- </li>
239
- <% end %>
240
- </ul>
658
+ <nav class="sidebar">
659
+ <nav class="tabs">
660
+ <a href="#" id="application_frames">Application Frames</a>
661
+ <a href="#" id="all_frames">All Frames</a>
662
+ </nav>
663
+ <ul class="frames">
664
+ <% backtrace_frames.each_with_index do |frame, index| %>
665
+ <li
666
+ class="<%= frame.context %>"
667
+ style="display: none"
668
+ data-context="<%= frame.context %>"
669
+ data-full-filename="<%= frame.filename %>"
670
+ data-filename="<%= frame.pretty_path %>"
671
+ data-line="<%= frame.line %>"
672
+ data-name="<%= frame.name %>"
673
+ data-index="<%= index %>"
674
+ >
675
+ <span class='stroke'></span>
676
+ <i class="icon <%= frame.context %>"></i>
677
+ <div class="info">
678
+ <div class="name">
679
+ <strong><%= frame.class_name %></strong><span class='method'><%= frame.method_name %></span>
680
+ </div>
681
+ <div class="location">
682
+ <span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span>
683
+ </div>
684
+ </div>
685
+ </li>
686
+ <% end %>
687
+ </ul>
688
+ </nav>
689
+
241
690
  <% backtrace_frames.each_with_index do |frame, index| %>
242
691
  <div class="frame_info" id="frame_info_<%= index %>" style="display:none;">
243
- <h2 class="name"><%= frame.name %></h2>
244
- <div class="location"><span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span></div>
245
- <%== highlighted_code_block frame %>
692
+ <header class="trace_info">
693
+ <div class="title">
694
+ <h2 class="name"><%= frame.name %></h2>
695
+ <div class="location"><span class="filename"><%= frame.pretty_path %></span></div>
696
+ </div>
697
+
698
+ <%== highlighted_code_block frame %>
246
699
 
247
- <% if BetterErrors.binding_of_caller_available? %>
248
- <% if frame.frame_binding %>
700
+ <% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
249
701
  <div class="repl">
250
- <h3>REPL</h3>
251
702
  <div class="console">
252
703
  <pre></pre>
253
704
  <div class="prompt"><span>&gt;&gt;</span> <input/></div>
254
705
  </div>
255
706
  </div>
256
-
257
- <div class="variable_info"></div>
258
707
  <% end %>
259
- <% else %>
260
- <h3>Advanced features unavailable</h3>
261
- <p class="error">
262
- You must add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
263
- </p>
708
+ </header>
709
+
710
+ <% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
711
+ <div class="hint">
712
+ This a live shell. Type in here.
713
+ </div>
714
+
715
+ <div class="variable_info"></div>
716
+ <% end %>
717
+
718
+ <% unless BetterErrors.binding_of_caller_available? %>
719
+ <div class="hint">
720
+ <strong>Tip:</strong> add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
721
+ </div>
264
722
  <% end %>
265
723
  </div>
266
724
  <% end %>
@@ -448,7 +906,11 @@
448
906
  })(i);
449
907
  }
450
908
 
451
- allFrames[0].click();
909
+ // Click the first application frame
910
+ (
911
+ document.querySelector(".frames li.application") ||
912
+ document.querySelector(".frames li")
913
+ ).click();
452
914
 
453
915
  var applicationFramesButton = document.getElementById("application_frames");
454
916
  var allFramesButton = document.getElementById("all_frames");
@@ -1,13 +1,21 @@
1
- <h3>Local Variables</h3>
2
- <table class="var_table">
3
- <% @frame.local_variables.each do |name, value| %>
4
- <tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
5
- <% end %>
6
- </table>
1
+ <div class="sub">
2
+ <h3>Local Variables</h3>
3
+ <div class='inset variables'>
4
+ <table class="var_table">
5
+ <% @frame.local_variables.each do |name, value| %>
6
+ <tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
7
+ <% end %>
8
+ </table>
9
+ </div>
10
+ </div>
7
11
 
8
- <h3>Instance Variables</h3>
9
- <table class="var_table">
10
- <% @frame.instance_variables.each do |name, value| %>
11
- <tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
12
- <% end %>
13
- </table>
12
+ <div class="sub">
13
+ <h3>Instance Variables</h3>
14
+ <div class="inset variables">
15
+ <table class="var_table">
16
+ <% @frame.instance_variables.each do |name, value| %>
17
+ <tr><td class="name"><%= name %></td><td><pre><%= value.inspect %></pre></td></tr>
18
+ <% end %>
19
+ </table>
20
+ </div>
21
+ </div>
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/better_errors.rb CHANGED
@@ -22,12 +22,12 @@ rescue LoadError => e
22
22
  BetterErrors.binding_of_caller_available = false
23
23
  end
24
24
 
25
- if BetterErrors.binding_of_caller_available?
26
- require "better_errors/core_ext/exception"
27
- else
25
+ unless BetterErrors.binding_of_caller_available?
28
26
  warn "BetterErrors: binding_of_caller gem unavailable, cannot display local variables on error pages."
29
27
  warn "Add 'binding_of_caller' to your Gemfile to make this warning go away."
30
28
  warn ""
31
29
  end
32
30
 
31
+ require "better_errors/core_ext/exception"
32
+
33
33
  require "better_errors/rails" if defined? Rails::Railtie
@@ -66,5 +66,19 @@ module BetterErrors
66
66
  frames.first.filename.should == "my_file.rb"
67
67
  frames.first.line.should == 123
68
68
  end
69
+
70
+ it "should not blow up if no method name is given" do
71
+ error = StandardError.new
72
+
73
+ error.stub!(:backtrace).and_return(["foo.rb:123"])
74
+ frames = StackFrame.from_exception(error)
75
+ frames.first.filename.should == "foo.rb"
76
+ frames.first.line.should == 123
77
+
78
+ error.stub!(:backtrace).and_return(["foo.rb:123: this is an error message"])
79
+ frames = StackFrame.from_exception(error)
80
+ frames.first.filename.should == "foo.rb"
81
+ frames.first.line.should == 123
82
+ end
69
83
  end
70
84
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -127,3 +127,4 @@ test_files:
127
127
  - spec/better_errors/stack_frame_spec.rb
128
128
  - spec/better_errors/support/my_source.rb
129
129
  - spec/spec_helper.rb
130
+ has_rdoc: