better_errors 2.6.0 → 2.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8cb5c2454ca55776cbfa1c596788008c56d584202c55fc0599e9fbb0c6d45e9
4
- data.tar.gz: ac7de8121e985ef3277da64604a72e1c117bddba34fa15aa5e838a2bb937bcb7
3
+ metadata.gz: 8d3d72dd8ce0e7e2cca7766facffd1e6ae40a51f23f870683427b2e50bec4e2c
4
+ data.tar.gz: 648379df7f566ebe03c271a42777920bae0b778f412b58d05f65a4eebd9066e7
5
5
  SHA512:
6
- metadata.gz: 4ae119905448207a0af32b0f62fe812c533fe6bc990c85fb5b10066696be80f8ea44ad141a8eb4c7435180042c964a2258c8a5212bf56eb2c45050621aaa467a
7
- data.tar.gz: 2ad99de05bd4905a79cd05bd5428b336e1cdf79d84889d3c6331275749fed3912671ed43e308e86d5afbccc83767ae43e4288bb48fccd00c205cd0c23571ece3
6
+ metadata.gz: c00de73b57d84b02f606bf8aca932ee54abd20a26ae4c8be0a77c57a93810e1483f9ef255ecf92beb4eb6b2573e3b870fa9a8891ea49951768627b02f0ae3852
7
+ data.tar.gz: 54172e86102ee07af71a12ae6e6dcda7d306bb85b0dc387d23ead5ec0c992d5e3372e56d2779bdad7370bed68e5d76c21cb7941083eba699ccc955045fb46941
@@ -1,4 +1,3 @@
1
- sudo: false
2
1
  language: ruby
3
2
  cache: bundler
4
3
  notifications:
@@ -12,20 +11,26 @@ rvm:
12
11
  - 2.3.8
13
12
  - 2.4.9
14
13
  - 2.5.7
14
+ - 2.6.5
15
+ - 2.7.0
15
16
  - ruby-head
17
+ - truffleruby-head
16
18
  gemfile:
17
19
  - gemfiles/rails42.gemfile
18
20
  - gemfiles/rails50.gemfile
19
21
  - gemfiles/rails51.gemfile
20
22
  - gemfiles/rails52.gemfile
23
+ - gemfiles/rails60.gemfile
21
24
  - gemfiles/rails42_haml.gemfile
22
25
  - gemfiles/rails50_haml.gemfile
23
26
  - gemfiles/rails51_haml.gemfile
24
27
  - gemfiles/rails52_haml.gemfile
28
+ - gemfiles/rails60_haml.gemfile
25
29
  - gemfiles/rails42_boc.gemfile
26
30
  - gemfiles/rails50_boc.gemfile
27
31
  - gemfiles/rails51_boc.gemfile
28
32
  - gemfiles/rails52_boc.gemfile
33
+ - gemfiles/rails60_boc.gemfile
29
34
  - gemfiles/rack.gemfile
30
35
  - gemfiles/rack_boc.gemfile
31
36
  - gemfiles/pry09.gemfile
@@ -38,21 +43,69 @@ matrix:
38
43
  - gemfile: gemfiles/pry010.gemfile
39
44
  - gemfile: gemfiles/pry011.gemfile
40
45
  exclude:
46
+ - rvm: 2.2.10
47
+ gemfile: gemfiles/rails60.gemfile
48
+ - rvm: 2.2.10
49
+ gemfile: gemfiles/rails60_boc.gemfile
50
+ - rvm: 2.2.10
51
+ gemfile: gemfiles/rails60_haml.gemfile
41
52
  - rvm: 2.3.8
42
53
  gemfile: gemfiles/rails42.gemfile
43
54
  - rvm: 2.3.8
44
55
  gemfile: gemfiles/rails42_boc.gemfile
45
56
  - rvm: 2.3.8
46
57
  gemfile: gemfiles/rails42_haml.gemfile
58
+ - rvm: 2.3.8
59
+ gemfile: gemfiles/rails60.gemfile
60
+ - rvm: 2.3.8
61
+ gemfile: gemfiles/rails60_boc.gemfile
62
+ - rvm: 2.3.8
63
+ gemfile: gemfiles/rails60_haml.gemfile
47
64
  - rvm: 2.4.9
48
65
  gemfile: gemfiles/rails42.gemfile
49
66
  - rvm: 2.4.9
50
67
  gemfile: gemfiles/rails42_boc.gemfile
51
68
  - rvm: 2.4.9
52
69
  gemfile: gemfiles/rails42_haml.gemfile
70
+ - rvm: 2.4.9
71
+ gemfile: gemfiles/rails60.gemfile
72
+ - rvm: 2.4.9
73
+ gemfile: gemfiles/rails60_boc.gemfile
74
+ - rvm: 2.4.9
75
+ gemfile: gemfiles/rails60_haml.gemfile
53
76
  - rvm: 2.5.7
54
77
  gemfile: gemfiles/rails42.gemfile
55
78
  - rvm: 2.5.7
56
79
  gemfile: gemfiles/rails42_boc.gemfile
57
80
  - rvm: 2.5.7
58
81
  gemfile: gemfiles/rails42_haml.gemfile
82
+ - rvm: 2.6.5
83
+ gemfile: gemfiles/rails42.gemfile
84
+ - rvm: 2.6.5
85
+ gemfile: gemfiles/rails42_boc.gemfile
86
+ - rvm: 2.6.5
87
+ gemfile: gemfiles/rails42_haml.gemfile
88
+ - rvm: 2.7.0
89
+ gemfile: gemfiles/rails42.gemfile
90
+ - rvm: 2.7.0
91
+ gemfile: gemfiles/rails42_boc.gemfile
92
+ - rvm: 2.7.0
93
+ gemfile: gemfiles/rails42_haml.gemfile
94
+ - rvm: ruby-head
95
+ gemfile: gemfiles/rails42.gemfile
96
+ - rvm: ruby-head
97
+ gemfile: gemfiles/rails42_boc.gemfile
98
+ - rvm: ruby-head
99
+ gemfile: gemfiles/rails42_haml.gemfile
100
+ - rvm: truffleruby-head
101
+ gemfile: gemfiles/rails42_boc.gemfile
102
+ - rvm: truffleruby-head
103
+ gemfile: gemfiles/rails50_boc.gemfile
104
+ - rvm: truffleruby-head
105
+ gemfile: gemfiles/rails51_boc.gemfile
106
+ - rvm: truffleruby-head
107
+ gemfile: gemfiles/rails52_boc.gemfile
108
+ - rvm: truffleruby-head
109
+ gemfile: gemfiles/rails60_boc.gemfile
110
+ - rvm: truffleruby-head
111
+ gemfile: gemfiles/rack_boc.gemfile
data/README.md CHANGED
@@ -35,6 +35,28 @@ end
35
35
 
36
36
  _Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._
37
37
 
38
+ ### Optional: Set `EDITOR`
39
+
40
+ For many reasons outside of Better Errors, you should have the `EDITOR` environment variable set to your preferred
41
+ editor.
42
+ Better Errors, like many other tools, will use that environment variable to show a link that opens your
43
+ editor to the file and line from the console.
44
+
45
+ By default the links will open TextMate-protocol links.
46
+
47
+ To see if your editor is supported or to set up a different editor, see [the wiki](https://github.com/BetterErrors/better_errors/wiki/Link-to-your-editor).
48
+
49
+ ### Optional: Set `BETTER_ERRORS_INSIDE_FRAME`
50
+
51
+ If your application is running inside of an iframe, or if you have a Content Security Policy that disallows links
52
+ to other protocols, the editor links will not work.
53
+
54
+ To work around this set `BETTER_ERRORS_INSIDE_FRAME=1` in the environment, and the links will include `target=_blank`,
55
+ allowing the link to open regardless of the policy.
56
+
57
+ _This works because it opens the editor from a new browser tab, escaping from the restrictions of your site._
58
+ _Unfortunately it leaves behind an empty tab each time, so only use this if needed._
59
+
38
60
  ## Security
39
61
 
40
62
  **NOTE:** It is *critical* you put better\_errors only in the **development** section of your Gemfile.
@@ -93,6 +115,16 @@ See [the wiki for instructions on configuring the editor](https://github.com/Bet
93
115
  BetterErrors.maximum_variable_inspect_size = 100_000
94
116
  ```
95
117
 
118
+ ## Ignore inspection of variables with certain classes.
119
+
120
+ ```ruby
121
+ # e.g. in config/initializers/better_errors.rb
122
+ # This will stop BetterErrors from trying to inspect objects of these classes, which can cause
123
+ # slow loading times and unneccessary database queries. Does not check inheritance chain, use
124
+ # strings not contants.
125
+ # default value: ['ActionDispatch::Request', 'ActionDispatch::Response']
126
+ BetterErrors.ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
127
+ ```
96
128
 
97
129
  ## Get in touch!
98
130
 
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency "rake", "~> 10.0"
24
24
  s.add_development_dependency "rspec", "~> 3.5"
25
+ s.add_development_dependency "rspec-html-matchers"
25
26
  s.add_development_dependency "rspec-its"
26
27
  s.add_development_dependency "yard"
27
28
  # kramdown 2.1 requires Ruby 2.3+
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+
5
+ gem 'coveralls', require: false
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+ gem "binding_of_caller"
5
+
6
+ gem 'coveralls', require: false
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0.0"
4
+ gem "haml"
5
+
6
+ gem 'coveralls', require: false
7
+
8
+ gemspec path: "../"
@@ -21,6 +21,7 @@ module BetterErrors
21
21
  { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" },
22
22
  { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" },
23
23
  { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" },
24
+ { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" },
24
25
  { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" },
25
26
  ]
26
27
 
@@ -54,9 +55,14 @@ module BetterErrors
54
55
  # the variable won't be returned.
55
56
  # @return int
56
57
  attr_accessor :maximum_variable_inspect_size
58
+
59
+ # List of classes that are excluded from inspection.
60
+ # @return [Array]
61
+ attr_accessor :ignored_classes
57
62
  end
58
63
  @ignored_instance_variables = []
59
64
  @maximum_variable_inspect_size = 100_000
65
+ @ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
60
66
 
61
67
  # Returns a proc, which when called with a filename and line number argument,
62
68
  # returns a URL to open the filename and line in the selected editor.
@@ -26,8 +26,13 @@ module BetterErrors
26
26
  @id ||= SecureRandom.hex(8)
27
27
  end
28
28
 
29
- def render(template_name = "main")
29
+ def render(template_name = "main", csrf_token = nil)
30
30
  binding.eval(self.class.template(template_name).src)
31
+ rescue => e
32
+ # Fix the backtrace, which doesn't identify the template that failed (within Better Errors).
33
+ # We don't know the line number, so just injecting the template path has to be enough.
34
+ e.backtrace.unshift "#{self.class.template_path(template_name)}:0"
35
+ raise
31
36
  end
32
37
 
33
38
  def do_variables(opts)
@@ -59,7 +64,19 @@ module BetterErrors
59
64
  end
60
65
 
61
66
  def exception_message
62
- exception.message.lstrip
67
+ exception.message.strip.gsub(/(\r?\n\s*\r?\n)+/, "\n")
68
+ end
69
+
70
+ def active_support_actions
71
+ return [] unless defined?(ActiveSupport::ActionableError)
72
+
73
+ ActiveSupport::ActionableError.actions(exception.type)
74
+ end
75
+
76
+ def action_dispatch_action_endpoint
77
+ return unless defined?(ActionDispatch::ActionableExceptions)
78
+
79
+ ActionDispatch::ActionableExceptions.endpoint
63
80
  end
64
81
 
65
82
  def application_frames
@@ -105,7 +122,13 @@ module BetterErrors
105
122
  end
106
123
 
107
124
  def inspect_value(obj)
108
- InspectableValue.new(obj).to_html
125
+ if BetterErrors.ignored_classes.include? obj.class.name
126
+ "<span class='unsupported'>(Instance of ignored class. "\
127
+ "#{obj.class.name ? "Remove #{CGI.escapeHTML(obj.class.name)} from" : "Modify"}"\
128
+ " BetterErrors.ignored_classes if you need to see it.)</span>"
129
+ else
130
+ InspectableValue.new(obj).to_html
131
+ end
109
132
  rescue BetterErrors::ValueLargerThanConfiguredMaximum
110
133
  "<span class='unsupported'>(Object too large. "\
111
134
  "#{obj.class.name ? "Modify #{CGI.escapeHTML(obj.class.name)}#inspect or a" : "A"}"\
@@ -1,5 +1,6 @@
1
1
  require "json"
2
2
  require "ipaddr"
3
+ require "securerandom"
3
4
  require "set"
4
5
  require "rack"
5
6
 
@@ -39,6 +40,8 @@ module BetterErrors
39
40
  allow_ip! "127.0.0.0/8"
40
41
  allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support
41
42
 
43
+ CSRF_TOKEN_COOKIE_NAME = "BetterErrors-#{VERSION}-CSRF-Token"
44
+
42
45
  # A new instance of BetterErrors::Middleware
43
46
  #
44
47
  # @param app The Rack app/middleware to wrap with Better Errors
@@ -72,7 +75,7 @@ module BetterErrors
72
75
  def better_errors_call(env)
73
76
  case env["PATH_INFO"]
74
77
  when %r{/__better_errors/(?<id>.+?)/(?<method>\w+)\z}
75
- internal_call env, $~
78
+ internal_call(env, $~[:id], $~[:method])
76
79
  when %r{/__better_errors/?\z}
77
80
  show_error_page env
78
81
  else
@@ -89,11 +92,14 @@ module BetterErrors
89
92
  end
90
93
 
91
94
  def show_error_page(env, exception=nil)
95
+ request = Rack::Request.new(env)
96
+ csrf_token = request.cookies[CSRF_TOKEN_COOKIE_NAME] || SecureRandom.uuid
97
+
92
98
  type, content = if @error_page
93
99
  if text?(env)
94
100
  [ 'plain', @error_page.render('text') ]
95
101
  else
96
- [ 'html', @error_page.render ]
102
+ [ 'html', @error_page.render('main', csrf_token) ]
97
103
  end
98
104
  else
99
105
  [ 'html', no_errors_page ]
@@ -104,12 +110,22 @@ module BetterErrors
104
110
  status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
105
111
  end
106
112
 
107
- [status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }, [content]]
113
+ response = Rack::Response.new(content, status_code, { "Content-Type" => "text/#{type}; charset=utf-8" })
114
+
115
+ unless request.cookies[CSRF_TOKEN_COOKIE_NAME]
116
+ response.set_cookie(CSRF_TOKEN_COOKIE_NAME, value: csrf_token, path: "/", httponly: true, same_site: :strict)
117
+ end
118
+
119
+ # In older versions of Rack, the body returned here is actually a Rack::BodyProxy which seems to be a bug.
120
+ # (It contains status, headers and body and does not act like an array of strings.)
121
+ # Since we already have status code and body here, there's no need to use the ones in the Rack::Response.
122
+ (_status_code, headers, _body) = response.finish
123
+ [status_code, headers, [content]]
108
124
  end
109
125
 
110
126
  def text?(env)
111
127
  env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" ||
112
- !env["HTTP_ACCEPT"].to_s.include?('html')
128
+ !env["HTTP_ACCEPT"].to_s.include?('html')
113
129
  end
114
130
 
115
131
  def log_exception
@@ -129,13 +145,22 @@ module BetterErrors
129
145
  end
130
146
  end
131
147
 
132
- def internal_call(env, opts)
148
+ def internal_call(env, id, method)
149
+ return not_found_json_response unless %w[variables eval].include?(method)
133
150
  return no_errors_json_response unless @error_page
134
- return invalid_error_json_response if opts[:id] != @error_page.id
151
+ return invalid_error_json_response if id != @error_page.id
152
+
153
+ request = Rack::Request.new(env)
154
+ return invalid_csrf_token_json_response unless request.cookies[CSRF_TOKEN_COOKIE_NAME]
155
+
156
+ request.body.rewind
157
+ body = JSON.parse(request.body.read)
158
+ return invalid_csrf_token_json_response unless request.cookies[CSRF_TOKEN_COOKIE_NAME] == body['csrfToken']
159
+
160
+ return not_acceptable_json_response unless request.content_type == 'application/json'
135
161
 
136
- env["rack.input"].rewind
137
- response = @error_page.send("do_#{opts[:method]}", JSON.parse(env["rack.input"].read))
138
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(response)]]
162
+ response = @error_page.send("do_#{method}", body)
163
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(response)]]
139
164
  end
140
165
 
141
166
  def no_errors_page
@@ -157,18 +182,40 @@ module BetterErrors
157
182
  "The application has been restarted since this page loaded, " +
158
183
  "or the framework is reloading all gems before each request "
159
184
  end
160
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(
185
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
161
186
  error: 'No exception information available',
162
187
  explanation: explanation,
163
188
  )]]
164
189
  end
165
190
 
166
191
  def invalid_error_json_response
167
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(
192
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
168
193
  error: "Session expired",
169
194
  explanation: "This page was likely opened from a previous exception, " +
170
195
  "and the exception is no longer available in memory.",
171
196
  )]]
172
197
  end
198
+
199
+ def invalid_csrf_token_json_response
200
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
201
+ error: "Invalid CSRF Token",
202
+ explanation: "The browser session might have been cleared, " +
203
+ "or something went wrong.",
204
+ )]]
205
+ end
206
+
207
+ def not_found_json_response
208
+ [404, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
209
+ error: "Not found",
210
+ explanation: "Not a recognized internal call.",
211
+ )]]
212
+ end
213
+
214
+ def not_acceptable_json_response
215
+ [406, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.dump(
216
+ error: "Request not acceptable",
217
+ explanation: "The internal request did not match an acceptable content type.",
218
+ )]]
219
+ end
173
220
  end
174
221
  end
@@ -4,9 +4,18 @@ module BetterErrors
4
4
  attr_reader :exception, :message, :backtrace
5
5
 
6
6
  def initialize(exception)
7
- if exception.respond_to?(:cause)
7
+ if exception.class.name == "ActionView::Template::Error" && exception.respond_to?(:cause)
8
+ # Rails 6+ exceptions of this type wrap the "real" exception, and the real exception
9
+ # is actually more useful than the ActionView-provided wrapper. Once Better Errors
10
+ # supports showing all exceptions in the cause stack, this should go away. Or perhaps
11
+ # this can be changed to provide guidance by showing the second error in the cause stack
12
+ # under this condition.
8
13
  exception = exception.cause if exception.cause
9
14
  elsif exception.respond_to?(:original_exception) && exception.original_exception
15
+ # This supports some specific Rails exceptions, and this is not intended to act the same as
16
+ # the Ruby's {Exception#cause}.
17
+ # It's possible this should only support ActionView::Template::Error, but by not changing
18
+ # this we're preserving longstanding behavior of Better Errors with Rails < 6.
10
19
  exception = exception.original_exception
11
20
  end
12
21
 
@@ -36,8 +45,13 @@ module BetterErrors
36
45
 
37
46
  def setup_backtrace_from_bindings
38
47
  @backtrace = exception.__better_errors_bindings_stack.map { |binding|
39
- file = binding.eval "__FILE__"
40
- line = binding.eval "__LINE__"
48
+ if binding.respond_to?(:source_location) # Ruby >= 2.6
49
+ file = binding.source_location[0]
50
+ line = binding.source_location[1]
51
+ else
52
+ file = binding.eval "__FILE__"
53
+ line = binding.eval "__LINE__"
54
+ end
41
55
  name = binding.frame_description
42
56
  StackFrame.new(file, line, name, binding)
43
57
  }
@@ -146,6 +146,14 @@
146
146
  }
147
147
 
148
148
  /* Heading */
149
+ header.exception .fix-actions {
150
+ margin-top: .5em;
151
+ }
152
+
153
+ header.exception .fix-actions input[type=submit] {
154
+ font-weight: bold;
155
+ }
156
+
149
157
  header.exception h2 {
150
158
  font-weight: 200;
151
159
  font-size: 11pt;
@@ -153,7 +161,7 @@
153
161
 
154
162
  header.exception h2,
155
163
  header.exception p {
156
- line-height: 1.4em;
164
+ line-height: 1.5em;
157
165
  overflow: hidden;
158
166
  white-space: pre;
159
167
  text-overflow: ellipsis;
@@ -166,7 +174,7 @@
166
174
 
167
175
  header.exception p {
168
176
  font-weight: 200;
169
- font-size: 20pt;
177
+ font-size: 17pt;
170
178
  color: white;
171
179
  }
172
180
 
@@ -744,6 +752,18 @@
744
752
  <header class="exception">
745
753
  <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
746
754
  <p><%= exception_message %></p>
755
+ <% unless active_support_actions.empty? %>
756
+ <div class='fix-actions'>
757
+ <% active_support_actions.each do |action, _| %>
758
+ <form class="button_to" method="post" action="<%= action_dispatch_action_endpoint %>">
759
+ <input type="submit" value="<%= action %>">
760
+ <input type="hidden" name="action" value="<%= action %>">
761
+ <input type="hidden" name="error" value="<%= exception_type %>">
762
+ <input type="hidden" name="location" value="<%= request_path %>">
763
+ </form>
764
+ <% end %>
765
+ </div>
766
+ <% end %>
747
767
  </header>
748
768
  </div>
749
769
 
@@ -780,6 +800,7 @@
780
800
  (function() {
781
801
 
782
802
  var OID = "<%= id %>";
803
+ var csrfToken = "<%= csrf_token %>";
783
804
 
784
805
  var previousFrame = null;
785
806
  var previousFrameInfo = null;
@@ -790,6 +811,7 @@
790
811
  var req = new XMLHttpRequest();
791
812
  req.open("POST", "//" + window.location.host + <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
792
813
  req.setRequestHeader("Content-Type", "application/json");
814
+ opts.csrfToken = csrfToken;
793
815
  req.send(JSON.stringify(opts));
794
816
  req.onreadystatechange = function() {
795
817
  if(req.readyState == 4) {
@@ -1,7 +1,14 @@
1
1
  <header class="trace_info clearfix">
2
2
  <div class="title">
3
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>
4
+ <div class="location">
5
+ <span class="filename">
6
+ <a
7
+ href="<%= editor_url(@frame) %>"
8
+ <%= ENV.key?('BETTER_ERRORS_INSIDE_FRAME') ? "target=_blank" : '' %>
9
+ ><%= @frame.pretty_path %></a>
10
+ </span>
11
+ </div>
5
12
  </div>
6
13
  <div class="code_block clearfix">
7
14
  <%== html_formatted_code_block @frame %>
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.6.0"
2
+ VERSION = "2.8.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-25 00:00:00.000000000 Z
11
+ date: 2020-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-html-matchers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec-its
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +171,9 @@ files:
157
171
  - gemfiles/rails52.gemfile
158
172
  - gemfiles/rails52_boc.gemfile
159
173
  - gemfiles/rails52_haml.gemfile
174
+ - gemfiles/rails60.gemfile
175
+ - gemfiles/rails60_boc.gemfile
176
+ - gemfiles/rails60_haml.gemfile
160
177
  - lib/better_errors.rb
161
178
  - lib/better_errors/code_formatter.rb
162
179
  - lib/better_errors/code_formatter/html.rb
@@ -197,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
214
  - !ruby/object:Gem::Version
198
215
  version: '0'
199
216
  requirements: []
200
- rubygems_version: 3.0.3
217
+ rubygems_version: 3.1.2
201
218
  signing_key:
202
219
  specification_version: 4
203
220
  summary: Better error page for Rails and other Rack apps