rails-footnotes 3.7.6 → 3.7.7
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.
- data/Gemfile +0 -11
- data/lib/rails-footnotes/after_filter.rb +10 -0
- data/lib/rails-footnotes/before_filter.rb +9 -0
- data/lib/rails-footnotes/each_with_rescue.rb +35 -0
- data/lib/rails-footnotes/filter.rb +315 -0
- data/lib/rails-footnotes/footnotes.rb +4 -356
- data/lib/rails-footnotes/notes/queries_note.rb +1 -1
- data/lib/rails-footnotes/version.rb +1 -1
- data/rails-footnotes.gemspec +3 -4
- data/spec/footnotes_spec.rb +10 -9
- metadata +18 -22
data/Gemfile
CHANGED
@@ -0,0 +1,35 @@
|
|
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
|
+
# Discard item if it has a problem
|
18
|
+
log_error("Footnotes #{item.to_s.camelize} Exception", e)
|
19
|
+
delete_me << item
|
20
|
+
next
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
delete_me.each { |item| collection.delete(item) }
|
25
|
+
return collection
|
26
|
+
end
|
27
|
+
|
28
|
+
# Logs the error using specified title and format
|
29
|
+
#
|
30
|
+
def log_error(title, exception)
|
31
|
+
Rails.logger.error "#{title}: #{exception}\n#{exception.backtrace.join("\n")}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,315 @@
|
|
1
|
+
module Footnotes
|
2
|
+
class Filter
|
3
|
+
@@no_style = false
|
4
|
+
@@multiple_notes = false
|
5
|
+
@@klasses = []
|
6
|
+
|
7
|
+
# Default link prefix is textmate
|
8
|
+
@@prefix = 'txmt://open?url=file://%s&line=%d&column=%d'
|
9
|
+
|
10
|
+
# Edit notes
|
11
|
+
@@notes = [ :controller, :view, :layout, :partials, :stylesheets, :javascripts ]
|
12
|
+
# Show notes
|
13
|
+
@@notes += [ :assigns, :session, :cookies, :params, :filters, :routes, :env, :queries, :log, :general ]
|
14
|
+
|
15
|
+
# :no_style => If you don't want the style to be appended to your pages
|
16
|
+
# :notes => Class variable that holds the notes to be processed
|
17
|
+
# :prefix => Prefix appended to FootnotesLinks
|
18
|
+
# :multiple_notes => Set to true if you want to open several notes at the same time
|
19
|
+
cattr_accessor :no_style, :notes, :prefix, :multiple_notes
|
20
|
+
|
21
|
+
class << self
|
22
|
+
include Footnotes::EachWithRescue
|
23
|
+
|
24
|
+
# Calls the class method start! in each note
|
25
|
+
# Sometimes notes need to set variables or clean the environment to work properly
|
26
|
+
# This method allows this kind of setup
|
27
|
+
#
|
28
|
+
def start!(controller)
|
29
|
+
self.each_with_rescue(Footnotes.before_hooks) {|hook| hook.call(controller, self)}
|
30
|
+
|
31
|
+
@@klasses = []
|
32
|
+
self.each_with_rescue(@@notes.flatten) do |note|
|
33
|
+
klass = "Footnotes::Notes::#{note.to_s.camelize}Note".constantize
|
34
|
+
klass.start!(controller) if klass.respond_to?(:start!)
|
35
|
+
@@klasses << klass
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# If none argument is sent, simply return the prefix.
|
40
|
+
# Otherwise, replace the args in the prefix.
|
41
|
+
#
|
42
|
+
def prefix(*args)
|
43
|
+
if args.empty?
|
44
|
+
@@prefix
|
45
|
+
else
|
46
|
+
format(@@prefix, *args)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize(controller)
|
53
|
+
@controller = controller
|
54
|
+
@template = controller.instance_variable_get(:@template)
|
55
|
+
@body = controller.response.body
|
56
|
+
@notes = []
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_footnotes!
|
60
|
+
add_footnotes_without_validation! if valid?
|
61
|
+
rescue Exception => e
|
62
|
+
# Discard footnotes if there are any problems
|
63
|
+
self.class.log_error("Footnotes Exception", e)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Calls the class method close! in each note
|
67
|
+
# Sometimes notes need to finish their work even after being read
|
68
|
+
# This method allows this kind of work
|
69
|
+
#
|
70
|
+
def close!(controller)
|
71
|
+
self.each_with_rescue(@@klasses) {|klass| klass.close!(controller)}
|
72
|
+
self.each_with_rescue(Footnotes.after_hooks) {|hook| hook.call(controller, self)}
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
def valid?
|
77
|
+
@body.is_a?(String) && performed_render? && valid_format? && valid_content_type? &&
|
78
|
+
!component_request? && !xhr? && !footnotes_disabled?
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_footnotes_without_validation!
|
82
|
+
initialize_notes!
|
83
|
+
insert_styles unless @@no_style
|
84
|
+
insert_footnotes
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize_notes!
|
88
|
+
each_with_rescue(@@klasses) do |klass|
|
89
|
+
note = klass.new(@controller)
|
90
|
+
@notes << note if note.respond_to?(:valid?) && note.valid?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def performed_render?
|
95
|
+
@controller.instance_variable_get(:@performed_render) || # rails 2.x
|
96
|
+
(@controller.respond_to?(:performed?) && @controller.performed?) # rails3, will break on redirect??
|
97
|
+
end
|
98
|
+
|
99
|
+
def valid_format?
|
100
|
+
if @template # Rails 2.x
|
101
|
+
[:html,:rhtml,:xhtml,:rxhtml].include?(@template.send(template_format_method.to_sym).to_sym)
|
102
|
+
else # Rails 3
|
103
|
+
@controller.response.content_type == 'text/html'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def template_format_method
|
108
|
+
if @template.respond_to?(:template_format)
|
109
|
+
return 'template_format'
|
110
|
+
else
|
111
|
+
return 'format'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def valid_content_type?
|
116
|
+
c = @controller.response.headers['Content-Type'].to_s
|
117
|
+
(c.empty? || c =~ /html/)
|
118
|
+
end
|
119
|
+
|
120
|
+
def component_request?
|
121
|
+
@controller.instance_variable_get(:@parent_controller)
|
122
|
+
end
|
123
|
+
|
124
|
+
def xhr?
|
125
|
+
@controller.request.xhr?
|
126
|
+
end
|
127
|
+
|
128
|
+
def footnotes_disabled?
|
129
|
+
@controller.params[:footnotes] == "false"
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Insertion methods
|
134
|
+
#
|
135
|
+
|
136
|
+
def insert_styles
|
137
|
+
#TODO More customizable(reset.css, from file etc.)
|
138
|
+
insert_text :before, /<\/head>/i, <<-HTML
|
139
|
+
<!-- Footnotes Style -->
|
140
|
+
<style type="text/css">
|
141
|
+
#footnotes_debug {font-size: 11px; font-weight: normal; margin: 2em 0 1em 0; text-align: center; color: #444; line-height: 16px;}
|
142
|
+
#footnotes_debug th, #footnotes_debug td {color: #444; line-height: 18px;}
|
143
|
+
#footnotes_debug a {color: #9b1b1b; font-weight: inherit; text-decoration: none; line-height: 18px;}
|
144
|
+
#footnotes_debug table {text-align: center;}
|
145
|
+
#footnotes_debug table td {padding: 0 5px;}
|
146
|
+
#footnotes_debug tbody {text-align: left;}
|
147
|
+
#footnotes_debug .name_values td {vertical-align: top;}
|
148
|
+
#footnotes_debug legend {background-color: #fff;}
|
149
|
+
#footnotes_debug fieldset {text-align: left; border: 1px dashed #aaa; padding: 0.5em 1em 1em 1em; margin: 1em 2em; color: #444; background-color: #FFF;}
|
150
|
+
/* Aditional Stylesheets */
|
151
|
+
#{@notes.map(&:stylesheet).compact.join("\n")}
|
152
|
+
</style>
|
153
|
+
<!-- End Footnotes Style -->
|
154
|
+
HTML
|
155
|
+
end
|
156
|
+
|
157
|
+
def insert_footnotes
|
158
|
+
# Fieldsets method should be called first
|
159
|
+
content = fieldsets
|
160
|
+
|
161
|
+
footnotes_html = <<-HTML
|
162
|
+
<!-- Footnotes -->
|
163
|
+
<div style="clear:both"></div>
|
164
|
+
<div id="footnotes_debug">
|
165
|
+
#{links}
|
166
|
+
#{content}
|
167
|
+
<script type="text/javascript">
|
168
|
+
var Footnotes = function() {
|
169
|
+
|
170
|
+
function hideAll(){
|
171
|
+
#{close unless @@multiple_notes}
|
172
|
+
}
|
173
|
+
|
174
|
+
function hideAllAndToggle(id) {
|
175
|
+
hideAll();
|
176
|
+
toggle(id)
|
177
|
+
|
178
|
+
location.href = '#footnotes_debug';
|
179
|
+
}
|
180
|
+
|
181
|
+
function toggle(id){
|
182
|
+
var el = document.getElementById(id);
|
183
|
+
if (el.style.display == 'none') {
|
184
|
+
Footnotes.show(el);
|
185
|
+
} else {
|
186
|
+
Footnotes.hide(el);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
function show(element) {
|
191
|
+
element.style.display = 'block'
|
192
|
+
}
|
193
|
+
|
194
|
+
function hide(element) {
|
195
|
+
element.style.display = 'none'
|
196
|
+
}
|
197
|
+
|
198
|
+
return {
|
199
|
+
show: show,
|
200
|
+
hide: hide,
|
201
|
+
toggle: toggle,
|
202
|
+
hideAllAndToggle: hideAllAndToggle
|
203
|
+
}
|
204
|
+
}();
|
205
|
+
/* Additional Javascript */
|
206
|
+
#{@notes.map(&:javascript).compact.join("\n")}
|
207
|
+
</script>
|
208
|
+
</div>
|
209
|
+
<!-- End Footnotes -->
|
210
|
+
HTML
|
211
|
+
|
212
|
+
placeholder = /<div[^>]+id=['"]footnotes_holder['"][^>]*>/i
|
213
|
+
if @controller.response.body =~ placeholder
|
214
|
+
insert_text :after, placeholder, footnotes_html
|
215
|
+
else
|
216
|
+
insert_text :before, /<\/body>/i, footnotes_html
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Process notes to gets their links in their equivalent row
|
221
|
+
#
|
222
|
+
def links
|
223
|
+
links = Hash.new([])
|
224
|
+
order = []
|
225
|
+
each_with_rescue(@notes) do |note|
|
226
|
+
order << note.row
|
227
|
+
links[note.row] += [link_helper(note)]
|
228
|
+
end
|
229
|
+
|
230
|
+
html = ''
|
231
|
+
order.uniq!
|
232
|
+
order.each do |row|
|
233
|
+
html << "#{row.is_a?(String) ? row : row.to_s.camelize}: #{links[row].join(" | \n")}<br />"
|
234
|
+
end
|
235
|
+
html
|
236
|
+
end
|
237
|
+
|
238
|
+
# Process notes to get their content
|
239
|
+
#
|
240
|
+
def fieldsets
|
241
|
+
content = ''
|
242
|
+
each_with_rescue(@notes) do |note|
|
243
|
+
next unless note.has_fieldset?
|
244
|
+
content << <<-HTML
|
245
|
+
<fieldset id="#{note.to_sym}_debug_info" style="display: none">
|
246
|
+
<legend>#{note.legend}</legend>
|
247
|
+
<div>#{note.content}</div>
|
248
|
+
</fieldset>
|
249
|
+
HTML
|
250
|
+
end
|
251
|
+
content
|
252
|
+
end
|
253
|
+
|
254
|
+
# Process notes to get javascript code to close them.
|
255
|
+
# This method is only used when multiple_notes is false.
|
256
|
+
#
|
257
|
+
def close
|
258
|
+
javascript = ''
|
259
|
+
each_with_rescue(@notes) do |note|
|
260
|
+
next unless note.has_fieldset?
|
261
|
+
javascript << close_helper(note)
|
262
|
+
end
|
263
|
+
javascript
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Helpers
|
268
|
+
#
|
269
|
+
|
270
|
+
# Helper that creates the javascript code to close the note
|
271
|
+
#
|
272
|
+
def close_helper(note)
|
273
|
+
"Footnotes.hide(document.getElementById('#{note.to_sym}_debug_info'));\n"
|
274
|
+
end
|
275
|
+
|
276
|
+
# Helper that creates the link and javascript code when note is clicked
|
277
|
+
#
|
278
|
+
def link_helper(note)
|
279
|
+
onclick = note.onclick
|
280
|
+
unless href = note.link
|
281
|
+
href = '#'
|
282
|
+
onclick ||= "Footnotes.hideAllAndToggle('#{note.to_sym}_debug_info');return false;" if note.has_fieldset?
|
283
|
+
end
|
284
|
+
|
285
|
+
"<a href=\"#{href}\" onclick=\"#{onclick}\">#{note.title}</a>"
|
286
|
+
end
|
287
|
+
|
288
|
+
# Inserts text in to the body of the document
|
289
|
+
# +pattern+ is a Regular expression which, when matched, will cause +new_text+
|
290
|
+
# to be inserted before or after the match. If no match is found, +new_text+ is appended
|
291
|
+
# to the body instead. +position+ may be either :before or :after
|
292
|
+
#
|
293
|
+
def insert_text(position, pattern, new_text)
|
294
|
+
index = case pattern
|
295
|
+
when Regexp
|
296
|
+
if match = @controller.response.body.match(pattern)
|
297
|
+
match.offset(0)[position == :before ? 0 : 1]
|
298
|
+
else
|
299
|
+
@controller.response.body.size
|
300
|
+
end
|
301
|
+
else
|
302
|
+
pattern
|
303
|
+
end
|
304
|
+
newbody = @controller.response.body
|
305
|
+
newbody.insert index, new_text
|
306
|
+
@controller.response.body = newbody
|
307
|
+
end
|
308
|
+
|
309
|
+
# Instance each_with_rescue method
|
310
|
+
#
|
311
|
+
def each_with_rescue(*args, &block)
|
312
|
+
self.class.each_with_rescue(*args, &block)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
@@ -1,359 +1,7 @@
|
|
1
1
|
module Footnotes
|
2
|
-
|
3
|
-
# Method called to start the notes
|
4
|
-
# It's a before filter prepend in the controller
|
5
|
-
def self.filter(controller)
|
6
|
-
Footnotes::Filter.start!(controller)
|
7
|
-
end
|
8
|
-
end
|
2
|
+
autoload :EachWithRescue, 'rails-footnotes/each_with_rescue'
|
9
3
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
filter = Footnotes::Filter.new(controller)
|
14
|
-
filter.add_footnotes!
|
15
|
-
filter.close!(controller)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class Filter
|
20
|
-
@@no_style = false
|
21
|
-
@@multiple_notes = false
|
22
|
-
@@klasses = []
|
23
|
-
|
24
|
-
# Default link prefix is textmate
|
25
|
-
@@prefix = 'txmt://open?url=file://%s&line=%d&column=%d'
|
26
|
-
|
27
|
-
# Edit notes
|
28
|
-
@@notes = [ :controller, :view, :layout, :partials, :stylesheets, :javascripts ]
|
29
|
-
# Show notes
|
30
|
-
@@notes += [ :assigns, :session, :cookies, :params, :filters, :routes, :env, :queries, :log, :general ]
|
31
|
-
|
32
|
-
# :no_style => If you don't want the style to be appended to your pages
|
33
|
-
# :notes => Class variable that holds the notes to be processed
|
34
|
-
# :prefix => Prefix appended to FootnotesLinks
|
35
|
-
# :multiple_notes => Set to true if you want to open several notes at the same time
|
36
|
-
cattr_accessor :no_style, :notes, :prefix, :multiple_notes
|
37
|
-
|
38
|
-
class << self
|
39
|
-
|
40
|
-
# Calls the class method start! in each note
|
41
|
-
# Sometimes notes need to set variables or clean the environment to work properly
|
42
|
-
# This method allows this kind of setup
|
43
|
-
#
|
44
|
-
def start!(controller)
|
45
|
-
self.each_with_rescue(Footnotes.before_hooks) {|hook| hook.call(controller, self)}
|
46
|
-
|
47
|
-
@@klasses = []
|
48
|
-
self.each_with_rescue(@@notes.flatten) do |note|
|
49
|
-
klass = "Footnotes::Notes::#{note.to_s.camelize}Note".constantize
|
50
|
-
klass.start!(controller) if klass.respond_to?(:start!)
|
51
|
-
@@klasses << klass
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Process notes, discarding only the note if any problem occurs
|
56
|
-
#
|
57
|
-
def each_with_rescue(collection)
|
58
|
-
delete_me = []
|
59
|
-
|
60
|
-
collection.each do |item|
|
61
|
-
begin
|
62
|
-
yield item
|
63
|
-
rescue Exception => e
|
64
|
-
# Discard item if it has a problem
|
65
|
-
log_error("Footnotes #{item.to_s.camelize} Exception", e)
|
66
|
-
delete_me << item
|
67
|
-
next
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
delete_me.each { |item| collection.delete(item) }
|
72
|
-
return collection
|
73
|
-
end
|
74
|
-
|
75
|
-
# Logs the error using specified title and format
|
76
|
-
#
|
77
|
-
def log_error(title, exception)
|
78
|
-
Rails.logger.error "#{title}: #{exception}\n#{exception.backtrace.join("\n")}"
|
79
|
-
end
|
80
|
-
|
81
|
-
# If none argument is sent, simply return the prefix.
|
82
|
-
# Otherwise, replace the args in the prefix.
|
83
|
-
#
|
84
|
-
def prefix(*args)
|
85
|
-
if args.empty?
|
86
|
-
@@prefix
|
87
|
-
else
|
88
|
-
format(@@prefix, *args)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def initialize(controller)
|
95
|
-
@controller = controller
|
96
|
-
@template = controller.instance_variable_get(:@template)
|
97
|
-
@body = controller.response.body
|
98
|
-
@notes = []
|
99
|
-
end
|
100
|
-
|
101
|
-
def add_footnotes!
|
102
|
-
add_footnotes_without_validation! if valid?
|
103
|
-
rescue Exception => e
|
104
|
-
# Discard footnotes if there are any problems
|
105
|
-
self.class.log_error("Footnotes Exception", e)
|
106
|
-
end
|
107
|
-
|
108
|
-
# Calls the class method close! in each note
|
109
|
-
# Sometimes notes need to finish their work even after being read
|
110
|
-
# This method allows this kind of work
|
111
|
-
#
|
112
|
-
def close!(controller)
|
113
|
-
self.each_with_rescue(@@klasses) {|klass| klass.close!(controller)}
|
114
|
-
self.each_with_rescue(Footnotes.after_hooks) {|hook| hook.call(controller, self)}
|
115
|
-
end
|
116
|
-
|
117
|
-
protected
|
118
|
-
def valid?
|
119
|
-
performed_render? && valid_format? && valid_content_type? &&
|
120
|
-
@body.is_a?(String) && !component_request? && !xhr? &&
|
121
|
-
!footnotes_disabled?
|
122
|
-
end
|
123
|
-
|
124
|
-
def add_footnotes_without_validation!
|
125
|
-
initialize_notes!
|
126
|
-
insert_styles unless @@no_style
|
127
|
-
insert_footnotes
|
128
|
-
end
|
129
|
-
|
130
|
-
def initialize_notes!
|
131
|
-
each_with_rescue(@@klasses) do |klass|
|
132
|
-
note = klass.new(@controller)
|
133
|
-
@notes << note if note.respond_to?(:valid?) && note.valid?
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def performed_render?
|
138
|
-
@controller.instance_variable_get(:@performed_render) || # rails 2.x
|
139
|
-
(@controller.respond_to?(:performed?) && @controller.performed?) # rails3, will break on redirect??
|
140
|
-
end
|
141
|
-
|
142
|
-
def valid_format?
|
143
|
-
if @template # Rails 2.x
|
144
|
-
[:html,:rhtml,:xhtml,:rxhtml].include?(@template.send(template_format_method.to_sym).to_sym)
|
145
|
-
else # Rails 3
|
146
|
-
@controller.response.content_type == 'text/html'
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def template_format_method
|
151
|
-
if @template.respond_to?(:template_format)
|
152
|
-
return 'template_format'
|
153
|
-
else
|
154
|
-
return 'format'
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def valid_content_type?
|
159
|
-
c = @controller.response.headers['Content-Type'].to_s
|
160
|
-
(c.empty? || c =~ /html/)
|
161
|
-
end
|
162
|
-
|
163
|
-
def component_request?
|
164
|
-
@controller.instance_variable_get(:@parent_controller)
|
165
|
-
end
|
166
|
-
|
167
|
-
def xhr?
|
168
|
-
@controller.request.xhr?
|
169
|
-
end
|
170
|
-
|
171
|
-
def footnotes_disabled?
|
172
|
-
@controller.params[:footnotes] == "false"
|
173
|
-
end
|
174
|
-
|
175
|
-
#
|
176
|
-
# Insertion methods
|
177
|
-
#
|
178
|
-
|
179
|
-
def insert_styles
|
180
|
-
#TODO More customizable(reset.css, from file etc.)
|
181
|
-
insert_text :before, /<\/head>/i, <<-HTML
|
182
|
-
<!-- Footnotes Style -->
|
183
|
-
<style type="text/css">
|
184
|
-
#footnotes_debug {font-size: 11px; font-weight: normal; margin: 2em 0 1em 0; text-align: center; color: #444; line-height: 16px;}
|
185
|
-
#footnotes_debug th, #footnotes_debug td {color: #444; line-height: 18px;}
|
186
|
-
#footnotes_debug a {color: #9b1b1b; font-weight: inherit; text-decoration: none; line-height: 18px;}
|
187
|
-
#footnotes_debug table {text-align: center;}
|
188
|
-
#footnotes_debug table td {padding: 0 5px;}
|
189
|
-
#footnotes_debug tbody {text-align: left;}
|
190
|
-
#footnotes_debug .name_values td {vertical-align: top;}
|
191
|
-
#footnotes_debug legend {background-color: #fff;}
|
192
|
-
#footnotes_debug fieldset {text-align: left; border: 1px dashed #aaa; padding: 0.5em 1em 1em 1em; margin: 1em 2em; color: #444; background-color: #FFF;}
|
193
|
-
/* Aditional Stylesheets */
|
194
|
-
#{@notes.map(&:stylesheet).compact.join("\n")}
|
195
|
-
</style>
|
196
|
-
<!-- End Footnotes Style -->
|
197
|
-
HTML
|
198
|
-
end
|
199
|
-
|
200
|
-
def insert_footnotes
|
201
|
-
# Fieldsets method should be called first
|
202
|
-
content = fieldsets
|
203
|
-
|
204
|
-
footnotes_html = <<-HTML
|
205
|
-
<!-- Footnotes -->
|
206
|
-
<div style="clear:both"></div>
|
207
|
-
<div id="footnotes_debug">
|
208
|
-
#{links}
|
209
|
-
#{content}
|
210
|
-
<script type="text/javascript">
|
211
|
-
var Footnotes = function() {
|
212
|
-
|
213
|
-
function hideAll(){
|
214
|
-
#{close unless @@multiple_notes}
|
215
|
-
}
|
216
|
-
|
217
|
-
function hideAllAndToggle(id) {
|
218
|
-
hideAll();
|
219
|
-
toggle(id)
|
220
|
-
|
221
|
-
location.href = '#footnotes_debug';
|
222
|
-
}
|
223
|
-
|
224
|
-
function toggle(id){
|
225
|
-
var el = document.getElementById(id);
|
226
|
-
if (el.style.display == 'none') {
|
227
|
-
Footnotes.show(el);
|
228
|
-
} else {
|
229
|
-
Footnotes.hide(el);
|
230
|
-
}
|
231
|
-
}
|
232
|
-
|
233
|
-
function show(element) {
|
234
|
-
element.style.display = 'block'
|
235
|
-
}
|
236
|
-
|
237
|
-
function hide(element) {
|
238
|
-
element.style.display = 'none'
|
239
|
-
}
|
240
|
-
|
241
|
-
return {
|
242
|
-
show: show,
|
243
|
-
hide: hide,
|
244
|
-
toggle: toggle,
|
245
|
-
hideAllAndToggle: hideAllAndToggle
|
246
|
-
}
|
247
|
-
}();
|
248
|
-
/* Additional Javascript */
|
249
|
-
#{@notes.map(&:javascript).compact.join("\n")}
|
250
|
-
</script>
|
251
|
-
</div>
|
252
|
-
<!-- End Footnotes -->
|
253
|
-
HTML
|
254
|
-
|
255
|
-
placeholder = /<div[^>]+id=['"]footnotes_holder['"][^>]*>/i
|
256
|
-
if @controller.response.body =~ placeholder
|
257
|
-
insert_text :after, placeholder, footnotes_html
|
258
|
-
else
|
259
|
-
insert_text :before, /<\/body>/i, footnotes_html
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
# Process notes to gets their links in their equivalent row
|
264
|
-
#
|
265
|
-
def links
|
266
|
-
links = Hash.new([])
|
267
|
-
order = []
|
268
|
-
each_with_rescue(@notes) do |note|
|
269
|
-
order << note.row
|
270
|
-
links[note.row] += [link_helper(note)]
|
271
|
-
end
|
272
|
-
|
273
|
-
html = ''
|
274
|
-
order.uniq!
|
275
|
-
order.each do |row|
|
276
|
-
html << "#{row.is_a?(String) ? row : row.to_s.camelize}: #{links[row].join(" | \n")}<br />"
|
277
|
-
end
|
278
|
-
html
|
279
|
-
end
|
280
|
-
|
281
|
-
# Process notes to get their content
|
282
|
-
#
|
283
|
-
def fieldsets
|
284
|
-
content = ''
|
285
|
-
each_with_rescue(@notes) do |note|
|
286
|
-
next unless note.has_fieldset?
|
287
|
-
content << <<-HTML
|
288
|
-
<fieldset id="#{note.to_sym}_debug_info" style="display: none">
|
289
|
-
<legend>#{note.legend}</legend>
|
290
|
-
<div>#{note.content}</div>
|
291
|
-
</fieldset>
|
292
|
-
HTML
|
293
|
-
end
|
294
|
-
content
|
295
|
-
end
|
296
|
-
|
297
|
-
# Process notes to get javascript code to close them.
|
298
|
-
# This method is only used when multiple_notes is false.
|
299
|
-
#
|
300
|
-
def close
|
301
|
-
javascript = ''
|
302
|
-
each_with_rescue(@notes) do |note|
|
303
|
-
next unless note.has_fieldset?
|
304
|
-
javascript << close_helper(note)
|
305
|
-
end
|
306
|
-
javascript
|
307
|
-
end
|
308
|
-
|
309
|
-
#
|
310
|
-
# Helpers
|
311
|
-
#
|
312
|
-
|
313
|
-
# Helper that creates the javascript code to close the note
|
314
|
-
#
|
315
|
-
def close_helper(note)
|
316
|
-
"Footnotes.hide(document.getElementById('#{note.to_sym}_debug_info'));\n"
|
317
|
-
end
|
318
|
-
|
319
|
-
# Helper that creates the link and javascript code when note is clicked
|
320
|
-
#
|
321
|
-
def link_helper(note)
|
322
|
-
onclick = note.onclick
|
323
|
-
unless href = note.link
|
324
|
-
href = '#'
|
325
|
-
onclick ||= "Footnotes.hideAllAndToggle('#{note.to_sym}_debug_info');return false;" if note.has_fieldset?
|
326
|
-
end
|
327
|
-
|
328
|
-
"<a href=\"#{href}\" onclick=\"#{onclick}\">#{note.title}</a>"
|
329
|
-
end
|
330
|
-
|
331
|
-
# Inserts text in to the body of the document
|
332
|
-
# +pattern+ is a Regular expression which, when matched, will cause +new_text+
|
333
|
-
# to be inserted before or after the match. If no match is found, +new_text+ is appended
|
334
|
-
# to the body instead. +position+ may be either :before or :after
|
335
|
-
#
|
336
|
-
def insert_text(position, pattern, new_text)
|
337
|
-
index = case pattern
|
338
|
-
when Regexp
|
339
|
-
if match = @controller.response.body.match(pattern)
|
340
|
-
match.offset(0)[position == :before ? 0 : 1]
|
341
|
-
else
|
342
|
-
@controller.response.body.size
|
343
|
-
end
|
344
|
-
else
|
345
|
-
pattern
|
346
|
-
end
|
347
|
-
newbody = @controller.response.body
|
348
|
-
newbody.insert index, new_text
|
349
|
-
@controller.response.body = newbody
|
350
|
-
end
|
351
|
-
|
352
|
-
# Instance each_with_rescue method
|
353
|
-
#
|
354
|
-
def each_with_rescue(*args, &block)
|
355
|
-
self.class.each_with_rescue(*args, &block)
|
356
|
-
end
|
357
|
-
|
358
|
-
end
|
4
|
+
autoload :BeforeFilter, 'rails-footnotes/before_filter'
|
5
|
+
autoload :AfterFilter, 'rails-footnotes/after_filter'
|
6
|
+
autoload :Filter, 'rails-footnotes/filter'
|
359
7
|
end
|
@@ -22,7 +22,7 @@ module Footnotes
|
|
22
22
|
|
23
23
|
def title
|
24
24
|
queries = self.events.count
|
25
|
-
total_time = self.events.map(&:duration).sum
|
25
|
+
total_time = self.events.map(&:duration).sum
|
26
26
|
query_color = generate_red_color(self.events.count, alert_sql_number)
|
27
27
|
db_color = generate_red_color(total_time, alert_db_time)
|
28
28
|
|
data/rails-footnotes.gemspec
CHANGED
@@ -6,8 +6,8 @@ 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 = ["Keenan Brock"]
|
10
|
-
s.email = ["
|
9
|
+
s.authors = ["Roman V. Babenko", "José Valim", "Keenan Brock", "Duane Johnson"]
|
10
|
+
s.email = ["romanvbabenko@gmail.com"]
|
11
11
|
s.homepage = "http://github.com/josevalim/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.}
|
@@ -17,8 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_dependency "rails", ">= 3.0.0"
|
18
18
|
|
19
19
|
s.add_development_dependency "rails", ">= 3.0.0"
|
20
|
-
s.add_development_dependency "rspec"
|
21
|
-
s.add_development_dependency "watchr"
|
20
|
+
s.add_development_dependency "rspec", "~> 2.9.0"
|
22
21
|
|
23
22
|
s.files = `git ls-files`.split("\n")
|
24
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/spec/footnotes_spec.rb
CHANGED
@@ -23,7 +23,7 @@ describe "Footnotes" do
|
|
23
23
|
@controller.template = Object.new
|
24
24
|
@controller.request = ActionController::TestRequest.new
|
25
25
|
@controller.response = ActionController::TestResponse.new
|
26
|
-
@controller.response_body =
|
26
|
+
@controller.response_body = HTML_DOCUMENT.dup
|
27
27
|
@controller.params = {}
|
28
28
|
|
29
29
|
Footnotes::Filter.notes = [ :test ]
|
@@ -40,7 +40,7 @@ describe "Footnotes" do
|
|
40
40
|
if RUBY_VERSION >= '1.9.0'
|
41
41
|
it "foonotes_included" do
|
42
42
|
footnotes_perform!
|
43
|
-
@controller.response_body.should_not ==
|
43
|
+
@controller.response_body.should_not == HTML_DOCUMENT
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -48,29 +48,30 @@ describe "Footnotes" do
|
|
48
48
|
@controller.request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
49
49
|
@controller.request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*'
|
50
50
|
footnotes_perform!
|
51
|
-
@controller.response.body.should eql
|
51
|
+
@controller.response.body.should eql HTML_DOCUMENT
|
52
52
|
end
|
53
53
|
|
54
54
|
specify "footnotes_not_included_when_content_type_is_javascript" do
|
55
55
|
@controller.response.headers['Content-Type'] = 'text/javascript'
|
56
56
|
footnotes_perform!
|
57
|
-
@controller.response.body.should eql
|
57
|
+
@controller.response.body.should eql HTML_DOCUMENT
|
58
58
|
end
|
59
59
|
|
60
60
|
specify "footnotes_included_when_content_type_is_html" do
|
61
61
|
@controller.response.headers['Content-Type'] = 'text/html'
|
62
62
|
footnotes_perform!
|
63
|
-
@controller.response.body.should_not eql
|
63
|
+
@controller.response.body.should_not eql HTML_DOCUMENT
|
64
64
|
end
|
65
65
|
|
66
66
|
specify "footnotes_included_when_content_type_is_nil" do
|
67
67
|
footnotes_perform!
|
68
|
-
@controller.response.body.should_not eql
|
68
|
+
@controller.response.body.should_not eql HTML_DOCUMENT
|
69
69
|
end
|
70
70
|
|
71
71
|
specify "not_included_when_body_is_not_a_string" do
|
72
|
-
@controller.response.body = Proc.new { Time.now }
|
73
|
-
|
72
|
+
@controller.response.stub(:body).and_return(Time.now)# = Proc.new { Time.now }
|
73
|
+
Footnotes::Filter.new(@controller).send(:valid?).should_not be
|
74
|
+
@controller.response.body.should_not =~ /<!-- Footnotes/
|
74
75
|
end
|
75
76
|
|
76
77
|
specify "notes_are_initialized" do
|
@@ -198,7 +199,7 @@ describe "Footnotes" do
|
|
198
199
|
end
|
199
200
|
end
|
200
201
|
|
201
|
-
|
202
|
+
HTML_DOCUMENT = <<EOF
|
202
203
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
203
204
|
<html>
|
204
205
|
<head>
|
metadata
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-footnotes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.7.
|
4
|
+
version: 3.7.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
+
- Roman V. Babenko
|
9
|
+
- José Valim
|
8
10
|
- Keenan Brock
|
11
|
+
- Duane Johnson
|
9
12
|
autorequire:
|
10
13
|
bindir: bin
|
11
14
|
cert_chain: []
|
12
|
-
date: 2012-
|
15
|
+
date: 2012-04-15 00:00:00.000000000 Z
|
13
16
|
dependencies:
|
14
17
|
- !ruby/object:Gem::Dependency
|
15
18
|
name: rails
|
16
|
-
requirement: &
|
19
|
+
requirement: &70198531287580 !ruby/object:Gem::Requirement
|
17
20
|
none: false
|
18
21
|
requirements:
|
19
22
|
- - ! '>='
|
@@ -21,10 +24,10 @@ dependencies:
|
|
21
24
|
version: 3.0.0
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
|
-
version_requirements: *
|
27
|
+
version_requirements: *70198531287580
|
25
28
|
- !ruby/object:Gem::Dependency
|
26
29
|
name: rails
|
27
|
-
requirement: &
|
30
|
+
requirement: &70198531286580 !ruby/object:Gem::Requirement
|
28
31
|
none: false
|
29
32
|
requirements:
|
30
33
|
- - ! '>='
|
@@ -32,33 +35,22 @@ dependencies:
|
|
32
35
|
version: 3.0.0
|
33
36
|
type: :development
|
34
37
|
prerelease: false
|
35
|
-
version_requirements: *
|
38
|
+
version_requirements: *70198531286580
|
36
39
|
- !ruby/object:Gem::Dependency
|
37
40
|
name: rspec
|
38
|
-
requirement: &
|
41
|
+
requirement: &70198531285700 !ruby/object:Gem::Requirement
|
39
42
|
none: false
|
40
43
|
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0'
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *70324691483080
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: watchr
|
49
|
-
requirement: &70324691482220 !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
44
|
+
- - ~>
|
53
45
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
46
|
+
version: 2.9.0
|
55
47
|
type: :development
|
56
48
|
prerelease: false
|
57
|
-
version_requirements: *
|
49
|
+
version_requirements: *70198531285700
|
58
50
|
description: Every Rails page has footnotes that gives information about your application
|
59
51
|
and links back to your editor.
|
60
52
|
email:
|
61
|
-
-
|
53
|
+
- romanvbabenko@gmail.com
|
62
54
|
executables: []
|
63
55
|
extensions: []
|
64
56
|
extra_rdoc_files: []
|
@@ -78,7 +70,11 @@ files:
|
|
78
70
|
- lib/generators/templates/rails_footnotes.rb
|
79
71
|
- lib/rails-footnotes.rb
|
80
72
|
- lib/rails-footnotes/abstract_note.rb
|
73
|
+
- lib/rails-footnotes/after_filter.rb
|
81
74
|
- lib/rails-footnotes/backtracer.rb
|
75
|
+
- lib/rails-footnotes/before_filter.rb
|
76
|
+
- lib/rails-footnotes/each_with_rescue.rb
|
77
|
+
- lib/rails-footnotes/filter.rb
|
82
78
|
- lib/rails-footnotes/footnotes.rb
|
83
79
|
- lib/rails-footnotes/notes/all.rb
|
84
80
|
- lib/rails-footnotes/notes/assigns_note.rb
|