yeast 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []