actionview 4.1.13 → 6.1.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +181 -359
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +12 -6
  5. data/lib/action_view/base.rb +115 -43
  6. data/lib/action_view/buffers.rb +22 -4
  7. data/lib/action_view/cache_expiry.rb +52 -0
  8. data/lib/action_view/context.rb +8 -12
  9. data/lib/action_view/dependency_tracker.rb +61 -21
  10. data/lib/action_view/digestor.rb +89 -84
  11. data/lib/action_view/flows.rb +12 -13
  12. data/lib/action_view/gem_version.rb +6 -4
  13. data/lib/action_view/helpers/active_model_helper.rb +16 -11
  14. data/lib/action_view/helpers/asset_tag_helper.rb +311 -105
  15. data/lib/action_view/helpers/asset_url_helper.rb +197 -80
  16. data/lib/action_view/helpers/atom_feed_helper.rb +20 -17
  17. data/lib/action_view/helpers/cache_helper.rb +109 -45
  18. data/lib/action_view/helpers/capture_helper.rb +20 -22
  19. data/lib/action_view/helpers/controller_helper.rb +15 -4
  20. data/lib/action_view/helpers/csp_helper.rb +26 -0
  21. data/lib/action_view/helpers/csrf_helper.rb +8 -6
  22. data/lib/action_view/helpers/date_helper.rb +245 -140
  23. data/lib/action_view/helpers/debug_helper.rb +14 -17
  24. data/lib/action_view/helpers/form_helper.rb +875 -148
  25. data/lib/action_view/helpers/form_options_helper.rb +128 -82
  26. data/lib/action_view/helpers/form_tag_helper.rb +253 -91
  27. data/lib/action_view/helpers/javascript_helper.rb +37 -15
  28. data/lib/action_view/helpers/number_helper.rb +100 -77
  29. data/lib/action_view/helpers/output_safety_helper.rb +42 -10
  30. data/lib/action_view/helpers/rendering_helper.rb +26 -15
  31. data/lib/action_view/helpers/sanitize_helper.rb +79 -164
  32. data/lib/action_view/helpers/tag_helper.rb +277 -64
  33. data/lib/action_view/helpers/tags/base.rb +143 -92
  34. data/lib/action_view/helpers/tags/check_box.rb +20 -19
  35. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  36. data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -30
  37. data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
  38. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
  39. data/lib/action_view/helpers/tags/collection_select.rb +4 -2
  40. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  41. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  42. data/lib/action_view/helpers/tags/date_select.rb +38 -37
  43. data/lib/action_view/helpers/tags/datetime_field.rb +14 -5
  44. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  45. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  46. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  47. data/lib/action_view/helpers/tags/file_field.rb +2 -0
  48. data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
  49. data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
  50. data/lib/action_view/helpers/tags/label.rb +41 -22
  51. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  52. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  53. data/lib/action_view/helpers/tags/password_field.rb +3 -1
  54. data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
  55. data/lib/action_view/helpers/tags/radio_button.rb +7 -6
  56. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  57. data/lib/action_view/helpers/tags/search_field.rb +3 -0
  58. data/lib/action_view/helpers/tags/select.rb +11 -10
  59. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  60. data/lib/action_view/helpers/tags/text_area.rb +7 -1
  61. data/lib/action_view/helpers/tags/text_field.rb +11 -7
  62. data/lib/action_view/helpers/tags/time_field.rb +3 -2
  63. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  64. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  65. data/lib/action_view/helpers/tags/translator.rb +39 -0
  66. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  67. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  68. data/lib/action_view/helpers/tags.rb +4 -1
  69. data/lib/action_view/helpers/text_helper.rb +80 -45
  70. data/lib/action_view/helpers/translation_helper.rb +148 -67
  71. data/lib/action_view/helpers/url_helper.rb +289 -147
  72. data/lib/action_view/helpers.rb +5 -3
  73. data/lib/action_view/layouts.rb +68 -63
  74. data/lib/action_view/log_subscriber.rb +80 -13
  75. data/lib/action_view/lookup_context.rb +137 -92
  76. data/lib/action_view/model_naming.rb +4 -2
  77. data/lib/action_view/path_set.rb +30 -16
  78. data/lib/action_view/railtie.rb +62 -13
  79. data/lib/action_view/record_identifier.rb +53 -26
  80. data/lib/action_view/renderer/abstract_renderer.rb +152 -13
  81. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  82. data/lib/action_view/renderer/object_renderer.rb +34 -0
  83. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
  84. data/lib/action_view/renderer/partial_renderer.rb +61 -261
  85. data/lib/action_view/renderer/renderer.rb +67 -6
  86. data/lib/action_view/renderer/streaming_template_renderer.rb +58 -54
  87. data/lib/action_view/renderer/template_renderer.rb +83 -75
  88. data/lib/action_view/rendering.rb +73 -46
  89. data/lib/action_view/routing_url_for.rb +54 -17
  90. data/lib/action_view/tasks/cache_digests.rake +25 -0
  91. data/lib/action_view/template/error.rb +44 -29
  92. data/lib/action_view/template/handlers/builder.rb +12 -13
  93. data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
  94. data/lib/action_view/template/handlers/erb.rb +23 -89
  95. data/lib/action_view/template/handlers/html.rb +11 -0
  96. data/lib/action_view/template/handlers/raw.rb +4 -4
  97. data/lib/action_view/template/handlers.rb +22 -9
  98. data/lib/action_view/template/html.rb +10 -11
  99. data/lib/action_view/template/inline.rb +22 -0
  100. data/lib/action_view/template/raw_file.rb +25 -0
  101. data/lib/action_view/template/renderable.rb +24 -0
  102. data/lib/action_view/template/resolver.rb +267 -181
  103. data/lib/action_view/template/sources/file.rb +17 -0
  104. data/lib/action_view/template/sources.rb +13 -0
  105. data/lib/action_view/template/text.rb +8 -10
  106. data/lib/action_view/template/types.rb +18 -18
  107. data/lib/action_view/template.rb +109 -99
  108. data/lib/action_view/test_case.rb +73 -53
  109. data/lib/action_view/testing/resolvers.rb +24 -33
  110. data/lib/action_view/unbound_template.rb +31 -0
  111. data/lib/action_view/version.rb +3 -1
  112. data/lib/action_view/view_paths.rb +74 -44
  113. data/lib/action_view.rb +14 -9
  114. data/lib/assets/compiled/rails-ujs.js +746 -0
  115. metadata +71 -26
  116. data/lib/action_view/helpers/record_tag_helper.rb +0 -108
  117. data/lib/action_view/tasks/dependencies.rake +0 -23
  118. data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
  119. data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
  120. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
  121. data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
  122. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
  123. data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
  124. data/lib/action_view/vendor/html-scanner.rb +0 -20
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.13
4
+ version: 6.1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-24 00:00:00.000000000 Z
11
+ date: 2021-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.1.13
19
+ version: 6.1.3.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.1.13
26
+ version: 6.1.3.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: builder
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,47 +39,81 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.1'
41
41
  - !ruby/object:Gem::Dependency
42
- name: erubis
42
+ name: erubi
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.7.0
47
+ version: '1.4'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.7.0
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails-html-sanitizer
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.2.0
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.1'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.2.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: rails-dom-testing
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '2.0'
55
89
  - !ruby/object:Gem::Dependency
56
90
  name: actionpack
57
91
  requirement: !ruby/object:Gem::Requirement
58
92
  requirements:
59
93
  - - '='
60
94
  - !ruby/object:Gem::Version
61
- version: 4.1.13
95
+ version: 6.1.3.1
62
96
  type: :development
63
97
  prerelease: false
64
98
  version_requirements: !ruby/object:Gem::Requirement
65
99
  requirements:
66
100
  - - '='
67
101
  - !ruby/object:Gem::Version
68
- version: 4.1.13
102
+ version: 6.1.3.1
69
103
  - !ruby/object:Gem::Dependency
70
104
  name: activemodel
71
105
  requirement: !ruby/object:Gem::Requirement
72
106
  requirements:
73
107
  - - '='
74
108
  - !ruby/object:Gem::Version
75
- version: 4.1.13
109
+ version: 6.1.3.1
76
110
  type: :development
77
111
  prerelease: false
78
112
  version_requirements: !ruby/object:Gem::Requirement
79
113
  requirements:
80
114
  - - '='
81
115
  - !ruby/object:Gem::Version
82
- version: 4.1.13
116
+ version: 6.1.3.1
83
117
  description: Simple, battle-tested conventions and helpers for building web pages.
84
118
  email: david@loudthinking.com
85
119
  executables: []
@@ -92,6 +126,7 @@ files:
92
126
  - lib/action_view.rb
93
127
  - lib/action_view/base.rb
94
128
  - lib/action_view/buffers.rb
129
+ - lib/action_view/cache_expiry.rb
95
130
  - lib/action_view/context.rb
96
131
  - lib/action_view/dependency_tracker.rb
97
132
  - lib/action_view/digestor.rb
@@ -105,6 +140,7 @@ files:
105
140
  - lib/action_view/helpers/cache_helper.rb
106
141
  - lib/action_view/helpers/capture_helper.rb
107
142
  - lib/action_view/helpers/controller_helper.rb
143
+ - lib/action_view/helpers/csp_helper.rb
108
144
  - lib/action_view/helpers/csrf_helper.rb
109
145
  - lib/action_view/helpers/date_helper.rb
110
146
  - lib/action_view/helpers/debug_helper.rb
@@ -114,7 +150,6 @@ files:
114
150
  - lib/action_view/helpers/javascript_helper.rb
115
151
  - lib/action_view/helpers/number_helper.rb
116
152
  - lib/action_view/helpers/output_safety_helper.rb
117
- - lib/action_view/helpers/record_tag_helper.rb
118
153
  - lib/action_view/helpers/rendering_helper.rb
119
154
  - lib/action_view/helpers/sanitize_helper.rb
120
155
  - lib/action_view/helpers/tag_helper.rb
@@ -140,6 +175,7 @@ files:
140
175
  - lib/action_view/helpers/tags/month_field.rb
141
176
  - lib/action_view/helpers/tags/number_field.rb
142
177
  - lib/action_view/helpers/tags/password_field.rb
178
+ - lib/action_view/helpers/tags/placeholderable.rb
143
179
  - lib/action_view/helpers/tags/radio_button.rb
144
180
  - lib/action_view/helpers/tags/range_field.rb
145
181
  - lib/action_view/helpers/tags/search_field.rb
@@ -150,6 +186,7 @@ files:
150
186
  - lib/action_view/helpers/tags/time_field.rb
151
187
  - lib/action_view/helpers/tags/time_select.rb
152
188
  - lib/action_view/helpers/tags/time_zone_select.rb
189
+ - lib/action_view/helpers/tags/translator.rb
153
190
  - lib/action_view/helpers/tags/url_field.rb
154
191
  - lib/action_view/helpers/tags/week_field.rb
155
192
  - lib/action_view/helpers/text_helper.rb
@@ -164,38 +201,48 @@ files:
164
201
  - lib/action_view/railtie.rb
165
202
  - lib/action_view/record_identifier.rb
166
203
  - lib/action_view/renderer/abstract_renderer.rb
204
+ - lib/action_view/renderer/collection_renderer.rb
205
+ - lib/action_view/renderer/object_renderer.rb
167
206
  - lib/action_view/renderer/partial_renderer.rb
207
+ - lib/action_view/renderer/partial_renderer/collection_caching.rb
168
208
  - lib/action_view/renderer/renderer.rb
169
209
  - lib/action_view/renderer/streaming_template_renderer.rb
170
210
  - lib/action_view/renderer/template_renderer.rb
171
211
  - lib/action_view/rendering.rb
172
212
  - lib/action_view/routing_url_for.rb
173
- - lib/action_view/tasks/dependencies.rake
213
+ - lib/action_view/tasks/cache_digests.rake
174
214
  - lib/action_view/template.rb
175
215
  - lib/action_view/template/error.rb
176
216
  - lib/action_view/template/handlers.rb
177
217
  - lib/action_view/template/handlers/builder.rb
178
218
  - lib/action_view/template/handlers/erb.rb
219
+ - lib/action_view/template/handlers/erb/erubi.rb
220
+ - lib/action_view/template/handlers/html.rb
179
221
  - lib/action_view/template/handlers/raw.rb
180
222
  - lib/action_view/template/html.rb
223
+ - lib/action_view/template/inline.rb
224
+ - lib/action_view/template/raw_file.rb
225
+ - lib/action_view/template/renderable.rb
181
226
  - lib/action_view/template/resolver.rb
227
+ - lib/action_view/template/sources.rb
228
+ - lib/action_view/template/sources/file.rb
182
229
  - lib/action_view/template/text.rb
183
230
  - lib/action_view/template/types.rb
184
231
  - lib/action_view/test_case.rb
185
232
  - lib/action_view/testing/resolvers.rb
186
- - lib/action_view/vendor/html-scanner.rb
187
- - lib/action_view/vendor/html-scanner/html/document.rb
188
- - lib/action_view/vendor/html-scanner/html/node.rb
189
- - lib/action_view/vendor/html-scanner/html/sanitizer.rb
190
- - lib/action_view/vendor/html-scanner/html/selector.rb
191
- - lib/action_view/vendor/html-scanner/html/tokenizer.rb
192
- - lib/action_view/vendor/html-scanner/html/version.rb
233
+ - lib/action_view/unbound_template.rb
193
234
  - lib/action_view/version.rb
194
235
  - lib/action_view/view_paths.rb
195
- homepage: http://www.rubyonrails.org
236
+ - lib/assets/compiled/rails-ujs.js
237
+ homepage: https://rubyonrails.org
196
238
  licenses:
197
239
  - MIT
198
- metadata: {}
240
+ metadata:
241
+ bug_tracker_uri: https://github.com/rails/rails/issues
242
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.3.1/actionview/CHANGELOG.md
243
+ documentation_uri: https://api.rubyonrails.org/v6.1.3.1/
244
+ mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
245
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.3.1/actionview
199
246
  post_install_message:
200
247
  rdoc_options: []
201
248
  require_paths:
@@ -204,7 +251,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
251
  requirements:
205
252
  - - ">="
206
253
  - !ruby/object:Gem::Version
207
- version: 1.9.3
254
+ version: 2.5.0
208
255
  required_rubygems_version: !ruby/object:Gem::Requirement
209
256
  requirements:
210
257
  - - ">="
@@ -212,10 +259,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
259
  version: '0'
213
260
  requirements:
214
261
  - none
215
- rubyforge_project:
216
- rubygems_version: 2.4.7
262
+ rubygems_version: 3.1.2
217
263
  signing_key:
218
264
  specification_version: 4
219
265
  summary: Rendering framework putting the V in MVC (part of Rails).
220
266
  test_files: []
221
- has_rdoc:
@@ -1,108 +0,0 @@
1
- require 'action_view/record_identifier'
2
-
3
- module ActionView
4
- # = Action View Record Tag Helpers
5
- module Helpers
6
- module RecordTagHelper
7
- include ActionView::RecordIdentifier
8
-
9
- # Produces a wrapper DIV element with id and class parameters that
10
- # relate to the specified Active Record object. Usage example:
11
- #
12
- # <%= div_for(@person, class: "foo") do %>
13
- # <%= @person.name %>
14
- # <% end %>
15
- #
16
- # produces:
17
- #
18
- # <div id="person_123" class="person foo"> Joe Bloggs </div>
19
- #
20
- # You can also pass an array of Active Record objects, which will then
21
- # get iterated over and yield each record as an argument for the block.
22
- # For example:
23
- #
24
- # <%= div_for(@people, class: "foo") do |person| %>
25
- # <%= person.name %>
26
- # <% end %>
27
- #
28
- # produces:
29
- #
30
- # <div id="person_123" class="person foo"> Joe Bloggs </div>
31
- # <div id="person_124" class="person foo"> Jane Bloggs </div>
32
- #
33
- def div_for(record, *args, &block)
34
- content_tag_for(:div, record, *args, &block)
35
- end
36
-
37
- # content_tag_for creates an HTML element with id and class parameters
38
- # that relate to the specified Active Record object. For example:
39
- #
40
- # <%= content_tag_for(:tr, @person) do %>
41
- # <td><%= @person.first_name %></td>
42
- # <td><%= @person.last_name %></td>
43
- # <% end %>
44
- #
45
- # would produce the following HTML (assuming @person is an instance of
46
- # a Person object, with an id value of 123):
47
- #
48
- # <tr id="person_123" class="person">....</tr>
49
- #
50
- # If you require the HTML id attribute to have a prefix, you can specify it:
51
- #
52
- # <%= content_tag_for(:tr, @person, :foo) do %> ...
53
- #
54
- # produces:
55
- #
56
- # <tr id="foo_person_123" class="person">...
57
- #
58
- # You can also pass an array of objects which this method will loop through
59
- # and yield the current object to the supplied block, reducing the need for
60
- # having to iterate through the object (using <tt>each</tt>) beforehand.
61
- # For example (assuming @people is an array of Person objects):
62
- #
63
- # <%= content_tag_for(:tr, @people) do |person| %>
64
- # <td><%= person.first_name %></td>
65
- # <td><%= person.last_name %></td>
66
- # <% end %>
67
- #
68
- # produces:
69
- #
70
- # <tr id="person_123" class="person">...</tr>
71
- # <tr id="person_124" class="person">...</tr>
72
- #
73
- # content_tag_for also accepts a hash of options, which will be converted to
74
- # additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined
75
- # with the default class name for your object. For example:
76
- #
77
- # <%= content_tag_for(:li, @person, class: "bar") %>...
78
- #
79
- # produces:
80
- #
81
- # <li id="person_123" class="person bar">...
82
- #
83
- def content_tag_for(tag_name, single_or_multiple_records, prefix = nil, options = nil, &block)
84
- options, prefix = prefix, nil if prefix.is_a?(Hash)
85
-
86
- Array(single_or_multiple_records).map do |single_record|
87
- content_tag_for_single_record(tag_name, single_record, prefix, options, &block)
88
- end.join("\n").html_safe
89
- end
90
-
91
- private
92
-
93
- # Called by <tt>content_tag_for</tt> internally to render a content tag
94
- # for each record.
95
- def content_tag_for_single_record(tag_name, record, prefix, options, &block)
96
- options = options ? options.dup : {}
97
- options[:class] = [ dom_class(record, prefix), options[:class] ].compact
98
- options[:id] = dom_id(record, prefix)
99
-
100
- if block_given?
101
- content_tag(tag_name, capture(record, &block), options)
102
- else
103
- content_tag(tag_name, "", options)
104
- end
105
- end
106
- end
107
- end
108
- end
@@ -1,23 +0,0 @@
1
- namespace :cache_digests do
2
- desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
3
- task :nested_dependencies => :environment do
4
- abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
5
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).nested_dependencies
6
- end
7
-
8
- desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
9
- task :dependencies => :environment do
10
- abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
11
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).dependencies
12
- end
13
-
14
- class CacheDigests
15
- def self.template_name
16
- ENV['TEMPLATE'].split('.', 2).first
17
- end
18
-
19
- def self.finder
20
- ApplicationController.new.lookup_context
21
- end
22
- end
23
- end
@@ -1,68 +0,0 @@
1
- require 'html/tokenizer'
2
- require 'html/node'
3
- require 'html/selector'
4
- require 'html/sanitizer'
5
-
6
- module HTML #:nodoc:
7
- # A top-level HTML document. You give it a body of text, and it will parse that
8
- # text into a tree of nodes.
9
- class Document #:nodoc:
10
-
11
- # The root of the parsed document.
12
- attr_reader :root
13
-
14
- # Create a new Document from the given text.
15
- def initialize(text, strict=false, xml=false)
16
- tokenizer = Tokenizer.new(text)
17
- @root = Node.new(nil)
18
- node_stack = [ @root ]
19
- while token = tokenizer.next
20
- node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token, strict)
21
-
22
- node_stack.last.children << node unless node.tag? && node.closing == :close
23
- if node.tag?
24
- if node_stack.length > 1 && node.closing == :close
25
- if node_stack.last.name == node.name
26
- if node_stack.last.children.empty?
27
- node_stack.last.children << Text.new(node_stack.last, node.line, node.position, "")
28
- end
29
- node_stack.pop
30
- else
31
- open_start = node_stack.last.position - 20
32
- open_start = 0 if open_start < 0
33
- close_start = node.position - 20
34
- close_start = 0 if close_start < 0
35
- msg = <<EOF.strip
36
- ignoring attempt to close #{node_stack.last.name} with #{node.name}
37
- opened at byte #{node_stack.last.position}, line #{node_stack.last.line}
38
- closed at byte #{node.position}, line #{node.line}
39
- attributes at open: #{node_stack.last.attributes.inspect}
40
- text around open: #{text[open_start,40].inspect}
41
- text around close: #{text[close_start,40].inspect}
42
- EOF
43
- strict ? raise(msg) : warn(msg)
44
- end
45
- elsif !node.childless?(xml) && node.closing != :close
46
- node_stack.push node
47
- end
48
- end
49
- end
50
- end
51
-
52
- # Search the tree for (and return) the first node that matches the given
53
- # conditions. The conditions are interpreted differently for different node
54
- # types, see HTML::Text#find and HTML::Tag#find.
55
- def find(conditions)
56
- @root.find(conditions)
57
- end
58
-
59
- # Search the tree for (and return) all nodes that match the given
60
- # conditions. The conditions are interpreted differently for different node
61
- # types, see HTML::Text#find and HTML::Tag#find.
62
- def find_all(conditions)
63
- @root.find_all(conditions)
64
- end
65
-
66
- end
67
-
68
- end
@@ -1,532 +0,0 @@
1
- require 'strscan'
2
-
3
- module HTML #:nodoc:
4
-
5
- class Conditions < Hash #:nodoc:
6
- def initialize(hash)
7
- super()
8
- hash = { :content => hash } unless Hash === hash
9
- hash = keys_to_symbols(hash)
10
- hash.each do |k,v|
11
- case k
12
- when :tag, :content then
13
- # keys are valid, and require no further processing
14
- when :attributes then
15
- hash[k] = keys_to_strings(v)
16
- when :parent, :child, :ancestor, :descendant, :sibling, :before,
17
- :after
18
- hash[k] = Conditions.new(v)
19
- when :children
20
- hash[k] = v = keys_to_symbols(v)
21
- v.each do |key,value|
22
- case key
23
- when :count, :greater_than, :less_than
24
- # keys are valid, and require no further processing
25
- when :only
26
- v[key] = Conditions.new(value)
27
- else
28
- raise "illegal key #{key.inspect} => #{value.inspect}"
29
- end
30
- end
31
- else
32
- raise "illegal key #{k.inspect} => #{v.inspect}"
33
- end
34
- end
35
- update hash
36
- end
37
-
38
- private
39
-
40
- def keys_to_strings(hash)
41
- Hash[hash.keys.map {|k| [k.to_s, hash[k]]}]
42
- end
43
-
44
- def keys_to_symbols(hash)
45
- Hash[hash.keys.map do |k|
46
- raise "illegal key #{k.inspect}" unless k.respond_to?(:to_sym)
47
- [k.to_sym, hash[k]]
48
- end]
49
- end
50
- end
51
-
52
- # The base class of all nodes, textual and otherwise, in an HTML document.
53
- class Node #:nodoc:
54
- # The array of children of this node. Not all nodes have children.
55
- attr_reader :children
56
-
57
- # The parent node of this node. All nodes have a parent, except for the
58
- # root node.
59
- attr_reader :parent
60
-
61
- # The line number of the input where this node was begun
62
- attr_reader :line
63
-
64
- # The byte position in the input where this node was begun
65
- attr_reader :position
66
-
67
- # Create a new node as a child of the given parent.
68
- def initialize(parent, line=0, pos=0)
69
- @parent = parent
70
- @children = []
71
- @line, @position = line, pos
72
- end
73
-
74
- # Returns a textual representation of the node.
75
- def to_s
76
- @children.join()
77
- end
78
-
79
- # Returns false (subclasses must override this to provide specific matching
80
- # behavior.) +conditions+ may be of any type.
81
- def match(conditions)
82
- false
83
- end
84
-
85
- # Search the children of this node for the first node for which #find
86
- # returns non +nil+. Returns the result of the #find call that succeeded.
87
- def find(conditions)
88
- conditions = validate_conditions(conditions)
89
- @children.each do |child|
90
- node = child.find(conditions)
91
- return node if node
92
- end
93
- nil
94
- end
95
-
96
- # Search for all nodes that match the given conditions, and return them
97
- # as an array.
98
- def find_all(conditions)
99
- conditions = validate_conditions(conditions)
100
-
101
- matches = []
102
- matches << self if match(conditions)
103
- @children.each do |child|
104
- matches.concat child.find_all(conditions)
105
- end
106
- matches
107
- end
108
-
109
- # Returns +false+. Subclasses may override this if they define a kind of
110
- # tag.
111
- def tag?
112
- false
113
- end
114
-
115
- def validate_conditions(conditions)
116
- Conditions === conditions ? conditions : Conditions.new(conditions)
117
- end
118
-
119
- def ==(node)
120
- return false unless self.class == node.class && children.size == node.children.size
121
-
122
- equivalent = true
123
-
124
- children.size.times do |i|
125
- equivalent &&= children[i] == node.children[i]
126
- end
127
-
128
- equivalent
129
- end
130
-
131
- class <<self
132
- def parse(parent, line, pos, content, strict=true)
133
- if content !~ /^<\S/
134
- Text.new(parent, line, pos, content)
135
- else
136
- scanner = StringScanner.new(content)
137
-
138
- unless scanner.skip(/</)
139
- if strict
140
- raise "expected <"
141
- else
142
- return Text.new(parent, line, pos, content)
143
- end
144
- end
145
-
146
- if scanner.skip(/!\[CDATA\[/)
147
- unless scanner.skip_until(/\]\]>/)
148
- if strict
149
- raise "expected ]]> (got #{scanner.rest.inspect} for #{content})"
150
- else
151
- scanner.skip_until(/\Z/)
152
- end
153
- end
154
-
155
- return CDATA.new(parent, line, pos, scanner.pre_match.gsub(/<!\[CDATA\[/, ''))
156
- end
157
-
158
- closing = ( scanner.scan(/\//) ? :close : nil )
159
- return Text.new(parent, line, pos, content) unless name = scanner.scan(/[^\s!>\/]+/)
160
- name.downcase!
161
-
162
- unless closing
163
- scanner.skip(/\s*/)
164
- attributes = {}
165
- while attr = scanner.scan(/[-\w:]+/)
166
- value = true
167
- if scanner.scan(/\s*=\s*/)
168
- if delim = scanner.scan(/['"]/)
169
- value = ""
170
- while text = scanner.scan(/[^#{delim}\\]+|./)
171
- case text
172
- when "\\" then
173
- value << text
174
- break if scanner.eos?
175
- value << scanner.getch
176
- when delim
177
- break
178
- else value << text
179
- end
180
- end
181
- else
182
- value = scanner.scan(/[^\s>\/]+/)
183
- end
184
- end
185
- attributes[attr.downcase] = value
186
- scanner.skip(/\s*/)
187
- end
188
-
189
- closing = ( scanner.scan(/\//) ? :self : nil )
190
- end
191
-
192
- unless scanner.scan(/\s*>/)
193
- if strict
194
- raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
195
- else
196
- # throw away all text until we find what we're looking for
197
- scanner.skip_until(/>/) or scanner.terminate
198
- end
199
- end
200
-
201
- Tag.new(parent, line, pos, name, attributes, closing)
202
- end
203
- end
204
- end
205
- end
206
-
207
- # A node that represents text, rather than markup.
208
- class Text < Node #:nodoc:
209
-
210
- attr_reader :content
211
-
212
- # Creates a new text node as a child of the given parent, with the given
213
- # content.
214
- def initialize(parent, line, pos, content)
215
- super(parent, line, pos)
216
- @content = content
217
- end
218
-
219
- # Returns the content of this node.
220
- def to_s
221
- @content
222
- end
223
-
224
- # Returns +self+ if this node meets the given conditions. Text nodes support
225
- # conditions of the following kinds:
226
- #
227
- # * if +conditions+ is a string, it must be a substring of the node's
228
- # content
229
- # * if +conditions+ is a regular expression, it must match the node's
230
- # content
231
- # * if +conditions+ is a hash, it must contain a <tt>:content</tt> key that
232
- # is either a string or a regexp, and which is interpreted as described
233
- # above.
234
- def find(conditions)
235
- match(conditions) && self
236
- end
237
-
238
- # Returns non-+nil+ if this node meets the given conditions, or +nil+
239
- # otherwise. See the discussion of #find for the valid conditions.
240
- def match(conditions)
241
- case conditions
242
- when String
243
- @content == conditions
244
- when Regexp
245
- @content =~ conditions
246
- when Hash
247
- conditions = validate_conditions(conditions)
248
-
249
- # Text nodes only have :content, :parent, :ancestor
250
- unless (conditions.keys - [:content, :parent, :ancestor]).empty?
251
- return false
252
- end
253
-
254
- match(conditions[:content])
255
- else
256
- nil
257
- end
258
- end
259
-
260
- def ==(node)
261
- return false unless super
262
- content == node.content
263
- end
264
- end
265
-
266
- # A CDATA node is simply a text node with a specialized way of displaying
267
- # itself.
268
- class CDATA < Text #:nodoc:
269
- def to_s
270
- "<![CDATA[#{super}]]>"
271
- end
272
- end
273
-
274
- # A Tag is any node that represents markup. It may be an opening tag, a
275
- # closing tag, or a self-closing tag. It has a name, and may have a hash of
276
- # attributes.
277
- class Tag < Node #:nodoc:
278
-
279
- # Either +nil+, <tt>:close</tt>, or <tt>:self</tt>
280
- attr_reader :closing
281
-
282
- # Either +nil+, or a hash of attributes for this node.
283
- attr_reader :attributes
284
-
285
- # The name of this tag.
286
- attr_reader :name
287
-
288
- # Create a new node as a child of the given parent, using the given content
289
- # to describe the node. It will be parsed and the node name, attributes and
290
- # closing status extracted.
291
- def initialize(parent, line, pos, name, attributes, closing)
292
- super(parent, line, pos)
293
- @name = name
294
- @attributes = attributes
295
- @closing = closing
296
- end
297
-
298
- # A convenience for obtaining an attribute of the node. Returns +nil+ if
299
- # the node has no attributes.
300
- def [](attr)
301
- @attributes ? @attributes[attr] : nil
302
- end
303
-
304
- # Returns non-+nil+ if this tag can contain child nodes.
305
- def childless?(xml = false)
306
- return false if xml && @closing.nil?
307
- !@closing.nil? ||
308
- @name =~ /^(img|br|hr|link|meta|area|base|basefont|
309
- col|frame|input|isindex|param)$/ox
310
- end
311
-
312
- # Returns a textual representation of the node
313
- def to_s
314
- if @closing == :close
315
- "</#{@name}>"
316
- else
317
- s = "<#{@name}"
318
- @attributes.each do |k,v|
319
- s << " #{k}"
320
- s << "=\"#{v}\"" if String === v
321
- end
322
- s << " /" if @closing == :self
323
- s << ">"
324
- @children.each { |child| s << child.to_s }
325
- s << "</#{@name}>" if @closing != :self && !@children.empty?
326
- s
327
- end
328
- end
329
-
330
- # If either the node or any of its children meet the given conditions, the
331
- # matching node is returned. Otherwise, +nil+ is returned. (See the
332
- # description of the valid conditions in the +match+ method.)
333
- def find(conditions)
334
- match(conditions) && self || super
335
- end
336
-
337
- # Returns +true+, indicating that this node represents an HTML tag.
338
- def tag?
339
- true
340
- end
341
-
342
- # Returns +true+ if the node meets any of the given conditions. The
343
- # +conditions+ parameter must be a hash of any of the following keys
344
- # (all are optional):
345
- #
346
- # * <tt>:tag</tt>: the node name must match the corresponding value
347
- # * <tt>:attributes</tt>: a hash. The node's values must match the
348
- # corresponding values in the hash.
349
- # * <tt>:parent</tt>: a hash. The node's parent must match the
350
- # corresponding hash.
351
- # * <tt>:child</tt>: a hash. At least one of the node's immediate children
352
- # must meet the criteria described by the hash.
353
- # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must
354
- # meet the criteria described by the hash.
355
- # * <tt>:descendant</tt>: a hash. At least one of the node's descendants
356
- # must meet the criteria described by the hash.
357
- # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must
358
- # meet the criteria described by the hash.
359
- # * <tt>:after</tt>: a hash. The node must be after any sibling meeting
360
- # the criteria described by the hash, and at least one sibling must match.
361
- # * <tt>:before</tt>: a hash. The node must be before any sibling meeting
362
- # the criteria described by the hash, and at least one sibling must match.
363
- # * <tt>:children</tt>: a hash, for counting children of a node. Accepts the
364
- # keys:
365
- # ** <tt>:count</tt>: either a number or a range which must equal (or
366
- # include) the number of children that match.
367
- # ** <tt>:less_than</tt>: the number of matching children must be less than
368
- # this number.
369
- # ** <tt>:greater_than</tt>: the number of matching children must be
370
- # greater than this number.
371
- # ** <tt>:only</tt>: another hash consisting of the keys to use
372
- # to match on the children, and only matching children will be
373
- # counted.
374
- #
375
- # Conditions are matched using the following algorithm:
376
- #
377
- # * if the condition is a string, it must be a substring of the value.
378
- # * if the condition is a regexp, it must match the value.
379
- # * if the condition is a number, the value must match number.to_s.
380
- # * if the condition is +true+, the value must not be +nil+.
381
- # * if the condition is +false+ or +nil+, the value must be +nil+.
382
- #
383
- # Usage:
384
- #
385
- # # test if the node is a "span" tag
386
- # node.match tag: "span"
387
- #
388
- # # test if the node's parent is a "div"
389
- # node.match parent: { tag: "div" }
390
- #
391
- # # test if any of the node's ancestors are "table" tags
392
- # node.match ancestor: { tag: "table" }
393
- #
394
- # # test if any of the node's immediate children are "em" tags
395
- # node.match child: { tag: "em" }
396
- #
397
- # # test if any of the node's descendants are "strong" tags
398
- # node.match descendant: { tag: "strong" }
399
- #
400
- # # test if the node has between 2 and 4 span tags as immediate children
401
- # node.match children: { count: 2..4, only: { tag: "span" } }
402
- #
403
- # # get funky: test to see if the node is a "div", has a "ul" ancestor
404
- # # and an "li" parent (with "class" = "enum"), and whether or not it has
405
- # # a "span" descendant that contains # text matching /hello world/:
406
- # node.match tag: "div",
407
- # ancestor: { tag: "ul" },
408
- # parent: { tag: "li",
409
- # attributes: { class: "enum" } },
410
- # descendant: { tag: "span",
411
- # child: /hello world/ }
412
- def match(conditions)
413
- conditions = validate_conditions(conditions)
414
- # check content of child nodes
415
- if conditions[:content]
416
- if children.empty?
417
- return false unless match_condition("", conditions[:content])
418
- else
419
- return false unless children.find { |child| child.match(conditions[:content]) }
420
- end
421
- end
422
-
423
- # test the name
424
- return false unless match_condition(@name, conditions[:tag]) if conditions[:tag]
425
-
426
- # test attributes
427
- (conditions[:attributes] || {}).each do |key, value|
428
- return false unless match_condition(self[key], value)
429
- end
430
-
431
- # test parent
432
- return false unless parent.match(conditions[:parent]) if conditions[:parent]
433
-
434
- # test children
435
- return false unless children.find { |child| child.match(conditions[:child]) } if conditions[:child]
436
-
437
- # test ancestors
438
- if conditions[:ancestor]
439
- return false unless catch :found do
440
- p = self
441
- throw :found, true if p.match(conditions[:ancestor]) while p = p.parent
442
- end
443
- end
444
-
445
- # test descendants
446
- if conditions[:descendant]
447
- return false unless children.find do |child|
448
- # test the child
449
- child.match(conditions[:descendant]) ||
450
- # test the child's descendants
451
- child.match(:descendant => conditions[:descendant])
452
- end
453
- end
454
-
455
- # count children
456
- if opts = conditions[:children]
457
- matches = children.select do |c|
458
- (c.kind_of?(HTML::Tag) and (c.closing == :self or ! c.childless?))
459
- end
460
-
461
- matches = matches.select { |c| c.match(opts[:only]) } if opts[:only]
462
- opts.each do |key, value|
463
- next if key == :only
464
- case key
465
- when :count
466
- if Integer === value
467
- return false if matches.length != value
468
- else
469
- return false unless value.include?(matches.length)
470
- end
471
- when :less_than
472
- return false unless matches.length < value
473
- when :greater_than
474
- return false unless matches.length > value
475
- else raise "unknown count condition #{key}"
476
- end
477
- end
478
- end
479
-
480
- # test siblings
481
- if conditions[:sibling] || conditions[:before] || conditions[:after]
482
- siblings = parent ? parent.children : []
483
- self_index = siblings.index(self)
484
-
485
- if conditions[:sibling]
486
- return false unless siblings.detect do |s|
487
- s != self && s.match(conditions[:sibling])
488
- end
489
- end
490
-
491
- if conditions[:before]
492
- return false unless siblings[self_index+1..-1].detect do |s|
493
- s != self && s.match(conditions[:before])
494
- end
495
- end
496
-
497
- if conditions[:after]
498
- return false unless siblings[0,self_index].detect do |s|
499
- s != self && s.match(conditions[:after])
500
- end
501
- end
502
- end
503
-
504
- true
505
- end
506
-
507
- def ==(node)
508
- return false unless super
509
- return false unless closing == node.closing && self.name == node.name
510
- attributes == node.attributes
511
- end
512
-
513
- private
514
- # Match the given value to the given condition.
515
- def match_condition(value, condition)
516
- case condition
517
- when String
518
- value && value == condition
519
- when Regexp
520
- value && value.match(condition)
521
- when Numeric
522
- value == condition.to_s
523
- when true
524
- !value.nil?
525
- when false, nil
526
- value.nil?
527
- else
528
- false
529
- end
530
- end
531
- end
532
- end