rails6-footnotes 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 +7 -0
- data/.github/workflows/ci.yml +25 -0
- data/.gitignore +15 -0
- data/.rspec.example +1 -0
- data/CHANGELOG +129 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +187 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +188 -0
- data/Rakefile +18 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/gemfiles/Gemfile.rails-3.2.22 +5 -0
- data/gemfiles/Gemfile.rails-4.0.x +6 -0
- data/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/gemfiles/Gemfile.rails-edge +5 -0
- data/lib/generators/rails_footnotes/install_generator.rb +14 -0
- data/lib/generators/templates/rails_footnotes.rb +26 -0
- data/lib/rails-footnotes.rb +68 -0
- data/lib/rails-footnotes/abstract_note.rb +178 -0
- data/lib/rails-footnotes/each_with_rescue.rb +36 -0
- data/lib/rails-footnotes/extension.rb +24 -0
- data/lib/rails-footnotes/filter.rb +359 -0
- data/lib/rails-footnotes/notes/all.rb +1 -0
- data/lib/rails-footnotes/notes/assigns_note.rb +60 -0
- data/lib/rails-footnotes/notes/controller_note.rb +55 -0
- data/lib/rails-footnotes/notes/cookies_note.rb +17 -0
- data/lib/rails-footnotes/notes/env_note.rb +24 -0
- data/lib/rails-footnotes/notes/files_note.rb +49 -0
- data/lib/rails-footnotes/notes/filters_note.rb +51 -0
- data/lib/rails-footnotes/notes/javascripts_note.rb +16 -0
- data/lib/rails-footnotes/notes/layout_note.rb +26 -0
- data/lib/rails-footnotes/notes/log_note.rb +47 -0
- data/lib/rails-footnotes/notes/log_note/note_logger.rb +59 -0
- data/lib/rails-footnotes/notes/params_note.rb +21 -0
- data/lib/rails-footnotes/notes/partials_note.rb +38 -0
- data/lib/rails-footnotes/notes/queries_note.rb +121 -0
- data/lib/rails-footnotes/notes/routes_note.rb +60 -0
- data/lib/rails-footnotes/notes/session_note.rb +27 -0
- data/lib/rails-footnotes/notes/stylesheets_note.rb +16 -0
- data/lib/rails-footnotes/notes/view_note.rb +41 -0
- data/lib/rails-footnotes/version.rb +3 -0
- data/lib/rails6-footnotes.rb +1 -0
- data/rails-footnotes.gemspec +22 -0
- data/spec/abstract_note_spec.rb +89 -0
- 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/app/views/partials/_foo.html.erb +1 -0
- data/spec/app/views/partials/index.html.erb +1 -0
- data/spec/controllers/files_note_controller_spec.rb +38 -0
- data/spec/controllers/footnotes_controller_spec.rb +128 -0
- data/spec/controllers/log_note_controller_spec.rb +32 -0
- data/spec/controllers/partials_note_controller_spec.rb +28 -0
- data/spec/env_note_spec.rb +73 -0
- data/spec/fixtures/html_download.html +5 -0
- data/spec/footnotes_spec.rb +234 -0
- data/spec/notes/assigns_note_spec.rb +50 -0
- data/spec/notes/controller_note_spec.rb +12 -0
- data/spec/notes/files_note_spec.rb +26 -0
- data/spec/notes/javascripts_note_spec.rb +18 -0
- data/spec/notes/stylesheets_note_spec.rb +19 -0
- data/spec/notes/view_note_spec.rb +12 -0
- data/spec/spec_helper.rb +68 -0
- metadata +153 -0
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
desc 'Default: run tests'
|
7
|
+
task :default => :spec
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
|
10
|
+
desc 'Generate documentation for Footnotes.'
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Footnotes'
|
14
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
15
|
+
rdoc.rdoc_files.include('README')
|
16
|
+
rdoc.rdoc_files.include('MIT-LICENSE')
|
17
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
18
|
+
end
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RailsFootnotes
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
5
|
+
|
6
|
+
desc "Copy rails-footnotes initializer to your application."
|
7
|
+
|
8
|
+
def copy_initializer
|
9
|
+
template "rails_footnotes.rb", "config/initializers/rails_footnotes.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Footnotes.setup do |f|
|
2
|
+
# Whether or not to enable footnotes
|
3
|
+
f.enabled = Rails.env.development?
|
4
|
+
# You can also use a lambda / proc to conditionally toggle footnotes, like
|
5
|
+
# f.enabled = -> { User.current.admin? }
|
6
|
+
# Beware of thread-safety though, Footnotes.enabled is NOT thread safe
|
7
|
+
# and should not be modified outside this initializer.
|
8
|
+
|
9
|
+
# Only toggle some notes :
|
10
|
+
# f.notes = [:session, :cookies, :params, :filters, :routes, :env, :queries, :log]
|
11
|
+
|
12
|
+
# Change the prefix :
|
13
|
+
# f.prefix = 'mvim://open?url=file://%s&line=%d&column=%d'
|
14
|
+
|
15
|
+
# Disable style :
|
16
|
+
# f.no_style = true
|
17
|
+
|
18
|
+
# Lock notes to top right :
|
19
|
+
# f.lock_top_right = true
|
20
|
+
|
21
|
+
# Change font size :
|
22
|
+
# f.font_size = '11px'
|
23
|
+
|
24
|
+
# Allow to open multiple notes :
|
25
|
+
# f.multiple_notes = true
|
26
|
+
end if defined?(Footnotes) && Footnotes.respond_to?(:setup)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'rails-footnotes/abstract_note'
|
4
|
+
require 'rails-footnotes/each_with_rescue'
|
5
|
+
require 'rails-footnotes/filter'
|
6
|
+
require 'rails-footnotes/notes/all'
|
7
|
+
require 'rails-footnotes/extension'
|
8
|
+
|
9
|
+
module Footnotes
|
10
|
+
mattr_accessor :before_hooks
|
11
|
+
@@before_hooks = []
|
12
|
+
|
13
|
+
mattr_accessor :after_hooks
|
14
|
+
@@after_hooks = []
|
15
|
+
|
16
|
+
mattr_accessor :enabled
|
17
|
+
@@enabled = false
|
18
|
+
|
19
|
+
class << self
|
20
|
+
delegate :notes, :to => Filter
|
21
|
+
delegate :notes=, :to => Filter
|
22
|
+
|
23
|
+
delegate :prefix, :to => Filter
|
24
|
+
delegate :prefix=, :to => Filter
|
25
|
+
|
26
|
+
delegate :no_style, :to => Filter
|
27
|
+
delegate :no_style=, :to => Filter
|
28
|
+
|
29
|
+
delegate :multiple_notes, :to => Filter
|
30
|
+
delegate :multiple_notes=, :to => Filter
|
31
|
+
|
32
|
+
delegate :lock_top_right, :to => Filter
|
33
|
+
delegate :lock_top_right=, :to => Filter
|
34
|
+
|
35
|
+
delegate :font_size, :to => Filter
|
36
|
+
delegate :font_size=, :to => Filter
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.before(&block)
|
40
|
+
@@before_hooks << block
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.after(&block)
|
44
|
+
@@after_hooks << block
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.enabled?(controller)
|
48
|
+
if @@enabled.is_a? Proc
|
49
|
+
if @@enabled.arity == 1
|
50
|
+
@@enabled.call(controller)
|
51
|
+
else
|
52
|
+
@@enabled.call
|
53
|
+
end
|
54
|
+
else
|
55
|
+
!!@@enabled
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.setup
|
60
|
+
yield self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ActiveSupport.on_load(:action_controller) do
|
65
|
+
ActionController::Base.send(:include, Footnotes::RailsFootnotesExtension)
|
66
|
+
end
|
67
|
+
|
68
|
+
load Rails.root.join('.rails_footnotes') if Rails.root && Rails.root.join('.rails_footnotes').exist?
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module Footnotes
|
2
|
+
module Notes
|
3
|
+
# This is the abstract class for notes.
|
4
|
+
# You can overwrite all instance public methods to create your notes.
|
5
|
+
#
|
6
|
+
class AbstractNote
|
7
|
+
|
8
|
+
# Class methods. Do NOT overwrite them.
|
9
|
+
#
|
10
|
+
class << self
|
11
|
+
# Returns the symbol that represents this note.
|
12
|
+
# It's the name of the class, underscored and without _note.
|
13
|
+
#
|
14
|
+
# For example, for ControllerNote it will return :controller.
|
15
|
+
#
|
16
|
+
def to_sym
|
17
|
+
@note_sym ||= self.title.underscore.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the title that represents this note.
|
21
|
+
# It's the name of the class without Note.
|
22
|
+
#
|
23
|
+
# For example, for ControllerNote it will return Controller.
|
24
|
+
#
|
25
|
+
def title
|
26
|
+
@note_title ||= self.name.match(/^Footnotes::Notes::(\w+)Note$/)[1]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return true if Note is included in notes array.
|
30
|
+
#
|
31
|
+
def included?
|
32
|
+
Footnotes::Filter.notes.include?(self.to_sym)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Action to be called to start the Note.
|
36
|
+
# This is applied as a before_filter.
|
37
|
+
#
|
38
|
+
def start!(controller = nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Action to be called after the Note was used.
|
42
|
+
# This is applied as an after_filter.
|
43
|
+
#
|
44
|
+
def close!(controller = nil)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initialize notes.
|
49
|
+
# Always receives a controller.
|
50
|
+
#
|
51
|
+
def initialize(controller = nil)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the symbol that represents this note.
|
55
|
+
#
|
56
|
+
def to_sym
|
57
|
+
self.class.to_sym
|
58
|
+
end
|
59
|
+
|
60
|
+
# Specifies in which row should appear the title.
|
61
|
+
# The default is :show.
|
62
|
+
#
|
63
|
+
def row
|
64
|
+
:show
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the title to be used as link.
|
68
|
+
# The default is the note title.
|
69
|
+
#
|
70
|
+
def title
|
71
|
+
self.class.title
|
72
|
+
end
|
73
|
+
|
74
|
+
# If has_fieldset? is true, create a fieldset with the value returned as legend.
|
75
|
+
# By default, returns the title of the class (defined above).
|
76
|
+
#
|
77
|
+
def legend
|
78
|
+
self.class.title
|
79
|
+
end
|
80
|
+
|
81
|
+
# If content is defined, has_fieldset? returns true and the value of content
|
82
|
+
# is displayed when the Note is clicked. See has_fieldset? below for more info.
|
83
|
+
#
|
84
|
+
# def content
|
85
|
+
# end
|
86
|
+
|
87
|
+
# Set href field for Footnotes links.
|
88
|
+
# If it's nil, Footnotes will use '#'.
|
89
|
+
#
|
90
|
+
def link
|
91
|
+
end
|
92
|
+
|
93
|
+
# Set onclick field for Footnotes links.
|
94
|
+
# If it's nil, Footnotes will make it open the fieldset.
|
95
|
+
#
|
96
|
+
def onclick
|
97
|
+
end
|
98
|
+
|
99
|
+
# Insert here any additional stylesheet.
|
100
|
+
# This is directly inserted into a <style> tag.
|
101
|
+
#
|
102
|
+
def stylesheet
|
103
|
+
end
|
104
|
+
|
105
|
+
# Insert here any additional javascript.
|
106
|
+
# This is directly inserted into a <script> tag.
|
107
|
+
#
|
108
|
+
def javascript
|
109
|
+
end
|
110
|
+
|
111
|
+
# Specifies when should create a note for it.
|
112
|
+
# By default, it's valid.
|
113
|
+
#
|
114
|
+
def valid?
|
115
|
+
true
|
116
|
+
end
|
117
|
+
|
118
|
+
# Specifies when should create a fieldset for it, considering it's valid.
|
119
|
+
#
|
120
|
+
def has_fieldset?
|
121
|
+
self.respond_to?(:content)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Some helpers to generate notes.
|
125
|
+
#
|
126
|
+
public
|
127
|
+
# Return if Footnotes::Filter.prefix exists or not.
|
128
|
+
# Some notes only work with prefix set.
|
129
|
+
#
|
130
|
+
def prefix?
|
131
|
+
!Footnotes::Filter.prefix.blank?
|
132
|
+
end
|
133
|
+
|
134
|
+
# Escape HTML special characters.
|
135
|
+
#
|
136
|
+
def escape(text)
|
137
|
+
text.gsub('&', '&').gsub('<', '<').gsub('>', '>')
|
138
|
+
end
|
139
|
+
|
140
|
+
# Gets a bidimensional array and create a table.
|
141
|
+
# The first array is used as label.
|
142
|
+
#
|
143
|
+
def mount_table(array, options = {})
|
144
|
+
header = array.shift
|
145
|
+
return '' if array.empty?
|
146
|
+
|
147
|
+
header = header.collect{|i| escape(i.to_s.humanize) }
|
148
|
+
rows = array.collect{|i| "<tr><td>#{i.join('</td><td>')}</td></tr>" }
|
149
|
+
|
150
|
+
<<-TABLE
|
151
|
+
<table #{hash_to_xml_attributes(options)}>
|
152
|
+
<thead><tr><th>#{header.join('</th><th>')}</th></tr></thead>
|
153
|
+
<tbody>#{rows.join}</tbody>
|
154
|
+
</table>
|
155
|
+
TABLE
|
156
|
+
end
|
157
|
+
|
158
|
+
# Mount table for hash, using name and value and adding a name_value class
|
159
|
+
# to the generated table.
|
160
|
+
#
|
161
|
+
def mount_table_for_hash(hash, options={})
|
162
|
+
rows = []
|
163
|
+
hash.each do |key, value|
|
164
|
+
rows << [ key.to_sym.inspect, escape(value.inspect) ]
|
165
|
+
end
|
166
|
+
mount_table(rows.unshift(['Name', 'Value']), {:class => 'name_value'}.merge(options))
|
167
|
+
end
|
168
|
+
|
169
|
+
def hash_to_xml_attributes(hash)
|
170
|
+
newstring = ""
|
171
|
+
hash.each do |key, value|
|
172
|
+
newstring << "#{key.to_s}=\"#{value.gsub('"','\"')}\" "
|
173
|
+
end
|
174
|
+
return newstring
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Footnotes
|
2
|
+
module EachWithRescue
|
3
|
+
def self.included(base)
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
# Process notes, discarding only the note if any problem occurs
|
9
|
+
#
|
10
|
+
def each_with_rescue(collection)
|
11
|
+
delete_me = []
|
12
|
+
|
13
|
+
collection.each do |item|
|
14
|
+
begin
|
15
|
+
yield item
|
16
|
+
rescue Exception => e
|
17
|
+
raise e if Rails.env.test?
|
18
|
+
# Discard item if it has a problem
|
19
|
+
log_error("Footnotes #{item.to_s.camelize} Exception", e)
|
20
|
+
delete_me << item
|
21
|
+
next
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
delete_me.each { |item| collection.delete(item) }
|
26
|
+
return collection
|
27
|
+
end
|
28
|
+
|
29
|
+
# Logs the error using specified title and format
|
30
|
+
#
|
31
|
+
def log_error(title, exception)
|
32
|
+
Rails.logger.error "#{title}: #{exception}\n#{exception.backtrace.join("\n")}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|