tilt 2.1.0 → 2.3.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/COPYING +1 -0
- data/bin/tilt +2 -120
- data/lib/tilt/_emacs_org.rb +2 -0
- data/lib/tilt/_handlebars.rb +2 -0
- data/lib/tilt/_jbuilder.rb +2 -0
- data/lib/tilt/_org.rb +2 -0
- data/lib/tilt/asciidoc.rb +11 -23
- data/lib/tilt/babel.rb +5 -13
- data/lib/tilt/builder.rb +18 -13
- data/lib/tilt/cli.rb +134 -0
- data/lib/tilt/coffee.rb +12 -31
- data/lib/tilt/commonmarker.rb +47 -81
- data/lib/tilt/creole.rb +9 -20
- data/lib/tilt/csv.rb +5 -4
- data/lib/tilt/erb.rb +9 -17
- data/lib/tilt/erubi.rb +7 -6
- data/lib/tilt/erubis.rb +9 -6
- data/lib/tilt/etanni.rb +3 -2
- data/lib/tilt/haml.rb +12 -9
- data/lib/tilt/kramdown.rb +8 -20
- data/lib/tilt/liquid.rb +10 -14
- data/lib/tilt/livescript.rb +8 -20
- data/lib/tilt/mapping.rb +180 -104
- data/lib/tilt/markaby.rb +5 -7
- data/lib/tilt/maruku.rb +5 -19
- data/lib/tilt/nokogiri.rb +11 -10
- data/lib/tilt/pandoc.rb +33 -51
- data/lib/tilt/pipeline.rb +1 -0
- data/lib/tilt/plain.rb +4 -15
- data/lib/tilt/prawn.rb +10 -25
- data/lib/tilt/radius.rb +15 -22
- data/lib/tilt/rdiscount.rb +17 -33
- data/lib/tilt/rdoc.rb +14 -35
- data/lib/tilt/redcarpet.rb +20 -75
- data/lib/tilt/redcloth.rb +9 -19
- data/lib/tilt/rst-pandoc.rb +6 -19
- data/lib/tilt/sass.rb +34 -43
- data/lib/tilt/slim.rb +5 -0
- data/lib/tilt/string.rb +9 -3
- data/lib/tilt/template.rb +151 -61
- data/lib/tilt/typescript.rb +11 -18
- data/lib/tilt/wikicloth.rb +7 -19
- data/lib/tilt/yajl.rb +5 -11
- data/lib/tilt.rb +56 -40
- metadata +10 -7
- data/lib/tilt/bluecloth.rb +0 -26
- data/lib/tilt/less.rb +0 -32
- data/lib/tilt/sigil.rb +0 -36
data/lib/tilt/erb.rb
CHANGED
@@ -1,38 +1,30 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'erb'
|
3
4
|
|
4
5
|
module Tilt
|
5
6
|
# ERB template implementation. See:
|
6
7
|
# http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html
|
7
8
|
class ERBTemplate < Template
|
8
|
-
@@default_output_variable = '_erbout'
|
9
|
-
|
10
9
|
SUPPORTS_KVARGS = ::ERB.instance_method(:initialize).parameters.assoc(:key) rescue false
|
11
10
|
|
12
|
-
def self.default_output_variable
|
13
|
-
@@default_output_variable
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.default_output_variable=(name)
|
17
|
-
warn "#{self}.default_output_variable= has been replaced with the :outvar-option"
|
18
|
-
@@default_output_variable = name
|
19
|
-
end
|
20
|
-
|
21
11
|
def prepare
|
22
12
|
@freeze_string_literals = !!@options[:freeze]
|
23
|
-
@outvar = options[:outvar] ||
|
24
|
-
trim = case options[:trim]
|
13
|
+
@outvar = @options[:outvar] || '_erbout'
|
14
|
+
trim = case @options[:trim]
|
25
15
|
when false
|
26
16
|
nil
|
27
17
|
when nil, true
|
28
18
|
'<>'
|
29
19
|
else
|
30
|
-
options[:trim]
|
20
|
+
@options[:trim]
|
31
21
|
end
|
32
22
|
@engine = if SUPPORTS_KVARGS
|
33
|
-
::ERB.new(data, trim_mode: trim, eoutvar: @outvar)
|
23
|
+
::ERB.new(@data, trim_mode: trim, eoutvar: @outvar)
|
24
|
+
# :nocov:
|
34
25
|
else
|
35
|
-
::ERB.new(data, options[:safe], trim, @outvar)
|
26
|
+
::ERB.new(@data, options[:safe], trim, @outvar)
|
27
|
+
# :nocov:
|
36
28
|
end
|
37
29
|
end
|
38
30
|
|
data/lib/tilt/erubi.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'erubi'
|
3
4
|
|
4
5
|
module Tilt
|
@@ -12,7 +13,9 @@ module Tilt
|
|
12
13
|
# instead of the default (which is ::Erubi::Engine).
|
13
14
|
class ErubiTemplate < Template
|
14
15
|
def prepare
|
15
|
-
@options
|
16
|
+
@options[:preamble] = false
|
17
|
+
@options[:postamble] = false
|
18
|
+
@options[:ensure] = true
|
16
19
|
|
17
20
|
engine_class = @options[:engine_class] || Erubi::Engine
|
18
21
|
|
@@ -34,11 +37,9 @@ module Tilt
|
|
34
37
|
@options[:freeze_template_literals] = false
|
35
38
|
end
|
36
39
|
|
37
|
-
@engine = engine_class.new(data, @options)
|
40
|
+
@engine = engine_class.new(@data, @options)
|
38
41
|
@outvar = @engine.bufvar
|
39
|
-
|
40
|
-
# Remove dup after tilt supports frozen source.
|
41
|
-
@src = @engine.src.dup
|
42
|
+
@src = @engine.src
|
42
43
|
|
43
44
|
@engine
|
44
45
|
end
|
data/lib/tilt/erubis.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'erb'
|
2
3
|
require 'erubis'
|
3
4
|
|
4
5
|
module Tilt
|
@@ -17,11 +18,13 @@ module Tilt
|
|
17
18
|
class ErubisTemplate < ERBTemplate
|
18
19
|
def prepare
|
19
20
|
@freeze_string_literals = !!@options.delete(:freeze)
|
20
|
-
@outvar = options.delete(:outvar) ||
|
21
|
-
@options
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
@outvar = @options.delete(:outvar) || '_erbout'
|
22
|
+
@options[:preamble] = false
|
23
|
+
@options[:postamble] = false
|
24
|
+
@options[:bufvar] = @outvar
|
25
|
+
engine_class = @options.delete(:engine_class)
|
26
|
+
engine_class = ::Erubis::EscapedEruby if @options.delete(:escape_html)
|
27
|
+
@engine = (engine_class || ::Erubis::Eruby).new(@data, @options)
|
25
28
|
end
|
26
29
|
|
27
30
|
def precompiled_preamble(locals)
|
data/lib/tilt/etanni.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
|
3
4
|
module Tilt
|
4
5
|
class EtanniTemplate < Template
|
@@ -9,7 +10,7 @@ module Tilt
|
|
9
10
|
stop = "\n#{separator}\n"
|
10
11
|
replacement = "#{stop}\\1#{start}"
|
11
12
|
|
12
|
-
temp = data.strip
|
13
|
+
temp = @data.strip
|
13
14
|
temp.gsub!(/<\?r\s+(.*?)\s+\?>/m, replacement)
|
14
15
|
|
15
16
|
@code = "_out_ = [<<#{separator}.chomp!]\n#{temp}#{stop}_out_.join"
|
data/lib/tilt/haml.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'haml'
|
3
4
|
|
4
5
|
module Tilt
|
@@ -14,13 +15,14 @@ module Tilt
|
|
14
15
|
# `Gem::Version.correct?` may return false because of Haml::VERSION #=> "3.1.8 (Separated Sally)". After Haml 4, it's always correct.
|
15
16
|
if Gem::Version.correct?(Haml::VERSION) && Gem::Version.new(Haml::VERSION) >= Gem::Version.new('5.0.0.beta.2')
|
16
17
|
def prepare
|
17
|
-
options =
|
18
|
-
|
19
|
-
|
20
|
-
options[:
|
18
|
+
@options[:filename] = eval_file
|
19
|
+
@options[:line] = @line
|
20
|
+
if @options.include?(:outvar)
|
21
|
+
@options[:buffer] = @options.delete(:outvar)
|
22
|
+
@options[:save_buffer] = true
|
21
23
|
end
|
22
|
-
@engine = ::Haml::TempleEngine.new(options)
|
23
|
-
@engine.compile(data)
|
24
|
+
@engine = ::Haml::TempleEngine.new(@options)
|
25
|
+
@engine.compile(@data)
|
24
26
|
end
|
25
27
|
|
26
28
|
def evaluate(scope, locals, &block)
|
@@ -39,8 +41,9 @@ module Tilt
|
|
39
41
|
end
|
40
42
|
else # Following definitions are for Haml <= 4 and deprecated.
|
41
43
|
def prepare
|
42
|
-
|
43
|
-
@
|
44
|
+
@options[:filename] = eval_file
|
45
|
+
@options[:line] = @line
|
46
|
+
@engine = ::Haml::Engine.new(@data, @options)
|
44
47
|
end
|
45
48
|
|
46
49
|
def evaluate(scope, locals, &block)
|
data/lib/tilt/kramdown.rb
CHANGED
@@ -1,25 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'kramdown'
|
3
4
|
|
4
|
-
|
5
|
-
# Kramdown Markdown implementation. See:
|
6
|
-
# http://kramdown.rubyforge.org/
|
7
|
-
class KramdownTemplate < Template
|
8
|
-
DUMB_QUOTES = [39, 39, 34, 34]
|
5
|
+
dumb_quotes = [39, 39, 34, 34].freeze
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
7
|
+
# Kramdown Markdown implementation. See: https://kramdown.gettalong.org/
|
8
|
+
Tilt::KramdownTemplate = Tilt::StaticTemplate.subclass do
|
9
|
+
# dup as Krawmdown modifies the passed option with map!
|
10
|
+
@options[:smart_quotes] = dumb_quotes.dup unless @options[:smartypants]
|
15
11
|
|
16
|
-
|
17
|
-
@output ||= @engine.to_html
|
18
|
-
end
|
19
|
-
|
20
|
-
def allows_script?
|
21
|
-
false
|
22
|
-
end
|
23
|
-
end
|
12
|
+
Kramdown::Document.new(@data, @options).to_html
|
24
13
|
end
|
25
|
-
|
data/lib/tilt/liquid.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'liquid'
|
3
4
|
|
4
5
|
module Tilt
|
5
6
|
# Liquid template implementation. See:
|
6
7
|
# http://liquidmarkup.org/
|
7
8
|
#
|
8
|
-
# Liquid is designed to be a *safe* template system and
|
9
|
+
# Liquid is designed to be a *safe* template system and therefore
|
9
10
|
# does not provide direct access to execuatable scopes. In order to
|
10
11
|
# support a +scope+, the +scope+ must be able to represent itself
|
11
12
|
# as a hash by responding to #to_h. If the +scope+ does not respond
|
@@ -17,16 +18,17 @@ module Tilt
|
|
17
18
|
# time when using this template engine.
|
18
19
|
class LiquidTemplate < Template
|
19
20
|
def prepare
|
20
|
-
@
|
21
|
+
@options[:line_numbers] = true unless @options.has_key?(:line_numbers)
|
22
|
+
@engine = ::Liquid::Template.parse(@data, @options)
|
21
23
|
end
|
22
24
|
|
23
|
-
def evaluate(scope,
|
24
|
-
locals =
|
25
|
+
def evaluate(scope, locs)
|
26
|
+
locals = {}
|
25
27
|
if scope.respond_to?(:to_h)
|
26
|
-
scope
|
27
|
-
locals = scope.merge(locals)
|
28
|
+
scope.to_h.each{|k, v| locals[k.to_s] = v}
|
28
29
|
end
|
29
|
-
locals[
|
30
|
+
locs.each{|k, v| locals[k.to_s] = v}
|
31
|
+
locals['yield'] = block_given? ? yield : ''
|
30
32
|
locals['content'] = locals['yield']
|
31
33
|
@engine.render(locals)
|
32
34
|
end
|
@@ -34,11 +36,5 @@ module Tilt
|
|
34
36
|
def allows_script?
|
35
37
|
false
|
36
38
|
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def liquid_options
|
41
|
-
{ line_numbers: true }.merge options
|
42
|
-
end
|
43
39
|
end
|
44
40
|
end
|
data/lib/tilt/livescript.rb
CHANGED
@@ -1,23 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'livescript'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.default_mime_type = 'application/javascript'
|
11
|
-
|
12
|
-
def prepare
|
13
|
-
end
|
14
|
-
|
15
|
-
def evaluate(scope, locals, &block)
|
16
|
-
@output ||= LiveScript.compile(data, options)
|
17
|
-
end
|
18
|
-
|
19
|
-
def allows_script?
|
20
|
-
false
|
21
|
-
end
|
22
|
-
end
|
5
|
+
# LiveScript template implementation. See:
|
6
|
+
# http://livescript.net/
|
7
|
+
#
|
8
|
+
# LiveScript templates do not support object scopes, locals, or yield.
|
9
|
+
Tilt::LiveScriptTemplate = Tilt::StaticTemplate.subclass(mime_type: 'application/javascript') do
|
10
|
+
LiveScript.compile(@data, @options)
|
23
11
|
end
|
data/lib/tilt/mapping.rb
CHANGED
@@ -1,7 +1,81 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require_relative 'pipeline'
|
3
3
|
|
4
4
|
module Tilt
|
5
|
+
# Private internal base class for both Mapping and FinalizedMapping, for the shared methods.
|
6
|
+
class BaseMapping
|
7
|
+
# Instantiates a new template class based on the file.
|
8
|
+
#
|
9
|
+
# @raise [RuntimeError] if there is no template class registered for the
|
10
|
+
# file name.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# mapping.new('index.mt') # => instance of MyEngine::Template
|
14
|
+
#
|
15
|
+
# @see Tilt::Template.new
|
16
|
+
def new(file, line=nil, options={}, &block)
|
17
|
+
if template_class = self[file]
|
18
|
+
template_class.new(file, line, options, &block)
|
19
|
+
else
|
20
|
+
fail "No template engine registered for #{File.basename(file)}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Looks up a template class based on file name and/or extension.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# mapping['views/hello.erb'] # => Tilt::ERBTemplate
|
28
|
+
# mapping['hello.erb'] # => Tilt::ERBTemplate
|
29
|
+
# mapping['erb'] # => Tilt::ERBTemplate
|
30
|
+
#
|
31
|
+
# @return [template class]
|
32
|
+
def [](file)
|
33
|
+
_, ext = split(file)
|
34
|
+
ext && lookup(ext)
|
35
|
+
end
|
36
|
+
|
37
|
+
alias template_for []
|
38
|
+
|
39
|
+
# Looks up a list of template classes based on file name. If the file name
|
40
|
+
# has multiple extensions, it will return all template classes matching the
|
41
|
+
# extensions from the end.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# mapping.templates_for('views/index.haml.erb')
|
45
|
+
# # => [Tilt::ERBTemplate, Tilt::HamlTemplate]
|
46
|
+
#
|
47
|
+
# @return [Array<template class>]
|
48
|
+
def templates_for(file)
|
49
|
+
templates = []
|
50
|
+
|
51
|
+
while true
|
52
|
+
prefix, ext = split(file)
|
53
|
+
break unless ext
|
54
|
+
templates << lookup(ext)
|
55
|
+
file = prefix
|
56
|
+
end
|
57
|
+
|
58
|
+
templates
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def split(file)
|
64
|
+
pattern = file.to_s.downcase
|
65
|
+
full_pattern = pattern.dup
|
66
|
+
|
67
|
+
until registered?(pattern)
|
68
|
+
return if pattern.empty?
|
69
|
+
pattern = File.basename(pattern)
|
70
|
+
pattern.sub!(/\A[^.]*\.?/, '')
|
71
|
+
end
|
72
|
+
|
73
|
+
prefix_size = full_pattern.size - pattern.size
|
74
|
+
[full_pattern[0,prefix_size-1], pattern]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
private_constant :BaseMapping
|
78
|
+
|
5
79
|
# Tilt::Mapping associates file extensions with template implementations.
|
6
80
|
#
|
7
81
|
# mapping = Tilt::Mapping.new
|
@@ -39,16 +113,18 @@ module Tilt
|
|
39
113
|
# the exception of the first, since that was the most preferred one.
|
40
114
|
#
|
41
115
|
# mapping = Tilt::Mapping.new
|
42
|
-
# mapping.register_lazy('
|
116
|
+
# mapping.register_lazy('Maruku::Template', 'maruku/template', 'md')
|
43
117
|
# mapping.register_lazy('RDiscount::Template', 'rdiscount/template', 'md')
|
44
118
|
# mapping['index.md']
|
45
119
|
# # => RDiscount::Template
|
46
120
|
#
|
47
121
|
# In the previous example we say that RDiscount has a *higher priority* than
|
48
|
-
#
|
49
|
-
# back to `require "
|
122
|
+
# Maruku. Tilt will first try to `require "rdiscount/template"`, falling
|
123
|
+
# back to `require "maruku/template"`. If none of these are successful,
|
50
124
|
# the first error will be raised.
|
51
|
-
class Mapping
|
125
|
+
class Mapping < BaseMapping
|
126
|
+
LOCK = Mutex.new
|
127
|
+
|
52
128
|
# @private
|
53
129
|
attr_reader :lazy_map, :template_map
|
54
130
|
|
@@ -59,8 +135,26 @@ module Tilt
|
|
59
135
|
|
60
136
|
# @private
|
61
137
|
def initialize_copy(other)
|
62
|
-
|
63
|
-
|
138
|
+
LOCK.synchronize do
|
139
|
+
@template_map = other.template_map.dup
|
140
|
+
@lazy_map = other.lazy_map.dup
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return a finalized mapping. A finalized mapping will only include
|
145
|
+
# support for template libraries already loaded, and will not
|
146
|
+
# allow registering new template libraries or lazy loading template
|
147
|
+
# libraries not yet loaded. Finalized mappings improve performance
|
148
|
+
# by not requiring synchronization and ensure that the mapping will
|
149
|
+
# not attempt to load additional files (useful when restricting
|
150
|
+
# file system access after template libraries in use are loaded).
|
151
|
+
def finalized
|
152
|
+
LOCK.synchronize{@lazy_map.dup}.each do |pattern, classes|
|
153
|
+
register_defined_classes(LOCK.synchronize{classes.map(&:first)}, pattern)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Check if a template class is already present
|
157
|
+
FinalizedMapping.new(LOCK.synchronize{@template_map.dup}.freeze)
|
64
158
|
end
|
65
159
|
|
66
160
|
# Registers a lazy template implementation by file extension. You
|
@@ -86,8 +180,9 @@ module Tilt
|
|
86
180
|
class_name = "Tilt::#{class_name}"
|
87
181
|
end
|
88
182
|
|
183
|
+
v = [class_name, file].freeze
|
89
184
|
extensions.each do |ext|
|
90
|
-
@lazy_map[ext].unshift(
|
185
|
+
LOCK.synchronize{@lazy_map[ext].unshift(v)}
|
91
186
|
end
|
92
187
|
end
|
93
188
|
|
@@ -109,7 +204,10 @@ module Tilt
|
|
109
204
|
end
|
110
205
|
|
111
206
|
extensions.each do |ext|
|
112
|
-
|
207
|
+
ext = ext.to_s
|
208
|
+
LOCK.synchronize do
|
209
|
+
@template_map[ext] = template_class
|
210
|
+
end
|
113
211
|
end
|
114
212
|
end
|
115
213
|
|
@@ -137,9 +235,9 @@ module Tilt
|
|
137
235
|
# mapping.register_pipeline('scss.erb', 'erb'=>{:outvar=>'@foo'})
|
138
236
|
# mapping.register_pipeline('scsserb', :extra_exts => 'scss.erb',
|
139
237
|
# :templates=>['erb', 'scss'])
|
140
|
-
def register_pipeline(ext, options=
|
238
|
+
def register_pipeline(ext, options=EMPTY_HASH)
|
141
239
|
templates = options[:templates] || ext.split('.').reverse
|
142
|
-
templates = templates.map{|t| [self[t], options[t] ||
|
240
|
+
templates = templates.map{|t| [self[t], options[t] || EMPTY_HASH]}
|
143
241
|
|
144
242
|
klass = Class.new(Pipeline)
|
145
243
|
klass.send(:const_set, :TEMPLATES, templates)
|
@@ -162,8 +260,10 @@ module Tilt
|
|
162
260
|
def unregister(*extensions)
|
163
261
|
extensions.each do |ext|
|
164
262
|
ext = ext.to_s
|
165
|
-
|
166
|
-
|
263
|
+
LOCK.synchronize do
|
264
|
+
@template_map.delete(ext)
|
265
|
+
@lazy_map.delete(ext)
|
266
|
+
end
|
167
267
|
end
|
168
268
|
|
169
269
|
nil
|
@@ -178,119 +278,52 @@ module Tilt
|
|
178
278
|
# mapping.registered?('erb') # => true
|
179
279
|
# mapping.registered?('nope') # => false
|
180
280
|
def registered?(ext)
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
# Instantiates a new template class based on the file.
|
185
|
-
#
|
186
|
-
# @raise [RuntimeError] if there is no template class registered for the
|
187
|
-
# file name.
|
188
|
-
#
|
189
|
-
# @example
|
190
|
-
# mapping.new('index.mt') # => instance of MyEngine::Template
|
191
|
-
#
|
192
|
-
# @see Tilt::Template.new
|
193
|
-
def new(file, line=nil, options={}, &block)
|
194
|
-
if template_class = self[file]
|
195
|
-
template_class.new(file, line, options, &block)
|
196
|
-
else
|
197
|
-
fail "No template engine registered for #{File.basename(file)}"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# Looks up a template class based on file name and/or extension.
|
202
|
-
#
|
203
|
-
# @example
|
204
|
-
# mapping['views/hello.erb'] # => Tilt::ERBTemplate
|
205
|
-
# mapping['hello.erb'] # => Tilt::ERBTemplate
|
206
|
-
# mapping['erb'] # => Tilt::ERBTemplate
|
207
|
-
#
|
208
|
-
# @return [template class]
|
209
|
-
def [](file)
|
210
|
-
_, ext = split(file)
|
211
|
-
ext && lookup(ext)
|
212
|
-
end
|
213
|
-
|
214
|
-
alias template_for []
|
215
|
-
|
216
|
-
# Looks up a list of template classes based on file name. If the file name
|
217
|
-
# has multiple extensions, it will return all template classes matching the
|
218
|
-
# extensions from the end.
|
219
|
-
#
|
220
|
-
# @example
|
221
|
-
# mapping.templates_for('views/index.haml.erb')
|
222
|
-
# # => [Tilt::ERBTemplate, Tilt::HamlTemplate]
|
223
|
-
#
|
224
|
-
# @return [Array<template class>]
|
225
|
-
def templates_for(file)
|
226
|
-
templates = []
|
227
|
-
|
228
|
-
while true
|
229
|
-
prefix, ext = split(file)
|
230
|
-
break unless ext
|
231
|
-
templates << lookup(ext)
|
232
|
-
file = prefix
|
233
|
-
end
|
234
|
-
|
235
|
-
templates
|
281
|
+
ext_downcase = ext.downcase
|
282
|
+
LOCK.synchronize{@template_map.has_key?(ext_downcase)} or lazy?(ext)
|
236
283
|
end
|
237
284
|
|
238
285
|
# Finds the extensions the template class has been registered under.
|
239
286
|
# @param [template class] template_class
|
240
287
|
def extensions_for(template_class)
|
241
288
|
res = []
|
242
|
-
template_map.each do |ext, klass|
|
289
|
+
LOCK.synchronize{@template_map.to_a}.each do |ext, klass|
|
243
290
|
res << ext if template_class == klass
|
244
291
|
end
|
245
|
-
lazy_map.each do |ext, choices|
|
246
|
-
res << ext if choices.any? { |klass, file| template_class.to_s == klass }
|
292
|
+
LOCK.synchronize{@lazy_map.to_a}.each do |ext, choices|
|
293
|
+
res << ext if LOCK.synchronize{choices.dup}.any? { |klass, file| template_class.to_s == klass }
|
247
294
|
end
|
248
|
-
res.uniq
|
295
|
+
res.uniq!
|
296
|
+
res
|
249
297
|
end
|
250
298
|
|
251
299
|
private
|
252
300
|
|
253
301
|
def lazy?(ext)
|
254
302
|
ext = ext.downcase
|
255
|
-
@lazy_map.has_key?(ext) && !@lazy_map[ext].empty?
|
256
|
-
end
|
257
|
-
|
258
|
-
def split(file)
|
259
|
-
pattern = file.to_s.downcase
|
260
|
-
full_pattern = pattern.dup
|
261
|
-
|
262
|
-
until registered?(pattern)
|
263
|
-
return if pattern.empty?
|
264
|
-
pattern = File.basename(pattern)
|
265
|
-
pattern.sub!(/^[^.]*\.?/, '')
|
266
|
-
end
|
267
|
-
|
268
|
-
prefix_size = full_pattern.size - pattern.size
|
269
|
-
[full_pattern[0,prefix_size-1], pattern]
|
303
|
+
LOCK.synchronize{@lazy_map.has_key?(ext) && !@lazy_map[ext].empty?}
|
270
304
|
end
|
271
305
|
|
272
306
|
def lookup(ext)
|
273
|
-
@template_map[ext] || lazy_load(ext)
|
307
|
+
LOCK.synchronize{@template_map[ext]} || lazy_load(ext)
|
274
308
|
end
|
275
309
|
|
276
|
-
|
277
|
-
|
278
|
-
def lazy_load(pattern)
|
279
|
-
return unless @lazy_map.has_key?(pattern)
|
280
|
-
|
281
|
-
LOCK.enter
|
282
|
-
entered = true
|
283
|
-
|
284
|
-
choices = @lazy_map[pattern]
|
285
|
-
|
286
|
-
# Check if a template class is already present
|
287
|
-
choices.each do |class_name, file|
|
310
|
+
def register_defined_classes(class_names, pattern)
|
311
|
+
class_names.each do |class_name|
|
288
312
|
template_class = constant_defined?(class_name)
|
289
313
|
if template_class
|
290
314
|
register(template_class, pattern)
|
291
|
-
|
315
|
+
yield template_class if block_given?
|
292
316
|
end
|
293
317
|
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def lazy_load(pattern)
|
321
|
+
choices = LOCK.synchronize{@lazy_map[pattern].dup}
|
322
|
+
|
323
|
+
# Check if a template class is already present
|
324
|
+
register_defined_classes(choices.map(&:first), pattern) do |template_class|
|
325
|
+
return template_class
|
326
|
+
end
|
294
327
|
|
295
328
|
first_failure = nil
|
296
329
|
|
@@ -309,9 +342,7 @@ module Tilt
|
|
309
342
|
end
|
310
343
|
end
|
311
344
|
|
312
|
-
raise first_failure
|
313
|
-
ensure
|
314
|
-
LOCK.exit if entered
|
345
|
+
raise first_failure
|
315
346
|
end
|
316
347
|
|
317
348
|
# The proper behavior (in MRI) for autoload? is to
|
@@ -333,4 +364,49 @@ module Tilt
|
|
333
364
|
end
|
334
365
|
end
|
335
366
|
end
|
367
|
+
|
368
|
+
# Private internal class for finalized mappings, which are frozen and
|
369
|
+
# cannot be modified.
|
370
|
+
class FinalizedMapping < BaseMapping
|
371
|
+
# Set the template map to use. The template map should already
|
372
|
+
# be frozen, but this is an internal class, so it does not
|
373
|
+
# explicitly check for that.
|
374
|
+
def initialize(template_map)
|
375
|
+
@template_map = template_map
|
376
|
+
freeze
|
377
|
+
end
|
378
|
+
|
379
|
+
# Returns receiver, since instances are always frozen.
|
380
|
+
def dup
|
381
|
+
self
|
382
|
+
end
|
383
|
+
|
384
|
+
# Returns receiver, since instances are always frozen.
|
385
|
+
def clone(freeze: false)
|
386
|
+
self
|
387
|
+
end
|
388
|
+
|
389
|
+
# Return whether the given file extension has been registered.
|
390
|
+
def registered?(ext)
|
391
|
+
@template_map.has_key?(ext.downcase)
|
392
|
+
end
|
393
|
+
|
394
|
+
# Returns an aarry of all extensions the template class will
|
395
|
+
# be used for.
|
396
|
+
def extensions_for(template_class)
|
397
|
+
res = []
|
398
|
+
@template_map.each do |ext, klass|
|
399
|
+
res << ext if template_class == klass
|
400
|
+
end
|
401
|
+
res.uniq!
|
402
|
+
res
|
403
|
+
end
|
404
|
+
|
405
|
+
private
|
406
|
+
|
407
|
+
def lookup(ext)
|
408
|
+
@template_map[ext]
|
409
|
+
end
|
410
|
+
end
|
411
|
+
private_constant :FinalizedMapping
|
336
412
|
end
|
data/lib/tilt/markaby.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'template'
|
2
3
|
require 'markaby'
|
3
4
|
|
4
5
|
module Tilt
|
@@ -15,19 +16,16 @@ module Tilt
|
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
def prepare
|
19
|
-
end
|
20
|
-
|
21
19
|
def evaluate(scope, locals, &block)
|
22
20
|
builder = self.class.builder_class.new({}, scope)
|
23
21
|
builder.locals = locals
|
24
22
|
|
25
|
-
if data.kind_of? Proc
|
26
|
-
(class << builder; self end).send(:define_method, :__run_markaby_tilt__,
|
23
|
+
if @data.kind_of? Proc
|
24
|
+
(class << builder; self end).send(:define_method, :__run_markaby_tilt__, &@data)
|
27
25
|
else
|
28
26
|
builder.instance_eval <<-CODE, __FILE__, __LINE__
|
29
27
|
def __run_markaby_tilt__
|
30
|
-
#{data}
|
28
|
+
#{@data}
|
31
29
|
end
|
32
30
|
CODE
|
33
31
|
end
|