tilt 1.4.1 → 2.0.11

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +1 -1
  3. data/bin/tilt +18 -8
  4. data/lib/tilt/asciidoc.rb +1 -8
  5. data/lib/tilt/babel.rb +16 -0
  6. data/lib/tilt/bluecloth.rb +24 -0
  7. data/lib/tilt/builder.rb +12 -15
  8. data/lib/tilt/coffee.rb +10 -6
  9. data/lib/tilt/commonmarker.rb +88 -0
  10. data/lib/tilt/creole.rb +25 -0
  11. data/lib/tilt/csv.rb +12 -18
  12. data/lib/tilt/dummy.rb +3 -0
  13. data/lib/tilt/erb.rb +9 -56
  14. data/lib/tilt/erubi.rb +32 -0
  15. data/lib/tilt/erubis.rb +43 -0
  16. data/lib/tilt/haml.rb +66 -44
  17. data/lib/tilt/kramdown.rb +25 -0
  18. data/lib/tilt/less.rb +30 -0
  19. data/lib/tilt/liquid.rb +9 -10
  20. data/lib/tilt/livescript.rb +23 -0
  21. data/lib/tilt/mapping.rb +293 -0
  22. data/lib/tilt/markaby.rb +1 -8
  23. data/lib/tilt/maruku.rb +22 -0
  24. data/lib/tilt/nokogiri.rb +1 -8
  25. data/lib/tilt/pandoc.rb +57 -0
  26. data/lib/tilt/plain.rb +0 -4
  27. data/lib/tilt/prawn.rb +43 -0
  28. data/lib/tilt/radius.rb +1 -8
  29. data/lib/tilt/rdiscount.rb +39 -0
  30. data/lib/tilt/rdoc.rb +3 -10
  31. data/lib/tilt/redcarpet.rb +86 -0
  32. data/lib/tilt/{textile.rb → redcloth.rb} +1 -8
  33. data/lib/tilt/rst-pandoc.rb +23 -0
  34. data/lib/tilt/sass.rb +78 -0
  35. data/lib/tilt/sigil.rb +34 -0
  36. data/lib/tilt/string.rb +1 -1
  37. data/lib/tilt/template.rb +121 -105
  38. data/lib/tilt/typescript.rb +26 -0
  39. data/lib/tilt/wikicloth.rb +22 -0
  40. data/lib/tilt/yajl.rb +1 -8
  41. data/lib/tilt.rb +118 -155
  42. metadata +38 -469
  43. data/CHANGELOG.md +0 -44
  44. data/Gemfile +0 -32
  45. data/HACKING +0 -16
  46. data/README.md +0 -232
  47. data/Rakefile +0 -104
  48. data/TEMPLATES.md +0 -516
  49. data/lib/tilt/css.rb +0 -80
  50. data/lib/tilt/markdown.rb +0 -214
  51. data/lib/tilt/wiki.rb +0 -58
  52. data/test/contest.rb +0 -68
  53. data/test/markaby/locals.mab +0 -1
  54. data/test/markaby/markaby.mab +0 -1
  55. data/test/markaby/markaby_other_static.mab +0 -1
  56. data/test/markaby/render_twice.mab +0 -1
  57. data/test/markaby/scope.mab +0 -1
  58. data/test/markaby/yielding.mab +0 -2
  59. data/test/tilt_asciidoctor_test.rb +0 -44
  60. data/test/tilt_blueclothtemplate_test.rb +0 -45
  61. data/test/tilt_buildertemplate_test.rb +0 -59
  62. data/test/tilt_cache_test.rb +0 -32
  63. data/test/tilt_coffeescripttemplate_test.rb +0 -114
  64. data/test/tilt_compilesite_test.rb +0 -51
  65. data/test/tilt_creoletemplate_test.rb +0 -28
  66. data/test/tilt_csv_test.rb +0 -69
  67. data/test/tilt_erbtemplate_test.rb +0 -239
  68. data/test/tilt_erubistemplate_test.rb +0 -151
  69. data/test/tilt_etannitemplate_test.rb +0 -173
  70. data/test/tilt_fallback_test.rb +0 -122
  71. data/test/tilt_hamltemplate_test.rb +0 -144
  72. data/test/tilt_kramdown_test.rb +0 -42
  73. data/test/tilt_lesstemplate_test.less +0 -1
  74. data/test/tilt_lesstemplate_test.rb +0 -42
  75. data/test/tilt_liquidtemplate_test.rb +0 -78
  76. data/test/tilt_markaby_test.rb +0 -88
  77. data/test/tilt_markdown_test.rb +0 -172
  78. data/test/tilt_marukutemplate_test.rb +0 -48
  79. data/test/tilt_nokogiritemplate_test.rb +0 -87
  80. data/test/tilt_radiustemplate_test.rb +0 -75
  81. data/test/tilt_rdiscounttemplate_test.rb +0 -55
  82. data/test/tilt_rdoctemplate_test.rb +0 -31
  83. data/test/tilt_redcarpettemplate_test.rb +0 -71
  84. data/test/tilt_redclothtemplate_test.rb +0 -36
  85. data/test/tilt_sasstemplate_test.rb +0 -41
  86. data/test/tilt_stringtemplate_test.rb +0 -170
  87. data/test/tilt_template_test.rb +0 -323
  88. data/test/tilt_test.rb +0 -65
  89. data/test/tilt_wikiclothtemplate_test.rb +0 -32
  90. data/test/tilt_yajltemplate_test.rb +0 -101
  91. data/tilt.gemspec +0 -120
data/lib/tilt/template.rb CHANGED
@@ -1,5 +1,19 @@
1
+ require 'thread'
2
+
1
3
  module Tilt
2
- TOPOBJECT = Object.superclass || Object
4
+ # @private
5
+ TOPOBJECT = if RUBY_VERSION >= '2.0'
6
+ # @private
7
+ module CompiledTemplates
8
+ self
9
+ end
10
+ elsif RUBY_VERSION >= '1.9'
11
+ BasicObject
12
+ else
13
+ Object
14
+ end
15
+ # @private
16
+ LOCK = Mutex.new
3
17
 
4
18
  # Base class for template implementations. Subclasses must implement
5
19
  # the #prepare method and one of the #evaluate or #precompiled_template
@@ -19,14 +33,22 @@ module Tilt
19
33
  # interface.
20
34
  attr_reader :options
21
35
 
22
- # Used to determine if this class's initialize_engine method has
23
- # been called yet.
24
- @engine_initialized = false
25
36
  class << self
26
- attr_accessor :engine_initialized
27
- alias engine_initialized? engine_initialized
37
+ # An empty Hash that the template engine can populate with various
38
+ # metadata.
39
+ def metadata
40
+ @metadata ||= {}
41
+ end
42
+
43
+ # @deprecated Use `.metadata[:mime_type]` instead.
44
+ def default_mime_type
45
+ metadata[:mime_type]
46
+ end
28
47
 
29
- attr_accessor :default_mime_type
48
+ # @deprecated Use `.metadata[:mime_type] = val` instead.
49
+ def default_mime_type=(value)
50
+ metadata[:mime_type] = value
51
+ end
30
52
  end
31
53
 
32
54
  # Create a new template with the file, line, and options specified. By
@@ -44,19 +66,14 @@ module Tilt
44
66
  when arg.respond_to?(:to_int) ; @line = arg.to_int
45
67
  when arg.respond_to?(:to_hash) ; @options = arg.to_hash.dup
46
68
  when arg.respond_to?(:path) ; @file = arg.path
47
- else raise TypeError
69
+ when arg.respond_to?(:to_path) ; @file = arg.to_path
70
+ else raise TypeError, "Can't load the template file. Pass a string with a path " +
71
+ "or an object that responds to 'to_str', 'path' or 'to_path'"
48
72
  end
49
73
  end
50
74
 
51
75
  raise ArgumentError, "file or block required" if (@file || block).nil?
52
76
 
53
- # call the initialize_engine method if this is the very first time
54
- # an instance of this class has been created.
55
- if !self.class.engine_initialized?
56
- initialize_engine
57
- self.class.engine_initialized = true
58
- end
59
-
60
77
  # used to hold compiled template methods
61
78
  @compiled_method = {}
62
79
 
@@ -69,7 +86,10 @@ module Tilt
69
86
  @data = @reader.call(self)
70
87
 
71
88
  if @data.respond_to?(:force_encoding)
72
- @data.force_encoding(default_encoding) if default_encoding
89
+ if default_encoding
90
+ @data = @data.dup if @data.frozen?
91
+ @data.force_encoding(default_encoding)
92
+ end
73
93
 
74
94
  if !@data.valid_encoding?
75
95
  raise Encoding::InvalidByteSequenceError, "#{eval_file} is not valid #{@data.encoding}"
@@ -79,28 +99,16 @@ module Tilt
79
99
  prepare
80
100
  end
81
101
 
82
- # The encoding of the source data. Defaults to the
83
- # default_encoding-option if present. You may override this method
84
- # in your template class if you have a better hint of the data's
85
- # encoding.
86
- def default_encoding
87
- @default_encoding
88
- end
89
-
90
- def read_template_file
91
- data = File.open(file, 'rb') { |io| io.read }
92
- if data.respond_to?(:force_encoding)
93
- # Set it to the default external (without verifying)
94
- data.force_encoding(Encoding.default_external) if Encoding.default_external
95
- end
96
- data
97
- end
98
-
99
102
  # Render the template in the given scope with the locals specified. If a
100
103
  # block is given, it is typically available within the template via
101
104
  # +yield+.
102
- def render(scope=Object.new, locals={}, &block)
103
- evaluate scope, locals || {}, &block
105
+ def render(scope=nil, locals={}, &block)
106
+ scope ||= Object.new
107
+ current_template = Thread.current[:tilt_current_template]
108
+ Thread.current[:tilt_current_template] = self
109
+ evaluate(scope, locals || {}, &block)
110
+ ensure
111
+ Thread.current[:tilt_current_template] = current_template
104
112
  end
105
113
 
106
114
  # The basename of the template file.
@@ -118,30 +126,26 @@ module Tilt
118
126
  file || '(__TEMPLATE__)'
119
127
  end
120
128
 
121
- # Whether or not this template engine allows executing Ruby script
122
- # within the template. If this is false, +scope+ and +locals+ will
123
- # generally not be used, nor will the provided block be avaiable
124
- # via +yield+.
125
- # This should be overridden by template subclasses.
126
- def allows_script?
127
- true
129
+ # An empty Hash that the template engine can populate with various
130
+ # metadata.
131
+ def metadata
132
+ if respond_to?(:allows_script?)
133
+ self.class.metadata.merge(:allows_script => allows_script?)
134
+ else
135
+ self.class.metadata
136
+ end
128
137
  end
129
138
 
130
- protected
131
- # Called once and only once for each template subclass the first time
132
- # the template class is initialized. This should be used to require the
133
- # underlying template library and perform any initial setup.
134
- def initialize_engine
135
- end
139
+ protected
136
140
 
137
- # Like Kernel#require but issues a warning urging a manual require when
138
- # running under a threaded environment.
139
- def require_template_library(name)
140
- if Thread.list.size > 1
141
- warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " +
142
- "explicit require '#{name}' suggested."
143
- end
144
- require name
141
+ # @!group For template implementations
142
+
143
+ # The encoding of the source data. Defaults to the
144
+ # default_encoding-option if present. You may override this method
145
+ # in your template class if you have a better hint of the data's
146
+ # encoding.
147
+ def default_encoding
148
+ @default_encoding
145
149
  end
146
150
 
147
151
  # Do whatever preparation is necessary to setup the underlying template
@@ -150,15 +154,11 @@ module Tilt
150
154
  #
151
155
  # Subclasses must provide an implementation of this method.
152
156
  def prepare
153
- if respond_to?(:compile!)
154
- # backward compat with tilt < 0.6; just in case
155
- warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.'
156
- compile!
157
- else
158
- raise NotImplementedError
159
- end
157
+ raise NotImplementedError
160
158
  end
161
159
 
160
+ CLASS_METHOD = Kernel.instance_method(:class)
161
+
162
162
  # Execute the compiled template and return the result string. Template
163
163
  # evaluation is guaranteed to be performed in the scope object with the
164
164
  # locals specified and with support for yielding to the block.
@@ -166,7 +166,18 @@ module Tilt
166
166
  # This method is only used by source generating templates. Subclasses that
167
167
  # override render() may not support all features.
168
168
  def evaluate(scope, locals, &block)
169
- method = compiled_method(locals.keys)
169
+ locals_keys = locals.keys
170
+ locals_keys.sort!{|x, y| x.to_s <=> y.to_s}
171
+ case scope
172
+ when Object
173
+ method = compiled_method(locals_keys, Module === scope ? scope : scope.class)
174
+ else
175
+ if RUBY_VERSION >= '2'
176
+ method = compiled_method(locals_keys, CLASS_METHOD.bind(scope).call)
177
+ else
178
+ method = compiled_method(locals_keys, Object)
179
+ end
180
+ end
170
181
  method.bind(scope).call(locals, &block)
171
182
  end
172
183
 
@@ -179,11 +190,11 @@ module Tilt
179
190
  # control over source generation or want to adjust the default line
180
191
  # offset. In most cases, overriding the #precompiled_template method is
181
192
  # easier and more appropriate.
182
- def precompiled(locals)
183
- preamble = precompiled_preamble(locals)
184
- template = precompiled_template(locals)
185
- postamble = precompiled_postamble(locals)
186
- source = ''
193
+ def precompiled(local_keys)
194
+ preamble = precompiled_preamble(local_keys)
195
+ template = precompiled_template(local_keys)
196
+ postamble = precompiled_postamble(local_keys)
197
+ source = String.new
187
198
 
188
199
  # Ensure that our generated source code has the same encoding as the
189
200
  # the source code generated by the template engine.
@@ -194,10 +205,7 @@ module Tilt
194
205
  template.force_encoding(template_encoding)
195
206
  end
196
207
 
197
- # https://github.com/rtomayko/tilt/issues/193
198
- warn "precompiled_preamble should return String (not Array)" if preamble.is_a?(Array)
199
- warn "precompiled_postamble should return String (not Array)" if postamble.is_a?(Array)
200
- source << [preamble, template, postamble].join("\n")
208
+ source << preamble << "\n" << template << "\n" << postamble
201
209
 
202
210
  [source, preamble.count("\n")+1]
203
211
  end
@@ -208,17 +216,40 @@ module Tilt
208
216
  # the base Template guarantees correct file/line handling, locals
209
217
  # support, custom scopes, proper encoding, and support for template
210
218
  # compilation.
211
- def precompiled_template(locals)
219
+ def precompiled_template(local_keys)
212
220
  raise NotImplementedError
213
221
  end
214
222
 
215
- # Generates preamble code for initializing template state, and performing
216
- # locals assignment. The default implementation performs locals
217
- # assignment only. Lines included in the preamble are subtracted from the
218
- # source line offset, so adding code to the preamble does not effect line
219
- # reporting in Kernel::caller and backtraces.
220
- def precompiled_preamble(locals)
221
- locals.map do |k,v|
223
+ def precompiled_preamble(local_keys)
224
+ ''
225
+ end
226
+
227
+ def precompiled_postamble(local_keys)
228
+ ''
229
+ end
230
+
231
+ # !@endgroup
232
+
233
+ private
234
+
235
+ def read_template_file
236
+ data = File.open(file, 'rb') { |io| io.read }
237
+ if data.respond_to?(:force_encoding)
238
+ # Set it to the default external (without verifying)
239
+ data.force_encoding(Encoding.default_external) if Encoding.default_external
240
+ end
241
+ data
242
+ end
243
+
244
+ # The compiled method for the locals keys provided.
245
+ def compiled_method(locals_keys, scope_class=nil)
246
+ LOCK.synchronize do
247
+ @compiled_method[[scope_class, locals_keys]] ||= compile_template_method(locals_keys, scope_class)
248
+ end
249
+ end
250
+
251
+ def local_extraction(local_keys)
252
+ local_keys.map do |k|
222
253
  if k.to_s =~ /\A[a-z_][a-zA-Z_0-9]*\z/
223
254
  "#{k} = locals[#{k.inspect}]"
224
255
  else
@@ -227,41 +258,26 @@ module Tilt
227
258
  end.join("\n")
228
259
  end
229
260
 
230
- # Generates postamble code for the precompiled template source. The
231
- # string returned from this method is appended to the precompiled
232
- # template source.
233
- def precompiled_postamble(locals)
234
- ''
235
- end
236
-
237
- # The compiled method for the locals keys provided.
238
- def compiled_method(locals_keys)
239
- @compiled_method[locals_keys] ||=
240
- compile_template_method(locals_keys)
241
- end
261
+ def compile_template_method(local_keys, scope_class=nil)
262
+ source, offset = precompiled(local_keys)
263
+ local_code = local_extraction(local_keys)
242
264
 
243
- private
244
- def compile_template_method(locals)
245
- source, offset = precompiled(locals)
246
265
  method_name = "__tilt_#{Thread.current.object_id.abs}"
247
- method_source = ""
266
+ method_source = String.new
248
267
 
249
268
  if method_source.respond_to?(:force_encoding)
250
- method_source.force_encoding(source.encoding)
269
+ method_source.force_encoding(source.encoding)
251
270
  end
252
271
 
253
272
  method_source << <<-RUBY
254
273
  TOPOBJECT.class_eval do
255
274
  def #{method_name}(locals)
256
- Thread.current[:tilt_vars] = [self, locals]
257
- class << self
258
- this, locals = Thread.current[:tilt_vars]
259
- this.instance_eval do
275
+ #{local_code}
260
276
  RUBY
261
277
  offset += method_source.count("\n")
262
278
  method_source << source
263
- method_source << "\nend;end;end;end"
264
- Object.class_eval method_source, eval_file, line - offset
279
+ method_source << "\nend;end;"
280
+ (scope_class || Object).class_eval(method_source, eval_file, line - offset)
265
281
  unbind_compiled_method(method_name)
266
282
  end
267
283
 
@@ -276,7 +292,7 @@ module Tilt
276
292
  end
277
293
 
278
294
  def extract_magic_comment(script)
279
- binary script do
295
+ binary(script) do
280
296
  script[/\A[ \t]*\#.*coding\s*[=:]\s*([[:alnum:]\-_]+).*$/n, 1]
281
297
  end
282
298
  end
@@ -0,0 +1,26 @@
1
+ require 'tilt/template'
2
+ require 'typescript-node'
3
+
4
+ module Tilt
5
+ class TypeScriptTemplate < Template
6
+ self.default_mime_type = 'application/javascript'
7
+
8
+ def prepare
9
+ @option_args = []
10
+
11
+ options.each do |key, value|
12
+ next unless value
13
+
14
+ @option_args << "--#{key}"
15
+
16
+ if value != true
17
+ @option_args << value.to_s
18
+ end
19
+ end
20
+ end
21
+
22
+ def evaluate(scope, locals, &block)
23
+ @output ||= TypeScript::Node.compile(data, *@option_args)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'tilt/template'
2
+ require 'wikicloth'
3
+
4
+ module Tilt
5
+ # WikiCloth implementation. See:
6
+ # http://redcloth.org/
7
+ class WikiClothTemplate < Template
8
+ def prepare
9
+ @parser = options.delete(:parser) || WikiCloth::Parser
10
+ @engine = @parser.new options.merge(:data => data)
11
+ @output = nil
12
+ end
13
+
14
+ def evaluate(scope, locals, &block)
15
+ @output ||= @engine.to_html
16
+ end
17
+
18
+ def allows_script?
19
+ false
20
+ end
21
+ end
22
+ end
data/lib/tilt/yajl.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'tilt/template'
2
+ require 'yajl'
2
3
 
3
4
  module Tilt
4
5
 
@@ -42,14 +43,6 @@ module Tilt
42
43
 
43
44
  self.default_mime_type = 'application/json'
44
45
 
45
- def self.engine_initialized?
46
- defined? ::Yajl
47
- end
48
-
49
- def initialize_engine
50
- require_template_library 'yajl'
51
- end
52
-
53
46
  def prepare
54
47
  end
55
48