yeast 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 96089b359d4b02af7bacf71b6148a7f5d2035ebf
4
+ data.tar.gz: 7e53269a950a4d111f83947878046c9e70a6e789
5
+ SHA512:
6
+ metadata.gz: 838701c38c6699dd26d72d23e053159d70ddebdea7709218f41dee71bc2b602baf030abbd25cf071c07e7841afd1d77a6ff9d2499a48c574b10d84761b6c1d97
7
+ data.tar.gz: bf8c953f9e8b511cefbd70184ffec9bcc33481aa8456cb0560ae218654c5c2d552f1452fd86c51bad70ab9a11bec71298ee8ee4c67335b9cddb27dfcf4847073
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in yeast.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Chris Oliver
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Yeast
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'yeast'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install yeast
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/yeast/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,13 @@
1
+ require "yeast/version"
2
+
3
+ require "better_errors"
4
+ require "binding_of_caller"
5
+
6
+ module BetterErrors
7
+ # @private
8
+ class ErrorPage
9
+ def self.template_path(template_name)
10
+ File.expand_path("../yeast/templates/#{template_name}.erb", __FILE__)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,1031 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= exception.type %> at <%= request_path %></title>
5
+ </head>
6
+ <body>
7
+ <%# Stylesheets are placed in the <body> for Turbolinks compatibility. %>
8
+ <style>
9
+ /* Basic reset */
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ table {
16
+ width: 100%;
17
+ border-collapse: collapse;
18
+ }
19
+
20
+ th, td {
21
+ vertical-align: top;
22
+ text-align: left;
23
+ }
24
+
25
+ textarea {
26
+ resize: none;
27
+ }
28
+
29
+ body {
30
+ font-size: 10pt;
31
+ }
32
+
33
+ body, td, input, textarea {
34
+ font-family: helvetica neue, lucida grande, sans-serif;
35
+ line-height: 1.5;
36
+ color: #333;
37
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
38
+ }
39
+
40
+ html {
41
+ background: #f0f0f5;
42
+ }
43
+
44
+ .clearfix::after{
45
+ clear: both;
46
+ content: ".";
47
+ display: block;
48
+ height: 0;
49
+ visibility: hidden;
50
+ }
51
+
52
+ /* ---------------------------------------------------------------------
53
+ * Basic layout
54
+ * --------------------------------------------------------------------- */
55
+
56
+ /* Small */
57
+ @media screen and (max-width: 1100px) {
58
+ html {
59
+ overflow-y: scroll;
60
+ }
61
+
62
+ body {
63
+ margin: 0 20px;
64
+ }
65
+
66
+ header.exception {
67
+ margin: 0 -20px;
68
+ }
69
+
70
+ nav.sidebar {
71
+ padding: 0;
72
+ margin: 20px 0;
73
+ }
74
+
75
+ ul.frames {
76
+ max-height: 200px;
77
+ overflow: auto;
78
+ }
79
+ }
80
+
81
+ /* Wide */
82
+ @media screen and (min-width: 1100px) {
83
+ header.exception {
84
+ position: fixed;
85
+ top: 0;
86
+ left: 0;
87
+ right: 0;
88
+ }
89
+
90
+ nav.sidebar,
91
+ .frame_info {
92
+ position: fixed;
93
+ top: 95px;
94
+ bottom: 0;
95
+
96
+ box-sizing: border-box;
97
+
98
+ overflow-y: auto;
99
+ overflow-x: hidden;
100
+ }
101
+
102
+ nav.sidebar {
103
+ width: 40%;
104
+ left: 20px;
105
+ top: 115px;
106
+ bottom: 20px;
107
+ }
108
+
109
+ .frame_info {
110
+ right: 0;
111
+ left: 40%;
112
+
113
+ padding: 20px;
114
+ padding-left: 10px;
115
+ margin-left: 30px;
116
+ }
117
+ }
118
+
119
+ nav.sidebar {
120
+ background: #d3d3da;
121
+ border-top: solid 3px #a33;
122
+ border-bottom: solid 3px #a33;
123
+ border-radius: 4px;
124
+ box-shadow: 0 0 6px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
125
+ }
126
+
127
+ /* ---------------------------------------------------------------------
128
+ * Header
129
+ * --------------------------------------------------------------------- */
130
+
131
+ header.exception {
132
+ padding: 18px 20px;
133
+
134
+ height: 59px;
135
+ min-height: 59px;
136
+
137
+ overflow: hidden;
138
+
139
+ background-color: #20202a;
140
+ color: #aaa;
141
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
142
+ font-weight: 200;
143
+ box-shadow: inset 0 -5px 3px -3px rgba(0, 0, 0, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
144
+
145
+ -webkit-text-smoothing: antialiased;
146
+ }
147
+
148
+ /* Heading */
149
+ header.exception h2 {
150
+ font-weight: 200;
151
+ font-size: 11pt;
152
+ }
153
+
154
+ header.exception h2,
155
+ header.exception p {
156
+ line-height: 1.4em;
157
+ overflow: hidden;
158
+ white-space: pre;
159
+ text-overflow: ellipsis;
160
+ }
161
+
162
+ header.exception h2 strong {
163
+ font-weight: 700;
164
+ color: #d55;
165
+ }
166
+
167
+ header.exception p {
168
+ font-weight: 200;
169
+ font-size: 20pt;
170
+ color: white;
171
+ }
172
+
173
+ header.exception:hover {
174
+ height: auto;
175
+ z-index: 2;
176
+ }
177
+
178
+ header.exception:hover h2,
179
+ header.exception:hover p {
180
+ padding-right: 20px;
181
+ overflow-y: auto;
182
+ word-wrap: break-word;
183
+ white-space: pre-wrap;
184
+ height: auto;
185
+ max-height: 7em;
186
+ }
187
+
188
+ @media screen and (max-width: 1100px) {
189
+ header.exception {
190
+ height: auto;
191
+ }
192
+
193
+ header.exception h2,
194
+ header.exception p {
195
+ padding-right: 20px;
196
+ overflow-y: auto;
197
+ word-wrap: break-word;
198
+ height: auto;
199
+ max-height: 7em;
200
+ }
201
+ }
202
+
203
+ <%#
204
+ /* Light theme */
205
+ header.exception {
206
+ text-shadow: 0 1px 0 rgba(250, 250, 250, 0.6);
207
+ background: rgba(200,100,50,0.10);
208
+ color: #977;
209
+ }
210
+ header.exception h2 strong {
211
+ color: #533;
212
+ }
213
+ header.exception p {
214
+ color: #744;
215
+ }
216
+ %>
217
+
218
+ /* ---------------------------------------------------------------------
219
+ * Navigation
220
+ * --------------------------------------------------------------------- */
221
+
222
+ nav.tabs {
223
+ border-bottom: solid 1px #ddd;
224
+
225
+ background-color: #eee;
226
+ text-align: center;
227
+
228
+ padding: 6px;
229
+
230
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
231
+ }
232
+
233
+ nav.tabs a {
234
+ display: inline-block;
235
+
236
+ height: 22px;
237
+ line-height: 22px;
238
+ padding: 0 10px;
239
+
240
+ text-decoration: none;
241
+ font-size: 8pt;
242
+ font-weight: bold;
243
+
244
+ color: #999;
245
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
246
+ }
247
+
248
+ nav.tabs a.selected {
249
+ color: white;
250
+ background: rgba(0, 0, 0, 0.5);
251
+ border-radius: 16px;
252
+ box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.1);
253
+ text-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.4);
254
+ }
255
+
256
+ nav.tabs a.disabled {
257
+ text-decoration: line-through;
258
+ text-shadow: none;
259
+ cursor: default;
260
+ }
261
+
262
+ /* ---------------------------------------------------------------------
263
+ * Sidebar
264
+ * --------------------------------------------------------------------- */
265
+
266
+ ul.frames {
267
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
268
+ }
269
+
270
+ /* Each item */
271
+ ul.frames li {
272
+ background-color: #f8f8f8;
273
+ background: -webkit-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
274
+ background: -moz-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
275
+ background: linear-gradient(top, #f8f8f8 80%, #f0f0f0);
276
+ box-shadow: inset 0 -1px 0 #e2e2e2;
277
+ padding: 7px 20px;
278
+
279
+ cursor: pointer;
280
+ overflow: hidden;
281
+ }
282
+
283
+ ul.frames .name,
284
+ ul.frames .location {
285
+ overflow: hidden;
286
+ height: 1.5em;
287
+
288
+ white-space: nowrap;
289
+ word-wrap: none;
290
+ text-overflow: ellipsis;
291
+ }
292
+
293
+ ul.frames .method {
294
+ color: #966;
295
+ }
296
+
297
+ ul.frames .location {
298
+ font-size: 0.85em;
299
+ font-weight: 400;
300
+ color: #999;
301
+ }
302
+
303
+ ul.frames .line {
304
+ font-weight: bold;
305
+ }
306
+
307
+ /* Selected frame */
308
+ ul.frames li.selected {
309
+ background: #38a;
310
+ 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);
311
+ }
312
+
313
+ ul.frames li.selected .name,
314
+ ul.frames li.selected .method,
315
+ ul.frames li.selected .location {
316
+ color: white;
317
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
318
+ }
319
+
320
+ ul.frames li.selected .location {
321
+ opacity: 0.6;
322
+ }
323
+
324
+ /* Iconography */
325
+ ul.frames li {
326
+ padding-left: 60px;
327
+ position: relative;
328
+ }
329
+
330
+ ul.frames li .icon {
331
+ display: block;
332
+ width: 20px;
333
+ height: 20px;
334
+ line-height: 20px;
335
+ border-radius: 15px;
336
+
337
+ text-align: center;
338
+
339
+ background: white;
340
+ border: solid 2px #ccc;
341
+
342
+ font-size: 9pt;
343
+ font-weight: 200;
344
+ font-style: normal;
345
+
346
+ position: absolute;
347
+ top: 14px;
348
+ left: 20px;
349
+ }
350
+
351
+ ul.frames .icon.application {
352
+ background: #808090;
353
+ border-color: #555;
354
+ }
355
+
356
+ ul.frames .icon.application:before {
357
+ content: 'A';
358
+ color: white;
359
+ text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
360
+ }
361
+
362
+ /* Responsiveness -- flow to single-line mode */
363
+ @media screen and (max-width: 1100px) {
364
+ ul.frames li {
365
+ padding-top: 6px;
366
+ padding-bottom: 6px;
367
+ padding-left: 36px;
368
+ line-height: 1.3;
369
+ }
370
+
371
+ ul.frames li .icon {
372
+ width: 11px;
373
+ height: 11px;
374
+ line-height: 11px;
375
+
376
+ top: 7px;
377
+ left: 10px;
378
+ font-size: 5pt;
379
+ }
380
+
381
+ ul.frames .name,
382
+ ul.frames .location {
383
+ display: inline-block;
384
+ line-height: 1.3;
385
+ height: 1.3em;
386
+ }
387
+
388
+ ul.frames .name {
389
+ margin-right: 10px;
390
+ }
391
+ }
392
+
393
+ /* ---------------------------------------------------------------------
394
+ * Monospace
395
+ * --------------------------------------------------------------------- */
396
+
397
+ pre, code, .repl input, .repl .prompt span, textarea, .code_linenums {
398
+ font-family: menlo, lucida console, monospace;
399
+ font-size: 8pt;
400
+ }
401
+
402
+ /* ---------------------------------------------------------------------
403
+ * Display area
404
+ * --------------------------------------------------------------------- */
405
+
406
+ .trace_info {
407
+ background: #fff;
408
+ padding: 6px;
409
+ border-radius: 3px;
410
+ margin-bottom: 2px;
411
+ 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);
412
+ }
413
+
414
+ .code_block{
415
+ background: #f1f1f1;
416
+ border-left: 1px solid #ccc;
417
+ }
418
+
419
+ /* Titlebar */
420
+ .trace_info .title {
421
+ background: #f1f1f1;
422
+
423
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
424
+ overflow: hidden;
425
+ padding: 6px 10px;
426
+
427
+ border: solid 1px #ccc;
428
+ border-bottom: 0;
429
+
430
+ border-top-left-radius: 2px;
431
+ border-top-right-radius: 2px;
432
+ }
433
+
434
+ .trace_info .title .name,
435
+ .trace_info .title .location {
436
+ font-size: 9pt;
437
+ line-height: 26px;
438
+ height: 26px;
439
+ overflow: hidden;
440
+ }
441
+
442
+ .trace_info .title .location {
443
+ float: left;
444
+ font-weight: bold;
445
+ font-size: 10pt;
446
+ }
447
+
448
+ .trace_info .title .location a {
449
+ color:inherit;
450
+ text-decoration:none;
451
+ border-bottom:1px solid #aaaaaa;
452
+ }
453
+
454
+ .trace_info .title .location a:hover {
455
+ border-color:#666666;
456
+ }
457
+
458
+ .trace_info .title .name {
459
+ float: right;
460
+ font-weight: 200;
461
+ }
462
+
463
+ .code, .console, .unavailable {
464
+ background: #fff;
465
+ padding: 5px;
466
+
467
+ box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
468
+ }
469
+
470
+ .code_linenums{
471
+ background:#f1f1f1;
472
+ padding-top:10px;
473
+ padding-bottom:9px;
474
+ float:left;
475
+ }
476
+
477
+ .code_linenums span{
478
+ display:block;
479
+ padding:0 12px;
480
+ }
481
+
482
+ .code {
483
+ margin-bottom: -1px;
484
+ border-top-left-radius:2px;
485
+ padding: 10px 0;
486
+ overflow: auto;
487
+ }
488
+
489
+ .code pre{
490
+ padding-left:12px;
491
+ min-height:16px;
492
+ }
493
+
494
+ /* Source unavailable */
495
+ p.unavailable {
496
+ padding: 20px 0 40px 0;
497
+ text-align: center;
498
+ color: #b99;
499
+ font-weight: bold;
500
+ }
501
+
502
+ p.unavailable:before {
503
+ content: '\00d7';
504
+ display: block;
505
+
506
+ color: #daa;
507
+
508
+ text-align: center;
509
+ font-size: 40pt;
510
+ font-weight: normal;
511
+ margin-bottom: -10px;
512
+ }
513
+
514
+ @-webkit-keyframes highlight {
515
+ 0% { background: rgba(220, 30, 30, 0.3); }
516
+ 100% { background: rgba(220, 30, 30, 0.1); }
517
+ }
518
+ @-moz-keyframes highlight {
519
+ 0% { background: rgba(220, 30, 30, 0.3); }
520
+ 100% { background: rgba(220, 30, 30, 0.1); }
521
+ }
522
+ @keyframes highlight {
523
+ 0% { background: rgba(220, 30, 30, 0.3); }
524
+ 100% { background: rgba(220, 30, 30, 0.1); }
525
+ }
526
+
527
+ .code .highlight, .code_linenums .highlight {
528
+ background: rgba(220, 30, 30, 0.1);
529
+ -webkit-animation: highlight 400ms linear 1;
530
+ -moz-animation: highlight 400ms linear 1;
531
+ animation: highlight 400ms linear 1;
532
+ }
533
+
534
+ /* REPL shell */
535
+ .console {
536
+ padding: 0 1px 10px 1px;
537
+ border-bottom-left-radius: 2px;
538
+ border-bottom-right-radius: 2px;
539
+ }
540
+
541
+ .console pre {
542
+ padding: 10px 10px 0 10px;
543
+ max-height: 400px;
544
+ overflow-x: none;
545
+ overflow-y: auto;
546
+ margin-bottom: -3px;
547
+ word-wrap: break-word;
548
+ white-space: pre-wrap;
549
+ }
550
+
551
+ /* .prompt > span + input */
552
+ .console .prompt {
553
+ display: table;
554
+ width: 100%;
555
+ }
556
+
557
+ .console .prompt span,
558
+ .console .prompt input {
559
+ display: table-cell;
560
+ }
561
+
562
+ .console .prompt span {
563
+ width: 1%;
564
+ padding-right: 5px;
565
+ padding-left: 10px;
566
+ }
567
+
568
+ .console .prompt input {
569
+ width: 99%;
570
+ }
571
+
572
+ /* Input box */
573
+ .console input,
574
+ .console input:focus {
575
+ outline: 0;
576
+ border: 0;
577
+ padding: 0;
578
+ background: transparent;
579
+ margin: 0;
580
+ }
581
+
582
+ /* Hint text */
583
+ .hint {
584
+ margin: 15px 0 20px 0;
585
+ font-size: 8pt;
586
+ color: #8080a0;
587
+ padding-left: 20px;
588
+ }
589
+
590
+ .hint:before {
591
+ content: '\25b2';
592
+ margin-right: 5px;
593
+ opacity: 0.5;
594
+ }
595
+
596
+ /* ---------------------------------------------------------------------
597
+ * Variable infos
598
+ * --------------------------------------------------------------------- */
599
+
600
+ .sub {
601
+ padding: 10px 0;
602
+ margin: 10px 0;
603
+ }
604
+
605
+ .sub:before {
606
+ content: '';
607
+ display: block;
608
+ width: 100%;
609
+ height: 4px;
610
+
611
+ border-radius: 2px;
612
+ background: rgba(0, 150, 200, 0.05);
613
+ 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);
614
+ }
615
+
616
+ .sub h3 {
617
+ color: #39a;
618
+ font-size: 1.1em;
619
+ margin: 10px 0;
620
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
621
+
622
+ -webkit-font-smoothing: antialiased;
623
+ }
624
+
625
+ .sub .inset {
626
+ overflow-y: auto;
627
+ }
628
+
629
+ .sub table {
630
+ table-layout: fixed;
631
+ }
632
+
633
+ .sub table td {
634
+ border-top: dotted 1px #ddd;
635
+ padding: 7px 1px;
636
+ }
637
+
638
+ .sub table td.name {
639
+ width: 150px;
640
+
641
+ font-weight: bold;
642
+ font-size: 0.8em;
643
+ padding-right: 20px;
644
+
645
+ word-wrap: break-word;
646
+ }
647
+
648
+ .sub table td pre {
649
+ max-height: 15em;
650
+ overflow-y: auto;
651
+ }
652
+
653
+ .sub table td pre {
654
+ width: 100%;
655
+
656
+ word-wrap: break-word;
657
+ white-space: normal;
658
+ }
659
+
660
+ /* "(object doesn't support inspect)" */
661
+ .sub .unsupported {
662
+ font-family: sans-serif;
663
+ color: #777;
664
+ }
665
+
666
+ /* ---------------------------------------------------------------------
667
+ * Scrollbar
668
+ * --------------------------------------------------------------------- */
669
+
670
+ nav.sidebar::-webkit-scrollbar,
671
+ .inset pre::-webkit-scrollbar,
672
+ .console pre::-webkit-scrollbar,
673
+ .code::-webkit-scrollbar {
674
+ width: 10px;
675
+ height: 10px;
676
+ }
677
+
678
+ .inset pre::-webkit-scrollbar-thumb,
679
+ .console pre::-webkit-scrollbar-thumb,
680
+ .code::-webkit-scrollbar-thumb {
681
+ background: #ccc;
682
+ border-radius: 5px;
683
+ }
684
+
685
+ nav.sidebar::-webkit-scrollbar-thumb {
686
+ background: rgba(0, 0, 0, 0.0);
687
+ border-radius: 5px;
688
+ }
689
+
690
+ nav.sidebar:hover::-webkit-scrollbar-thumb {
691
+ background-color: #999;
692
+ background: -webkit-linear-gradient(left, #aaa, #999);
693
+ }
694
+
695
+ .console pre:hover::-webkit-scrollbar-thumb,
696
+ .inset pre:hover::-webkit-scrollbar-thumb,
697
+ .code:hover::-webkit-scrollbar-thumb {
698
+ background: #888;
699
+ }
700
+ </style>
701
+
702
+ <%# IE8 compatibility crap %>
703
+ <script>
704
+ (function() {
705
+ var elements = ["section", "nav", "header", "footer", "audio"];
706
+ for (var i = 0; i < elements.length; i++) {
707
+ document.createElement(elements[i]);
708
+ }
709
+ })();
710
+ </script>
711
+
712
+ <%#
713
+ If Rails's Turbolinks is used, the Better Errors page is probably
714
+ rendered in the host app's layout. Let's empty out the styles of the
715
+ host app.
716
+ %>
717
+ <script>
718
+ if (window.Turbolinks) {
719
+ for(var i=0; i < document.styleSheets.length; i++) {
720
+ if(document.styleSheets[i].href)
721
+ document.styleSheets[i].disabled = true;
722
+ }
723
+ document.addEventListener("page:restore", function restoreCSS(e) {
724
+ for(var i=0; i < document.styleSheets.length; i++) {
725
+ document.styleSheets[i].disabled = false;
726
+ }
727
+ document.removeEventListener("page:restore", restoreCSS, false);
728
+ });
729
+ }
730
+ </script>
731
+
732
+ <div class='top'>
733
+ <header class="exception">
734
+ <h2><strong><%= exception.type %></strong> <span>at <%= request_path %></span></h2>
735
+ <p><%= exception.message %></p>
736
+ </header>
737
+ </div>
738
+
739
+ <section class="backtrace">
740
+ <nav class="sidebar">
741
+ <nav class="tabs">
742
+ <a href="#" id="application_frames">Application Frames</a>
743
+ <a href="#" id="all_frames">All Frames</a>
744
+ </nav>
745
+ <ul class="frames">
746
+ <% backtrace_frames.each_with_index do |frame, index| %>
747
+ <li class="<%= frame.context %>" data-context="<%= frame.context %>" data-index="<%= index %>">
748
+ <span class='stroke'></span>
749
+ <i class="icon <%= frame.context %>"></i>
750
+ <div class="info">
751
+ <div class="name">
752
+ <strong><%= frame.class_name %></strong><span class='method'><%= frame.method_name %></span>
753
+ </div>
754
+ <div class="location">
755
+ <span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span>
756
+ </div>
757
+ </div>
758
+ </li>
759
+ <% end %>
760
+ </ul>
761
+ </nav>
762
+
763
+ <% backtrace_frames.each_with_index do |frame, index| %>
764
+ <div class="frame_info" id="frame_info_<%= index %>" style="display:none;"></div>
765
+ <% end %>
766
+ </section>
767
+ </body>
768
+ <script>
769
+ (function() {
770
+
771
+ var OID = "<%= id %>";
772
+
773
+ var previousFrame = null;
774
+ var previousFrameInfo = null;
775
+ var allFrames = document.querySelectorAll("ul.frames li");
776
+ var allFrameInfos = document.querySelectorAll(".frame_info");
777
+
778
+ function apiCall(method, opts, cb) {
779
+ var req = new XMLHttpRequest();
780
+ req.open("POST", <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
781
+ req.setRequestHeader("Content-Type", "application/json");
782
+ req.send(JSON.stringify(opts));
783
+ req.onreadystatechange = function() {
784
+ if(req.readyState == 4) {
785
+ var res = JSON.parse(req.responseText);
786
+ cb(res);
787
+ }
788
+ };
789
+ }
790
+
791
+ function escapeHTML(html) {
792
+ return html.replace(/&/, "&amp;").replace(/</g, "&lt;");
793
+ }
794
+
795
+ function REPL(index) {
796
+ this.index = index;
797
+
798
+ var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
799
+ if(previousCommands === null) {
800
+ localStorage.setItem("better_errors_previous_commands", JSON.stringify([]));
801
+ previousCommands = [];
802
+ }
803
+
804
+ this.previousCommandOffset = previousCommands.length;
805
+ }
806
+
807
+ REPL.all = [];
808
+
809
+ REPL.prototype.install = function(containerElement) {
810
+ this.container = containerElement;
811
+
812
+ this.promptElement = this.container.querySelector(".prompt span");
813
+ this.inputElement = this.container.querySelector("input");
814
+ this.outputElement = this.container.querySelector("pre");
815
+
816
+ var self = this;
817
+ this.inputElement.onkeydown = function(ev) {
818
+ self.onKeyDown(ev);
819
+ };
820
+
821
+ this.setPrompt(">>");
822
+
823
+ REPL.all[this.index] = this;
824
+ }
825
+
826
+ REPL.prototype.focus = function() {
827
+ this.inputElement.focus();
828
+ };
829
+
830
+ REPL.prototype.setPrompt = function(prompt) {
831
+ this._prompt = prompt;
832
+ this.promptElement.innerHTML = escapeHTML(prompt);
833
+ };
834
+
835
+ REPL.prototype.getInput = function() {
836
+ return this.inputElement.value;
837
+ };
838
+
839
+ REPL.prototype.setInput = function(text) {
840
+ this.inputElement.value = text;
841
+
842
+ if(this.inputElement.setSelectionRange) {
843
+ // set cursor to end of input
844
+ this.inputElement.setSelectionRange(text.length, text.length);
845
+ }
846
+ };
847
+
848
+ REPL.prototype.writeRawOutput = function(output) {
849
+ this.outputElement.innerHTML += output;
850
+ this.outputElement.scrollTop = this.outputElement.scrollHeight;
851
+ };
852
+
853
+ REPL.prototype.writeOutput = function(output) {
854
+ this.writeRawOutput(escapeHTML(output));
855
+ };
856
+
857
+ REPL.prototype.sendInput = function(line) {
858
+ var self = this;
859
+ apiCall("eval", { "index": this.index, source: line }, function(response) {
860
+ if(response.error) {
861
+ self.writeOutput(response.error + "\n");
862
+ }
863
+ self.writeOutput(self._prompt + " ");
864
+ self.writeRawOutput(response.highlighted_input + "\n");
865
+ self.writeOutput(response.result);
866
+ self.setPrompt(response.prompt);
867
+ self.setInput(response.prefilled_input);
868
+ });
869
+ };
870
+
871
+ REPL.prototype.onEnterKey = function() {
872
+ var text = this.getInput();
873
+ if(text != "" && text !== undefined) {
874
+ var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
875
+ this.previousCommandOffset = previousCommands.push(text);
876
+ if(previousCommands.length > 100) {
877
+ previousCommands.splice(0, 1);
878
+ }
879
+ localStorage.setItem("better_errors_previous_commands", JSON.stringify(previousCommands));
880
+ }
881
+ this.setInput("");
882
+ this.sendInput(text);
883
+ };
884
+
885
+ REPL.prototype.onNavigateHistory = function(direction) {
886
+ this.previousCommandOffset += direction;
887
+ var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
888
+
889
+ if(this.previousCommandOffset < 0) {
890
+ this.previousCommandOffset = -1;
891
+ this.setInput("");
892
+ return;
893
+ }
894
+
895
+ if(this.previousCommandOffset >= previousCommands.length) {
896
+ this.previousCommandOffset = previousCommands.length;
897
+ this.setInput("");
898
+ return;
899
+ }
900
+
901
+ this.setInput(previousCommands[this.previousCommandOffset]);
902
+ };
903
+
904
+ REPL.prototype.onKeyDown = function(ev) {
905
+ if(ev.keyCode == 13) {
906
+ this.onEnterKey();
907
+ } else if(ev.keyCode == 38 || (ev.ctrlKey && ev.keyCode == 80)) {
908
+ // the user pressed the up arrow or Ctrl-P
909
+ this.onNavigateHistory(-1);
910
+ ev.preventDefault();
911
+ return false;
912
+ } else if(ev.keyCode == 40 || (ev.ctrlKey && ev.keyCode == 78)) {
913
+ // the user pressed the down arrow or Ctrl-N
914
+ this.onNavigateHistory(1);
915
+ ev.preventDefault();
916
+ return false;
917
+ }
918
+ };
919
+
920
+ function switchTo(el) {
921
+ if(previousFrameInfo) previousFrameInfo.style.display = "none";
922
+ previousFrameInfo = el;
923
+
924
+ el.style.display = "block";
925
+
926
+ var replInput = el.querySelector('.console input');
927
+ if (replInput) replInput.focus();
928
+ }
929
+
930
+ function selectFrameInfo(index) {
931
+ var el = allFrameInfos[index];
932
+ if(el) {
933
+ if (el.loaded) {
934
+ return switchTo(el);
935
+ }
936
+
937
+ apiCall("variables", { "index": index }, function(response) {
938
+ el.loaded = true;
939
+ if(response.error) {
940
+ el.innerHTML = "<span class='error'>" + escapeHTML(response.error) + "</span>";
941
+ } else {
942
+ el.innerHTML = response.html;
943
+
944
+ var repl = el.querySelector(".repl .console");
945
+ if(repl) {
946
+ new REPL(index).install(repl);
947
+ }
948
+
949
+ switchTo(el);
950
+ }
951
+ });
952
+ }
953
+ }
954
+
955
+ for(var i = 0; i < allFrames.length; i++) {
956
+ (function(i, el) {
957
+ var el = allFrames[i];
958
+ el.onclick = function() {
959
+ if(previousFrame) {
960
+ previousFrame.className = "";
961
+ }
962
+ el.className = "selected";
963
+ previousFrame = el;
964
+
965
+ selectFrameInfo(el.attributes["data-index"].value);
966
+ };
967
+ })(i);
968
+ }
969
+
970
+ // Click the first application frame
971
+ (
972
+ document.querySelector(".frames li.application") ||
973
+ document.querySelector(".frames li")
974
+ ).onclick();
975
+
976
+ // This is the second query performed for frames; maybe the 'allFrames' list
977
+ // currently used and this list can be better used to avoid the repetition:
978
+ var applicationFramesCount = document.querySelectorAll(
979
+ "ul.frames li[data-context=application]"
980
+ ).length;
981
+
982
+ var applicationFramesButtonIsInstalled = false;
983
+ var applicationFramesButton = document.getElementById("application_frames");
984
+ var allFramesButton = document.getElementById("all_frames");
985
+
986
+ // The application frames button only needs to be bound if
987
+ // there are actually any application frames to look at.
988
+ var installApplicationFramesButton = function() {
989
+ applicationFramesButton.onclick = function() {
990
+ allFramesButton.className = "";
991
+ applicationFramesButton.className = "selected";
992
+ for(var i = 0; i < allFrames.length; i++) {
993
+ if(allFrames[i].attributes["data-context"].value == "application") {
994
+ allFrames[i].style.display = "block";
995
+ } else {
996
+ allFrames[i].style.display = "none";
997
+ }
998
+ }
999
+ return false;
1000
+ };
1001
+
1002
+ applicationFramesButtonIsInstalled = true;
1003
+ }
1004
+
1005
+ allFramesButton.onclick = function() {
1006
+ if(applicationFramesButtonIsInstalled) {
1007
+ applicationFramesButton.className = "";
1008
+ }
1009
+
1010
+ allFramesButton.className = "selected";
1011
+ for(var i = 0; i < allFrames.length; i++) {
1012
+ allFrames[i].style.display = "block";
1013
+ }
1014
+ return false;
1015
+ };
1016
+
1017
+ // If there are no application frames, select the 'All Frames'
1018
+ // tab by default.
1019
+ if(applicationFramesCount > 0) {
1020
+ installApplicationFramesButton();
1021
+ applicationFramesButton.onclick();
1022
+ } else {
1023
+ applicationFramesButton.className = "disabled";
1024
+ applicationFramesButton.title = "No application frames available";
1025
+ allFramesButton.onclick();
1026
+ }
1027
+ })();
1028
+ </script>
1029
+ </html>
1030
+
1031
+ <!-- generated by Better Errors in <%= Time.now.to_f - @start_time %> seconds -->
@@ -0,0 +1,21 @@
1
+ <%== text_heading("=", "%s at %s" % [exception.type, request_path]) %>
2
+
3
+ > <%== exception.message %>
4
+ <% if backtrace_frames.any? %>
5
+
6
+ <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
7
+
8
+ ``` ruby
9
+ <%== text_formatted_code_block(first_frame) %>```
10
+
11
+ App backtrace
12
+ -------------
13
+
14
+ <%== application_frames.map { |s| " - #{s}" }.join("\n") %>
15
+
16
+ Full backtrace
17
+ --------------
18
+
19
+ <%== backtrace_frames.map { |s| " - #{s}" }.join("\n") %>
20
+
21
+ <% end %>
@@ -0,0 +1,70 @@
1
+ <header class="trace_info clearfix">
2
+ <div class="title">
3
+ <h2 class="name"><%= @frame.name %></h2>
4
+ <div class="location"><span class="filename"><a href="<%= editor_url(@frame) %>"><%= @frame.pretty_path %></a></span></div>
5
+ </div>
6
+ <div class="code_block clearfix">
7
+ <%== html_formatted_code_block @frame %>
8
+ </div>
9
+
10
+ <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
11
+ <div class="repl">
12
+ <div class="console">
13
+ <pre></pre>
14
+ <div class="prompt"><span>&gt;&gt;</span> <input/></div>
15
+ </div>
16
+ </div>
17
+ <% end %>
18
+ </header>
19
+
20
+ <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
21
+ <div class="hint">
22
+ This is a live shell. Type in here.
23
+ </div>
24
+
25
+ <div class="variable_info"></div>
26
+ <% end %>
27
+
28
+ <% unless BetterErrors.binding_of_caller_available? %>
29
+ <div class="hint">
30
+ <strong>Tip:</strong> add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
31
+ </div>
32
+ <% end %>
33
+
34
+ <div class="sub">
35
+ <h3>Request info</h3>
36
+ <div class='inset variables'>
37
+ <table class="var_table">
38
+ <% if rails_params %>
39
+ <tr><td class="name">Request parameters</td><td><pre><%== inspect_value rails_params %></pre></td></tr>
40
+ <% end %>
41
+ <% if rack_session %>
42
+ <tr><td class="name">Rack session</td><td><pre><%== inspect_value rack_session %></pre></td></tr>
43
+ <% end %>
44
+ </table>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="sub">
49
+ <h3>Local Variables</h3>
50
+ <div class='inset variables'>
51
+ <table class="var_table">
52
+ <% @frame.local_variables.each do |name, value| %>
53
+ <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
54
+ <% end %>
55
+ </table>
56
+ </div>
57
+ </div>
58
+
59
+ <div class="sub">
60
+ <h3>Instance Variables</h3>
61
+ <div class="inset variables">
62
+ <table class="var_table">
63
+ <% @frame.instance_variables.each do |name, value| %>
64
+ <tr><td class="name"><%= name %></td><td><pre><%== inspect_value value %></pre></td></tr>
65
+ <% end %>
66
+ </table>
67
+ </div>
68
+ </div>
69
+
70
+ <!-- <%= Time.now.to_f - @var_start_time %> seconds -->
@@ -0,0 +1,3 @@
1
+ module Yeast
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'yeast/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "yeast"
8
+ spec.version = Yeast::VERSION
9
+ spec.authors = ["Chris Oliver"]
10
+ spec.email = ["excid3@gmail.com"]
11
+ spec.summary = %q{Learn from errors in your Rails apps}
12
+ spec.description = %q{A better error page for your Rails apps that helps you learn from your errors}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.add_dependency "better_errors", "~> 2.0.0"
25
+ spec.add_dependency "binding_of_caller", "~> 0.7.2"
26
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yeast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Oliver
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: better_errors
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: binding_of_caller
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.7.2
69
+ description: A better error page for your Rails apps that helps you learn from your
70
+ errors
71
+ email:
72
+ - excid3@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - lib/yeast.rb
83
+ - lib/yeast/templates/main.erb
84
+ - lib/yeast/templates/text.erb
85
+ - lib/yeast/templates/variable_info.erb
86
+ - lib/yeast/version.rb
87
+ - yeast.gemspec
88
+ homepage: ''
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.2.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Learn from errors in your Rails apps
112
+ test_files: []