omg-actionview 8.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +25 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +40 -0
- data/app/assets/javascripts/rails-ujs.esm.js +686 -0
- data/app/assets/javascripts/rails-ujs.js +630 -0
- data/lib/action_view/base.rb +316 -0
- data/lib/action_view/buffers.rb +165 -0
- data/lib/action_view/cache_expiry.rb +69 -0
- data/lib/action_view/context.rb +32 -0
- data/lib/action_view/dependency_tracker/erb_tracker.rb +159 -0
- data/lib/action_view/dependency_tracker/ruby_tracker.rb +43 -0
- data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
- data/lib/action_view/dependency_tracker.rb +41 -0
- data/lib/action_view/deprecator.rb +7 -0
- data/lib/action_view/digestor.rb +130 -0
- data/lib/action_view/flows.rb +75 -0
- data/lib/action_view/gem_version.rb +17 -0
- data/lib/action_view/helpers/active_model_helper.rb +54 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +680 -0
- data/lib/action_view/helpers/asset_url_helper.rb +473 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +205 -0
- data/lib/action_view/helpers/cache_helper.rb +315 -0
- data/lib/action_view/helpers/capture_helper.rb +236 -0
- data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
- data/lib/action_view/helpers/controller_helper.rb +42 -0
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +35 -0
- data/lib/action_view/helpers/date_helper.rb +1266 -0
- data/lib/action_view/helpers/debug_helper.rb +38 -0
- data/lib/action_view/helpers/form_helper.rb +2765 -0
- data/lib/action_view/helpers/form_options_helper.rb +927 -0
- data/lib/action_view/helpers/form_tag_helper.rb +1088 -0
- data/lib/action_view/helpers/javascript_helper.rb +96 -0
- data/lib/action_view/helpers/number_helper.rb +165 -0
- data/lib/action_view/helpers/output_safety_helper.rb +70 -0
- data/lib/action_view/helpers/rendering_helper.rb +218 -0
- data/lib/action_view/helpers/sanitize_helper.rb +201 -0
- data/lib/action_view/helpers/tag_helper.rb +621 -0
- data/lib/action_view/helpers/tags/base.rb +138 -0
- data/lib/action_view/helpers/tags/check_box.rb +65 -0
- data/lib/action_view/helpers/tags/checkable.rb +18 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +37 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +118 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +31 -0
- data/lib/action_view/helpers/tags/collection_select.rb +33 -0
- data/lib/action_view/helpers/tags/color_field.rb +26 -0
- data/lib/action_view/helpers/tags/date_field.rb +14 -0
- data/lib/action_view/helpers/tags/date_select.rb +75 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +39 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +29 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +10 -0
- data/lib/action_view/helpers/tags/email_field.rb +10 -0
- data/lib/action_view/helpers/tags/file_field.rb +26 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +34 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +14 -0
- data/lib/action_view/helpers/tags/label.rb +84 -0
- data/lib/action_view/helpers/tags/month_field.rb +14 -0
- data/lib/action_view/helpers/tags/number_field.rb +20 -0
- data/lib/action_view/helpers/tags/password_field.rb +14 -0
- data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
- data/lib/action_view/helpers/tags/radio_button.rb +32 -0
- data/lib/action_view/helpers/tags/range_field.rb +10 -0
- data/lib/action_view/helpers/tags/search_field.rb +27 -0
- data/lib/action_view/helpers/tags/select.rb +45 -0
- data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
- data/lib/action_view/helpers/tags/tel_field.rb +10 -0
- data/lib/action_view/helpers/tags/text_area.rb +24 -0
- data/lib/action_view/helpers/tags/text_field.rb +33 -0
- data/lib/action_view/helpers/tags/time_field.rb +23 -0
- data/lib/action_view/helpers/tags/time_select.rb +10 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +25 -0
- data/lib/action_view/helpers/tags/translator.rb +39 -0
- data/lib/action_view/helpers/tags/url_field.rb +10 -0
- data/lib/action_view/helpers/tags/week_field.rb +14 -0
- data/lib/action_view/helpers/tags/weekday_select.rb +31 -0
- data/lib/action_view/helpers/tags.rb +47 -0
- data/lib/action_view/helpers/text_helper.rb +568 -0
- data/lib/action_view/helpers/translation_helper.rb +161 -0
- data/lib/action_view/helpers/url_helper.rb +812 -0
- data/lib/action_view/helpers.rb +68 -0
- data/lib/action_view/layouts.rb +434 -0
- data/lib/action_view/locale/en.yml +56 -0
- data/lib/action_view/log_subscriber.rb +132 -0
- data/lib/action_view/lookup_context.rb +299 -0
- data/lib/action_view/model_naming.rb +14 -0
- data/lib/action_view/path_registry.rb +57 -0
- data/lib/action_view/path_set.rb +84 -0
- data/lib/action_view/railtie.rb +132 -0
- data/lib/action_view/record_identifier.rb +118 -0
- data/lib/action_view/render_parser/prism_render_parser.rb +139 -0
- data/lib/action_view/render_parser/ripper_render_parser.rb +350 -0
- data/lib/action_view/render_parser.rb +40 -0
- data/lib/action_view/renderer/abstract_renderer.rb +186 -0
- data/lib/action_view/renderer/collection_renderer.rb +204 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +120 -0
- data/lib/action_view/renderer/partial_renderer.rb +267 -0
- data/lib/action_view/renderer/renderer.rb +107 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +107 -0
- data/lib/action_view/renderer/template_renderer.rb +115 -0
- data/lib/action_view/rendering.rb +190 -0
- data/lib/action_view/routing_url_for.rb +149 -0
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +264 -0
- data/lib/action_view/template/handlers/builder.rb +25 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +85 -0
- data/lib/action_view/template/handlers/erb.rb +157 -0
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/handlers.rb +66 -0
- data/lib/action_view/template/html.rb +33 -0
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +30 -0
- data/lib/action_view/template/resolver.rb +212 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +32 -0
- data/lib/action_view/template/types.rb +50 -0
- data/lib/action_view/template.rb +580 -0
- data/lib/action_view/template_details.rb +66 -0
- data/lib/action_view/template_path.rb +66 -0
- data/lib/action_view/test_case.rb +449 -0
- data/lib/action_view/testing/resolvers.rb +44 -0
- data/lib/action_view/unbound_template.rb +67 -0
- data/lib/action_view/version.rb +10 -0
- data/lib/action_view/view_paths.rb +117 -0
- data/lib/action_view.rb +104 -0
- metadata +275 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class Template
|
5
|
+
# = Action View Renderable Template for objects that respond to #render_in
|
6
|
+
class Renderable # :nodoc:
|
7
|
+
def initialize(renderable)
|
8
|
+
@renderable = renderable
|
9
|
+
end
|
10
|
+
|
11
|
+
def identifier
|
12
|
+
@renderable.class.name
|
13
|
+
end
|
14
|
+
|
15
|
+
def render(context, *args)
|
16
|
+
@renderable.render_in(context)
|
17
|
+
rescue NoMethodError
|
18
|
+
if !@renderable.respond_to?(:render_in)
|
19
|
+
raise ArgumentError, "'#{@renderable.inspect}' is not a renderable object. It must implement #render_in."
|
20
|
+
else
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def format
|
26
|
+
@renderable.try(:format)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "active_support/core_ext/class"
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "action_view/template"
|
7
|
+
require "concurrent/map"
|
8
|
+
|
9
|
+
module ActionView
|
10
|
+
# = Action View Resolver
|
11
|
+
class Resolver
|
12
|
+
class PathParser # :nodoc:
|
13
|
+
ParsedPath = Struct.new(:path, :details)
|
14
|
+
|
15
|
+
def build_path_regex
|
16
|
+
handlers = Regexp.union(Template::Handlers.extensions.map(&:to_s))
|
17
|
+
formats = Regexp.union(Template::Types.symbols.map(&:to_s))
|
18
|
+
available_locales = I18n.available_locales.map(&:to_s)
|
19
|
+
regular_locales = [/[a-z]{2}(?:[-_][A-Z]{2})?/]
|
20
|
+
locales = Regexp.union(available_locales + regular_locales)
|
21
|
+
variants = "[^.]*"
|
22
|
+
|
23
|
+
%r{
|
24
|
+
\A
|
25
|
+
(?:(?<prefix>.*)/)?
|
26
|
+
(?<partial>_)?
|
27
|
+
(?<action>.*?)
|
28
|
+
(?:\.(?<locale>#{locales}))??
|
29
|
+
(?:\.(?<format>#{formats}))??
|
30
|
+
(?:\+(?<variant>#{variants}))??
|
31
|
+
(?:\.(?<handler>#{handlers}))?
|
32
|
+
\z
|
33
|
+
}x
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(path)
|
37
|
+
@regex ||= build_path_regex
|
38
|
+
match = @regex.match(path)
|
39
|
+
path = TemplatePath.build(match[:action], match[:prefix] || "", !!match[:partial])
|
40
|
+
details = TemplateDetails.new(
|
41
|
+
match[:locale]&.to_sym,
|
42
|
+
match[:handler]&.to_sym,
|
43
|
+
match[:format]&.to_sym,
|
44
|
+
match[:variant]&.to_sym
|
45
|
+
)
|
46
|
+
ParsedPath.new(path, details)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
cattr_accessor :caching, default: true
|
51
|
+
|
52
|
+
class << self
|
53
|
+
alias :caching? :caching
|
54
|
+
end
|
55
|
+
|
56
|
+
def clear_cache
|
57
|
+
end
|
58
|
+
|
59
|
+
# Normalizes the arguments and passes it on to find_templates.
|
60
|
+
def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
|
61
|
+
_find_all(name, prefix, partial, details, key, locals)
|
62
|
+
end
|
63
|
+
|
64
|
+
def built_templates # :nodoc:
|
65
|
+
# Used for error pages
|
66
|
+
[]
|
67
|
+
end
|
68
|
+
|
69
|
+
def all_template_paths # :nodoc:
|
70
|
+
# Not implemented by default
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def _find_all(name, prefix, partial, details, key, locals)
|
76
|
+
find_templates(name, prefix, partial, details, locals)
|
77
|
+
end
|
78
|
+
|
79
|
+
delegate :caching?, to: :class
|
80
|
+
|
81
|
+
# This is what child classes implement. No defaults are needed
|
82
|
+
# because Resolver guarantees that the arguments are present and
|
83
|
+
# normalized.
|
84
|
+
def find_templates(name, prefix, partial, details, locals = [])
|
85
|
+
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, locals = []) method"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# A resolver that loads files from the filesystem.
|
90
|
+
class FileSystemResolver < Resolver
|
91
|
+
attr_reader :path
|
92
|
+
|
93
|
+
def initialize(path)
|
94
|
+
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
95
|
+
@unbound_templates = Concurrent::Map.new
|
96
|
+
@path_parser = PathParser.new
|
97
|
+
@path = File.expand_path(path)
|
98
|
+
super()
|
99
|
+
end
|
100
|
+
|
101
|
+
def clear_cache
|
102
|
+
@unbound_templates.clear
|
103
|
+
@path_parser = PathParser.new
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
@path.to_s
|
109
|
+
end
|
110
|
+
alias :to_path :to_s
|
111
|
+
|
112
|
+
def eql?(resolver)
|
113
|
+
self.class.equal?(resolver.class) && to_path == resolver.to_path
|
114
|
+
end
|
115
|
+
alias :== :eql?
|
116
|
+
|
117
|
+
def all_template_paths # :nodoc:
|
118
|
+
paths = template_glob("**/*")
|
119
|
+
paths.map do |filename|
|
120
|
+
filename.from(@path.size + 1).remove(/\.[^\/]*\z/)
|
121
|
+
end.uniq.map do |filename|
|
122
|
+
TemplatePath.parse(filename)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def built_templates # :nodoc:
|
127
|
+
@unbound_templates.values.flatten.flat_map(&:built_templates)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
def _find_all(name, prefix, partial, details, key, locals)
|
132
|
+
requested_details = key || TemplateDetails::Requested.new(**details)
|
133
|
+
cache = key ? @unbound_templates : Concurrent::Map.new
|
134
|
+
|
135
|
+
unbound_templates =
|
136
|
+
cache.compute_if_absent(TemplatePath.virtual(name, prefix, partial)) do
|
137
|
+
path = TemplatePath.build(name, prefix, partial)
|
138
|
+
unbound_templates_from_path(path)
|
139
|
+
end
|
140
|
+
|
141
|
+
filter_and_sort_by_details(unbound_templates, requested_details).map do |unbound_template|
|
142
|
+
unbound_template.bind_locals(locals)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def source_for_template(template)
|
147
|
+
Template::Sources::File.new(template)
|
148
|
+
end
|
149
|
+
|
150
|
+
def build_unbound_template(template)
|
151
|
+
parsed = @path_parser.parse(template.from(@path.size + 1))
|
152
|
+
details = parsed.details
|
153
|
+
source = source_for_template(template)
|
154
|
+
|
155
|
+
UnboundTemplate.new(
|
156
|
+
source,
|
157
|
+
template,
|
158
|
+
details: details,
|
159
|
+
virtual_path: parsed.path.virtual,
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def unbound_templates_from_path(path)
|
164
|
+
if path.name.include?(".")
|
165
|
+
return []
|
166
|
+
end
|
167
|
+
|
168
|
+
# Instead of checking for every possible path, as our other globs would
|
169
|
+
# do, scan the directory for files with the right prefix.
|
170
|
+
paths = template_glob("#{escape_entry(path.to_s)}*")
|
171
|
+
|
172
|
+
paths.map do |path|
|
173
|
+
build_unbound_template(path)
|
174
|
+
end.select do |template|
|
175
|
+
# Select for exact virtual path match, including case sensitivity
|
176
|
+
template.virtual_path == path.virtual
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def filter_and_sort_by_details(templates, requested_details)
|
181
|
+
filtered_templates = templates.select do |template|
|
182
|
+
template.details.matches?(requested_details)
|
183
|
+
end
|
184
|
+
|
185
|
+
if filtered_templates.count > 1
|
186
|
+
filtered_templates.sort_by! do |template|
|
187
|
+
template.details.sort_key_for(requested_details)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
filtered_templates
|
192
|
+
end
|
193
|
+
|
194
|
+
# Safe glob within @path
|
195
|
+
def template_glob(glob)
|
196
|
+
query = File.join(escape_entry(@path), glob)
|
197
|
+
path_with_slash = File.join(@path, "")
|
198
|
+
|
199
|
+
Dir.glob(query).filter_map do |filename|
|
200
|
+
filename = File.expand_path(filename)
|
201
|
+
next if File.directory?(filename)
|
202
|
+
next unless filename.start_with?(path_with_slash)
|
203
|
+
|
204
|
+
filename
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def escape_entry(entry)
|
209
|
+
entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView # :nodoc:
|
4
|
+
class Template # :nodoc:
|
5
|
+
# = Action View Text Template
|
6
|
+
class Text # :nodoc:
|
7
|
+
attr_accessor :type
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
@string = string.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def identifier
|
14
|
+
"text template"
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :inspect, :identifier
|
18
|
+
|
19
|
+
def to_str
|
20
|
+
@string
|
21
|
+
end
|
22
|
+
|
23
|
+
def render(*args)
|
24
|
+
to_str
|
25
|
+
end
|
26
|
+
|
27
|
+
def format
|
28
|
+
:text
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/attribute_accessors"
|
4
|
+
|
5
|
+
module ActionView
|
6
|
+
class Template # :nodoc:
|
7
|
+
# SimpleType is mostly just a stub implementation for when Action View
|
8
|
+
# is used without Action Dispatch.
|
9
|
+
class SimpleType # :nodoc:
|
10
|
+
@symbols = [ :html, :text, :js, :css, :xml, :json ]
|
11
|
+
class << self
|
12
|
+
attr_reader :symbols
|
13
|
+
|
14
|
+
def [](type)
|
15
|
+
if type.is_a?(self)
|
16
|
+
type
|
17
|
+
else
|
18
|
+
new(type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_symbols?(symbols) # :nodoc
|
23
|
+
symbols.all? { |s| @symbols.include?(s) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :symbol
|
28
|
+
|
29
|
+
def initialize(symbol)
|
30
|
+
@symbol = symbol.to_sym
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
@symbol.to_s
|
35
|
+
end
|
36
|
+
alias to_str to_s
|
37
|
+
|
38
|
+
def ref
|
39
|
+
@symbol
|
40
|
+
end
|
41
|
+
alias to_sym ref
|
42
|
+
|
43
|
+
def ==(type)
|
44
|
+
@symbol == type.to_sym unless type.blank?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Types = SimpleType # :nodoc:
|
49
|
+
end
|
50
|
+
end
|