omg-actionview 8.0.0.alpha1
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/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
|