actionview_precompiler 0.2.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|