better_errors 2.7.0 → 2.9.1

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: f0a9449e2952fc0366176c6e7160b9c3dc0ea875902510fd60d6f6e54e0b8110
4
- data.tar.gz: f03dd3cf91ed360f4bd0a826e7b99827b9149f50efff44ea8dbc8bb1b585fa45
3
+ metadata.gz: 4526a605f0982bee6fd507b813eca6e7185bad35bd14ecd289a0a269afe4ec5e
4
+ data.tar.gz: 897e7c5a8fd3350b6cba2b1e46feccb872ed519d45d169dbbde9e6ab1c7387ad
5
5
  SHA512:
6
- metadata.gz: e70808745a84bd58172df545a84371e64f7a42c0dc330ae44b271b759194ae534f7afb918d890c321e0dc075dc9cc66082e0ec9cef0dd769a3738ffa1aafcbd3
7
- data.tar.gz: 1d69c89a9b05b116eac00cc03267abcd831bbcb9314f7462ea13279f5960db3abdab27c408f517af79259e837f60403650196fa06acacb59a820b8cdc166dcd1
6
+ metadata.gz: 6e9116392957f7941b7217a1e08226587081d55904c6e4722d7af28aba0e47d376f886702e958db5f7d02dfaf1480fe686af154fdf500ff817a67e46c5144a30
7
+ data.tar.gz: ad5453cf355f951ad5db132454934ebe5efbdfc339f4607985d76ddb9f430a06c55e95dbffdf944ce33c63b344d4a0ef632176d4b3da00d4db4f3561c02acf39
@@ -0,0 +1,130 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ schedule:
7
+ - cron: '0 0 12,26 * *' # roughly every two weeks to run on new Ruby versions
8
+ pull_request:
9
+ branches: [ master ]
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ ruby:
19
+ - 2.2
20
+ - 2.3
21
+ - 2.4
22
+ - 2.5
23
+ - 2.6
24
+ - 2.7
25
+ # - ruby-head
26
+ # - truffleruby-head
27
+ gemfile:
28
+ # These are located in the gemfiles/ folder
29
+ - rails42
30
+ - rails50
31
+ - rails51
32
+ - rails52
33
+ - rails60
34
+ - rails42_haml
35
+ - rails50_haml
36
+ - rails51_haml
37
+ - rails52_haml
38
+ - rails60_haml
39
+ - rails42_boc
40
+ - rails50_boc
41
+ - rails51_boc
42
+ - rails52_boc
43
+ - rails60_boc
44
+ - rack
45
+ - rack_boc
46
+ # - pry09
47
+ # - pry10
48
+ # - pry11
49
+ exclude:
50
+ - { ruby: 2.2, gemfile: rails60 }
51
+ - { ruby: 2.2, gemfile: rails60_boc }
52
+ - { ruby: 2.2, gemfile: rails60_haml }
53
+ - { ruby: 2.3, gemfile: rails42 }
54
+ - { ruby: 2.3, gemfile: rails42_boc }
55
+ - { ruby: 2.3, gemfile: rails42_haml }
56
+ - { ruby: 2.3, gemfile: rails60 }
57
+ - { ruby: 2.3, gemfile: rails60_boc }
58
+ - { ruby: 2.3, gemfile: rails60_haml }
59
+ - { ruby: 2.4, gemfile: rails42 }
60
+ - { ruby: 2.4, gemfile: rails42_boc }
61
+ - { ruby: 2.4, gemfile: rails42_haml }
62
+ - { ruby: 2.4, gemfile: rails60 }
63
+ - { ruby: 2.4, gemfile: rails60_boc }
64
+ - { ruby: 2.4, gemfile: rails60_haml }
65
+ - { ruby: 2.5, gemfile: rails42 }
66
+ - { ruby: 2.5, gemfile: rails42_boc }
67
+ - { ruby: 2.5, gemfile: rails42_haml }
68
+ - { ruby: 2.6, gemfile: rails42 }
69
+ - { ruby: 2.6, gemfile: rails42_boc }
70
+ - { ruby: 2.6, gemfile: rails42_haml }
71
+ - { ruby: 2.7, gemfile: rails42 }
72
+ - { ruby: 2.7, gemfile: rails42_boc }
73
+ - { ruby: 2.7, gemfile: rails42_haml }
74
+ # - { ruby: ruby-head, gemfile: rails42 }
75
+ # - { ruby: ruby-head, gemfile: rails42_boc }
76
+ # - { ruby: ruby-head, gemfile: rails42_haml }
77
+ - { ruby: truffleruby-head, gemfile: rails42_boc }
78
+ - { ruby: truffleruby-head, gemfile: rails50_boc }
79
+ - { ruby: truffleruby-head, gemfile: rails51_boc }
80
+ - { ruby: truffleruby-head, gemfile: rails52_boc }
81
+ - { ruby: truffleruby-head, gemfile: rails60_boc }
82
+ - { ruby: truffleruby-head, gemfile: rack_boc }
83
+
84
+ steps:
85
+
86
+ - uses: actions/checkout@v2
87
+
88
+ - name: Set up Ruby
89
+ uses: ruby/setup-ruby@v1
90
+ with:
91
+ ruby-version: ${{ matrix.ruby }}
92
+
93
+ - uses: actions/cache@v2
94
+ with:
95
+ path: gemfiles/vendor/bundle
96
+ key: v3-${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }}
97
+ restore-keys: |
98
+ v3-${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}
99
+ v3-${{ runner.os }}-branch-master-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}
100
+
101
+ - name: Bundle install
102
+ run: |
103
+ bundle config path vendor/bundle
104
+ bundle install --jobs 4 --retry 3
105
+ env:
106
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
107
+
108
+ - name: RSpec
109
+ run: bundle exec rspec -f doc --color
110
+ env:
111
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
112
+
113
+ - name: Report to Coveralls
114
+ uses: coverallsapp/github-action@v1.1.2
115
+ with:
116
+ github-token: ${{ secrets.github_token }}
117
+ flag-name: test-${{ matrix.ruby }}-${{ matrix.gemfile }}
118
+ parallel: true
119
+
120
+
121
+ finish:
122
+ needs: test
123
+ runs-on: ubuntu-latest
124
+ steps:
125
+
126
+ - name: Report completion to Coveralls
127
+ uses: coverallsapp/github-action@v1.1.2
128
+ with:
129
+ github-token: ${{ secrets.github_token }}
130
+ parallel-finished: true
@@ -0,0 +1,64 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+
13
+ - uses: actions/checkout@v2
14
+
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.7
19
+
20
+ - uses: actions/cache@v2
21
+ with:
22
+ path: vendor/bundle
23
+ key: v1-${{ runner.os }}-${{ hashFiles('Gemfile', 'better_errors.gemspec') }}
24
+ restore-keys: |
25
+ v1-${{ runner.os }}
26
+
27
+ - name: Bundle install
28
+ run: |
29
+ bundle config path vendor/bundle
30
+ bundle install --jobs 4 --retry 3
31
+
32
+ - name: Get release version
33
+ id: get_version
34
+ run: |
35
+ version="${github_ref//refs\/tags\/v/}"
36
+ echo "${version}"
37
+ echo "::set-output name=version::${version}"
38
+ env:
39
+ github_ref: ${{ github.ref }}
40
+
41
+ - name: Get Release
42
+ id: get_release
43
+ uses: bruceadams/get-release@v1.2.2
44
+ env:
45
+ GITHUB_TOKEN: ${{ github.token }}
46
+
47
+ - name: Set gem version
48
+ run: |
49
+ bundle exec gem bump better_errors --version ${{ steps.get_version.outputs.version }} --no-commit
50
+
51
+ - name: Build gem
52
+ run: gem build better_errors.gemspec
53
+
54
+ - name: Upload gem to Release
55
+ uses: actions/upload-release-asset@v1
56
+ env:
57
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58
+ with:
59
+ upload_url: ${{ steps.get_release.outputs.upload_url }}
60
+ asset_path: ./better_errors-${{ steps.get_version.outputs.version }}.gem
61
+ asset_name: better_errors-${{ steps.get_version.outputs.version }}.gem
62
+ asset_content_type: application/octet-stream
63
+
64
+ # TODO: if this release is on master, add a commit updating the version in master.
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.2
data/Gemfile CHANGED
@@ -2,5 +2,10 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- # gem "pry-byebug"
6
5
  gem 'simplecov', require: false
6
+ gem 'simplecov-lcov', require: false
7
+
8
+ # For managing release version in CI
9
+ gem 'gem-release'
10
+
11
+ # gem "pry-byebug"
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- [![Build Status](https://travis-ci.org/BetterErrors/better_errors.svg)](https://travis-ci.org/BetterErrors/better_errors)
1
+ [![Build Status](https://github.com/BetterErrors/better_errors/workflows/CI/badge.svg?event=push&branch=master)](https://github.com/BetterErrors/better_errors/actions?query=branch%3Amaster)
2
2
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6bc3e7d6118d47e6959b16690b815909)](https://www.codacy.com/app/BetterErrors/better_errors?utm_source=github.com&utm_medium=referral&utm_content=BetterErrors/better_errors&utm_campaign=Badge_Grade)
3
- [![Coverage](https://coveralls.io/repos/github/BetterErrors/better_errors/badge.svg?branch=master)](https://coveralls.io/github/BetterErrors/better_errors?branch=master)
3
+ [![Test Coverage](https://coveralls.io/repos/github/BetterErrors/better_errors/badge.svg?branch=master)](https://coveralls.io/github/BetterErrors/better_errors?branch=master)
4
4
  [![Gem Version](https://img.shields.io/gem/v/better_errors.svg)](https://rubygems.org/gems/better_errors)
5
5
 
6
6
  # Better Errors
@@ -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.
@@ -4,6 +4,7 @@ gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0'
4
4
  gem "binding_of_caller"
5
5
  gem "pry", "~> 0.10.0"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0'
4
4
  gem "pry", "~> 0.11.0pre"
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0'
4
4
  gem "pry", "~> 0.9.12"
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0'
4
4
 
5
- gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+ gem 'simplecov-lcov', require: false
6
7
 
7
8
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0'
4
4
  gem "binding_of_caller"
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 4.2.0"
4
4
  gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
5
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -5,6 +5,7 @@ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
5
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
6
6
  gem "binding_of_caller"
7
7
 
8
- gem 'coveralls', require: false
8
+ gem 'simplecov', require: false
9
+ gem 'simplecov-lcov', require: false
9
10
 
10
11
  gemspec path: "../"
@@ -5,6 +5,7 @@ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7'
5
5
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
6
6
  gem "haml"
7
7
 
8
- gem 'coveralls', require: false
8
+ gem 'simplecov', require: false
9
+ gem 'simplecov-lcov', require: false
9
10
 
10
11
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem "rails", "~> 5.0.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.0.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "binding_of_caller"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.0.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "haml"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem "rails", "~> 5.1.0"
4
4
  gem 'i18n', '< 1.5.2', require: false if RUBY_VERSION < '2.3'
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.1.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "binding_of_caller"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.1.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "haml"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem "rails", "~> 5.2.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.2.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "binding_of_caller"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -4,6 +4,7 @@ gem "rails", "~> 5.2.0"
4
4
  gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3'
5
5
  gem "haml"
6
6
 
7
- gem 'coveralls', require: false
7
+ gem 'simplecov', require: false
8
+ gem 'simplecov-lcov', require: false
8
9
 
9
10
  gemspec path: "../"
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "rails", "~> 6.0.0"
4
4
 
5
- gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+ gem 'simplecov-lcov', require: false
6
7
 
7
8
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem "rails", "~> 6.0.0"
4
4
  gem "binding_of_caller"
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  gem "rails", "~> 6.0.0"
4
4
  gem "haml"
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'simplecov', require: false
7
+ gem 'simplecov-lcov', require: false
7
8
 
8
9
  gemspec path: "../"
data/lib/better_errors.rb CHANGED
@@ -3,6 +3,7 @@ require "erubi"
3
3
  require "coderay"
4
4
  require "uri"
5
5
 
6
+ require "better_errors/version"
6
7
  require "better_errors/code_formatter"
7
8
  require "better_errors/inspectable_value"
8
9
  require "better_errors/error_page"
@@ -10,21 +11,9 @@ require "better_errors/middleware"
10
11
  require "better_errors/raised_exception"
11
12
  require "better_errors/repl"
12
13
  require "better_errors/stack_frame"
13
- require "better_errors/version"
14
+ require "better_errors/editor"
14
15
 
15
16
  module BetterErrors
16
- POSSIBLE_EDITOR_PRESETS = [
17
- { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" },
18
- { symbols: [:macvim, :mvim], sniff: /vim/i, url: proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" } },
19
- { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" },
20
- { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" },
21
- { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" },
22
- { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" },
23
- { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" },
24
- { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" },
25
- { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" },
26
- ]
27
-
28
17
  class << self
29
18
  # The path to the root of the application. Better Errors uses this property
30
19
  # to determine if a file in a backtrace should be considered an application
@@ -64,17 +53,18 @@ module BetterErrors
64
53
  @maximum_variable_inspect_size = 100_000
65
54
  @ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
66
55
 
67
- # Returns a proc, which when called with a filename and line number argument,
56
+ # Returns an object which responds to #url, which when called with
57
+ # a filename and line number argument,
68
58
  # returns a URL to open the filename and line in the selected editor.
69
59
  #
70
60
  # Generates TextMate URLs by default.
71
61
  #
72
- # BetterErrors.editor["/some/file", 123]
62
+ # BetterErrors.editor.url("/some/file", 123)
73
63
  # # => txmt://open?url=file:///some/file&line=123
74
64
  #
75
65
  # @return [Proc]
76
66
  def self.editor
77
- @editor
67
+ @editor ||= default_editor
78
68
  end
79
69
 
80
70
  # Configures how Better Errors generates open-in-editor URLs.
@@ -115,20 +105,15 @@ module BetterErrors
115
105
  # @param [Proc] proc
116
106
  #
117
107
  def self.editor=(editor)
118
- POSSIBLE_EDITOR_PRESETS.each do |config|
119
- if config[:symbols].include?(editor)
120
- return self.editor = config[:url]
121
- end
122
- end
123
-
124
- if editor.is_a? String
125
- self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } }
108
+ if editor.is_a? Symbol
109
+ @editor = Editor.editor_from_symbol(editor)
110
+ raise(ArgumentError, "Symbol #{editor} is not a symbol in the list of supported errors.") unless editor
111
+ elsif editor.is_a? String
112
+ @editor = Editor.for_formatting_string(editor)
113
+ elsif editor.respond_to? :call
114
+ @editor = Editor.for_proc(editor)
126
115
  else
127
- if editor.respond_to? :call
128
- @editor = editor
129
- else
130
- raise TypeError, "Expected editor to be a valid editor key, a format string or a callable."
131
- end
116
+ raise ArgumentError, "Expected editor to be a valid editor key, a format string or a callable."
132
117
  end
133
118
  end
134
119
 
@@ -145,12 +130,8 @@ module BetterErrors
145
130
  #
146
131
  # @return [Symbol]
147
132
  def self.default_editor
148
- POSSIBLE_EDITOR_PRESETS.detect(-> { {} }) { |config|
149
- ENV["EDITOR"] =~ config[:sniff]
150
- }[:url] || :textmate
133
+ Editor.default_editor
151
134
  end
152
-
153
- BetterErrors.editor = default_editor
154
135
  end
155
136
 
156
137
  begin
@@ -0,0 +1,99 @@
1
+ require "uri"
2
+
3
+ module BetterErrors
4
+ class Editor
5
+ KNOWN_EDITORS = [
6
+ { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" },
7
+ { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" },
8
+ { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" },
9
+ { symbols: [:macvim, :mvim], sniff: /vim/i, url: "mvim://open?url=file://%{file_unencoded}&line=%{line}" },
10
+ { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" },
11
+ { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" },
12
+ { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" },
13
+ { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" },
14
+ { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" },
15
+ ]
16
+
17
+ def self.for_formatting_string(formatting_string)
18
+ new proc { |file, line|
19
+ formatting_string % { file: URI.encode_www_form_component(file), file_unencoded: file, line: line }
20
+ }
21
+ end
22
+
23
+ def self.for_proc(url_proc)
24
+ new url_proc
25
+ end
26
+
27
+ # Automatically sniffs a default editor preset based on
28
+ # environment variables.
29
+ #
30
+ # @return [Symbol]
31
+ def self.default_editor
32
+ editor_from_environment_formatting_string ||
33
+ editor_from_environment_editor ||
34
+ editor_from_symbol(:textmate)
35
+ end
36
+
37
+ def self.editor_from_environment_editor
38
+ if ENV["BETTER_ERRORS_EDITOR"]
39
+ editor = editor_from_command(ENV["BETTER_ERRORS_EDITOR"])
40
+ return editor if editor
41
+ puts "BETTER_ERRORS_EDITOR environment variable is not recognized as a supported Better Errors editor."
42
+ end
43
+ if ENV["EDITOR"]
44
+ editor = editor_from_command(ENV["EDITOR"])
45
+ return editor if editor
46
+ puts "EDITOR environment variable is not recognized as a supported Better Errors editor. Using TextMate by default."
47
+ else
48
+ puts "Since there is no EDITOR or BETTER_ERRORS_EDITOR environment variable, using Textmate by default."
49
+ end
50
+ end
51
+
52
+ def self.editor_from_command(editor_command)
53
+ env_preset = KNOWN_EDITORS.find { |preset| editor_command =~ preset[:sniff] }
54
+ for_formatting_string(env_preset[:url]) if env_preset
55
+ end
56
+
57
+ def self.editor_from_environment_formatting_string
58
+ return unless ENV['BETTER_ERRORS_EDITOR_URL']
59
+
60
+ for_formatting_string(ENV['BETTER_ERRORS_EDITOR_URL'])
61
+ end
62
+
63
+ def self.editor_from_symbol(symbol)
64
+ KNOWN_EDITORS.each do |preset|
65
+ return for_formatting_string(preset[:url]) if preset[:symbols].include?(symbol)
66
+ end
67
+ end
68
+
69
+ def initialize(url_proc)
70
+ @url_proc = url_proc
71
+ end
72
+
73
+ def url(raw_path, line)
74
+ if virtual_path && raw_path.start_with?(virtual_path)
75
+ if host_path
76
+ file = raw_path.sub(%r{\A#{virtual_path}}, host_path)
77
+ else
78
+ file = raw_path.sub(%r{\A#{virtual_path}/}, '')
79
+ end
80
+ else
81
+ file = raw_path
82
+ end
83
+
84
+ url_proc.call(file, line)
85
+ end
86
+
87
+ private
88
+
89
+ attr_reader :url_proc
90
+
91
+ def virtual_path
92
+ @virtual_path ||= ENV['BETTER_ERRORS_VIRTUAL_PATH']
93
+ end
94
+
95
+ def host_path
96
+ @host_path ||= ENV['BETTER_ERRORS_HOST_PATH']
97
+ end
98
+ end
99
+ end
@@ -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,23 @@ 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 exception_hint
71
+ exception.hint
72
+ end
73
+
74
+ def active_support_actions
75
+ return [] unless defined?(ActiveSupport::ActionableError)
76
+
77
+ ActiveSupport::ActionableError.actions(exception.type)
78
+ end
79
+
80
+ def action_dispatch_action_endpoint
81
+ return unless defined?(ActionDispatch::ActionableExceptions)
82
+
83
+ ActionDispatch::ActionableExceptions.endpoint
63
84
  end
64
85
 
65
86
  def application_frames
@@ -73,7 +94,7 @@ module BetterErrors
73
94
  private
74
95
 
75
96
  def editor_url(frame)
76
- BetterErrors.editor[frame.filename, frame.line]
97
+ BetterErrors.editor.url(frame.filename, frame.line)
77
98
  end
78
99
 
79
100
  def rack_session
@@ -0,0 +1,29 @@
1
+ module BetterErrors
2
+ class ExceptionHint
3
+ def initialize(exception)
4
+ @exception = exception
5
+ end
6
+
7
+ def hint
8
+ case exception
9
+ when NoMethodError
10
+ /\Aundefined method `(?<method>[^']+)' for (?<val>[^:]+):(?<klass>\w+)/.match(exception.message) do |match|
11
+ if match[:val] == "nil"
12
+ return "Something is `nil` when it probably shouldn't be."
13
+ elsif !match[:klass].start_with? '0x'
14
+ return "`#{match[:method]}` is being called on a `#{match[:klass]}` object, "\
15
+ "which might not be the type of object you were expecting."
16
+ end
17
+ end
18
+ when NameError
19
+ /\Aundefined local variable or method `(?<method>[^']+)' for/.match(exception.message) do |match|
20
+ return "`#{match[:method]}` is probably misspelled."
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :exception
28
+ end
29
+ end
@@ -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-#{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
@@ -1,11 +1,23 @@
1
+ require 'better_errors/exception_hint'
2
+
1
3
  # @private
2
4
  module BetterErrors
3
5
  class RaisedException
4
- attr_reader :exception, :message, :backtrace
6
+ attr_reader :exception, :message, :backtrace, :hint
5
7
 
6
8
  def initialize(exception)
7
- if exception.respond_to?(:original_exception) && exception.original_exception
8
- # This supports some specific Rails exceptions, and is not intended to act the same as `#cause`.
9
+ if exception.class.name == "ActionView::Template::Error" && exception.respond_to?(:cause)
10
+ # Rails 6+ exceptions of this type wrap the "real" exception, and the real exception
11
+ # is actually more useful than the ActionView-provided wrapper. Once Better Errors
12
+ # supports showing all exceptions in the cause stack, this should go away. Or perhaps
13
+ # this can be changed to provide guidance by showing the second error in the cause stack
14
+ # under this condition.
15
+ exception = exception.cause if exception.cause
16
+ elsif exception.respond_to?(:original_exception) && exception.original_exception
17
+ # This supports some specific Rails exceptions, and this is not intended to act the same as
18
+ # the Ruby's {Exception#cause}.
19
+ # It's possible this should only support ActionView::Template::Error, but by not changing
20
+ # this we're preserving longstanding behavior of Better Errors with Rails < 6.
9
21
  exception = exception.original_exception
10
22
  end
11
23
 
@@ -13,6 +25,7 @@ module BetterErrors
13
25
  @message = exception.message
14
26
 
15
27
  setup_backtrace
28
+ setup_hint
16
29
  massage_syntax_error
17
30
  end
18
31
 
@@ -68,5 +81,9 @@ module BetterErrors
68
81
  end
69
82
  end
70
83
  end
84
+
85
+ def setup_hint
86
+ @hint = ExceptionHint.new(exception).hint
87
+ end
71
88
  end
72
89
  end
@@ -90,7 +90,7 @@
90
90
  nav.sidebar,
91
91
  .frame_info {
92
92
  position: fixed;
93
- top: 95px;
93
+ top: 102px;
94
94
  bottom: 0;
95
95
 
96
96
  box-sizing: border-box;
@@ -102,7 +102,7 @@
102
102
  nav.sidebar {
103
103
  width: 40%;
104
104
  left: 20px;
105
- top: 115px;
105
+ top: 122px;
106
106
  bottom: 20px;
107
107
  }
108
108
 
@@ -131,7 +131,7 @@
131
131
  header.exception {
132
132
  padding: 18px 20px;
133
133
 
134
- height: 59px;
134
+ height: 66px;
135
135
  min-height: 59px;
136
136
 
137
137
  overflow: hidden;
@@ -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
 
@@ -587,6 +595,9 @@
587
595
  color: #8080a0;
588
596
  padding-left: 20px;
589
597
  }
598
+ .console-has-been-used .live-console-hint {
599
+ display: none;
600
+ }
590
601
 
591
602
  .hint:before {
592
603
  content: '\25b2';
@@ -603,17 +614,6 @@
603
614
  margin: 10px 0;
604
615
  }
605
616
 
606
- .sub:before {
607
- content: '';
608
- display: block;
609
- width: 100%;
610
- height: 4px;
611
-
612
- border-radius: 2px;
613
- background: rgba(0, 150, 200, 0.05);
614
- 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);
615
- }
616
-
617
617
  .sub h3 {
618
618
  color: #39a;
619
619
  font-size: 1.1em;
@@ -744,6 +744,21 @@
744
744
  <header class="exception">
745
745
  <h2><strong><%= exception_type %></strong> <span>at <%= request_path %></span></h2>
746
746
  <p><%= exception_message %></p>
747
+ <% unless active_support_actions.empty? %>
748
+ <div class='fix-actions'>
749
+ <% active_support_actions.each do |action, _| %>
750
+ <form class="button_to" method="post" action="<%= action_dispatch_action_endpoint %>">
751
+ <input type="submit" value="<%= action %>">
752
+ <input type="hidden" name="action" value="<%= action %>">
753
+ <input type="hidden" name="error" value="<%= exception_type %>">
754
+ <input type="hidden" name="location" value="<%= request_path %>">
755
+ </form>
756
+ <% end %>
757
+ </div>
758
+ <% end %>
759
+ <% if exception_hint %>
760
+ <h2>Hint: <%= exception_hint %></h2>
761
+ <% end %>
747
762
  </header>
748
763
  </div>
749
764
 
@@ -780,6 +795,7 @@
780
795
  (function() {
781
796
 
782
797
  var OID = "<%= id %>";
798
+ var csrfToken = "<%= csrf_token %>";
783
799
 
784
800
  var previousFrame = null;
785
801
  var previousFrameInfo = null;
@@ -790,6 +806,7 @@
790
806
  var req = new XMLHttpRequest();
791
807
  req.open("POST", "//" + window.location.host + <%== uri_prefix.gsub("<", "&lt;").inspect %> + "/__better_errors/" + OID + "/" + method, true);
792
808
  req.setRequestHeader("Content-Type", "application/json");
809
+ opts.csrfToken = csrfToken;
793
810
  req.send(JSON.stringify(opts));
794
811
  req.onreadystatechange = function() {
795
812
  if(req.readyState == 4) {
@@ -803,6 +820,28 @@
803
820
  return html.replace(/&/, "&amp;").replace(/</g, "&lt;");
804
821
  }
805
822
 
823
+ function hasConsoleBeenUsedPreviously() {
824
+ return !!document.cookie.split('; ').find(function(cookie) {
825
+ return cookie.startsWith('BetterErrors-has-used-console=');
826
+ });
827
+ }
828
+
829
+ var consoleHasBeenUsed = hasConsoleBeenUsedPreviously();
830
+
831
+ function consoleWasJustUsed() {
832
+ if (consoleHasBeenUsed) {
833
+ return;
834
+ }
835
+
836
+ hideConsoleHint();
837
+ consoleHasBeenUsed = true;
838
+ document.cookie = "BetterErrors-has-used-console=true;path=/;max-age=31536000;samesite"
839
+ }
840
+
841
+ function hideConsoleHint() {
842
+ document.querySelector('body').className += " console-has-been-used";
843
+ }
844
+
806
845
  function REPL(index) {
807
846
  this.index = index;
808
847
 
@@ -824,15 +863,20 @@
824
863
  this.inputElement = this.container.querySelector("input");
825
864
  this.outputElement = this.container.querySelector("pre");
826
865
 
866
+ if (consoleHasBeenUsed) {
867
+ hideConsoleHint();
868
+ }
869
+
827
870
  var self = this;
828
871
  this.inputElement.onkeydown = function(ev) {
829
872
  self.onKeyDown(ev);
873
+ consoleWasJustUsed();
830
874
  };
831
875
 
832
876
  this.setPrompt(">>");
833
877
 
834
878
  REPL.all[this.index] = this;
835
- }
879
+ };
836
880
 
837
881
  REPL.prototype.focus = function() {
838
882
  this.inputElement.focus();
@@ -1,7 +1,10 @@
1
1
  <%== text_heading("=", "%s at %s" % [exception_type, request_path]) %>
2
2
 
3
- > <%== exception_message %>
4
- <% if backtrace_frames.any? %>
3
+ <%== exception_message %>
4
+
5
+ > To access an interactive console with this error, point your browser to: /__better_errors
6
+
7
+ <% if backtrace_frames.any? -%>
5
8
 
6
9
  <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
7
10
 
@@ -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 %>
@@ -18,7 +25,7 @@
18
25
  </header>
19
26
 
20
27
  <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %>
21
- <div class="hint">
28
+ <div class="hint live-console-hint">
22
29
  This is a live shell. Type in here.
23
30
  </div>
24
31
 
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "2.7.0"
2
+ VERSION = "2.9.1"
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.7.0
4
+ version: 2.9.1
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-04-24 00:00:00.000000000 Z
11
+ date: 2020-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -146,8 +146,10 @@ extensions: []
146
146
  extra_rdoc_files: []
147
147
  files:
148
148
  - ".coveralls.yml"
149
+ - ".github/workflows/ci.yml"
150
+ - ".github/workflows/release.yml"
149
151
  - ".gitignore"
150
- - ".travis.yml"
152
+ - ".ruby-version"
151
153
  - ".yardopts"
152
154
  - CHANGELOG.md
153
155
  - Gemfile
@@ -178,8 +180,10 @@ files:
178
180
  - lib/better_errors/code_formatter.rb
179
181
  - lib/better_errors/code_formatter/html.rb
180
182
  - lib/better_errors/code_formatter/text.rb
183
+ - lib/better_errors/editor.rb
181
184
  - lib/better_errors/error_page.rb
182
185
  - lib/better_errors/exception_extension.rb
186
+ - lib/better_errors/exception_hint.rb
183
187
  - lib/better_errors/inspectable_value.rb
184
188
  - lib/better_errors/middleware.rb
185
189
  - lib/better_errors/rails.rb
@@ -214,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
218
  - !ruby/object:Gem::Version
215
219
  version: '0'
216
220
  requirements: []
217
- rubygems_version: 3.0.3
221
+ rubygems_version: 3.1.4
218
222
  signing_key:
219
223
  specification_version: 4
220
224
  summary: Better error page for Rails and other Rack apps
data/.travis.yml DELETED
@@ -1,98 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- notifications:
4
- webhooks:
5
- # With COVERALLS_PARALLEL, coverage information sent to coveralls will not be processed until
6
- # this webhook is sent.
7
- # https://coveralls.zendesk.com/hc/en-us/articles/203484329-Parallel-Build-Webhook
8
- - secure: "YnHYbTq51ySistjvOxsuNhyg4GLuUffEJstTYeGYXiBF7HG5h43IVYo8KNuLzwkgsOYBcNo+YMdQX7qCqJffSbhsr1FZRSzBmjFFxcyD4hu+ukM2theZ4mePVAZiePscYvQPRNY4hIb4d3egStJEytkalDhB3sOebF57tIaCssg="
9
- rvm:
10
- - 2.2.10
11
- - 2.3.8
12
- - 2.4.9
13
- - 2.5.7
14
- - 2.6.5
15
- - 2.7.0
16
- - ruby-head
17
- gemfile:
18
- - gemfiles/rails42.gemfile
19
- - gemfiles/rails50.gemfile
20
- - gemfiles/rails51.gemfile
21
- - gemfiles/rails52.gemfile
22
- - gemfiles/rails60.gemfile
23
- - gemfiles/rails42_haml.gemfile
24
- - gemfiles/rails50_haml.gemfile
25
- - gemfiles/rails51_haml.gemfile
26
- - gemfiles/rails52_haml.gemfile
27
- - gemfiles/rails60_haml.gemfile
28
- - gemfiles/rails42_boc.gemfile
29
- - gemfiles/rails50_boc.gemfile
30
- - gemfiles/rails51_boc.gemfile
31
- - gemfiles/rails52_boc.gemfile
32
- - gemfiles/rails60_boc.gemfile
33
- - gemfiles/rack.gemfile
34
- - gemfiles/rack_boc.gemfile
35
- - gemfiles/pry09.gemfile
36
- - gemfiles/pry010.gemfile
37
- - gemfiles/pry011.gemfile
38
- matrix:
39
- fast_finish: true
40
- allow_failures:
41
- - rvm: ruby-head
42
- - gemfile: gemfiles/pry010.gemfile
43
- - gemfile: gemfiles/pry011.gemfile
44
- exclude:
45
- - rvm: 2.2.10
46
- gemfile: gemfiles/rails60.gemfile
47
- - rvm: 2.2.10
48
- gemfile: gemfiles/rails60_boc.gemfile
49
- - rvm: 2.2.10
50
- gemfile: gemfiles/rails60_haml.gemfile
51
- - rvm: 2.3.8
52
- gemfile: gemfiles/rails42.gemfile
53
- - rvm: 2.3.8
54
- gemfile: gemfiles/rails42_boc.gemfile
55
- - rvm: 2.3.8
56
- gemfile: gemfiles/rails42_haml.gemfile
57
- - rvm: 2.3.8
58
- gemfile: gemfiles/rails60.gemfile
59
- - rvm: 2.3.8
60
- gemfile: gemfiles/rails60_boc.gemfile
61
- - rvm: 2.3.8
62
- gemfile: gemfiles/rails60_haml.gemfile
63
- - rvm: 2.4.9
64
- gemfile: gemfiles/rails42.gemfile
65
- - rvm: 2.4.9
66
- gemfile: gemfiles/rails42_boc.gemfile
67
- - rvm: 2.4.9
68
- gemfile: gemfiles/rails42_haml.gemfile
69
- - rvm: 2.4.9
70
- gemfile: gemfiles/rails60.gemfile
71
- - rvm: 2.4.9
72
- gemfile: gemfiles/rails60_boc.gemfile
73
- - rvm: 2.4.9
74
- gemfile: gemfiles/rails60_haml.gemfile
75
- - rvm: 2.5.7
76
- gemfile: gemfiles/rails42.gemfile
77
- - rvm: 2.5.7
78
- gemfile: gemfiles/rails42_boc.gemfile
79
- - rvm: 2.5.7
80
- gemfile: gemfiles/rails42_haml.gemfile
81
- - rvm: 2.6.5
82
- gemfile: gemfiles/rails42.gemfile
83
- - rvm: 2.6.5
84
- gemfile: gemfiles/rails42_boc.gemfile
85
- - rvm: 2.6.5
86
- gemfile: gemfiles/rails42_haml.gemfile
87
- - rvm: 2.7.0
88
- gemfile: gemfiles/rails42.gemfile
89
- - rvm: 2.7.0
90
- gemfile: gemfiles/rails42_boc.gemfile
91
- - rvm: 2.7.0
92
- gemfile: gemfiles/rails42_haml.gemfile
93
- - rvm: ruby-head
94
- gemfile: gemfiles/rails42.gemfile
95
- - rvm: ruby-head
96
- gemfile: gemfiles/rails42_boc.gemfile
97
- - rvm: ruby-head
98
- gemfile: gemfiles/rails42_haml.gemfile