actionview_precompiler 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/actionview_precompiler/ast_parser/jruby.rb +58 -4
- data/lib/actionview_precompiler/ast_parser/prism.rb +155 -0
- data/lib/actionview_precompiler/ast_parser/ripper.rb +206 -0
- data/lib/actionview_precompiler/ast_parser/ruby26.rb +69 -5
- data/lib/actionview_precompiler/ast_parser.rb +25 -4
- data/lib/actionview_precompiler/controller_parser.rb +13 -0
- data/lib/actionview_precompiler/controller_scanner.rb +48 -0
- data/lib/actionview_precompiler/helper_parser.rb +13 -0
- data/lib/actionview_precompiler/helper_scanner.rb +34 -0
- data/lib/actionview_precompiler/precompiler.rb +47 -73
- data/lib/actionview_precompiler/render_parser.rb +144 -42
- data/lib/actionview_precompiler/template_file.rb +22 -0
- data/lib/actionview_precompiler/template_loader.rb +36 -0
- data/lib/actionview_precompiler/template_parser.rb +9 -17
- data/lib/actionview_precompiler/template_scanner.rb +44 -0
- data/lib/actionview_precompiler/version.rb +1 -1
- data/lib/actionview_precompiler.rb +31 -17
- metadata +15 -6
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActionviewPrecompiler
|
2
|
+
class HelperParser
|
3
|
+
def initialize(filename)
|
4
|
+
@filename = filename
|
5
|
+
end
|
6
|
+
|
7
|
+
def render_calls
|
8
|
+
src = File.read(@filename)
|
9
|
+
return [] unless src.include?("render")
|
10
|
+
RenderParser.new(src).render_calls
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActionviewPrecompiler
|
2
|
+
class HelperScanner
|
3
|
+
def initialize(dir)
|
4
|
+
@dir = dir
|
5
|
+
end
|
6
|
+
|
7
|
+
def template_renders
|
8
|
+
template_renders = []
|
9
|
+
|
10
|
+
each_helper do |fullpath|
|
11
|
+
parser = HelperParser.new(fullpath)
|
12
|
+
parser.render_calls.each do |render_call|
|
13
|
+
virtual_path = render_call.virtual_path
|
14
|
+
|
15
|
+
locals = render_call.locals_keys.map(&:to_s).sort
|
16
|
+
|
17
|
+
template_renders << [virtual_path, locals]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
template_renders.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def each_helper
|
27
|
+
Dir["#{@dir}/**/*_helper.rb"].sort.map do |fullpath|
|
28
|
+
next if File.directory?(fullpath)
|
29
|
+
|
30
|
+
yield fullpath
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,95 +1,69 @@
|
|
1
|
+
require "actionview_precompiler/template_scanner"
|
2
|
+
require "actionview_precompiler/controller_scanner"
|
3
|
+
require "actionview_precompiler/helper_scanner"
|
4
|
+
require "actionview_precompiler/template_loader"
|
5
|
+
|
1
6
|
module ActionviewPrecompiler
|
2
7
|
class Precompiler
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@relative_path = relative_path
|
10
|
-
@virtual_path = relative_path.slice(0, relative_path.index("."))
|
11
|
-
|
12
|
-
parsed = ParsedFilename.new(relative_path)
|
13
|
-
@prefix = parsed.prefix
|
14
|
-
@action = parsed.action
|
15
|
-
@partial = parsed.partial?
|
16
|
-
@details = parsed.details
|
17
|
-
end
|
18
|
-
|
19
|
-
def partial?
|
20
|
-
@partial
|
21
|
-
end
|
8
|
+
def initialize(verbose: false)
|
9
|
+
@scanners = []
|
10
|
+
@loader = TemplateLoader.new
|
11
|
+
@verbose = verbose
|
12
|
+
@static_templates = []
|
13
|
+
@template_renders = nil
|
22
14
|
end
|
23
15
|
|
24
|
-
|
16
|
+
def scan_view_dir(view_dir)
|
17
|
+
@scanners << TemplateScanner.new(view_dir)
|
18
|
+
end
|
25
19
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
|
29
|
-
Dir["**/*", base: view_dir].map do |file|
|
30
|
-
fullpath = File.expand_path(file, view_dir)
|
31
|
-
next if File.directory?(fullpath)
|
20
|
+
def scan_controller_dir(controller_dir)
|
21
|
+
@scanners << ControllerScanner.new(controller_dir)
|
22
|
+
end
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
24
|
+
def scan_helper_dir(controller_dir)
|
25
|
+
@scanners << HelperScanner.new(controller_dir)
|
26
|
+
end
|
36
27
|
|
37
|
-
|
28
|
+
def add_template(virtual_path, locals = [])
|
29
|
+
locals = locals.map(&:to_s).sort
|
30
|
+
@static_templates << [virtual_path, locals]
|
38
31
|
end
|
39
32
|
|
40
|
-
def
|
41
|
-
|
33
|
+
def run
|
34
|
+
count = 0
|
35
|
+
template_renders.each do |virtual_path, locals|
|
36
|
+
debug "precompiling: #{virtual_path}"
|
42
37
|
|
43
|
-
|
44
|
-
|
45
|
-
locale: Array(template.details[:locale]),
|
46
|
-
variants: Array(template.details[:variant]),
|
47
|
-
formats: Array(template.details[:format]),
|
48
|
-
handlers: Array(template.details[:handler])
|
49
|
-
}
|
38
|
+
templates = @loader.load_template(virtual_path, locals)
|
39
|
+
count += templates.count
|
50
40
|
|
51
|
-
|
41
|
+
debug " No templates found at #{virtual_path}" if templates.empty?
|
52
42
|
end
|
53
43
|
|
54
|
-
|
44
|
+
debug "Precompiled #{count} Templates"
|
55
45
|
end
|
56
46
|
|
57
|
-
def
|
58
|
-
return
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
yield template, locals
|
65
|
-
end
|
66
|
-
elsif !template.partial?
|
67
|
-
# For now, guess that non-partials we haven't seen take no locals
|
68
|
-
yield template, []
|
69
|
-
else
|
70
|
-
# Locals unknown
|
71
|
-
end
|
47
|
+
def template_renders
|
48
|
+
return @template_renders if @template_renders
|
49
|
+
|
50
|
+
template_renders = []
|
51
|
+
|
52
|
+
@scanners.each do |scanner|
|
53
|
+
template_renders.concat scanner.template_renders
|
72
54
|
end
|
55
|
+
|
56
|
+
template_renders.concat @static_templates
|
57
|
+
|
58
|
+
template_renders.uniq!
|
59
|
+
|
60
|
+
@template_renders = template_renders
|
73
61
|
end
|
74
62
|
|
75
|
-
|
76
|
-
@locals_sets = {}
|
77
|
-
|
78
|
-
@templates.each do |template|
|
79
|
-
parser = TemplateParser.new(template.fullpath)
|
80
|
-
parser.render_calls.each do |render_call|
|
81
|
-
virtual_path = render_call.virtual_path
|
82
|
-
unless virtual_path.include?("/")
|
83
|
-
# Not necessarily true, since the perfix is based on the current
|
84
|
-
# controller, but is a safe bet most of the time.
|
85
|
-
virtual_path = "#{template.prefix}/#{virtual_path}"
|
86
|
-
end
|
87
|
-
@locals_sets[virtual_path] ||= []
|
88
|
-
@locals_sets[virtual_path] << render_call.locals_keys.map(&:to_s).sort
|
89
|
-
end
|
90
|
-
end
|
63
|
+
private
|
91
64
|
|
92
|
-
|
65
|
+
def debug(msg)
|
66
|
+
puts msg if @verbose
|
93
67
|
end
|
94
68
|
end
|
95
69
|
end
|
@@ -1,50 +1,84 @@
|
|
1
1
|
module ActionviewPrecompiler
|
2
|
-
RenderCall = Struct.new(:
|
3
|
-
def virtual_path
|
4
|
-
if render_type == :partial
|
5
|
-
@virtual_path ||= template.gsub(%r{(/|^)([^/]*)\z}, '\1_\2')
|
6
|
-
else
|
7
|
-
template
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
2
|
+
RenderCall = Struct.new(:virtual_path, :locals_keys)
|
11
3
|
|
12
4
|
class RenderParser
|
13
|
-
|
14
|
-
|
15
|
-
def initialize(code)
|
5
|
+
def initialize(code, parser: ASTParser, from_controller: false)
|
16
6
|
@code = code
|
17
|
-
@
|
7
|
+
@parser = parser
|
8
|
+
@from_controller = from_controller
|
18
9
|
end
|
19
10
|
|
20
11
|
def render_calls
|
21
|
-
render_nodes =
|
22
|
-
render_nodes.map do |
|
23
|
-
|
24
|
-
|
12
|
+
render_nodes = @parser.parse_render_nodes(@code)
|
13
|
+
render_nodes.map do |method, nodes|
|
14
|
+
parse_method = case method
|
15
|
+
when :layout
|
16
|
+
:parse_layout
|
17
|
+
else
|
18
|
+
:parse_render
|
19
|
+
end
|
20
|
+
|
21
|
+
nodes.map { |n| send(parse_method, n) }
|
22
|
+
end.flatten.compact
|
25
23
|
end
|
26
24
|
|
27
25
|
private
|
28
26
|
|
27
|
+
# Convert
|
28
|
+
# render("foo", ...)
|
29
|
+
# into either
|
30
|
+
# render(template: "foo", ...)
|
31
|
+
# or
|
32
|
+
# render(partial: "foo", ...)
|
33
|
+
# depending on controller or view context
|
34
|
+
def normalize_args(string, options_hash)
|
35
|
+
if @from_controller
|
36
|
+
if options_hash
|
37
|
+
options = parse_hash_to_symbols(options_hash)
|
38
|
+
else
|
39
|
+
options = {}
|
40
|
+
end
|
41
|
+
return nil unless options
|
42
|
+
options.merge(template: string)
|
43
|
+
else
|
44
|
+
if options_hash
|
45
|
+
{ partial: string, locals: options_hash }
|
46
|
+
else
|
47
|
+
{ partial: string }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
29
52
|
def parse_render(node)
|
30
53
|
node = node.argument_nodes
|
31
|
-
if (node.length == 1 || node.length == 2) && node[0].
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
if node.length == 2
|
54
|
+
if (node.length == 1 || node.length == 2) && !node[0].hash?
|
55
|
+
if node.length == 1
|
56
|
+
options = normalize_args(node[0], nil)
|
57
|
+
elsif node.length == 2
|
36
58
|
return unless node[1].hash?
|
37
|
-
options
|
59
|
+
options = normalize_args(node[0], node[1])
|
38
60
|
end
|
61
|
+
return nil unless options
|
39
62
|
return parse_render_from_options(options)
|
40
63
|
elsif node.length == 1 && node[0].hash?
|
41
64
|
options = parse_hash_to_symbols(node[0])
|
65
|
+
return nil unless options
|
42
66
|
return parse_render_from_options(options)
|
43
67
|
else
|
44
68
|
nil
|
45
69
|
end
|
46
70
|
end
|
47
71
|
|
72
|
+
def parse_layout(node)
|
73
|
+
return nil unless from_controller?
|
74
|
+
|
75
|
+
template = parse_str(node.argument_nodes[0])
|
76
|
+
return nil unless template
|
77
|
+
|
78
|
+
virtual_path = layout_to_virtual_path(template)
|
79
|
+
RenderCall.new(virtual_path, [])
|
80
|
+
end
|
81
|
+
|
48
82
|
def parse_hash(node)
|
49
83
|
node.hash? && node.to_hash
|
50
84
|
end
|
@@ -52,22 +86,28 @@ module ActionviewPrecompiler
|
|
52
86
|
def parse_hash_to_symbols(node)
|
53
87
|
hash = parse_hash(node)
|
54
88
|
return unless hash
|
55
|
-
hash.transform_keys do |
|
56
|
-
key = parse_sym(
|
89
|
+
hash.transform_keys do |key_node|
|
90
|
+
key = parse_sym(key_node)
|
57
91
|
return unless key
|
58
92
|
key
|
59
93
|
end
|
60
94
|
end
|
61
95
|
|
62
|
-
|
63
|
-
IGNORED_KEYS = [:formats]
|
64
|
-
ALL_KNOWN_KEYS = [*RENDER_TYPE_KEYS, *IGNORED_KEYS, :locals, :object, :collection, :as]
|
96
|
+
ALL_KNOWN_KEYS = [:partial, :template, :layout, :formats, :locals, :object, :collection, :as, :status, :content_type, :location, :spacer_template]
|
65
97
|
|
66
98
|
def parse_render_from_options(options_hash)
|
99
|
+
renders = []
|
67
100
|
keys = options_hash.keys
|
68
101
|
|
69
|
-
|
70
|
-
|
102
|
+
render_type_keys =
|
103
|
+
if from_controller?
|
104
|
+
[:partial, :template]
|
105
|
+
else
|
106
|
+
[:partial, :template, :layout]
|
107
|
+
end
|
108
|
+
|
109
|
+
if (keys & render_type_keys).size < 1
|
110
|
+
# Must have at least one of render keys
|
71
111
|
return nil
|
72
112
|
end
|
73
113
|
|
@@ -76,8 +116,26 @@ module ActionviewPrecompiler
|
|
76
116
|
return nil
|
77
117
|
end
|
78
118
|
|
79
|
-
render_type = (keys &
|
80
|
-
|
119
|
+
render_type = (keys & render_type_keys)[0]
|
120
|
+
|
121
|
+
node = options_hash[render_type]
|
122
|
+
if node.string?
|
123
|
+
template = node.to_string
|
124
|
+
else
|
125
|
+
if node.variable_reference?
|
126
|
+
dependency = node.variable_name.sub(/\A(?:\$|@{1,2})/, "")
|
127
|
+
elsif node.vcall?
|
128
|
+
dependency = node.variable_name
|
129
|
+
elsif node.call?
|
130
|
+
dependency = node.call_method_name
|
131
|
+
return unless dependency.is_a? String
|
132
|
+
else
|
133
|
+
return
|
134
|
+
end
|
135
|
+
object_template = true
|
136
|
+
template = "#{dependency.pluralize}/#{dependency.singularize}"
|
137
|
+
end
|
138
|
+
|
81
139
|
return unless template
|
82
140
|
|
83
141
|
if options_hash.key?(:locals)
|
@@ -93,7 +151,13 @@ module ActionviewPrecompiler
|
|
93
151
|
locals_keys = []
|
94
152
|
end
|
95
153
|
|
96
|
-
if
|
154
|
+
if spacer_template = render_template_with_spacer?(options_hash)
|
155
|
+
virtual_path = partial_to_virtual_path(:partial, spacer_template)
|
156
|
+
# Locals keys should not include collection keys
|
157
|
+
renders << RenderCall.new(virtual_path, locals_keys.dup)
|
158
|
+
end
|
159
|
+
|
160
|
+
if options_hash.key?(:object) || options_hash.key?(:collection) || object_template
|
97
161
|
return nil if options_hash.key?(:object) && options_hash.key?(:collection)
|
98
162
|
return nil unless options_hash.key?(:partial)
|
99
163
|
|
@@ -112,7 +176,28 @@ module ActionviewPrecompiler
|
|
112
176
|
end
|
113
177
|
end
|
114
178
|
|
115
|
-
|
179
|
+
virtual_path = partial_to_virtual_path(render_type, template)
|
180
|
+
renders << RenderCall.new(virtual_path, locals_keys)
|
181
|
+
|
182
|
+
# Support for rendering multiple templates (i.e. a partial with a layout)
|
183
|
+
if layout_template = render_template_with_layout?(render_type, options_hash)
|
184
|
+
virtual_path = if from_controller?
|
185
|
+
layout_to_virtual_path(layout_template)
|
186
|
+
else
|
187
|
+
if !layout_template.include?("/") &&
|
188
|
+
partial_prefix = template.match(%r{(.*)/([^/]*)\z})
|
189
|
+
# TODO: use the file path that this render call was found in to
|
190
|
+
# generate the partial prefix instead of rendered partial.
|
191
|
+
partial_prefix = partial_prefix[1]
|
192
|
+
layout_template = "#{partial_prefix}/#{layout_template}"
|
193
|
+
end
|
194
|
+
partial_to_virtual_path(:layout, layout_template)
|
195
|
+
end
|
196
|
+
|
197
|
+
renders << RenderCall.new(virtual_path, locals_keys)
|
198
|
+
end
|
199
|
+
|
200
|
+
renders
|
116
201
|
end
|
117
202
|
|
118
203
|
def parse_str(node)
|
@@ -123,21 +208,38 @@ module ActionviewPrecompiler
|
|
123
208
|
node.symbol? && node.to_symbol
|
124
209
|
end
|
125
210
|
|
211
|
+
private
|
212
|
+
|
126
213
|
def debug(message)
|
127
214
|
warn message
|
128
215
|
end
|
129
216
|
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
217
|
+
def from_controller?
|
218
|
+
@from_controller
|
219
|
+
end
|
220
|
+
|
221
|
+
def render_template_with_layout?(render_type, options_hash)
|
222
|
+
if render_type != :layout && options_hash.key?(:layout)
|
223
|
+
parse_str(options_hash[:layout])
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def render_template_with_spacer?(options_hash)
|
228
|
+
if !from_controller? && options_hash.key?(:spacer_template)
|
229
|
+
parse_str(options_hash[:spacer_template])
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def partial_to_virtual_path(render_type, partial_path)
|
234
|
+
if render_type == :partial || render_type == :layout
|
235
|
+
partial_path.gsub(%r{(/|^)([^/]*)\z}, '\1_\2')
|
236
|
+
else
|
237
|
+
partial_path
|
135
238
|
end
|
136
|
-
renders
|
137
239
|
end
|
138
240
|
|
139
|
-
def
|
140
|
-
|
241
|
+
def layout_to_virtual_path(layout_path)
|
242
|
+
"layouts/#{layout_path}"
|
141
243
|
end
|
142
244
|
end
|
143
245
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActionviewPrecompiler
|
2
|
+
class TemplateFile
|
3
|
+
attr_reader :fullpath, :relative_path, :virtual_path
|
4
|
+
attr_reader :action, :prefix, :details
|
5
|
+
|
6
|
+
def initialize(fullpath, relative_path)
|
7
|
+
@fullpath = fullpath
|
8
|
+
@relative_path = relative_path
|
9
|
+
@virtual_path = relative_path.slice(0, relative_path.index("."))
|
10
|
+
|
11
|
+
parsed = ParsedFilename.new(relative_path)
|
12
|
+
@prefix = parsed.prefix
|
13
|
+
@action = parsed.action
|
14
|
+
@partial = parsed.partial?
|
15
|
+
@details = parsed.details
|
16
|
+
end
|
17
|
+
|
18
|
+
def partial?
|
19
|
+
@partial
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActionviewPrecompiler
|
2
|
+
class TemplateLoader
|
3
|
+
VIRTUAL_PATH_REGEX = %r{\A(?:(?<prefix>.*)\/)?(?<partial>_)?(?<action>[^\/\.]+)}
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
target = ActionController::Base
|
7
|
+
@lookup_context = ActionView::LookupContext.new(target.view_paths)
|
8
|
+
@view_context_class = target.view_context_class
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_template(virtual_path, locals)
|
12
|
+
templates = find_all_templates(virtual_path, locals)
|
13
|
+
templates.each do |template|
|
14
|
+
template.send(:compile!, @view_context_class)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def find_all_templates(virtual_path, locals)
|
21
|
+
match = virtual_path.match(VIRTUAL_PATH_REGEX)
|
22
|
+
if match
|
23
|
+
action = match[:action]
|
24
|
+
prefix = match[:prefix] ? [match[:prefix]] : []
|
25
|
+
partial = !!match[:partial]
|
26
|
+
|
27
|
+
# Assume templates with different details take same locals
|
28
|
+
details = {}
|
29
|
+
|
30
|
+
@lookup_context.find_all(action, prefix, partial, locals, details)
|
31
|
+
else
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -2,8 +2,6 @@ require "action_view"
|
|
2
2
|
|
3
3
|
module ActionviewPrecompiler
|
4
4
|
class TemplateParser
|
5
|
-
include ASTParser
|
6
|
-
|
7
5
|
attr_reader :filename, :basename, :handler
|
8
6
|
|
9
7
|
class FakeTemplate
|
@@ -24,24 +22,18 @@ module ActionviewPrecompiler
|
|
24
22
|
@filename = filename
|
25
23
|
@basename = File.basename(filename)
|
26
24
|
handler_ext = @basename.split(".").last
|
27
|
-
@handler =
|
28
|
-
@is_partial = !!@basename.start_with?("_")
|
29
|
-
end
|
30
|
-
|
31
|
-
def partial?
|
32
|
-
@is_partial
|
25
|
+
@handler = HANDLERS_FOR_EXTENSION[handler_ext]
|
33
26
|
end
|
34
27
|
|
35
28
|
def render_calls
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@handler.call(FakeTemplate.new, File.read(@filename))
|
29
|
+
src = File.read(@filename)
|
30
|
+
if src.include?("render")
|
31
|
+
compiled_source = @handler.call(FakeTemplate.new, File.read(@filename))
|
32
|
+
compiled_source = "def _template; #{compiled_source}; end"
|
33
|
+
RenderParser.new(compiled_source).render_calls
|
34
|
+
else
|
35
|
+
[]
|
36
|
+
end
|
45
37
|
end
|
46
38
|
end
|
47
39
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "actionview_precompiler/template_file"
|
2
|
+
|
3
|
+
module ActionviewPrecompiler
|
4
|
+
class TemplateScanner
|
5
|
+
attr_reader :view_dir
|
6
|
+
|
7
|
+
def initialize(view_dir)
|
8
|
+
@view_dir = view_dir
|
9
|
+
end
|
10
|
+
|
11
|
+
def template_renders
|
12
|
+
template_renders = []
|
13
|
+
|
14
|
+
each_template do |template|
|
15
|
+
parser = TemplateParser.new(template.fullpath)
|
16
|
+
parser.render_calls.each do |render_call|
|
17
|
+
virtual_path = render_call.virtual_path
|
18
|
+
unless virtual_path.include?("/")
|
19
|
+
# Not necessarily true, since the perfix is based on the current
|
20
|
+
# controller, but is a safe bet most of the time.
|
21
|
+
virtual_path = "#{template.prefix}/#{virtual_path}"
|
22
|
+
end
|
23
|
+
|
24
|
+
locals = render_call.locals_keys.map(&:to_s).sort
|
25
|
+
|
26
|
+
template_renders << [virtual_path, locals]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
template_renders.uniq
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def each_template
|
36
|
+
Dir["**/*", base: view_dir].sort.map do |file|
|
37
|
+
fullpath = File.expand_path(file, view_dir)
|
38
|
+
next if File.directory?(fullpath)
|
39
|
+
|
40
|
+
yield TemplateFile.new(fullpath, file)
|
41
|
+
end.compact
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,33 +1,47 @@
|
|
1
|
+
require "action_controller"
|
2
|
+
require "action_view"
|
3
|
+
|
1
4
|
require "actionview_precompiler/version"
|
2
5
|
require "actionview_precompiler/ast_parser"
|
3
6
|
require "actionview_precompiler/template_parser"
|
4
7
|
require "actionview_precompiler/render_parser"
|
8
|
+
require "actionview_precompiler/controller_parser"
|
9
|
+
require "actionview_precompiler/helper_parser"
|
5
10
|
require "actionview_precompiler/precompiler"
|
6
11
|
require "actionview_precompiler/parsed_filename"
|
7
12
|
|
8
13
|
module ActionviewPrecompiler
|
9
14
|
class Error < StandardError; end
|
10
15
|
|
16
|
+
# Allow overriding from ActionView default handlers if necessary
|
17
|
+
HANDLERS_FOR_EXTENSION = Hash.new do |h, ext|
|
18
|
+
h[ext] = ActionView::Template.handler_for_extension(ext)
|
19
|
+
end
|
20
|
+
|
11
21
|
def self.precompile(verbose: false)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
templates = lookup_context.find_all(*args)
|
22
|
-
templates.each do |template|
|
23
|
-
puts "precompiling: #{template.inspect}" if verbose
|
24
|
-
count += 1
|
25
|
-
template.send(:compile!, mod)
|
22
|
+
precompiler = Precompiler.new(verbose: verbose)
|
23
|
+
|
24
|
+
if block_given?
|
25
|
+
# Custom configuration
|
26
|
+
yield precompiler
|
27
|
+
else
|
28
|
+
# Scan view dirs
|
29
|
+
ActionController::Base.view_paths.each do |view_path|
|
30
|
+
precompiler.scan_view_dir view_path.path
|
26
31
|
end
|
27
|
-
end
|
28
32
|
|
29
|
-
|
30
|
-
|
33
|
+
# If we have an application, scan controllers
|
34
|
+
if Rails.respond_to?(:application)
|
35
|
+
Rails.application.paths["app/controllers"].each do |path|
|
36
|
+
precompiler.scan_controller_dir path.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
Rails.application.paths["app/helpers"].each do |path|
|
40
|
+
precompiler.scan_helper_dir path.to_s
|
41
|
+
end
|
42
|
+
end
|
31
43
|
end
|
44
|
+
|
45
|
+
precompiler.run
|
32
46
|
end
|
33
47
|
end
|