card-mod-format 0.11.0
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.
- checksums.yaml +7 -0
- data/lib/card/format/css_format.rb +17 -0
- data/lib/card/format/csv_format.rb +19 -0
- data/lib/card/format/data_format.rb +6 -0
- data/lib/card/format/file_format.rb +8 -0
- data/lib/card/format/html_format.rb +45 -0
- data/lib/card/format/js_format.rb +17 -0
- data/lib/card/format/json_format.rb +24 -0
- data/lib/card/format/rss_format.rb +9 -0
- data/lib/card/format/text_format.rb +16 -0
- data/lib/card/format/xml_format.rb +13 -0
- data/lib/card/path.rb +127 -0
- data/set/all/active_card.rb +6 -0
- data/set/all/base.rb +137 -0
- data/set/all/css.rb +37 -0
- data/set/all/csv.rb +93 -0
- data/set/all/error.rb +79 -0
- data/set/all/export.rb +68 -0
- data/set/all/file.rb +9 -0
- data/set/all/frame.rb +53 -0
- data/set/all/haml.rb +75 -0
- data/set/all/head.rb +148 -0
- data/set/all/header.rb +62 -0
- data/set/all/header/header_wrap.haml +4 -0
- data/set/all/html_content.rb +168 -0
- data/set/all/html_content/labeled.haml +4 -0
- data/set/all/html_error.rb +193 -0
- data/set/all/html_error/debug_server_error.haml +1015 -0
- data/set/all/html_error/not_found.haml +7 -0
- data/set/all/html_error/server_error.haml +5 -0
- data/set/all/html_show.rb +53 -0
- data/set/all/html_title.rb +47 -0
- data/set/all/html_wrapper.rb +159 -0
- data/set/all/js.rb +10 -0
- data/set/all/json.rb +166 -0
- data/set/all/links.rb +149 -0
- data/set/all/menu.rb +129 -0
- data/set/all/meta_tags.haml +4 -0
- data/set/all/path.rb +78 -0
- data/set/all/rich_html.rb +4 -0
- data/set/all/rss.rb +76 -0
- data/set/all/text.rb +7 -0
- data/set/self/home.rb +9 -0
- data/set/type/html.rb +27 -0
- data/set/type/json.rb +41 -0
- data/set/type/number.rb +22 -0
- data/set/type/phrase.rb +5 -0
- data/set/type/plain_text.rb +9 -0
- data/set/type/toggle.rb +38 -0
- data/set/type/uri.rb +15 -0
- metadata +123 -0
data/set/all/header.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# LOCALIZE first item
|
2
|
+
TOGGLE_MAP = { close: %w[open open], open: %w[close closed] }.freeze
|
3
|
+
|
4
|
+
format :html do
|
5
|
+
view :header, perms: :none do
|
6
|
+
main_header
|
7
|
+
end
|
8
|
+
|
9
|
+
def main_header
|
10
|
+
header_wrap _render_header_title
|
11
|
+
end
|
12
|
+
|
13
|
+
def header_wrap content=nil
|
14
|
+
haml :header_wrap, content: (block_given? ? yield : output(content))
|
15
|
+
end
|
16
|
+
|
17
|
+
view :header_title, perms: :none do
|
18
|
+
header_title_elements
|
19
|
+
end
|
20
|
+
|
21
|
+
def header_title_elements
|
22
|
+
voo.hide :title_toggle if show_view?(:icon_toggle, :hide)
|
23
|
+
title_view = show_view?(:title_toggle, :hide) ? :title_toggle : :title
|
24
|
+
[_render_icon_toggle(optional: :hide), _render(title_view)]
|
25
|
+
end
|
26
|
+
|
27
|
+
def show_draft_link?
|
28
|
+
card.drafts.present? && @slot_view == :edit
|
29
|
+
end
|
30
|
+
|
31
|
+
view :title_toggle, perms: :none do
|
32
|
+
content_toggle(_render_title(hide: :title_link))
|
33
|
+
end
|
34
|
+
|
35
|
+
view :icon_toggle, perms: :none do
|
36
|
+
direction = @toggle_mode == :close ? :expand : :collapse_down
|
37
|
+
content_toggle icon_tag(direction)
|
38
|
+
end
|
39
|
+
|
40
|
+
view :toggle, :icon_toggle # deprecated; use icon_toggle
|
41
|
+
|
42
|
+
def content_toggle text=""
|
43
|
+
return if text.nil?
|
44
|
+
|
45
|
+
verb, adjective = toggle_verb_adjective
|
46
|
+
link_to_view adjective, text, title: "#{verb} #{card.name}", # LOCALIZE
|
47
|
+
class: "toggle-#{adjective} toggler nodblclick"
|
48
|
+
end
|
49
|
+
|
50
|
+
def toggle_view
|
51
|
+
toggle_verb_adjective.last
|
52
|
+
end
|
53
|
+
|
54
|
+
def toggle_verb_adjective
|
55
|
+
TOGGLE_MAP[@toggle_mode || :open] ||
|
56
|
+
raise(Card::Error, "invalid toggle mode: #{@toggle_mode}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def structure_editable?
|
60
|
+
card.structure && card.template.ok?(:update)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
format :html do
|
2
|
+
def prepare_content_slot
|
3
|
+
class_up "card-slot", "d0-card-content"
|
4
|
+
voo.hide :menu
|
5
|
+
end
|
6
|
+
|
7
|
+
before(:content) { prepare_content_slot }
|
8
|
+
|
9
|
+
view :content do
|
10
|
+
voo.hide :edit_button
|
11
|
+
wrap do
|
12
|
+
[_render_menu, _render_core, _render_edit_button(edit: :inline)]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before(:content_with_edit_button) do
|
17
|
+
prepare_content_slot
|
18
|
+
end
|
19
|
+
|
20
|
+
view :content_with_edit_button do
|
21
|
+
wrap do
|
22
|
+
[_render_menu, _render_core, _render_edit_button(edit: :inline)]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
view :short_content, wrap: { div: { class: "text-muted" } } do
|
27
|
+
short_content
|
28
|
+
end
|
29
|
+
|
30
|
+
view :raw_one_line_content, unknown: :mini_unknown,
|
31
|
+
wrap: { div: { class: "text-muted" } } do
|
32
|
+
raw_one_line_content
|
33
|
+
end
|
34
|
+
|
35
|
+
view :one_line_content, unknown: :mini_unknown,
|
36
|
+
wrap: { div: { class: "text-muted" } } do
|
37
|
+
one_line_content
|
38
|
+
end
|
39
|
+
|
40
|
+
before(:content_with_title) { prepare_content_slot }
|
41
|
+
|
42
|
+
view :content_with_title do
|
43
|
+
wrap true, title: card.format(:text).render_core do
|
44
|
+
[_render_menu, _render_core]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before :content_panel do
|
49
|
+
prepare_content_slot
|
50
|
+
class_up "card-slot", "card"
|
51
|
+
end
|
52
|
+
|
53
|
+
view :content_panel do
|
54
|
+
wrap do
|
55
|
+
wrap_with :div, class: "card-body" do
|
56
|
+
[_render_menu, _render_core]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
view :titled do
|
62
|
+
@content_body = true
|
63
|
+
wrap do
|
64
|
+
[
|
65
|
+
naming { render_header },
|
66
|
+
render_flash,
|
67
|
+
wrap_body { render_titled_content },
|
68
|
+
render_comment_box(optional: :hide)
|
69
|
+
]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
view :labeled, unknown: true do
|
74
|
+
@content_body = true
|
75
|
+
wrap(true, class: "row") do
|
76
|
+
labeled(render_title, wrap_body { "#{render_menu}#{render_labeled_content}" })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def labeled label, content
|
81
|
+
haml :labeled, label: label, content: content
|
82
|
+
end
|
83
|
+
|
84
|
+
def labeled_field field, item_view=:name, opts={}
|
85
|
+
opts[:title] ||= Card.fetch_name field
|
86
|
+
field_nest field, opts.merge(view: :labeled,
|
87
|
+
items: (opts[:items] || {}).merge(view: item_view))
|
88
|
+
end
|
89
|
+
|
90
|
+
view :open do
|
91
|
+
toggle_logic
|
92
|
+
@toggle_mode = :open
|
93
|
+
@content_body = true
|
94
|
+
frame do
|
95
|
+
[_render_open_content, render_comment_box(optional: :hide)]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
view :closed do
|
100
|
+
with_nest_mode :compact do
|
101
|
+
toggle_logic
|
102
|
+
class_up "d0-card-body", "closed-content"
|
103
|
+
@content_body = false
|
104
|
+
@toggle_mode = :close
|
105
|
+
frame
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def toggle_logic
|
110
|
+
show_view?(:title_link, :hide) ? voo.show(:icon_toggle) : voo.show(:title_toggle)
|
111
|
+
end
|
112
|
+
|
113
|
+
def current_set_card
|
114
|
+
set_name = params[:current_set]
|
115
|
+
set_name ||= "#{card.name}+*type" if card.known? && card.type_id == Card::CardtypeID
|
116
|
+
set_name ||= "#{card.name}+*self"
|
117
|
+
Card.fetch(set_name)
|
118
|
+
end
|
119
|
+
|
120
|
+
def raw_one_line_content
|
121
|
+
cleaned = Card::Content.clean! render_raw, {}
|
122
|
+
cut_with_ellipsis cleaned
|
123
|
+
end
|
124
|
+
|
125
|
+
def one_line_content
|
126
|
+
# TODO: use a version of Card::Content.smart_truncate
|
127
|
+
# that counts characters instead of clean!
|
128
|
+
cleaned = Card::Content.clean! render_core, {}
|
129
|
+
cut_with_ellipsis cleaned
|
130
|
+
end
|
131
|
+
|
132
|
+
# LOCALIZE
|
133
|
+
def short_content
|
134
|
+
short_content_items || short_content_fields || short_content_from_core
|
135
|
+
end
|
136
|
+
|
137
|
+
def short_content_items
|
138
|
+
return unless card.respond_to? :count
|
139
|
+
"#{count} #{'item'.pluralize count}"
|
140
|
+
end
|
141
|
+
|
142
|
+
def short_content_fields
|
143
|
+
with_short_content_fields do |num_fields|
|
144
|
+
"#{num_fields} #{'field'.pluralize num_fields}" if num_fields.positive?
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def with_short_content_fields
|
149
|
+
yield nested_field_names.size if voo.structure || card.structure
|
150
|
+
end
|
151
|
+
|
152
|
+
def short_content_from_core
|
153
|
+
content = render_core
|
154
|
+
if content.blank?
|
155
|
+
"empty"
|
156
|
+
elsif content.size <= 5
|
157
|
+
content
|
158
|
+
elsif content.count("\n") < 2
|
159
|
+
"#{content.size} characters"
|
160
|
+
else
|
161
|
+
"#{content.count("\n") + 1} lines"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def count
|
166
|
+
@count ||= card.count
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
format :html do
|
2
|
+
view :server_error, template: :haml
|
3
|
+
|
4
|
+
view :debug_server_error, wrap: { modal: { size: :full } } do
|
5
|
+
error_page = BetterErrors::ErrorPage.new Card::Error.current,
|
6
|
+
"PATH_INFO" => request.env["REQUEST_URI"]
|
7
|
+
haml :debug_server_error, {}, error_page
|
8
|
+
end
|
9
|
+
|
10
|
+
view :unknown do
|
11
|
+
createable { wrap { unknown_link "#{unknown_icon} #{render_title}" } }
|
12
|
+
end
|
13
|
+
|
14
|
+
# icon only, no wrap
|
15
|
+
view :mini_unknown, unknown: true, cache: :never do
|
16
|
+
createable { unknown_link unknown_icon }
|
17
|
+
end
|
18
|
+
|
19
|
+
def createable
|
20
|
+
card.ok?(:create) ? yield : ""
|
21
|
+
end
|
22
|
+
|
23
|
+
def unknown_link text
|
24
|
+
path_opts = voo.type ? { card: { type: voo.type } } : {}
|
25
|
+
link_to_view :new_in_modal, text, path: path_opts, class: classy("unknown-link")
|
26
|
+
end
|
27
|
+
|
28
|
+
def unknown_icon
|
29
|
+
fa_icon "plus-square"
|
30
|
+
end
|
31
|
+
|
32
|
+
view :compact_missing, perms: :none do
|
33
|
+
wrap_with :span, h(title_in_context), class: "text-muted"
|
34
|
+
end
|
35
|
+
|
36
|
+
view :conflict, cache: :never do
|
37
|
+
actor_link = link_to_card card.last_action.act.actor.name
|
38
|
+
class_up "card-slot", "error-view"
|
39
|
+
wrap do # LOCALIZE
|
40
|
+
alert "warning" do
|
41
|
+
%(
|
42
|
+
<strong>Conflict!</strong>
|
43
|
+
<span class="new-current-revision-id">#{card.last_action_id}</span>
|
44
|
+
<div>#{actor_link} has also been making changes.</div>
|
45
|
+
<div>Please examine below, resolve above, and re-submit.</div>
|
46
|
+
#{render_act}
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
view :errors, perms: :none do
|
53
|
+
return if card.errors.empty?
|
54
|
+
|
55
|
+
voo.title = card.name.blank? ? "Problems" : tr(:problems_name, cardname: card.name)
|
56
|
+
voo.hide! :menu
|
57
|
+
class_up "alert", "card-error-msg"
|
58
|
+
standard_errors voo.title
|
59
|
+
end
|
60
|
+
|
61
|
+
view :not_found do
|
62
|
+
voo.hide! :menu
|
63
|
+
voo.title = "Not Found"
|
64
|
+
frame do
|
65
|
+
[not_found_errors, sign_in_or_up_links("to create it")]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
view :denial do
|
70
|
+
focal? ? loud_denial : quiet_denial
|
71
|
+
end
|
72
|
+
|
73
|
+
def view_for_unknown view
|
74
|
+
main? && ok?(:create) ? :new : super
|
75
|
+
end
|
76
|
+
|
77
|
+
def show_all_errors?
|
78
|
+
# make configurable by env
|
79
|
+
Auth.always_ok? || Rails.env.development?
|
80
|
+
end
|
81
|
+
|
82
|
+
def error_cardname exception
|
83
|
+
cardname = super
|
84
|
+
show_all_errors? ? backtrace_link(cardname, exception) : cardname
|
85
|
+
end
|
86
|
+
|
87
|
+
def rendering_error exception, view
|
88
|
+
wrap_with(:span, class: "render-error alert alert-danger") { super }
|
89
|
+
end
|
90
|
+
|
91
|
+
def error_modal_id
|
92
|
+
@error_modal_id ||= unique_id
|
93
|
+
end
|
94
|
+
|
95
|
+
def error_message exception
|
96
|
+
%{
|
97
|
+
<h3>Error message (visible to admin only)</h3>
|
98
|
+
<p><strong>#{CGI.escapeHTML exception.message}</strong></p>
|
99
|
+
<div>#{exception.backtrace * "<br>\n"}</div>
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def backtrace_link cardname, exception
|
104
|
+
# TODO: make this a modal link after new modal handling is merged in
|
105
|
+
wrap_with(:span, title: error_message(exception)) { cardname }
|
106
|
+
end
|
107
|
+
|
108
|
+
def standard_errors heading=nil
|
109
|
+
alert "warning", true do
|
110
|
+
[
|
111
|
+
(wrap_with(:h4, heading, class: "alert-heading error") if heading),
|
112
|
+
error_messages.join("<hr>")
|
113
|
+
]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def simple_error_message message
|
118
|
+
h message
|
119
|
+
end
|
120
|
+
|
121
|
+
def standard_error_message error
|
122
|
+
"<p><strong>#{h error.attribute.to_s.upcase}:</strong> #{h error.message}</p>"
|
123
|
+
end
|
124
|
+
|
125
|
+
def not_found_errors
|
126
|
+
if card.errors.any?
|
127
|
+
standard_errors
|
128
|
+
else
|
129
|
+
haml :not_found
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def sign_in_or_up_links to_task
|
134
|
+
return if Auth.signed_in?
|
135
|
+
|
136
|
+
links = [signin_link, signup_link].compact.join " #{tr :or} "
|
137
|
+
wrap_with(:div) do
|
138
|
+
[tr(:please), links, to_task].join(" ") + "."
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def signin_link
|
143
|
+
link_to_card :signin, tr(:sign_in),
|
144
|
+
class: "signin-link", slotter: true, path: { view: :open }
|
145
|
+
end
|
146
|
+
|
147
|
+
def signup_link
|
148
|
+
return unless signup_ok?
|
149
|
+
|
150
|
+
link_to_card :signup, tr(:sign_up),
|
151
|
+
class: "signup-link", slotter: true, path: { action: :new }
|
152
|
+
end
|
153
|
+
|
154
|
+
def signup_ok?
|
155
|
+
Card.new(type_id: Card::SignupID).ok? :create
|
156
|
+
end
|
157
|
+
|
158
|
+
def quiet_denial
|
159
|
+
wrap_with :span, class: "denied" do
|
160
|
+
"<!-- Sorry, you don't have permission (#{@denied_task}) -->"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def loud_denial
|
165
|
+
voo.hide :menu
|
166
|
+
frame do
|
167
|
+
[wrap_with(:h1, tr(:sorry)),
|
168
|
+
wrap_with(:div, loud_denial_message)]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def loud_denial_message
|
173
|
+
to_task = @denied_task ? tr(:denied_task, denied_task: @denied_task) : tr(:to_do_that)
|
174
|
+
|
175
|
+
case
|
176
|
+
when not_denied_task_read?
|
177
|
+
tr(:read_only)
|
178
|
+
when Auth.signed_in?
|
179
|
+
tr(:need_permission_task, task: to_task)
|
180
|
+
else
|
181
|
+
Env.save_interrupted_action request.env["REQUEST_URI"]
|
182
|
+
sign_in_or_up_links to_do_unauthorized_task
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def not_denied_task_read?
|
187
|
+
@denied_task != :read && Card.config.read_only
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_do_unauthorized_task
|
191
|
+
@denied_task ? tr(:denied_task, denied_task: @denied_task) : tr(:to_do_that)
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,1015 @@
|
|
1
|
+
|
2
|
+
:css
|
3
|
+
/* Basic reset */
|
4
|
+
* {
|
5
|
+
margin: 0;
|
6
|
+
padding: 0;
|
7
|
+
}
|
8
|
+
|
9
|
+
table {
|
10
|
+
width: 100%;
|
11
|
+
border-collapse: collapse;
|
12
|
+
}
|
13
|
+
|
14
|
+
th, td {
|
15
|
+
vertical-align: top;
|
16
|
+
text-align: left;
|
17
|
+
}
|
18
|
+
|
19
|
+
textarea {
|
20
|
+
resize: none;
|
21
|
+
}
|
22
|
+
|
23
|
+
body {
|
24
|
+
font-size: 10pt;
|
25
|
+
}
|
26
|
+
|
27
|
+
body, td, input, textarea {
|
28
|
+
font-family: helvetica neue, lucida grande, sans-serif;
|
29
|
+
line-height: 1.5;
|
30
|
+
color: #333;
|
31
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
32
|
+
}
|
33
|
+
|
34
|
+
html {
|
35
|
+
background: #f0f0f5;
|
36
|
+
}
|
37
|
+
|
38
|
+
.clearfix::after{
|
39
|
+
clear: both;
|
40
|
+
content: ".";
|
41
|
+
display: block;
|
42
|
+
height: 0;
|
43
|
+
visibility: hidden;
|
44
|
+
}
|
45
|
+
|
46
|
+
/* ---------------------------------------------------------------------
|
47
|
+
* Basic layout
|
48
|
+
* --------------------------------------------------------------------- */
|
49
|
+
|
50
|
+
/* Small */
|
51
|
+
@media screen and (max-width: 1100px) {
|
52
|
+
html {
|
53
|
+
overflow-y: scroll;
|
54
|
+
}
|
55
|
+
|
56
|
+
body {
|
57
|
+
margin: 0 20px;
|
58
|
+
}
|
59
|
+
|
60
|
+
header.exception {
|
61
|
+
margin: 0 -20px;
|
62
|
+
}
|
63
|
+
|
64
|
+
nav.sidebar {
|
65
|
+
padding: 0;
|
66
|
+
margin: 20px 0;
|
67
|
+
}
|
68
|
+
|
69
|
+
ul.frames {
|
70
|
+
max-height: 200px;
|
71
|
+
overflow: auto;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
/* Wide */
|
76
|
+
@media screen and (min-width: 1100px) {
|
77
|
+
header.exception {
|
78
|
+
position: fixed;
|
79
|
+
top: 0;
|
80
|
+
left: 0;
|
81
|
+
right: 0;
|
82
|
+
}
|
83
|
+
|
84
|
+
nav.sidebar,
|
85
|
+
.frame_info {
|
86
|
+
position: fixed;
|
87
|
+
top: 95px;
|
88
|
+
bottom: 0;
|
89
|
+
|
90
|
+
box-sizing: border-box;
|
91
|
+
|
92
|
+
overflow-y: auto;
|
93
|
+
overflow-x: hidden;
|
94
|
+
}
|
95
|
+
|
96
|
+
nav.sidebar {
|
97
|
+
width: 40%;
|
98
|
+
left: 20px;
|
99
|
+
top: 115px;
|
100
|
+
bottom: 20px;
|
101
|
+
}
|
102
|
+
|
103
|
+
.frame_info {
|
104
|
+
right: 0;
|
105
|
+
left: 40%;
|
106
|
+
|
107
|
+
padding: 20px;
|
108
|
+
padding-left: 10px;
|
109
|
+
margin-left: 30px;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
nav.sidebar {
|
114
|
+
background: #d3d3da;
|
115
|
+
border-top: solid 3px #a33;
|
116
|
+
border-bottom: solid 3px #a33;
|
117
|
+
border-radius: 4px;
|
118
|
+
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
119
|
+
}
|
120
|
+
|
121
|
+
/* ---------------------------------------------------------------------
|
122
|
+
* Header
|
123
|
+
* --------------------------------------------------------------------- */
|
124
|
+
|
125
|
+
header.exception {
|
126
|
+
padding: 18px 20px;
|
127
|
+
|
128
|
+
height: 59px;
|
129
|
+
min-height: 59px;
|
130
|
+
|
131
|
+
overflow: hidden;
|
132
|
+
|
133
|
+
background-color: #20202a;
|
134
|
+
color: #aaa;
|
135
|
+
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
|
136
|
+
font-weight: 200;
|
137
|
+
box-shadow: inset 0 -5px 3px -3px rgba(0, 0, 0, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
|
138
|
+
|
139
|
+
-webkit-text-smoothing: antialiased;
|
140
|
+
}
|
141
|
+
|
142
|
+
/* Heading */
|
143
|
+
header.exception h2 {
|
144
|
+
font-weight: 200;
|
145
|
+
font-size: 11pt;
|
146
|
+
}
|
147
|
+
|
148
|
+
header.exception h2,
|
149
|
+
header.exception p {
|
150
|
+
line-height: 1.4em;
|
151
|
+
overflow: hidden;
|
152
|
+
white-space: pre;
|
153
|
+
text-overflow: ellipsis;
|
154
|
+
}
|
155
|
+
|
156
|
+
header.exception h2 strong {
|
157
|
+
font-weight: 700;
|
158
|
+
color: #d55;
|
159
|
+
}
|
160
|
+
|
161
|
+
header.exception p {
|
162
|
+
font-weight: 200;
|
163
|
+
font-size: 20pt;
|
164
|
+
color: white;
|
165
|
+
}
|
166
|
+
|
167
|
+
header.exception:hover {
|
168
|
+
height: auto;
|
169
|
+
z-index: 2;
|
170
|
+
}
|
171
|
+
|
172
|
+
header.exception:hover h2,
|
173
|
+
header.exception:hover p {
|
174
|
+
padding-right: 20px;
|
175
|
+
overflow-y: auto;
|
176
|
+
word-wrap: break-word;
|
177
|
+
white-space: pre-wrap;
|
178
|
+
height: auto;
|
179
|
+
max-height: 7.5em;
|
180
|
+
}
|
181
|
+
|
182
|
+
@media screen and (max-width: 1100px) {
|
183
|
+
header.exception {
|
184
|
+
height: auto;
|
185
|
+
}
|
186
|
+
|
187
|
+
header.exception h2,
|
188
|
+
header.exception p {
|
189
|
+
padding-right: 20px;
|
190
|
+
overflow-y: auto;
|
191
|
+
word-wrap: break-word;
|
192
|
+
height: auto;
|
193
|
+
max-height: 7em;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
<haml_silent>
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
</haml_silent>
|
212
|
+
/* ---------------------------------------------------------------------
|
213
|
+
* Navigation
|
214
|
+
* --------------------------------------------------------------------- */
|
215
|
+
|
216
|
+
nav.tabs {
|
217
|
+
border-bottom: solid 1px #ddd;
|
218
|
+
|
219
|
+
background-color: #eee;
|
220
|
+
text-align: center;
|
221
|
+
|
222
|
+
padding: 6px;
|
223
|
+
|
224
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
225
|
+
}
|
226
|
+
|
227
|
+
nav.tabs a {
|
228
|
+
display: inline-block;
|
229
|
+
|
230
|
+
height: 22px;
|
231
|
+
line-height: 22px;
|
232
|
+
padding: 0 10px;
|
233
|
+
|
234
|
+
text-decoration: none;
|
235
|
+
font-size: 8pt;
|
236
|
+
font-weight: bold;
|
237
|
+
|
238
|
+
color: #999;
|
239
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
240
|
+
}
|
241
|
+
|
242
|
+
nav.tabs a.selected {
|
243
|
+
color: white;
|
244
|
+
background: rgba(0, 0, 0, 0.5);
|
245
|
+
border-radius: 16px;
|
246
|
+
box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.1);
|
247
|
+
text-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.4);
|
248
|
+
}
|
249
|
+
|
250
|
+
nav.tabs a.disabled {
|
251
|
+
text-decoration: line-through;
|
252
|
+
text-shadow: none;
|
253
|
+
cursor: default;
|
254
|
+
}
|
255
|
+
|
256
|
+
/* ---------------------------------------------------------------------
|
257
|
+
* Sidebar
|
258
|
+
* --------------------------------------------------------------------- */
|
259
|
+
|
260
|
+
ul.frames {
|
261
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
262
|
+
}
|
263
|
+
|
264
|
+
/* Each item */
|
265
|
+
ul.frames li {
|
266
|
+
background-color: #f8f8f8;
|
267
|
+
background: -webkit-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
268
|
+
background: -moz-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
269
|
+
background: linear-gradient(top, #f8f8f8 80%, #f0f0f0);
|
270
|
+
box-shadow: inset 0 -1px 0 #e2e2e2;
|
271
|
+
padding: 7px 20px;
|
272
|
+
|
273
|
+
cursor: pointer;
|
274
|
+
overflow: hidden;
|
275
|
+
}
|
276
|
+
|
277
|
+
ul.frames .name,
|
278
|
+
ul.frames .location {
|
279
|
+
overflow: hidden;
|
280
|
+
height: 1.5em;
|
281
|
+
|
282
|
+
white-space: nowrap;
|
283
|
+
word-wrap: none;
|
284
|
+
text-overflow: ellipsis;
|
285
|
+
}
|
286
|
+
|
287
|
+
ul.frames .method {
|
288
|
+
color: #966;
|
289
|
+
}
|
290
|
+
|
291
|
+
ul.frames .location {
|
292
|
+
font-size: 0.85em;
|
293
|
+
font-weight: 400;
|
294
|
+
color: #999;
|
295
|
+
}
|
296
|
+
|
297
|
+
ul.frames .line {
|
298
|
+
font-weight: bold;
|
299
|
+
}
|
300
|
+
|
301
|
+
/* Selected frame */
|
302
|
+
ul.frames li.selected {
|
303
|
+
background: #38a;
|
304
|
+
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);
|
305
|
+
}
|
306
|
+
|
307
|
+
ul.frames li.selected .name,
|
308
|
+
ul.frames li.selected .method,
|
309
|
+
ul.frames li.selected .location {
|
310
|
+
color: white;
|
311
|
+
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
|
312
|
+
}
|
313
|
+
|
314
|
+
ul.frames li.selected .location {
|
315
|
+
opacity: 0.6;
|
316
|
+
}
|
317
|
+
|
318
|
+
/* Iconography */
|
319
|
+
ul.frames li {
|
320
|
+
padding-left: 60px;
|
321
|
+
position: relative;
|
322
|
+
}
|
323
|
+
|
324
|
+
ul.frames li .icon {
|
325
|
+
display: block;
|
326
|
+
width: 20px;
|
327
|
+
height: 20px;
|
328
|
+
line-height: 20px;
|
329
|
+
border-radius: 15px;
|
330
|
+
|
331
|
+
text-align: center;
|
332
|
+
|
333
|
+
background: white;
|
334
|
+
border: solid 2px #ccc;
|
335
|
+
|
336
|
+
font-size: 9pt;
|
337
|
+
font-weight: 200;
|
338
|
+
font-style: normal;
|
339
|
+
|
340
|
+
position: absolute;
|
341
|
+
top: 14px;
|
342
|
+
left: 20px;
|
343
|
+
}
|
344
|
+
|
345
|
+
ul.frames .icon.application {
|
346
|
+
background: #808090;
|
347
|
+
border-color: #555;
|
348
|
+
}
|
349
|
+
|
350
|
+
ul.frames .icon.application:before {
|
351
|
+
content: 'A';
|
352
|
+
color: white;
|
353
|
+
text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
|
354
|
+
}
|
355
|
+
|
356
|
+
/* Responsiveness -- flow to single-line mode */
|
357
|
+
@media screen and (max-width: 1100px) {
|
358
|
+
ul.frames li {
|
359
|
+
padding-top: 6px;
|
360
|
+
padding-bottom: 6px;
|
361
|
+
padding-left: 36px;
|
362
|
+
line-height: 1.3;
|
363
|
+
}
|
364
|
+
|
365
|
+
ul.frames li .icon {
|
366
|
+
width: 11px;
|
367
|
+
height: 11px;
|
368
|
+
line-height: 11px;
|
369
|
+
|
370
|
+
top: 7px;
|
371
|
+
left: 10px;
|
372
|
+
font-size: 5pt;
|
373
|
+
}
|
374
|
+
|
375
|
+
ul.frames .name,
|
376
|
+
ul.frames .location {
|
377
|
+
display: inline-block;
|
378
|
+
line-height: 1.3;
|
379
|
+
height: 1.3em;
|
380
|
+
}
|
381
|
+
|
382
|
+
ul.frames .name {
|
383
|
+
margin-right: 10px;
|
384
|
+
}
|
385
|
+
}
|
386
|
+
|
387
|
+
/* ---------------------------------------------------------------------
|
388
|
+
* Monospace
|
389
|
+
* --------------------------------------------------------------------- */
|
390
|
+
|
391
|
+
pre, code, .be-repl input, .be-repl .command-line span, textarea, .code_linenums {
|
392
|
+
font-family: menlo, lucida console, monospace;
|
393
|
+
font-size: 8pt;
|
394
|
+
}
|
395
|
+
|
396
|
+
/* ---------------------------------------------------------------------
|
397
|
+
* Display area
|
398
|
+
* --------------------------------------------------------------------- */
|
399
|
+
|
400
|
+
.trace_info {
|
401
|
+
background: #fff;
|
402
|
+
padding: 6px;
|
403
|
+
border-radius: 3px;
|
404
|
+
margin-bottom: 2px;
|
405
|
+
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);
|
406
|
+
}
|
407
|
+
|
408
|
+
.code_block{
|
409
|
+
background: #f1f1f1;
|
410
|
+
border-left: 1px solid #ccc;
|
411
|
+
}
|
412
|
+
|
413
|
+
/* Titlebar */
|
414
|
+
.trace_info .title {
|
415
|
+
background: #f1f1f1;
|
416
|
+
|
417
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
418
|
+
overflow: hidden;
|
419
|
+
padding: 6px 10px;
|
420
|
+
|
421
|
+
border: solid 1px #ccc;
|
422
|
+
border-bottom: 0;
|
423
|
+
|
424
|
+
border-top-left-radius: 2px;
|
425
|
+
border-top-right-radius: 2px;
|
426
|
+
}
|
427
|
+
|
428
|
+
.trace_info .title .name,
|
429
|
+
.trace_info .title .location {
|
430
|
+
font-size: 9pt;
|
431
|
+
line-height: 26px;
|
432
|
+
height: 26px;
|
433
|
+
overflow: hidden;
|
434
|
+
}
|
435
|
+
|
436
|
+
.trace_info .title .location {
|
437
|
+
float: left;
|
438
|
+
font-weight: bold;
|
439
|
+
font-size: 10pt;
|
440
|
+
}
|
441
|
+
|
442
|
+
.trace_info .title .location a {
|
443
|
+
color:inherit;
|
444
|
+
text-decoration:none;
|
445
|
+
border-bottom:1px solid #aaaaaa;
|
446
|
+
}
|
447
|
+
|
448
|
+
.trace_info .title .location a:hover {
|
449
|
+
border-color:#666666;
|
450
|
+
}
|
451
|
+
|
452
|
+
.trace_info .title .name {
|
453
|
+
float: right;
|
454
|
+
font-weight: 200;
|
455
|
+
}
|
456
|
+
|
457
|
+
.code, .be-console, .unavailable {
|
458
|
+
background: #fff;
|
459
|
+
padding: 5px;
|
460
|
+
|
461
|
+
box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
462
|
+
}
|
463
|
+
|
464
|
+
.code_linenums{
|
465
|
+
background:#f1f1f1;
|
466
|
+
padding-top:10px;
|
467
|
+
padding-bottom:9px;
|
468
|
+
float:left;
|
469
|
+
}
|
470
|
+
|
471
|
+
.code_linenums span{
|
472
|
+
display:block;
|
473
|
+
padding:0 12px;
|
474
|
+
}
|
475
|
+
|
476
|
+
.code {
|
477
|
+
margin-bottom: -1px;
|
478
|
+
border-top-left-radius:2px;
|
479
|
+
padding: 10px 0;
|
480
|
+
overflow: auto;
|
481
|
+
}
|
482
|
+
|
483
|
+
.code pre{
|
484
|
+
padding-left:12px;
|
485
|
+
min-height:16px;
|
486
|
+
}
|
487
|
+
|
488
|
+
/* Source unavailable */
|
489
|
+
p.unavailable {
|
490
|
+
padding: 20px 0 40px 0;
|
491
|
+
text-align: center;
|
492
|
+
color: #b99;
|
493
|
+
font-weight: bold;
|
494
|
+
}
|
495
|
+
|
496
|
+
p.unavailable:before {
|
497
|
+
content: '\00d7';
|
498
|
+
display: block;
|
499
|
+
|
500
|
+
color: #daa;
|
501
|
+
|
502
|
+
text-align: center;
|
503
|
+
font-size: 40pt;
|
504
|
+
font-weight: normal;
|
505
|
+
margin-bottom: -10px;
|
506
|
+
}
|
507
|
+
|
508
|
+
@-webkit-keyframes highlight {
|
509
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
510
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
511
|
+
}
|
512
|
+
@-moz-keyframes highlight {
|
513
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
514
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
515
|
+
}
|
516
|
+
@keyframes highlight {
|
517
|
+
0% { background: rgba(220, 30, 30, 0.3); }
|
518
|
+
100% { background: rgba(220, 30, 30, 0.1); }
|
519
|
+
}
|
520
|
+
|
521
|
+
.code .highlight, .code_linenums .highlight {
|
522
|
+
background: rgba(220, 30, 30, 0.1);
|
523
|
+
-webkit-animation: highlight 400ms linear 1;
|
524
|
+
-moz-animation: highlight 400ms linear 1;
|
525
|
+
animation: highlight 400ms linear 1;
|
526
|
+
}
|
527
|
+
|
528
|
+
/* REPL shell */
|
529
|
+
.be-console {
|
530
|
+
padding: 0 1px 10px 1px;
|
531
|
+
border-bottom-left-radius: 2px;
|
532
|
+
border-bottom-right-radius: 2px;
|
533
|
+
}
|
534
|
+
|
535
|
+
.be-console pre {
|
536
|
+
padding: 10px 10px 0 10px;
|
537
|
+
max-height: 400px;
|
538
|
+
overflow-x: none;
|
539
|
+
overflow-y: auto;
|
540
|
+
margin-bottom: -3px;
|
541
|
+
word-wrap: break-word;
|
542
|
+
white-space: pre-wrap;
|
543
|
+
}
|
544
|
+
|
545
|
+
/* .command-line > span + input */
|
546
|
+
.be-console .command-line {
|
547
|
+
display: table;
|
548
|
+
width: 100%;
|
549
|
+
}
|
550
|
+
|
551
|
+
.be-console .command-line span,
|
552
|
+
.be-console .command-line input {
|
553
|
+
display: table-cell;
|
554
|
+
}
|
555
|
+
|
556
|
+
.be-console .command-line span {
|
557
|
+
width: 1%;
|
558
|
+
padding-right: 5px;
|
559
|
+
padding-left: 10px;
|
560
|
+
white-space: pre;
|
561
|
+
}
|
562
|
+
|
563
|
+
.be-console .command-line input {
|
564
|
+
width: 99%;
|
565
|
+
}
|
566
|
+
|
567
|
+
/* Input box */
|
568
|
+
.be-console input,
|
569
|
+
.be-console input:focus {
|
570
|
+
outline: 0;
|
571
|
+
border: 0;
|
572
|
+
padding: 0;
|
573
|
+
background: transparent;
|
574
|
+
margin: 0;
|
575
|
+
}
|
576
|
+
|
577
|
+
/* Hint text */
|
578
|
+
.hint {
|
579
|
+
margin: 15px 0 20px 0;
|
580
|
+
font-size: 8pt;
|
581
|
+
color: #8080a0;
|
582
|
+
padding-left: 20px;
|
583
|
+
}
|
584
|
+
|
585
|
+
.hint:before {
|
586
|
+
content: '\25b2';
|
587
|
+
margin-right: 5px;
|
588
|
+
opacity: 0.5;
|
589
|
+
}
|
590
|
+
|
591
|
+
/* ---------------------------------------------------------------------
|
592
|
+
* Variable infos
|
593
|
+
* --------------------------------------------------------------------- */
|
594
|
+
|
595
|
+
.sub {
|
596
|
+
padding: 10px 0;
|
597
|
+
margin: 10px 0;
|
598
|
+
}
|
599
|
+
|
600
|
+
.sub:before {
|
601
|
+
content: '';
|
602
|
+
display: block;
|
603
|
+
width: 100%;
|
604
|
+
height: 4px;
|
605
|
+
|
606
|
+
border-radius: 2px;
|
607
|
+
background: rgba(0, 150, 200, 0.05);
|
608
|
+
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);
|
609
|
+
}
|
610
|
+
|
611
|
+
.sub h3 {
|
612
|
+
color: #39a;
|
613
|
+
font-size: 1.1em;
|
614
|
+
margin: 10px 0;
|
615
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
616
|
+
|
617
|
+
-webkit-font-smoothing: antialiased;
|
618
|
+
}
|
619
|
+
|
620
|
+
.sub .inset {
|
621
|
+
overflow-y: auto;
|
622
|
+
}
|
623
|
+
|
624
|
+
.sub table {
|
625
|
+
table-layout: fixed;
|
626
|
+
}
|
627
|
+
|
628
|
+
.sub table td {
|
629
|
+
border-top: dotted 1px #ddd;
|
630
|
+
padding: 7px 1px;
|
631
|
+
}
|
632
|
+
|
633
|
+
.sub table td.name {
|
634
|
+
width: 150px;
|
635
|
+
|
636
|
+
font-weight: bold;
|
637
|
+
font-size: 0.8em;
|
638
|
+
padding-right: 20px;
|
639
|
+
|
640
|
+
word-wrap: break-word;
|
641
|
+
}
|
642
|
+
|
643
|
+
.sub table td pre {
|
644
|
+
max-height: 15em;
|
645
|
+
overflow-y: auto;
|
646
|
+
}
|
647
|
+
|
648
|
+
.sub table td pre {
|
649
|
+
width: 100%;
|
650
|
+
|
651
|
+
word-wrap: break-word;
|
652
|
+
white-space: normal;
|
653
|
+
}
|
654
|
+
|
655
|
+
/* "(object doesn't support inspect)" */
|
656
|
+
.sub .unsupported {
|
657
|
+
font-family: sans-serif;
|
658
|
+
color: #777;
|
659
|
+
}
|
660
|
+
|
661
|
+
/* ---------------------------------------------------------------------
|
662
|
+
* Scrollbar
|
663
|
+
* --------------------------------------------------------------------- */
|
664
|
+
|
665
|
+
nav.sidebar::-webkit-scrollbar,
|
666
|
+
.inset pre::-webkit-scrollbar,
|
667
|
+
.be-console pre::-webkit-scrollbar,
|
668
|
+
.code::-webkit-scrollbar {
|
669
|
+
width: 10px;
|
670
|
+
height: 10px;
|
671
|
+
}
|
672
|
+
|
673
|
+
.inset pre::-webkit-scrollbar-thumb,
|
674
|
+
.be-console pre::-webkit-scrollbar-thumb,
|
675
|
+
.code::-webkit-scrollbar-thumb {
|
676
|
+
background: #ccc;
|
677
|
+
border-radius: 5px;
|
678
|
+
}
|
679
|
+
|
680
|
+
nav.sidebar::-webkit-scrollbar-thumb {
|
681
|
+
background: rgba(0, 0, 0, 0.0);
|
682
|
+
border-radius: 5px;
|
683
|
+
}
|
684
|
+
|
685
|
+
nav.sidebar:hover::-webkit-scrollbar-thumb {
|
686
|
+
background-color: #999;
|
687
|
+
background: -webkit-linear-gradient(left, #aaa, #999);
|
688
|
+
}
|
689
|
+
|
690
|
+
.be-console pre:hover::-webkit-scrollbar-thumb,
|
691
|
+
.inset pre:hover::-webkit-scrollbar-thumb,
|
692
|
+
.code:hover::-webkit-scrollbar-thumb {
|
693
|
+
background: #888;
|
694
|
+
}
|
695
|
+
:javascript
|
696
|
+
(function() {
|
697
|
+
var elements = ["section", "nav", "header", "footer", "audio"];
|
698
|
+
for (var i = 0; i < elements.length; i++) {
|
699
|
+
document.createElement(elements[i]);
|
700
|
+
}
|
701
|
+
})();
|
702
|
+
:javascript
|
703
|
+
if (window.Turbolinks) {
|
704
|
+
for(var i=0; i < document.styleSheets.length; i++) {
|
705
|
+
if(document.styleSheets[i].href)
|
706
|
+
document.styleSheets[i].disabled = true;
|
707
|
+
}
|
708
|
+
if (window.Turbolinks.controller) {
|
709
|
+
// Turbolinks > 5 (see https://github.com/turbolinks/turbolinks/issues/6)
|
710
|
+
document.addEventListener("turbolinks:load", function restoreCSS(e) {
|
711
|
+
for(var i=0; i < document.styleSheets.length; i++) {
|
712
|
+
document.styleSheets[i].disabled = false;
|
713
|
+
}
|
714
|
+
document.removeEventListener("turbolinks:load", restoreCSS, false);
|
715
|
+
});
|
716
|
+
} else {
|
717
|
+
document.addEventListener("page:restore", function restoreCSS(e) {
|
718
|
+
for(var i=0; i < document.styleSheets.length; i++) {
|
719
|
+
document.styleSheets[i].disabled = false;
|
720
|
+
}
|
721
|
+
document.removeEventListener("page:restore", restoreCSS, false);
|
722
|
+
});
|
723
|
+
}
|
724
|
+
}
|
725
|
+
.top
|
726
|
+
%header.exception
|
727
|
+
%h2
|
728
|
+
%strong= exception_type
|
729
|
+
%span
|
730
|
+
at #{request_path}
|
731
|
+
%p= exception_message
|
732
|
+
%section.backtrace
|
733
|
+
%nav.sidebar
|
734
|
+
%nav.tabs
|
735
|
+
%a#application_frames{:href => "#"} Application Frames
|
736
|
+
%a#all_frames{:href => "#"} All Frames
|
737
|
+
%ul.frames
|
738
|
+
- backtrace_frames.each_with_index do |frame, index|
|
739
|
+
%li{:class => "#{frame.context}", "data-context" => "#{frame.context}", "data-index" => index}
|
740
|
+
%span.stroke
|
741
|
+
%i{:class => "icon #{frame.context}"}
|
742
|
+
.info
|
743
|
+
.name
|
744
|
+
%strong= frame.class_name
|
745
|
+
%span.method= frame.method_name
|
746
|
+
.location
|
747
|
+
%span.filename>= frame.pretty_path
|
748
|
+
, line
|
749
|
+
%span.line= frame.line
|
750
|
+
- backtrace_frames.each_with_index do |frame, index|
|
751
|
+
.frame_info{:id => "frame_info_#{index}", :style => "display:none;"}
|
752
|
+
:javascript
|
753
|
+
(function() {
|
754
|
+
|
755
|
+
var OID = "#{id}";
|
756
|
+
|
757
|
+
var previousFrame = null;
|
758
|
+
var previousFrameInfo = null;
|
759
|
+
var allFrames = document.querySelectorAll("ul.frames li");
|
760
|
+
var allFrameInfos = document.querySelectorAll(".frame_info");
|
761
|
+
|
762
|
+
function apiCall(method, opts, cb) {
|
763
|
+
var req = new XMLHttpRequest();
|
764
|
+
req.open("POST", "//" + window.location.host + "/__better_errors/" + OID + "/" + method, true);
|
765
|
+
req.setRequestHeader("Content-Type", "application/json");
|
766
|
+
req.send(JSON.stringify(opts));
|
767
|
+
req.onreadystatechange = function() {
|
768
|
+
if(req.readyState == 4) {
|
769
|
+
var res = JSON.parse(req.responseText);
|
770
|
+
cb(res);
|
771
|
+
}
|
772
|
+
};
|
773
|
+
}
|
774
|
+
|
775
|
+
function escapeHTML(html) {
|
776
|
+
return html.replace(/&/, "&").replace(/</g, "<");
|
777
|
+
}
|
778
|
+
|
779
|
+
function REPL(index) {
|
780
|
+
this.index = index;
|
781
|
+
|
782
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
783
|
+
if(previousCommands === null) {
|
784
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify([]));
|
785
|
+
previousCommands = [];
|
786
|
+
}
|
787
|
+
|
788
|
+
this.previousCommandOffset = previousCommands.length;
|
789
|
+
}
|
790
|
+
|
791
|
+
REPL.all = [];
|
792
|
+
|
793
|
+
REPL.prototype.install = function(containerElement) {
|
794
|
+
this.container = containerElement;
|
795
|
+
|
796
|
+
this.promptElement = this.container.querySelector(".command-line .prompt");
|
797
|
+
this.inputElement = this.container.querySelector("input");
|
798
|
+
this.outputElement = this.container.querySelector("pre");
|
799
|
+
|
800
|
+
var self = this;
|
801
|
+
this.inputElement.onkeydown = function(ev) {
|
802
|
+
self.onKeyDown(ev);
|
803
|
+
};
|
804
|
+
|
805
|
+
this.setPrompt(">>");
|
806
|
+
|
807
|
+
REPL.all[this.index] = this;
|
808
|
+
}
|
809
|
+
|
810
|
+
REPL.prototype.focus = function() {
|
811
|
+
this.inputElement.focus();
|
812
|
+
};
|
813
|
+
|
814
|
+
REPL.prototype.setPrompt = function(prompt) {
|
815
|
+
this._prompt = prompt;
|
816
|
+
this.promptElement.innerHTML = escapeHTML(prompt);
|
817
|
+
};
|
818
|
+
|
819
|
+
REPL.prototype.getInput = function() {
|
820
|
+
return this.inputElement.value;
|
821
|
+
};
|
822
|
+
|
823
|
+
REPL.prototype.setInput = function(text) {
|
824
|
+
this.inputElement.value = text;
|
825
|
+
|
826
|
+
if(this.inputElement.setSelectionRange) {
|
827
|
+
// set cursor to end of input
|
828
|
+
this.inputElement.setSelectionRange(text.length, text.length);
|
829
|
+
}
|
830
|
+
};
|
831
|
+
|
832
|
+
REPL.prototype.writeRawOutput = function(output) {
|
833
|
+
this.outputElement.innerHTML += output;
|
834
|
+
this.outputElement.scrollTop = this.outputElement.scrollHeight;
|
835
|
+
};
|
836
|
+
|
837
|
+
REPL.prototype.writeOutput = function(output) {
|
838
|
+
this.writeRawOutput(escapeHTML(output));
|
839
|
+
};
|
840
|
+
|
841
|
+
REPL.prototype.sendInput = function(line) {
|
842
|
+
var self = this;
|
843
|
+
apiCall("eval", { "index": this.index, source: line }, function(response) {
|
844
|
+
if(response.error) {
|
845
|
+
self.writeOutput(response.error + "\n");
|
846
|
+
}
|
847
|
+
self.writeOutput(self._prompt + " ");
|
848
|
+
self.writeRawOutput(response.highlighted_input + "\n");
|
849
|
+
self.writeOutput(response.result);
|
850
|
+
self.setPrompt(response.prompt);
|
851
|
+
self.setInput(response.prefilled_input);
|
852
|
+
});
|
853
|
+
};
|
854
|
+
|
855
|
+
REPL.prototype.onEnterKey = function() {
|
856
|
+
var text = this.getInput();
|
857
|
+
if(text != "" && text !== undefined) {
|
858
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
859
|
+
this.previousCommandOffset = previousCommands.push(text);
|
860
|
+
if(previousCommands.length > 100) {
|
861
|
+
previousCommands.splice(0, 1);
|
862
|
+
this.previousCommandOffset -= 1;
|
863
|
+
}
|
864
|
+
localStorage.setItem("better_errors_previous_commands", JSON.stringify(previousCommands));
|
865
|
+
}
|
866
|
+
this.setInput("");
|
867
|
+
this.sendInput(text);
|
868
|
+
};
|
869
|
+
|
870
|
+
REPL.prototype.onNavigateHistory = function(direction) {
|
871
|
+
this.previousCommandOffset += direction;
|
872
|
+
var previousCommands = JSON.parse(localStorage.getItem("better_errors_previous_commands"));
|
873
|
+
|
874
|
+
if(this.previousCommandOffset < 0) {
|
875
|
+
this.previousCommandOffset = -1;
|
876
|
+
this.setInput("");
|
877
|
+
return;
|
878
|
+
}
|
879
|
+
|
880
|
+
if(this.previousCommandOffset >= previousCommands.length) {
|
881
|
+
this.previousCommandOffset = previousCommands.length;
|
882
|
+
this.setInput("");
|
883
|
+
return;
|
884
|
+
}
|
885
|
+
|
886
|
+
this.setInput(previousCommands[this.previousCommandOffset]);
|
887
|
+
};
|
888
|
+
|
889
|
+
REPL.prototype.onKeyDown = function(ev) {
|
890
|
+
if(ev.keyCode == 13) {
|
891
|
+
this.onEnterKey();
|
892
|
+
} else if(ev.keyCode == 38 || (ev.ctrlKey && ev.keyCode == 80)) {
|
893
|
+
// the user pressed the up arrow or Ctrl-P
|
894
|
+
this.onNavigateHistory(-1);
|
895
|
+
ev.preventDefault();
|
896
|
+
return false;
|
897
|
+
} else if(ev.keyCode == 40 || (ev.ctrlKey && ev.keyCode == 78)) {
|
898
|
+
// the user pressed the down arrow or Ctrl-N
|
899
|
+
this.onNavigateHistory(1);
|
900
|
+
ev.preventDefault();
|
901
|
+
return false;
|
902
|
+
}
|
903
|
+
};
|
904
|
+
|
905
|
+
function switchTo(el) {
|
906
|
+
if(previousFrameInfo) previousFrameInfo.style.display = "none";
|
907
|
+
previousFrameInfo = el;
|
908
|
+
|
909
|
+
el.style.display = "block";
|
910
|
+
|
911
|
+
var replInput = el.querySelector('.be-console input');
|
912
|
+
if (replInput) replInput.focus();
|
913
|
+
}
|
914
|
+
|
915
|
+
function selectFrameInfo(index) {
|
916
|
+
var el = allFrameInfos[index];
|
917
|
+
if(el) {
|
918
|
+
if (el.loaded) {
|
919
|
+
return switchTo(el);
|
920
|
+
}
|
921
|
+
|
922
|
+
apiCall("variables", { "index": index }, function(response) {
|
923
|
+
el.loaded = true;
|
924
|
+
if(response.error) {
|
925
|
+
el.innerHTML = "<h2 class='error'>" + escapeHTML(response.error) + "</h2>";
|
926
|
+
if(response.explanation) {
|
927
|
+
el.innerHTML += "<p class='explanation'>" + escapeHTML(response.explanation) + "</p>";
|
928
|
+
}
|
929
|
+
el.innerHTML += "<p><a target='_new' href='https://github.com/BetterErrors/better_errors'>More about Better Errors</a></p>";
|
930
|
+
} else {
|
931
|
+
el.innerHTML = response.html;
|
932
|
+
|
933
|
+
var repl = el.querySelector(".be-repl .be-console");
|
934
|
+
if(repl) {
|
935
|
+
new REPL(index).install(repl);
|
936
|
+
}
|
937
|
+
}
|
938
|
+
switchTo(el);
|
939
|
+
});
|
940
|
+
}
|
941
|
+
}
|
942
|
+
|
943
|
+
for(var i = 0; i < allFrames.length; i++) {
|
944
|
+
(function(i, el) {
|
945
|
+
var el = allFrames[i];
|
946
|
+
el.onclick = function() {
|
947
|
+
if(previousFrame) {
|
948
|
+
previousFrame.className = "";
|
949
|
+
}
|
950
|
+
el.className = "selected";
|
951
|
+
previousFrame = el;
|
952
|
+
|
953
|
+
selectFrameInfo(el.attributes["data-index"].value);
|
954
|
+
};
|
955
|
+
})(i);
|
956
|
+
}
|
957
|
+
|
958
|
+
// Click the first application frame
|
959
|
+
(
|
960
|
+
document.querySelector(".frames li.application") ||
|
961
|
+
document.querySelector(".frames li")
|
962
|
+
).onclick();
|
963
|
+
|
964
|
+
// This is the second query performed for frames; maybe the 'allFrames' list
|
965
|
+
// currently used and this list can be better used to avoid the repetition:
|
966
|
+
var applicationFramesCount = document.querySelectorAll(
|
967
|
+
"ul.frames li[data-context=application]"
|
968
|
+
).length;
|
969
|
+
|
970
|
+
var applicationFramesButtonIsInstalled = false;
|
971
|
+
var applicationFramesButton = document.getElementById("application_frames");
|
972
|
+
var allFramesButton = document.getElementById("all_frames");
|
973
|
+
|
974
|
+
// The application frames button only needs to be bound if
|
975
|
+
// there are actually any application frames to look at.
|
976
|
+
var installApplicationFramesButton = function() {
|
977
|
+
applicationFramesButton.onclick = function() {
|
978
|
+
allFramesButton.className = "";
|
979
|
+
applicationFramesButton.className = "selected";
|
980
|
+
for(var i = 0; i < allFrames.length; i++) {
|
981
|
+
if(allFrames[i].attributes["data-context"].value == "application") {
|
982
|
+
allFrames[i].style.display = "block";
|
983
|
+
} else {
|
984
|
+
allFrames[i].style.display = "none";
|
985
|
+
}
|
986
|
+
}
|
987
|
+
return false;
|
988
|
+
};
|
989
|
+
|
990
|
+
applicationFramesButtonIsInstalled = true;
|
991
|
+
}
|
992
|
+
|
993
|
+
allFramesButton.onclick = function() {
|
994
|
+
if(applicationFramesButtonIsInstalled) {
|
995
|
+
applicationFramesButton.className = "";
|
996
|
+
}
|
997
|
+
|
998
|
+
allFramesButton.className = "selected";
|
999
|
+
for(var i = 0; i < allFrames.length; i++) {
|
1000
|
+
allFrames[i].style.display = "block";
|
1001
|
+
}
|
1002
|
+
return false;
|
1003
|
+
};
|
1004
|
+
|
1005
|
+
// If there are no application frames, select the 'All Frames'
|
1006
|
+
// tab by default.
|
1007
|
+
if(applicationFramesCount > 0) {
|
1008
|
+
installApplicationFramesButton();
|
1009
|
+
applicationFramesButton.onclick();
|
1010
|
+
} else {
|
1011
|
+
applicationFramesButton.className = "disabled";
|
1012
|
+
applicationFramesButton.title = "No application frames available";
|
1013
|
+
allFramesButton.onclick();
|
1014
|
+
}
|
1015
|
+
})();
|