deprecation_collector 0.3.0 → 0.5.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.
@@ -2,26 +2,31 @@
2
2
 
3
3
  class DeprecationCollector
4
4
  class Web
5
+ # :nodoc:
5
6
  module Helpers
6
7
  def collector_instance
7
8
  @collector_instance || DeprecationCollector.instance
8
9
  end
9
10
 
11
+ def import_enabled?
12
+ @web.import_enabled
13
+ end
14
+
10
15
  def root_path
11
16
  # request.base_url ?
12
17
  "#{env["SCRIPT_NAME"]}/"
13
18
  end
14
19
 
15
20
  def current_path
16
- @current_path ||= request.path_info.gsub(/^\//, "")
21
+ @current_path ||= request.path_info.gsub(%r{^/}, "")
17
22
  end
18
23
 
19
24
  def deprecations_path
20
- "#{root_path}"
25
+ root_path # /
21
26
  end
22
27
 
23
- def deprecation_path(id)
24
- "#{root_path}#{id}"
28
+ def deprecation_path(id, format: nil)
29
+ ["#{root_path}#{id}", format].compact.join('.')
25
30
  end
26
31
 
27
32
  def enable_deprecations_path
@@ -32,12 +37,51 @@ class DeprecationCollector
32
37
  "#{root_path}disable"
33
38
  end
34
39
 
40
+ def dump_deprecations_path
41
+ "#{root_path}dump.json"
42
+ end
43
+
44
+ def import_deprecations_path
45
+ "#{root_path}import"
46
+ end
47
+
35
48
  def trigger_kwargs_error_warning(foo: nil); end
36
49
 
37
50
  def trigger_rails_deprecation
38
51
  return unless defined?(ActiveSupport::Deprecation)
52
+
39
53
  -> { ActiveSupport::Deprecation.warn("Test deprecation") } []
40
54
  end
55
+
56
+ def current_color_theme
57
+ return "dark" if params["dark"]
58
+ return "light" if params["light"]
59
+ return "dark" if request.get_header("HTTP_Sec_CH_Prefers_Color_Scheme").to_s.downcase.include?("dark")
60
+
61
+ "auto"
62
+ end
63
+
64
+ def detect_tag(deprecation)
65
+ msg = deprecation[:message]
66
+ return :kwargs if msg.include?("Using the last argument as keyword parameters is deprecated") ||
67
+ msg.include?("Passing the keyword argument as the last hash parameter is deprecated")
68
+ return :test if msg.include?("trigger_kwargs_error_warning") || msg.include?("trigger_rails_deprecation")
69
+ end
70
+
71
+ def deprecation_tags(deprecation)
72
+ tags = Set.new
73
+ if (detected_tag = detect_tag(deprecation))
74
+ tags << detected_tag
75
+ end
76
+ tags << deprecation[:realm] if deprecation[:realm] && deprecation[:realm] != "rails"
77
+ tags.merge(deprecation.dig(:notes, :tags) || [])
78
+
79
+ tags.to_h do |tag|
80
+ next [tag, "bg-success"] if tag == :test
81
+
82
+ [tag, "bg-secondary"]
83
+ end
84
+ end
41
85
  end
42
86
  end
43
87
  end
@@ -2,19 +2,20 @@
2
2
 
3
3
  class DeprecationCollector
4
4
  class Web
5
+ # :nodoc:
5
6
  module Router
6
7
  HTTP_METHODS = %w[GET HEAD POST PUT PATCH DELETE].freeze
7
8
  HTTP_METHODS.each do |http_method|
8
9
  const_set http_method, http_method
9
- class_eval <<~RUBY, __FILE__, __LINE__+1
10
- def #{http_method.downcase}(path, &block)
11
- route(#{http_method}, path, &block)
12
- end
10
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
11
+ def #{http_method.downcase}(path, &block) # def get(path, &block)
12
+ route(#{http_method}, path, &block) # route('GET', path, &block)
13
+ end # end
13
14
  RUBY
14
15
  end
15
16
 
16
17
  def root(&block)
17
- route(GET, '/', &block)
18
+ route(GET, "/", &block)
18
19
  end
19
20
 
20
21
  def route(method, path, &block)
@@ -23,10 +24,10 @@ class DeprecationCollector
23
24
 
24
25
  def helpers(mod = nil, &block)
25
26
  return ActionContext.class_eval(&block) if block
27
+
26
28
  ActionContext.send(:include, mod)
27
29
  end
28
30
 
29
-
30
31
  ROUTE_PARAMS = "rack.route_params"
31
32
  PATH_INFO = "PATH_INFO"
32
33
 
@@ -39,35 +40,33 @@ class DeprecationCollector
39
40
  path_info = "/" if path_info == "" # some buggy servers may pass empty root path
40
41
 
41
42
  @routes[request_method.upcase]&.find do |route|
42
- params = route.match(request_method, path_info)
43
+ params = route.match(request_method.upcase, path_info)
43
44
  next unless params
45
+
44
46
  env[ROUTE_PARAMS] = params
45
47
  break ActionContext.new(request, &route.block)
46
48
  end
47
49
  end
48
50
 
49
- def call(env)
51
+ def call(env, application = nil)
50
52
  action = match(env)
51
53
  unless action
52
54
  return [
53
55
  404,
54
- {"content-type" => "text/plain", "x-cascade" => "pass"},
56
+ { "content-type" => "text/plain", "x-cascade" => "pass" },
55
57
  ["Not Found #{env["REQUEST_METHOD"].inspect} #{env[PATH_INFO].inspect}"]
56
58
  ]
57
59
  end
58
60
 
59
- resp = catch(:halt) do
60
- action.call(env)
61
- ensure
62
- end
61
+ resp = catch(:halt) { action.call(env, application) }
63
62
 
64
63
  return resp if resp.is_a?(Array) # raw rack responses (redirects etc.)
65
64
 
66
65
  # rendered content goes here
67
66
  headers = {
68
67
  "content-type" => "text/html",
69
- "cache-control" => "private, no-store",
70
- # TODO:
68
+ "cache-control" => "private, no-store"
69
+ # TODO: locale/csp
71
70
  # "content-language" => action.locale,
72
71
  # "content-security-policy" => CSP_HEADER
73
72
  }
@@ -75,10 +74,11 @@ class DeprecationCollector
75
74
  [200, headers, [resp]]
76
75
  end
77
76
 
77
+ # :nodoc:
78
78
  class Route
79
79
  attr_accessor :request_method, :pattern, :block
80
80
 
81
- NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^.:$\/]+)/
81
+ NAMED_SEGMENTS_PATTERN = %r{/([^/]*):([^.:$/]+)}.freeze
82
82
 
83
83
  def initialize(request_method, pattern, block)
84
84
  @request_method = request_method
@@ -92,12 +92,15 @@ class DeprecationCollector
92
92
 
93
93
  def compile_matcher
94
94
  return pattern unless pattern.match?(NAMED_SEGMENTS_PATTERN)
95
- regex_pattern = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)') # /some/:id => /some/(?<id>[^$/]+)
96
95
 
96
+ regex_pattern = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)') # /some/:id => /some/(?<id>[^$/]+)
97
97
  Regexp.new("\\A#{regex_pattern}\\Z")
98
98
  end
99
99
 
100
100
  def match(request_method, path)
101
+ # this is actually not needed because of groupping by method, but just in case:
102
+ return unless self.request_method == request_method
103
+
101
104
  case matcher
102
105
  when String
103
106
  {} if path == matcher
@@ -108,6 +111,7 @@ class DeprecationCollector
108
111
  end
109
112
  end
110
113
 
114
+ # :nodoc:
111
115
  class ActionContext
112
116
  attr_accessor :request
113
117
 
@@ -116,7 +120,8 @@ class DeprecationCollector
116
120
  @block = block
117
121
  end
118
122
 
119
- def call(env)
123
+ def call(_env, application)
124
+ @web = application.web
120
125
  instance_exec(&@block)
121
126
  end
122
127
 
@@ -129,24 +134,30 @@ class DeprecationCollector
129
134
  end
130
135
 
131
136
  def params
132
- @params ||= Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
133
- .merge!(request.params)
134
- .merge!(route_params.transform_keys(&:to_s))
137
+ @params ||= Hash.new { |hash, key| hash[key.to_s] if key.is_a?(Symbol) }
138
+ .merge!(request.params)
139
+ .merge!(route_params.transform_keys(&:to_s))
135
140
  end
136
141
 
137
- def halt(res)
138
- throw :halt, [res, {"content-type" => "text/plain"}, [res.to_s]]
142
+ def halt(res, content = nil)
143
+ throw :halt, [res, { "content-type" => "text/plain" }, [content || res.to_s]]
139
144
  end
140
145
 
141
146
  def redirect_to(location)
142
- throw :halt, [302, {"location" => "#{request.base_url}#{location}"}, []]
147
+ throw :halt, [302, { "location" => "#{request.base_url}#{location}" }, []]
143
148
  end
144
149
 
145
- def render(plain: nil, html: nil, json: nil, erb: nil, slim: nil, status: 200, locals: nil, layout: 'layout.html.slim')
146
- raise ArgumentError, "provide exactly one render format" unless [plain, html, json, erb, slim].compact.size == 1
150
+ def render(plain: nil, html: nil, json: nil, erb: nil, slim: nil, # rubocop:disable Metrics
151
+ status: 200, locals: nil, layout: "layout.html.slim")
152
+ unless [plain, html, json, erb, slim].compact.size == 1
153
+ raise ArgumentError, "provide exactly one render format"
154
+ end
147
155
 
148
- return [status, {"content-type" => "application/json"}, [JSON.generate(json)]] if json
149
- return [status, {"content-type" => "text/plain"}, [plain.to_s]] if plain
156
+ if json
157
+ json = JSON.generate(json) unless json.is_a?(String)
158
+ return [status, { "content-type" => "application/json" }, [json]]
159
+ end
160
+ return [status, { "content-type" => "text/plain" }, [plain.to_s]] if plain
150
161
 
151
162
  _define_locals(locals) if locals
152
163
  template = "#{erb}.erb" if erb
@@ -154,39 +165,55 @@ class DeprecationCollector
154
165
  html = render_template(template) if template
155
166
  html = render_template(layout) { html } if layout
156
167
 
157
- return [status, {"content-type" => "text/html"}, [html.to_s]] if html
168
+ color_scheme_headers = {
169
+ "Accept-CH" => "Sec-CH-Prefers-Color-Scheme",
170
+ "Vary" => "Sec-CH-Prefers-Color-Scheme",
171
+ "Critical-CH" => "Sec-CH-Prefers-Color-Scheme"
172
+ }
173
+
174
+ return [status, { "content-type" => "text/html" }.merge(color_scheme_headers), [html.to_s]] if html
158
175
  end
159
176
 
160
177
  VIEW_PATH = "#{__dir__}/views"
161
178
 
162
179
  def render_template(template, &block)
163
- original_template_name = File.join(VIEW_PATH, template.to_s)
164
- template = template.gsub(/\.slim\z/, '.template.rb')
165
- template_method_name = "_template_#{template.gsub(/[^\w]/, '_')}"
166
- template_filename = File.join(VIEW_PATH, template.to_s)
167
-
168
- if ENV['DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES']
169
- require 'slim'
170
- puts "Recompiling #{original_template_name}"
171
- ActionContext.class_eval { undef_method(template_method_name) } if respond_to?(template_method_name)
172
- if original_template_name.end_with?('.slim')
173
- File.write(template_filename, Slim::Template.new(original_template_name).precompiled_template)
174
- end
175
- end
180
+ template_target = template.gsub(/\.slim\z/, ".template.rb")
181
+ template_method_name = "_template_#{template_target.gsub(/[^\w]/, "_")}"
182
+ template_filename = File.join(VIEW_PATH, template_target.to_s)
176
183
 
177
- unless respond_to?(template_method_name)
178
- src = File.read(template_filename)
179
- src = ERB.new(src).src if template_filename.end_with?('.erb')
180
- ActionContext.class_eval <<-RUBY, template_filename.gsub(/\.template\.rb\z/, '.slim'), 1
181
- def #{template_method_name}; #{src}
182
- end
183
- RUBY
184
+ if ENV["DEPRECATION_COLLECTOR_RELOAD_WEB_TEMPLATES"]
185
+ _recompile_template(template, template_filename, template_method_name)
184
186
  end
185
187
 
188
+ _load_template(template_filename, template_method_name) unless respond_to?(template_method_name)
189
+
186
190
  send(template_method_name, &block)
187
191
  end
188
192
 
189
193
  private
194
+
195
+ def _load_template(template_filename, template_method_name)
196
+ src = File.read(template_filename)
197
+ src = ERB.new(src).src if template_filename.end_with?(".erb")
198
+ src = <<-RUBY
199
+ def #{template_method_name}; #{src}
200
+ end
201
+ RUBY
202
+ ActionContext.class_eval(src, template_filename.gsub(/\.template\.rb\z/, ".slim"), 1)
203
+ end
204
+
205
+ def _recompile_template(template, template_filename, template_method_name)
206
+ original_template_name = File.join(VIEW_PATH, template.to_s)
207
+ puts "Recompiling #{original_template_name}"
208
+ ActionContext.class_eval { undef_method(template_method_name) } if respond_to?(template_method_name)
209
+
210
+ if original_template_name.end_with?(".slim")
211
+ require "slim"
212
+ File.write(template_filename, Slim::Template.new(original_template_name).precompiled_template)
213
+ end
214
+ template_method_name
215
+ end
216
+
190
217
  def _define_locals(locals)
191
218
  locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include?(k) }
192
219
  end
@@ -1,13 +1,16 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  begin
3
- require 'cgi/escape'
4
+ # this is stdgem in ruby 2.7+
5
+ require "cgi/escape"
4
6
  rescue LoadError
7
+ # optional dependency not present
5
8
  end
6
9
 
7
10
  module Temple
8
11
  # @api public
9
12
  module Utils
10
- extend self
13
+ extend self # rubocop:disable Style/ModuleFunction
11
14
 
12
15
  # Returns an escaped copy of `html`.
13
16
  # Strings which are declared as html_safe are not escaped.
@@ -31,11 +34,11 @@ module Temple
31
34
  # Used by escape_html
32
35
  # @api private
33
36
  ESCAPE_HTML = {
34
- '&' => '&amp;',
35
- '"' => '&quot;',
36
- '\'' => '&#39;',
37
- '<' => '&lt;',
38
- '>' => '&gt;'
37
+ "&" => "&amp;",
38
+ '"' => "&quot;",
39
+ "'" => "&#39;",
40
+ "<" => "&lt;",
41
+ ">" => "&gt;"
39
42
  }.freeze
40
43
 
41
44
  ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
@@ -0,0 +1,13 @@
1
+ _buf = ''; _buf << ("<header><h1>Import dump</h1></header><main><form".freeze);
2
+ ;
3
+ ;
4
+ ;
5
+ ; _slim_codeattributes1 = import_deprecations_path; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" action=\"\"".freeze); else; _buf << (" action=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" enctype=\"multipart/form-data\" method=\"post\"><div class=\"mb-3\"><label class=\"form-label\" for=\"file\">Choose a JSON file to upload:</label> <input class=\"form-comtrol\" id=\"file\" name=\"file\" type=\"file\" /></div><div class=\"mb-3\"><button class=\"btn btn-primary\" type=\"submit\">Upload</button> <a class=\"btn btn-secondary\"".freeze);
6
+ ;
7
+ ;
8
+ ;
9
+ ;
10
+ ;
11
+ ; _slim_codeattributes2 = dump_deprecations_path; if _slim_codeattributes2; if _slim_codeattributes2 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes2))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Dump</a> <a class=\"btn btn-secondary\"".freeze);
12
+ ; _slim_codeattributes3 = deprecations_path; if _slim_codeattributes3; if _slim_codeattributes3 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes3))).to_s); _buf << ("\"".freeze); end; end; _buf << (">Back</a> </div></form></main>".freeze);
13
+ ; _buf
@@ -1,4 +1,4 @@
1
- _buf = ''; _buf << ("<header><h1>Deprecations</h1><a class=\"btn btn-primary\" data-method=\"post\"".freeze);
1
+ _buf = ''; _buf << ("<header class=\"mb-3\"><h1>Deprecations</h1><a class=\"btn btn-primary\" data-method=\"post\"".freeze);
2
2
  ;
3
3
  ;
4
4
  ; _slim_codeattributes1 = deprecation_path(:trigger); if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">Trigger a couple</a> <a class=\"btn btn-danger\" data-confirm=\"Sure?\" data-method=\"delete\"".freeze);
@@ -25,67 +25,93 @@ _buf = ''; _buf << ("<header><h1>Deprecations</h1><a class=\"btn btn-primary\" d
25
25
  ;
26
26
  ;
27
27
  ; total = 0;
28
+ ; by_realm = Hash.new(0);
28
29
  ; @deprecations.each do |deprecation|;
29
30
  ; total += 1;
31
+ ; by_realm[deprecation[:realm]] += 1;
30
32
  ; _buf << ("<tr".freeze); _slim_codeattributes5 = deprecation[:digest]; if _slim_codeattributes5; if _slim_codeattributes5 == true; _buf << (" data-digest=\"\"".freeze); else; _buf << (" data-digest=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes5))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><td><a".freeze);
31
33
  ;
32
34
  ; _slim_codeattributes6 = deprecation_path(deprecation[:digest]); if _slim_codeattributes6; if _slim_codeattributes6 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes6))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:count]))).to_s);
33
35
  ; _buf << ("</a><br />".freeze);
34
- ; if deprecation[:message].include?("Using the last argument as keyword parameters is deprecated") || \
35
- deprecation[:message].include?("Passing the keyword argument as the last hash parameter is deprecated");
36
- ; _buf << ("<div class=\"badge bg-secondary\">kwargs</div> ".freeze);
37
- ; end; if deprecation[:message].include?("trigger_kwargs_error_warning") || \
38
- deprecation[:message].include?("trigger_rails_deprecation");
39
- ; _buf << ("<div class=\"badge bg-success\">test</div> ".freeze);
40
- ; end; if deprecation[:realm] && deprecation[:realm] != 'rails';
41
- ; _buf << ("<div class=\"badge bg-secondary\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:realm]))).to_s);
42
- ; _buf << ("</div> ".freeze); end; deprecation.dig(:notes, :tags)&.each do |tag|;
43
- ; _buf << ("<div class=\"badge bg-secondary\">".freeze); _buf << ((::Temple::Utils.escape_html((tag))).to_s);
36
+ ; deprecation_tags(deprecation).each_pair do |tag, cls|;
37
+ ; _buf << ("<div".freeze); _temple_html_attributeremover1 = ''; _temple_html_attributemerger1 = []; _temple_html_attributemerger1[0] = "badge"; _temple_html_attributemerger1[1] = ''; _slim_codeattributes7 = cls; if Array === _slim_codeattributes7; _slim_codeattributes7 = _slim_codeattributes7.flatten; _slim_codeattributes7.map!(&:to_s); _slim_codeattributes7.reject!(&:empty?); _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7.join(" ")))).to_s); else; _temple_html_attributemerger1[1] << ((::Temple::Utils.escape_html((_slim_codeattributes7))).to_s); end; _temple_html_attributemerger1[1]; _temple_html_attributeremover1 << ((_temple_html_attributemerger1.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover1; if !_temple_html_attributeremover1.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover1).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((tag))).to_s);
44
38
  ;
45
39
  ; _buf << ("</div> ".freeze); end; _buf << ("</td><td>".freeze);
46
40
  ;
47
41
  ; msg = deprecation[:message]
48
42
  delete_prefixes = Gem.path + [defined?(Rails) && Rails.root.to_s].compact
49
43
  delete_prefixes.each { |path| msg.gsub!(path, '') }
50
- ;
51
- ; _buf << ("<div class=\"card text-dark bg-light\"><pre class=\"pre-scrollable\" style=\"overflow: auto; max-width: 700px; max-height: 200px; font-size: 11px\"><code>".freeze);
52
- ;
53
- ; _buf << ((::Temple::Utils.escape_html((msg.delete_prefix("DEPRECATION WARNING: ")))).to_s);
54
- ; _buf << ("</code></pre></div>".freeze); if deprecation.dig(:notes, :comment);
44
+ msg.delete_prefix! deprecation[:gem_traceline].gsub(/:in .+/, ':') if deprecation[:gem_traceline]
45
+ msg.delete_prefix! deprecation[:app_traceline].gsub(/:in .+/, ':') if deprecation[:app_traceline]
46
+ msg.strip!
47
+ msg.delete_prefix!("DEPRECATION WARNING: ")
48
+ msg.delete_prefix!("warning: ")
49
+ ;
50
+ ; if msg.lines.size > 2;
51
+ ; _buf << ("<pre class=\"pre-scrollable p-1\" style=\"overflow: auto; max-width: 700px; max-height: 200px; font-size: 11px\"><code>".freeze);
52
+ ; _buf << ((::Temple::Utils.escape_html((msg))).to_s);
53
+ ; _buf << ("</code></pre>".freeze); else;
54
+ ; _buf << ("<div class=\"msg\">".freeze); _buf << ((::Temple::Utils.escape_html((msg))).to_s);
55
+ ; _buf << ("</div>".freeze); end; if deprecation.dig(:notes, :comment);
55
56
  ; _buf << ((::Temple::Utils.escape_html((deprecation.dig(:notes, :comment)))).to_s);
56
57
  ;
57
58
  ; end; if deprecation.dig(:context, :action);
58
- ; _buf << ("<div class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :action)))).to_s);
59
- ; _buf << ("</div>".freeze); elsif deprecation.dig(:context, :params, :controller);
60
- ; _buf << ("<div class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :params).slice(:controller, :action).values.join('#')))).to_s);
61
- ; _buf << ("</div>".freeze); end; _buf << ("</td><td>".freeze);
59
+ ; _buf << ("<i class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :action)))).to_s);
60
+ ; _buf << ("</i>".freeze); elsif deprecation.dig(:context, :params, :controller);
61
+ ; _buf << ("<i class=\"small controller\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation.dig(:context, :params).slice(:controller, :action).values.join('#')))).to_s);
62
+ ;
63
+ ; _buf << ("</i>".freeze); end; _buf << ("</td><td class=\"small\">".freeze);
62
64
  ; if deprecation[:gem_traceline];
63
- ; _buf << ((::Temple::Utils.escape_html((deprecation[:gem_traceline]))).to_s);
64
- ; _buf << ("<br>".freeze);
65
- ; end; if deprecation[:app_traceline];
65
+ ; _buf << ("<div class=\"gem_location\">".freeze);
66
+ ; location, function = deprecation[:gem_traceline].split(':in `', 2);
67
+ ; full_gemname = location.delete_prefix('/gems/').gsub(%r{/.*}, '');
68
+ ; location_in_gem = location.delete_prefix("/gems/#{full_gemname}/");
69
+ ; _buf << ("<i>".freeze); _buf << ((::Temple::Utils.escape_html((full_gemname))).to_s);
70
+ ; _buf << ("</i> <code class=\"code_location\"".freeze); _slim_codeattributes8 = location_in_gem; if _slim_codeattributes8; if _slim_codeattributes8 == true; _buf << (" data-copy-value=\"\"".freeze); else; _buf << (" data-copy-value=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes8))).to_s); _buf << ("\"".freeze); end; end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((location_in_gem.delete_prefix('lib/')))).to_s);
71
+ ; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
72
+ ; _buf << ("</i></div>".freeze); end; if deprecation[:app_traceline];
73
+ ; _buf << ("<div class=\"app_location\">".freeze);
66
74
  ; location, function = deprecation[:app_traceline].split(':in `', 2);
67
- ; _buf << ("<code class=\"code_location\" style=\"cursor: pointer\">".freeze); _buf << ((::Temple::Utils.escape_html((location))).to_s);
68
- ; _buf << ("</code> ".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
69
- ; end; _buf << ("</td><td><div class=\"small ruby\">".freeze);
75
+ ; _buf << ("<code class=\"code_location\">".freeze); _buf << ((::Temple::Utils.escape_html((location))).to_s);
76
+ ; _buf << ("</code> <i>".freeze); _buf << ((::Temple::Utils.escape_html((function.delete_suffix("'")))).to_s);
77
+ ; _buf << ("</i></div>".freeze); end; _buf << ("</td><td><div class=\"small ruby\">".freeze);
70
78
  ; _buf << ((::Temple::Utils.escape_html((deprecation[:ruby_version]))).to_s);
71
79
  ; _buf << ("</div><div class=\"small rails\">".freeze); _buf << ((::Temple::Utils.escape_html((deprecation[:rails_version]))).to_s);
72
80
  ;
73
- ; _buf << ("</div><a data-confirm=\"Delete?\" data-method=\"delete\"".freeze); _slim_codeattributes7 = deprecation_path(deprecation[:digest]); if _slim_codeattributes7; if _slim_codeattributes7 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes7))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><i class=\"bi bi-trash\"></i></a></td></tr>".freeze);
81
+ ; _buf << ("</div><a data-confirm=\"Delete?\" data-method=\"delete\"".freeze); _slim_codeattributes9 = deprecation_path(deprecation[:digest]); if _slim_codeattributes9; if _slim_codeattributes9 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes9))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\" title=\"Delete\"><i class=\"bi bi-trash\"></i></a></td></tr>".freeze);
74
82
  ;
75
83
  ; end; if total.zero?;
76
84
  ; _buf << ("<tr><td".freeze);
77
- ; _slim_codeattributes8 = 4; if _slim_codeattributes8; if _slim_codeattributes8 == true; _buf << (" colspan=\"\"".freeze); else; _buf << (" colspan=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes8))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><p>Looks like there're no deprecations</p><p>You can try <a data-method=\"post\"".freeze);
85
+ ; _slim_codeattributes10 = 4; if _slim_codeattributes10; if _slim_codeattributes10 == true; _buf << (" colspan=\"\"".freeze); else; _buf << (" colspan=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes10))).to_s); _buf << ("\"".freeze); end; end; _buf << ("><p>Looks like there're no deprecations (or workers have not yet wrote to redis)</p><p>You can try <a data-method=\"post\"".freeze);
78
86
  ;
79
87
  ;
80
88
  ;
81
- ; _slim_codeattributes9 = deprecation_path(:trigger); if _slim_codeattributes9; if _slim_codeattributes9 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes9))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">trigger a couple</a></p></td></tr>".freeze);
89
+ ; _slim_codeattributes11 = deprecation_path(:trigger); if _slim_codeattributes11; if _slim_codeattributes11 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes11))).to_s); _buf << ("\"".freeze); end; end; _buf << (" rel=\"nofollow\">trigger a couple</a>".freeze);
90
+ ; if import_enabled?;
91
+ ; _buf << (", or <a".freeze);
92
+ ; _slim_codeattributes12 = import_deprecations_path; if _slim_codeattributes12; if _slim_codeattributes12 == true; _buf << (" href=\"\"".freeze); else; _buf << (" href=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes12))).to_s); _buf << ("\"".freeze); end; end; _buf << (">import</a> ".freeze);
82
93
  ;
83
- ; end; _buf << ("</table></main><footer>".freeze);
94
+ ;
95
+ ; end; _buf << ("</p></td></tr>".freeze); end; _buf << ("</table></main><footer>".freeze);
84
96
  ; if total > 3;
85
97
  ; _buf << ((::Temple::Utils.escape_html((total))).to_s);
86
98
  ; _buf << (" deprecations ".freeze);
99
+ ; end; by_realm.each_pair do |realm, count|;
100
+ ; _buf << ("<a class=\"btn btn-sm btn-outline-secondary\" href=\"?realm=".freeze); _buf << ((::Temple::Utils.escape_html((realm))).to_s); _buf << ("\">".freeze);
101
+ ; _buf << ((::Temple::Utils.escape_html((realm))).to_s);
102
+ ; _buf << (" <div".freeze); _temple_html_attributeremover2 = ''; _temple_html_attributemerger2 = []; _temple_html_attributemerger2[0] = "badge"; _temple_html_attributemerger2[1] = ''; _slim_codeattributes13 = (count == 0 ? 'bg-success' : 'bg-secondary'); if Array === _slim_codeattributes13; _slim_codeattributes13 = _slim_codeattributes13.flatten; _slim_codeattributes13.map!(&:to_s); _slim_codeattributes13.reject!(&:empty?); _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13.join(" ")))).to_s); else; _temple_html_attributemerger2[1] << ((::Temple::Utils.escape_html((_slim_codeattributes13))).to_s); end; _temple_html_attributemerger2[1]; _temple_html_attributeremover2 << ((_temple_html_attributemerger2.reject(&:empty?).join(" ")).to_s); _temple_html_attributeremover2; if !_temple_html_attributeremover2.empty?; _buf << (" class=\"".freeze); _buf << ((_temple_html_attributeremover2).to_s); _buf << ("\"".freeze); end; _buf << (">".freeze); _buf << ((::Temple::Utils.escape_html((count))).to_s);
103
+ ; _buf << ("</div> </a> ".freeze); end; if params[:realm] && params[:realm] != '';
104
+ ; _buf << ("<a class=\"btn btn-sm btn-outline-primary\" href=\"?realm=\">Other realms </a> ".freeze);
105
+ ;
106
+ ;
107
+ ; end; _buf << ("</footer><style>.code_location {\n cursor: pointer;\n}</style><script>document.querySelectorAll('.code_location').forEach(function(elem){\n elem.addEventListener('click', function () {\n let textToCopy = elem.getAttribute('data-copy-value');\n if(!textToCopy) textToCopy = elem.innerText;\n console.log(\"Copying\", textToCopy)\n navigator.clipboard.writeText(textToCopy);\n }, false);\n});</script>".freeze);
108
+ ;
109
+ ;
110
+ ;
111
+ ;
112
+ ;
113
+ ;
87
114
  ;
88
- ; end; _buf << ("</footer><script>document.querySelectorAll('.code_location').forEach(function(elem){\n elem.addEventListener('click', function () {\n console.log(\"Copying\", elem.innerText)\n navigator.clipboard.writeText(elem.innerText);\n }, false);\n});</script>".freeze);
89
115
  ;
90
116
  ;
91
117
  ;
@@ -1,11 +1,11 @@
1
- _buf = ''; _buf << ("<!DOCTYPE html><html><head><meta charset=\"utf-8\" /><meta content=\"IE=edge;chrome=1\" http-equiv=\"X-UA-Compatible\" /><title>".freeze);
2
- ;
1
+ _buf = ''; _buf << ("<!DOCTYPE html><html".freeze);
2
+ ; _slim_codeattributes1 = current_color_theme; if _slim_codeattributes1; if _slim_codeattributes1 == true; _buf << (" data-bs-theme=\"\"".freeze); else; _buf << (" data-bs-theme=\"".freeze); _buf << ((::Temple::Utils.escape_html((_slim_codeattributes1))).to_s); _buf << ("\"".freeze); end; end; _buf << (" lang=\"en\"><head><meta charset=\"utf-8\" /><meta content=\"IE=edge;chrome=1\" http-equiv=\"X-UA-Compatible\" /><title>".freeze);
3
3
  ;
4
4
  ;
5
5
  ;
6
6
  ;
7
7
  ; _buf << ((::Temple::Utils.escape_html(("Deprecations"))).to_s);
8
- ; _buf << ("</title><meta content=\"\" name=\"description\" /><meta content=\"width=device-width\" name=\"viewport\" /><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\" /><link href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css\" rel=\"stylesheet\" /></head><body><div class=\"container-fluid\">".freeze);
8
+ ; _buf << ("</title><meta content=\"Deprecation collector ui\" name=\"description\" /><meta content=\"width=device-width\" name=\"viewport\" /><link crossorigin=\"anonymous\" href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css\" integrity=\"sha256-Fu5/PVNGJlC70y4mPEjA6nWVdPz2IMaBrXGQCJEsRho= sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ\" rel=\"stylesheet\" /><link crossorigin=\"anonymous\" href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css\" integrity=\"sha256-4RctOgogjPAdwGbwq+rxfwAmSpZhWaafcZR9btzUk18= sha384-b6lVK+yci+bfDmaY1u0zE8YYJt0TZxLEAFyYSLHId4xoVvsrQu3INevFKo+Xir8e\" rel=\"stylesheet\" /></head><body><div class=\"container-fluid\">".freeze);
9
9
  ;
10
10
  ;
11
11
  ;
@@ -14,5 +14,78 @@ _buf = ''; _buf << ("<!DOCTYPE html><html><head><meta charset=\"utf-8\" /><meta
14
14
  ;
15
15
  ; _buf << ((yield).to_s);
16
16
  ;
17
- ; _buf << ("</div><script src=\"https://cdn.jsdelivr.net/npm/rails-ujs@5.2.8-1/lib/assets/compiled/rails-ujs.min.js\"></script></body></html>".freeze);
17
+ ; _buf << ("</div><script async=\"\" crossorigin=\"anonymous\" integrity=\"sha256-9Mbe9mGA7d+AJbnz0O6CoLGabCbe6JAYnGshvGIADiE=\" src=\"https://cdn.jsdelivr.net/npm/@rails/ujs@7.0.4-3/lib/assets/compiled/rails-ujs.js\"></script><script async=\"\" crossorigin=\"anonymous\" integrity=\"sha256-QucgBAKNM4KKPJHqTfH8e+JON1G/gmPPqtMmBb+wHpc= sha384-Y4oOpwW3duJdCWv5ly8SCFYWqFDsfob/3GkgExXKV4idmbt98QcxXYs9UoXAB7BZ\" src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.min.js\"></script><script>(() => {\n 'use strict'\n\n const storedTheme = localStorage.getItem('theme')\n\n const getPreferredTheme = () => {\n if (storedTheme) { return storedTheme }\n let fromServer = document.documentElement.getAttribute('data-bs-theme')\n if(fromServer) { return fromServer }\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n\n const setTheme = function (theme) {\n if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n document.documentElement.setAttribute('data-bs-theme', 'dark')\n } else {\n document.documentElement.setAttribute('data-bs-theme', theme)\n }\n }\n\n setTheme(getPreferredTheme())\n\n const showActiveTheme = (theme, focus = false) => {\n const themeSwitcher = document.querySelector('#bd-theme')\n\n if (!themeSwitcher) {\n return\n }\n\n const themeSwitcherText = document.querySelector('#bd-theme-text')\n const activeThemeIcon = document.querySelector('.theme-icon-active use')\n const btnToActive = document.querySelector(`[data-bs-theme-value=\"${theme}\"]`)\n const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')\n\n document.querySelectorAll('[data-bs-theme-value]').forEach(element => {\n element.classList.remove('active')\n element.setAttribute('aria-pressed', 'false')\n })\n\n btnToActive.classList.add('active')\n btnToActive.setAttribute('aria-pressed', 'true')\n activeThemeIcon.setAttribute('href', svgOfActiveBtn)\n const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`\n themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)\n\n if (focus) {\n themeSwitcher.focus()\n }\n }\n\n window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {\n if (storedTheme !== 'light' || storedTheme !== 'dark') {\n setTheme(getPreferredTheme())\n }\n })\n\n window.addEventListener('DOMContentLoaded', () => {\n showActiveTheme(getPreferredTheme())\n\n document.querySelectorAll('[data-bs-theme-value]')\n .forEach(toggle => {\n toggle.addEventListener('click', () => {\n const theme = toggle.getAttribute('data-bs-theme-value')\n localStorage.setItem('theme', theme)\n setTheme(theme)\n showActiveTheme(theme, true)\n })\n })\n })\n})()</script></body></html>".freeze);
18
+ ;
19
+ ;
20
+ ;
21
+ ;
22
+ ;
23
+ ;
24
+ ;
25
+ ;
26
+ ;
27
+ ;
28
+ ;
29
+ ;
30
+ ;
31
+ ;
32
+ ;
33
+ ;
34
+ ;
35
+ ;
36
+ ;
37
+ ;
38
+ ;
39
+ ;
40
+ ;
41
+ ;
42
+ ;
43
+ ;
44
+ ;
45
+ ;
46
+ ;
47
+ ;
48
+ ;
49
+ ;
50
+ ;
51
+ ;
52
+ ;
53
+ ;
54
+ ;
55
+ ;
56
+ ;
57
+ ;
58
+ ;
59
+ ;
60
+ ;
61
+ ;
62
+ ;
63
+ ;
64
+ ;
65
+ ;
66
+ ;
67
+ ;
68
+ ;
69
+ ;
70
+ ;
71
+ ;
72
+ ;
73
+ ;
74
+ ;
75
+ ;
76
+ ;
77
+ ;
78
+ ;
79
+ ;
80
+ ;
81
+ ;
82
+ ;
83
+ ;
84
+ ;
85
+ ;
86
+ ;
87
+ ;
88
+ ;
89
+ ;
90
+ ;
18
91
  ; _buf