rails-footnotes 4.1.5 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +25 -0
- data/.gitignore +4 -3
- data/CHANGELOG +8 -0
- data/Gemfile +8 -1
- data/Gemfile.lock +187 -0
- data/README.rdoc +8 -54
- data/Rakefile +1 -6
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/gemfiles/{Gemfile.rails-3.2.x → Gemfile.rails-3.2.22} +1 -1
- data/lib/generators/templates/rails_footnotes.rb +4 -5
- data/lib/rails-footnotes.rb +9 -9
- data/lib/rails-footnotes/extension.rb +8 -11
- data/lib/rails-footnotes/filter.rb +13 -4
- data/lib/rails-footnotes/notes/assigns_note.rb +2 -2
- data/lib/rails-footnotes/notes/files_note.rb +12 -23
- data/lib/rails-footnotes/notes/log_note.rb +1 -1
- data/lib/rails-footnotes/notes/params_note.rb +5 -1
- data/lib/rails-footnotes/notes/queries_note.rb +9 -10
- data/lib/rails-footnotes/notes/view_note.rb +16 -7
- data/lib/rails-footnotes/version.rb +1 -1
- data/lib/rails6-footnotes.rb +1 -0
- data/rails-footnotes.gemspec +5 -10
- data/spec/abstract_note_spec.rb +17 -13
- data/spec/app/assets/config/manifest.js +2 -0
- data/spec/app/assets/javascripts/foobar.js +1 -0
- data/spec/app/assets/stylesheets/foobar.css +0 -0
- data/spec/app/views/files/index.html.erb +1 -0
- data/spec/app/views/layouts/application.html.erb +12 -0
- data/spec/{views → app/views}/partials/_foo.html.erb +0 -0
- data/spec/{views → app/views}/partials/index.html.erb +0 -0
- data/spec/controllers/files_note_controller_spec.rb +38 -0
- data/spec/controllers/footnotes_controller_spec.rb +49 -34
- data/spec/controllers/log_note_controller_spec.rb +4 -8
- data/spec/controllers/partials_note_controller_spec.rb +2 -3
- data/spec/env_note_spec.rb +4 -4
- data/spec/footnotes_spec.rb +38 -54
- data/spec/notes/assigns_note_spec.rb +13 -9
- data/spec/notes/controller_note_spec.rb +2 -2
- data/spec/notes/files_note_spec.rb +12 -3
- data/spec/notes/javascripts_note_spec.rb +1 -1
- data/spec/notes/stylesheets_note_spec.rb +1 -1
- data/spec/notes/view_note_spec.rb +18 -0
- data/spec/spec_helper.rb +35 -3
- metadata +38 -48
- data/.travis.yml +0 -14
@@ -1,11 +1,10 @@
|
|
1
|
-
|
1
|
+
Footnotes.setup do |f|
|
2
2
|
# Whether or not to enable footnotes
|
3
3
|
f.enabled = Rails.env.development?
|
4
|
-
# You can also use a lambda / proc to conditionally toggle footnotes
|
5
|
-
# Example :
|
4
|
+
# You can also use a lambda / proc to conditionally toggle footnotes, like
|
6
5
|
# f.enabled = -> { User.current.admin? }
|
7
6
|
# Beware of thread-safety though, Footnotes.enabled is NOT thread safe
|
8
|
-
# and should not be modified
|
7
|
+
# and should not be modified outside this initializer.
|
9
8
|
|
10
9
|
# Only toggle some notes :
|
11
10
|
# f.notes = [:session, :cookies, :params, :filters, :routes, :env, :queries, :log]
|
@@ -24,4 +23,4 @@ defined?(Footnotes) && Footnotes.setup do |f|
|
|
24
23
|
|
25
24
|
# Allow to open multiple notes :
|
26
25
|
# f.multiple_notes = true
|
27
|
-
end
|
26
|
+
end if defined?(Footnotes) && Footnotes.respond_to?(:setup)
|
data/lib/rails-footnotes.rb
CHANGED
@@ -5,7 +5,6 @@ require 'rails-footnotes/each_with_rescue'
|
|
5
5
|
require 'rails-footnotes/filter'
|
6
6
|
require 'rails-footnotes/notes/all'
|
7
7
|
require 'rails-footnotes/extension'
|
8
|
-
require 'active_support/deprecation'
|
9
8
|
|
10
9
|
module Footnotes
|
11
10
|
mattr_accessor :before_hooks
|
@@ -37,11 +36,6 @@ module Footnotes
|
|
37
36
|
delegate :font_size=, :to => Filter
|
38
37
|
end
|
39
38
|
|
40
|
-
def self.run!
|
41
|
-
ActiveSupport::Deprecation.warn "run! is deprecated and will be removed from future releases, use Footnotes.setup or Footnotes.enabled instead.", caller
|
42
|
-
Footnotes.enabled = true
|
43
|
-
end
|
44
|
-
|
45
39
|
def self.before(&block)
|
46
40
|
@@before_hooks << block
|
47
41
|
end
|
@@ -50,9 +44,13 @@ module Footnotes
|
|
50
44
|
@@after_hooks << block
|
51
45
|
end
|
52
46
|
|
53
|
-
def self.enabled?
|
47
|
+
def self.enabled?(controller)
|
54
48
|
if @@enabled.is_a? Proc
|
55
|
-
@@enabled.
|
49
|
+
if @@enabled.arity == 1
|
50
|
+
@@enabled.call(controller)
|
51
|
+
else
|
52
|
+
@@enabled.call
|
53
|
+
end
|
56
54
|
else
|
57
55
|
!!@@enabled
|
58
56
|
end
|
@@ -63,6 +61,8 @@ module Footnotes
|
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
66
|
-
|
64
|
+
ActiveSupport.on_load(:action_controller) do
|
65
|
+
ActionController::Base.send(:include, Footnotes::RailsFootnotesExtension)
|
66
|
+
end
|
67
67
|
|
68
68
|
load Rails.root.join('.rails_footnotes') if Rails.root && Rails.root.join('.rails_footnotes').exist?
|
@@ -2,26 +2,23 @@ require 'active_support/concern'
|
|
2
2
|
|
3
3
|
module Footnotes
|
4
4
|
module RailsFootnotesExtension
|
5
|
-
|
6
5
|
extend ActiveSupport::Concern
|
7
6
|
|
8
7
|
included do
|
9
|
-
|
10
|
-
|
8
|
+
prepend_before_action :rails_footnotes_before_filter
|
9
|
+
after_action :rails_footnotes_after_filter
|
11
10
|
end
|
12
11
|
|
13
12
|
def rails_footnotes_before_filter
|
14
|
-
if Footnotes.enabled?
|
15
|
-
Footnotes::Filter.start!(self)
|
16
|
-
end
|
13
|
+
Footnotes::Filter.start!(self) if Footnotes.enabled?(self)
|
17
14
|
end
|
18
15
|
|
19
16
|
def rails_footnotes_after_filter
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
return unless Footnotes.enabled?(self)
|
18
|
+
|
19
|
+
filter = Footnotes::Filter.new(self)
|
20
|
+
filter.add_footnotes!
|
21
|
+
filter.close!(self)
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
@@ -47,7 +47,7 @@ module Footnotes
|
|
47
47
|
if args.empty?
|
48
48
|
@@prefix
|
49
49
|
else
|
50
|
-
args.map! { |arg|
|
50
|
+
args.map! { |arg| arg.to_s.split("/").map{|s| ERB::Util.url_encode(s) }.join("/") }
|
51
51
|
|
52
52
|
if @@prefix.respond_to? :call
|
53
53
|
@@prefix.call *args
|
@@ -116,7 +116,8 @@ module Footnotes
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def valid_format?
|
119
|
-
|
119
|
+
format = @controller.response.content_type
|
120
|
+
format.nil? || format.include?("text/html")
|
120
121
|
end
|
121
122
|
|
122
123
|
def valid_content_type?
|
@@ -169,7 +170,7 @@ module Footnotes
|
|
169
170
|
#footnotes_debug table td {padding: 5px; border-bottom: 1px solid #ccc;}
|
170
171
|
#footnotes_debug table td strong {color: #9b1b1b;}
|
171
172
|
#footnotes_debug table th {padding: 5px; border-bottom: 1px solid #ccc;}
|
172
|
-
#footnotes_debug table tr:nth-child(2n) td {background: #
|
173
|
+
#footnotes_debug table tr:nth-child(2n) td {background: #f5f5f5;}
|
173
174
|
#footnotes_debug table tr:nth-child(2n + 1) td {background: #fff;}
|
174
175
|
#footnotes_debug tbody {text-align: left;}
|
175
176
|
#footnotes_debug .name_values td {vertical-align: top;}
|
@@ -207,14 +208,22 @@ module Footnotes
|
|
207
208
|
}
|
208
209
|
|
209
210
|
function hideAllAndToggle(id) {
|
211
|
+
var n = note(id);
|
212
|
+
var display = n.style.display;
|
210
213
|
hideAll();
|
214
|
+
// Restore original display to allow toggling
|
215
|
+
n.style.display = display;
|
211
216
|
toggle(id)
|
212
217
|
|
213
218
|
location.href = '#footnotes_debug';
|
214
219
|
}
|
215
220
|
|
221
|
+
function note(id) {
|
222
|
+
return (document.getElementById(id));
|
223
|
+
}
|
224
|
+
|
216
225
|
function toggle(id){
|
217
|
-
var el =
|
226
|
+
var el = note(id);
|
218
227
|
if (el.style.display == 'none') {
|
219
228
|
Footnotes.show(el);
|
220
229
|
} else {
|
@@ -16,9 +16,9 @@ module Footnotes
|
|
16
16
|
:@view_runtime,
|
17
17
|
:@marked_for_same_origin_verification
|
18
18
|
]
|
19
|
-
cattr_accessor :ignored_assigns, :
|
19
|
+
cattr_accessor :ignored_assigns, :instance_writer => false
|
20
20
|
@@ignored_assigns_pattern = /^@_/
|
21
|
-
cattr_accessor :ignored_assigns_pattern, :
|
21
|
+
cattr_accessor :ignored_assigns_pattern, :instance_writer => false
|
22
22
|
|
23
23
|
def initialize(controller)
|
24
24
|
@controller = controller
|
@@ -24,36 +24,25 @@ module Footnotes
|
|
24
24
|
|
25
25
|
protected
|
26
26
|
def scan_text(text)
|
27
|
-
|
27
|
+
raise NotImplementedError, "implement this in your subclass"
|
28
28
|
end
|
29
29
|
|
30
30
|
def parse_files!
|
31
|
-
|
32
|
-
|
33
|
-
linked_files = []
|
31
|
+
asset_paths = Rails.application.config.try(:assets).try(:paths) || []
|
32
|
+
linked_files = []
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
break if results.present?
|
43
|
-
end
|
44
|
-
end
|
45
|
-
@files = linked_files
|
46
|
-
else
|
47
|
-
#Original Implementation
|
48
|
-
@files.collect! do |filename|
|
49
|
-
if filename =~ %r{^/}
|
50
|
-
full_filename = File.join(File.expand_path(Rails.root), 'public', filename)
|
51
|
-
%[<a href="#{Footnotes::Filter.prefix(full_filename, 1, 1)}">#{filename}</a>]
|
52
|
-
else
|
53
|
-
%[<a href="#{filename}">#{filename}</a>]
|
34
|
+
@files.collect do |file|
|
35
|
+
file.gsub!(/-[a-f0-9]{64}\./, '.')
|
36
|
+
base_name = File.basename(file)
|
37
|
+
asset_paths.each do |asset_path|
|
38
|
+
results = Dir[File.expand_path(base_name, asset_path) + '*']
|
39
|
+
results.each do |r|
|
40
|
+
linked_files << %[<a href="#{Footnotes::Filter.prefix(r, 1, 1)}">#{File.basename(r)}</a>]
|
54
41
|
end
|
42
|
+
break if results.present?
|
55
43
|
end
|
56
44
|
end
|
45
|
+
@files = linked_files
|
57
46
|
end
|
58
47
|
end
|
59
48
|
end
|
@@ -20,7 +20,7 @@ module Footnotes
|
|
20
20
|
end
|
21
21
|
# Rails 3 don't have ActiveSupport::Logger#broadcast so we backported it
|
22
22
|
extend_module = defined?(ActiveSupport::Logger) ? ActiveSupport::Logger.broadcast(note_logger) : NoteLogger.broadcast(note_logger)
|
23
|
-
Rails.logger = self.original_logger.
|
23
|
+
Rails.logger = self.original_logger.clone.extend(extend_module)
|
24
24
|
end
|
25
25
|
|
26
26
|
def title
|
@@ -2,7 +2,11 @@ module Footnotes
|
|
2
2
|
module Notes
|
3
3
|
class ParamsNote < AbstractNote
|
4
4
|
def initialize(controller)
|
5
|
-
@params =
|
5
|
+
@params = if Rails::VERSION::MAJOR >= 5
|
6
|
+
controller.params.to_unsafe_h
|
7
|
+
else
|
8
|
+
controller.params
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
def title
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Footnotes
|
2
2
|
module Notes
|
3
3
|
class QueriesNote < AbstractNote
|
4
|
-
cattr_accessor :alert_db_time, :alert_sql_number, :orm, :ignored_regexps, :
|
4
|
+
cattr_accessor :alert_db_time, :alert_sql_number, :orm, :ignored_regexps, :instance_writer => false
|
5
5
|
@@alert_db_time = 16.0
|
6
6
|
@@alert_sql_number = 8
|
7
7
|
@@query_subscriber = nil
|
@@ -23,8 +23,8 @@ module Footnotes
|
|
23
23
|
def title
|
24
24
|
queries = self.events.count
|
25
25
|
total_time = self.events.map(&:duration).sum
|
26
|
-
query_color =
|
27
|
-
db_color =
|
26
|
+
query_color = alert_color(self.events.count, alert_sql_number)
|
27
|
+
db_color = alert_color(total_time, alert_db_time)
|
28
28
|
|
29
29
|
<<-TITLE
|
30
30
|
<span style="background-color:#{query_color}">Queries (#{queries})</span>
|
@@ -47,7 +47,7 @@ module Footnotes
|
|
47
47
|
<td>
|
48
48
|
<span id="sql_#{index}">#{print_query(event.payload[:sql])}</span>
|
49
49
|
</td>
|
50
|
-
<td>#{print_name_and_time(event.payload[:name], event.duration
|
50
|
+
<td>#{print_name_and_time(event.payload[:name], event.duration)}</td>
|
51
51
|
</tr>
|
52
52
|
HTML
|
53
53
|
end
|
@@ -57,17 +57,16 @@ module Footnotes
|
|
57
57
|
|
58
58
|
protected
|
59
59
|
def print_name_and_time(name, time)
|
60
|
-
"<span style='background-color:#{
|
60
|
+
"<span style='background-color:#{alert_color(time, alert_ratio)}'>#{escape(name || 'SQL')} (#{'%.3fms' % time})</span>"
|
61
61
|
end
|
62
62
|
|
63
63
|
def print_query(query)
|
64
64
|
escape(query.to_s.gsub(/(\s)+/, ' ').gsub('`', ''))
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
"#ff#{c*4}"
|
67
|
+
def alert_color(value, threshold)
|
68
|
+
return 'transparent' if value < threshold
|
69
|
+
'#ffff00'
|
71
70
|
end
|
72
71
|
|
73
72
|
def alert_ratio
|
@@ -103,7 +102,7 @@ module Footnotes
|
|
103
102
|
attr_accessor :events, :ignore_regexps
|
104
103
|
|
105
104
|
def initialize(orm)
|
106
|
-
super()
|
105
|
+
super()
|
107
106
|
@events = []
|
108
107
|
orm.each {|adapter| ActiveSupport::LogSubscriber.attach_to adapter, self}
|
109
108
|
end
|
@@ -1,31 +1,40 @@
|
|
1
1
|
module Footnotes
|
2
2
|
module Notes
|
3
3
|
class ViewNote < AbstractNote
|
4
|
+
cattr_accessor :template
|
5
|
+
|
6
|
+
def self.start!(controller)
|
7
|
+
@subscriber ||= ActiveSupport::Notifications.subscribe('render_template.action_view') do |*args|
|
8
|
+
event = ActiveSupport::Notifications::Event.new *args
|
9
|
+
self.template = {:file => event.payload[:identifier], :duration => event.duration}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
4
13
|
def initialize(controller)
|
5
14
|
@controller = controller
|
6
|
-
@template = controller.instance_variable_get(:@template)
|
7
15
|
end
|
8
16
|
|
9
17
|
def row
|
10
18
|
:edit
|
11
19
|
end
|
12
20
|
|
21
|
+
def title
|
22
|
+
"View (#{"%.3f" % self.template[:duration]}ms)"
|
23
|
+
end
|
24
|
+
|
13
25
|
def link
|
14
26
|
escape(Footnotes::Filter.prefix(filename, 1, 1))
|
15
27
|
end
|
16
28
|
|
17
29
|
def valid?
|
18
|
-
prefix? &&
|
30
|
+
prefix? && filename && File.exists?(filename)
|
19
31
|
end
|
20
32
|
|
21
33
|
protected
|
22
34
|
|
23
|
-
def first_render?
|
24
|
-
@template.instance_variable_get(:@_first_render)
|
25
|
-
end
|
26
|
-
|
27
35
|
def filename
|
28
|
-
@filename
|
36
|
+
return @filename if defined?(@filename)
|
37
|
+
@filename = self.class.template.try(:[], :file)
|
29
38
|
end
|
30
39
|
|
31
40
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "./rails-footnotes"
|
data/rails-footnotes.gemspec
CHANGED
@@ -6,21 +6,16 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "rails-footnotes"
|
7
7
|
s.version = Footnotes::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson", "Adrien Siami"]
|
10
|
-
s.email = ["
|
11
|
-
s.homepage = "http://github.com/
|
9
|
+
s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson", "Adrien Siami", "André Arko"]
|
10
|
+
s.email = ["andre@arko.net"]
|
11
|
+
s.homepage = "http://github.com/indirect/rails-footnotes"
|
12
12
|
s.summary = %q{Every Rails page has footnotes that gives information about your application and links back to your editor.}
|
13
13
|
s.description = %q{Every Rails page has footnotes that gives information about your application and links back to your editor.}
|
14
14
|
|
15
|
-
s.
|
16
|
-
|
17
|
-
s.add_dependency "rails", ">= 3.2"
|
18
|
-
|
19
|
-
s.add_development_dependency "rspec-rails", '~> 2.14.0'
|
20
|
-
s.add_development_dependency "capybara"
|
15
|
+
s.add_dependency "rails", "~> 6.0"
|
16
|
+
s.required_ruby_version = "~> 3.0"
|
21
17
|
|
22
18
|
s.files = `git ls-files`.split("\n")
|
23
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
25
20
|
s.require_paths = ["lib"]
|
26
21
|
end
|
data/spec/abstract_note_spec.rb
CHANGED
@@ -11,17 +11,21 @@ describe Footnotes::Notes::AbstractNote do
|
|
11
11
|
Footnotes::Filter.notes = @notes
|
12
12
|
end
|
13
13
|
|
14
|
-
it {described_class.
|
15
|
-
it {described_class.
|
16
|
-
it {described_class.
|
14
|
+
it {expect(described_class).to respond_to :start!}
|
15
|
+
it {expect(described_class).to respond_to :close!}
|
16
|
+
it {expect(described_class).to respond_to :title}
|
17
17
|
|
18
18
|
it {should respond_to :to_sym}
|
19
|
-
its(:to_sym) {should eql :abstract}
|
20
19
|
|
21
|
-
|
20
|
+
describe '#to_sym' do
|
21
|
+
subject { super().to_sym }
|
22
|
+
it {should eql :abstract}
|
23
|
+
end
|
24
|
+
|
25
|
+
it { expect(described_class).to be_included }
|
22
26
|
specify do
|
23
27
|
Footnotes::Filter.notes = []
|
24
|
-
described_class.
|
28
|
+
expect(described_class).not_to be_included
|
25
29
|
end
|
26
30
|
|
27
31
|
it { should respond_to :row }
|
@@ -45,12 +49,12 @@ describe Footnotes::Notes::AbstractNote do
|
|
45
49
|
|
46
50
|
#TODO should be moved to builder
|
47
51
|
#helpers
|
48
|
-
specify { subject.escape('<').
|
49
|
-
specify { subject.escape('&').
|
50
|
-
specify { subject.escape('>').
|
52
|
+
specify { expect(subject.escape('<')).to eql '<' }
|
53
|
+
specify { expect(subject.escape('&')).to eql '&' }
|
54
|
+
specify { expect(subject.escape('>')).to eql '>' }
|
51
55
|
|
52
|
-
specify { subject.mount_table([]).
|
53
|
-
specify { subject.mount_table([['h1', 'h2', 'h3']], :class => 'table').
|
56
|
+
specify { expect(subject.mount_table([])).to be_blank }
|
57
|
+
specify { expect(subject.mount_table([['h1', 'h2', 'h3']], :class => 'table')).to be_blank }
|
54
58
|
|
55
59
|
specify {
|
56
60
|
tab = <<-TABLE
|
@@ -60,7 +64,7 @@ describe Footnotes::Notes::AbstractNote do
|
|
60
64
|
</table>
|
61
65
|
TABLE
|
62
66
|
|
63
|
-
subject.mount_table([['h1'],['r1c1']], :class => 'table').
|
67
|
+
expect(subject.mount_table([['h1'],['r1c1']], :class => 'table')).to eql tab
|
64
68
|
}
|
65
69
|
|
66
70
|
specify {
|
@@ -70,7 +74,7 @@ describe Footnotes::Notes::AbstractNote do
|
|
70
74
|
<tbody><tr><td>r1c1</td><td>r1c2</td><td>r1c3</td></tr></tbody>
|
71
75
|
</table>
|
72
76
|
TABLE
|
73
|
-
subject.mount_table([['h1', 'h2', 'h3'],['r1c1', 'r1c2', 'r1c3']]).
|
77
|
+
expect(subject.mount_table([['h1', 'h2', 'h3'],['r1c1', 'r1c2', 'r1c3']])).to eql tab
|
74
78
|
}
|
75
79
|
|
76
80
|
specify {
|