tilt 2.0.0 → 2.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.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +2 -1
  3. data/bin/tilt +2 -110
  4. data/lib/tilt/_emacs_org.rb +2 -0
  5. data/lib/tilt/_handlebars.rb +2 -0
  6. data/lib/tilt/_jbuilder.rb +2 -0
  7. data/lib/tilt/_org.rb +2 -0
  8. data/lib/tilt/asciidoc.rb +11 -23
  9. data/lib/tilt/babel.rb +8 -0
  10. data/lib/tilt/builder.rb +23 -14
  11. data/lib/tilt/cli.rb +134 -0
  12. data/lib/tilt/coffee.rb +17 -25
  13. data/lib/tilt/commonmarker.rb +95 -0
  14. data/lib/tilt/creole.rb +9 -20
  15. data/lib/tilt/csv.rb +9 -21
  16. data/lib/tilt/erb.rb +27 -19
  17. data/lib/tilt/erubi.rb +55 -0
  18. data/lib/tilt/erubis.rb +20 -12
  19. data/lib/tilt/etanni.rb +5 -4
  20. data/lib/tilt/haml.rb +79 -42
  21. data/lib/tilt/kramdown.rb +8 -28
  22. data/lib/tilt/liquid.rb +11 -9
  23. data/lib/tilt/livescript.rb +11 -0
  24. data/lib/tilt/mapping.rb +242 -95
  25. data/lib/tilt/markaby.rb +5 -7
  26. data/lib/tilt/maruku.rb +6 -18
  27. data/lib/tilt/nokogiri.rb +11 -10
  28. data/lib/tilt/pandoc.rb +39 -0
  29. data/lib/tilt/pipeline.rb +19 -0
  30. data/lib/tilt/plain.rb +4 -19
  31. data/lib/tilt/prawn.rb +28 -0
  32. data/lib/tilt/radius.rb +15 -22
  33. data/lib/tilt/rdiscount.rb +17 -33
  34. data/lib/tilt/rdoc.rb +14 -35
  35. data/lib/tilt/redcarpet.rb +20 -93
  36. data/lib/tilt/redcloth.rb +9 -19
  37. data/lib/tilt/rst-pandoc.rb +10 -0
  38. data/lib/tilt/sass.rb +59 -22
  39. data/lib/tilt/slim.rb +5 -0
  40. data/lib/tilt/string.rb +9 -3
  41. data/lib/tilt/template.rb +246 -78
  42. data/lib/tilt/typescript.rb +19 -0
  43. data/lib/tilt/wikicloth.rb +8 -18
  44. data/lib/tilt/yajl.rb +5 -11
  45. data/lib/tilt.rb +91 -41
  46. metadata +39 -102
  47. data/CHANGELOG.md +0 -61
  48. data/Gemfile +0 -39
  49. data/HACKING +0 -16
  50. data/README.md +0 -206
  51. data/Rakefile +0 -95
  52. data/docs/TEMPLATES.md +0 -523
  53. data/docs/common.css +0 -14
  54. data/lib/tilt/bluecloth.rb +0 -24
  55. data/lib/tilt/less.rb +0 -38
  56. data/test/markaby/locals.mab +0 -1
  57. data/test/markaby/markaby.mab +0 -1
  58. data/test/markaby/markaby_other_static.mab +0 -1
  59. data/test/markaby/render_twice.mab +0 -1
  60. data/test/markaby/scope.mab +0 -1
  61. data/test/markaby/yielding.mab +0 -2
  62. data/test/test_helper.rb +0 -64
  63. data/test/tilt_asciidoctor_test.rb +0 -44
  64. data/test/tilt_blueclothtemplate_test.rb +0 -33
  65. data/test/tilt_buildertemplate_test.rb +0 -59
  66. data/test/tilt_cache_test.rb +0 -32
  67. data/test/tilt_coffeescripttemplate_test.rb +0 -104
  68. data/test/tilt_compilesite_test.rb +0 -51
  69. data/test/tilt_creoletemplate_test.rb +0 -24
  70. data/test/tilt_csv_test.rb +0 -65
  71. data/test/tilt_erbtemplate_test.rb +0 -239
  72. data/test/tilt_erubistemplate_test.rb +0 -151
  73. data/test/tilt_etannitemplate_test.rb +0 -174
  74. data/test/tilt_hamltemplate_test.rb +0 -144
  75. data/test/tilt_kramdown_test.rb +0 -20
  76. data/test/tilt_lesstemplate_test.less +0 -1
  77. data/test/tilt_lesstemplate_test.rb +0 -42
  78. data/test/tilt_liquidtemplate_test.rb +0 -78
  79. data/test/tilt_mapping_test.rb +0 -229
  80. data/test/tilt_markaby_test.rb +0 -88
  81. data/test/tilt_markdown_test.rb +0 -174
  82. data/test/tilt_marukutemplate_test.rb +0 -36
  83. data/test/tilt_metadata_test.rb +0 -42
  84. data/test/tilt_nokogiritemplate_test.rb +0 -87
  85. data/test/tilt_radiustemplate_test.rb +0 -75
  86. data/test/tilt_rdiscounttemplate_test.rb +0 -43
  87. data/test/tilt_rdoctemplate_test.rb +0 -29
  88. data/test/tilt_redcarpettemplate_test.rb +0 -59
  89. data/test/tilt_redclothtemplate_test.rb +0 -36
  90. data/test/tilt_sasstemplate_test.rb +0 -41
  91. data/test/tilt_stringtemplate_test.rb +0 -171
  92. data/test/tilt_template_test.rb +0 -316
  93. data/test/tilt_test.rb +0 -60
  94. data/test/tilt_wikiclothtemplate_test.rb +0 -32
  95. data/test/tilt_yajltemplate_test.rb +0 -101
  96. data/tilt.gemspec +0 -107
data/lib/tilt/mapping.rb CHANGED
@@ -1,4 +1,81 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'pipeline'
3
+
1
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
+
2
79
  # Tilt::Mapping associates file extensions with template implementations.
3
80
  #
4
81
  # mapping = Tilt::Mapping.new
@@ -36,16 +113,18 @@ module Tilt
36
113
  # the exception of the first, since that was the most preferred one.
37
114
  #
38
115
  # mapping = Tilt::Mapping.new
39
- # mapping.register_lazy('Bluecloth::Template', 'bluecloth/template', 'md')
116
+ # mapping.register_lazy('Maruku::Template', 'maruku/template', 'md')
40
117
  # mapping.register_lazy('RDiscount::Template', 'rdiscount/template', 'md')
41
118
  # mapping['index.md']
42
119
  # # => RDiscount::Template
43
120
  #
44
121
  # In the previous example we say that RDiscount has a *higher priority* than
45
- # BlueCloth. Tilt will first try to `require "rdiscount/template"`, falling
46
- # back to `require "bluecloth/template"`. If none of these are successful,
122
+ # Maruku. Tilt will first try to `require "rdiscount/template"`, falling
123
+ # back to `require "maruku/template"`. If none of these are successful,
47
124
  # the first error will be raised.
48
- class Mapping
125
+ class Mapping < BaseMapping
126
+ LOCK = Mutex.new
127
+
49
128
  # @private
50
129
  attr_reader :lazy_map, :template_map
51
130
 
@@ -56,11 +135,29 @@ module Tilt
56
135
 
57
136
  # @private
58
137
  def initialize_copy(other)
59
- @template_map = other.template_map.dup
60
- @lazy_map = other.lazy_map.dup
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)
61
158
  end
62
159
 
63
- # Registrers a lazy template implementation by file extension. You
160
+ # Registers a lazy template implementation by file extension. You
64
161
  # can have multiple lazy template implementations defined on the
65
162
  # same file extension, in which case the template implementation
66
163
  # defined *last* will be attempted loaded *first*.
@@ -83,8 +180,9 @@ module Tilt
83
180
  class_name = "Tilt::#{class_name}"
84
181
  end
85
182
 
183
+ v = [class_name, file].freeze
86
184
  extensions.each do |ext|
87
- @lazy_map[ext].unshift([class_name, file])
185
+ LOCK.synchronize{@lazy_map[ext].unshift(v)}
88
186
  end
89
187
  end
90
188
 
@@ -106,86 +204,95 @@ module Tilt
106
204
  end
107
205
 
108
206
  extensions.each do |ext|
109
- @template_map[ext.to_s] = template_class
207
+ ext = ext.to_s
208
+ LOCK.synchronize do
209
+ @template_map[ext] = template_class
210
+ end
110
211
  end
111
212
  end
112
213
 
113
- # Checks if a file extension is registered (either eagerly or
114
- # lazily) in this mapping.
214
+ # Register a new template class using the given extension that
215
+ # represents a pipeline of multiple existing template, where the
216
+ # output from the previous template is used as input to the next
217
+ # template.
115
218
  #
116
- # @param ext [String] File extension.
219
+ # This will register a template class that processes the input
220
+ # with the *erb* template processor, and takes the output of
221
+ # that and feeds it to the *scss* template processor, returning
222
+ # the output of the *scss* template processor as the result of
223
+ # the pipeline.
224
+ #
225
+ # @param ext [String] Primary extension to register
226
+ # @option :templates [Array<String>] Extensions of templates
227
+ # to execute in order (defaults to the ext.split('.').reverse)
228
+ # @option :extra_exts [Array<String>] Additional extensions to register
229
+ # @option String [Hash] Options hash for individual template in the
230
+ # pipeline (key is extension).
231
+ # @return [void]
117
232
  #
118
233
  # @example
119
- # mapping.registered?('erb') # => true
120
- # mapping.registered?('nope') # => false
121
- def registered?(ext)
122
- @template_map.has_key?(ext.downcase) or lazy?(ext)
234
+ # mapping.register_pipeline('scss.erb')
235
+ # mapping.register_pipeline('scss.erb', 'erb'=>{:outvar=>'@foo'})
236
+ # mapping.register_pipeline('scsserb', :extra_exts => 'scss.erb',
237
+ # :templates=>['erb', 'scss'])
238
+ def register_pipeline(ext, options=EMPTY_HASH)
239
+ templates = options[:templates] || ext.split('.').reverse
240
+ templates = templates.map{|t| [self[t], options[t] || EMPTY_HASH]}
241
+
242
+ klass = Class.new(Pipeline)
243
+ klass.send(:const_set, :TEMPLATES, templates)
244
+
245
+ register(klass, ext, *Array(options[:extra_exts]))
246
+ klass
123
247
  end
124
248
 
125
- # Instantiates a new template class based on the file.
249
+ # Unregisters an extension. This removes the both normal registrations
250
+ # and lazy registrations.
126
251
  #
127
- # @raise [RuntimeError] if there is no template class registered for the
128
- # file name.
252
+ # @param extensions [Array<String>] List of extensions.
253
+ # @return nil
129
254
  #
130
255
  # @example
131
- # mapping.new('index.mt') # => instance of MyEngine::Template
132
- #
133
- # @see Tilt::Template.new
134
- def new(file, line=nil, options={}, &block)
135
- if template_class = self[file]
136
- template_class.new(file, line, options, &block)
137
- else
138
- fail "No template engine registered for #{File.basename(file)}"
256
+ # mapping.register MyEngine::Template, 'mt'
257
+ # mapping['index.mt'] # => MyEngine::Template
258
+ # mapping.unregister('mt')
259
+ # mapping['index.mt'] # => nil
260
+ def unregister(*extensions)
261
+ extensions.each do |ext|
262
+ ext = ext.to_s
263
+ LOCK.synchronize do
264
+ @template_map.delete(ext)
265
+ @lazy_map.delete(ext)
266
+ end
139
267
  end
140
- end
141
268
 
142
- # Looks up a template class based on file name and/or extension.
143
- #
144
- # @example
145
- # mapping['views/hello.erb'] # => Tilt::ERBTemplate
146
- # mapping['hello.erb'] # => Tilt::ERBTemplate
147
- # mapping['erb'] # => Tilt::ERBTemplate
148
- #
149
- # @return [template class]
150
- def [](file)
151
- prefix, ext = split(file)
152
- ext && lookup(ext)
269
+ nil
153
270
  end
154
271
 
155
- alias template_for []
156
-
157
- # Looks up a list of template classes based on file name. If the file name
158
- # has multiple extensions, it will return all template classes matching the
159
- # extensions from the end.
272
+ # Checks if a file extension is registered (either eagerly or
273
+ # lazily) in this mapping.
160
274
  #
161
- # @example
162
- # mapping.templates_for('views/index.haml.erb')
163
- # # => [Tilt::ERBTemplate, Tilt::HamlTemplate]
275
+ # @param ext [String] File extension.
164
276
  #
165
- # @return [Array<template class>]
166
- def templates_for(file)
167
- templates = []
168
-
169
- while true
170
- prefix, ext = split(file)
171
- break unless ext
172
- templates << lookup(ext)
173
- file = prefix
174
- end
175
-
176
- templates
277
+ # @example
278
+ # mapping.registered?('erb') # => true
279
+ # mapping.registered?('nope') # => false
280
+ def registered?(ext)
281
+ ext_downcase = ext.downcase
282
+ LOCK.synchronize{@template_map.has_key?(ext_downcase)} or lazy?(ext)
177
283
  end
178
284
 
179
285
  # Finds the extensions the template class has been registered under.
180
286
  # @param [template class] template_class
181
287
  def extensions_for(template_class)
182
288
  res = []
183
- template_map.each do |ext, klass|
289
+ LOCK.synchronize{@template_map.to_a}.each do |ext, klass|
184
290
  res << ext if template_class == klass
185
291
  end
186
- lazy_map.each do |ext, choices|
187
- 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 }
188
294
  end
295
+ res.uniq!
189
296
  res
190
297
  end
191
298
 
@@ -193,40 +300,30 @@ module Tilt
193
300
 
194
301
  def lazy?(ext)
195
302
  ext = ext.downcase
196
- @lazy_map.has_key?(ext) && !@lazy_map[ext].empty?
197
- end
198
-
199
- def split(file)
200
- pattern = file.to_s.downcase
201
- full_pattern = pattern.dup
202
-
203
- until registered?(pattern)
204
- return if pattern.empty?
205
- pattern = File.basename(pattern)
206
- pattern.sub!(/^[^.]*\.?/, '')
207
- end
208
-
209
- prefix_size = full_pattern.size - pattern.size
210
- [full_pattern[0,prefix_size-1], pattern]
303
+ LOCK.synchronize{@lazy_map.has_key?(ext) && !@lazy_map[ext].empty?}
211
304
  end
212
305
 
213
306
  def lookup(ext)
214
- @template_map[ext] || lazy_load(ext)
307
+ LOCK.synchronize{@template_map[ext]} || lazy_load(ext)
215
308
  end
216
309
 
217
- def lazy_load(pattern)
218
- return unless @lazy_map.has_key?(pattern)
219
-
220
- choices = @lazy_map[pattern]
221
-
222
- # Check if a template class is already present
223
- choices.each do |class_name, file|
310
+ def register_defined_classes(class_names, pattern)
311
+ class_names.each do |class_name|
224
312
  template_class = constant_defined?(class_name)
225
313
  if template_class
226
314
  register(template_class, pattern)
227
- return template_class
315
+ yield template_class if block_given?
228
316
  end
229
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
230
327
 
231
328
  first_failure = nil
232
329
 
@@ -234,12 +331,6 @@ module Tilt
234
331
  choices.each do |class_name, file|
235
332
  begin
236
333
  require file
237
-
238
- if Thread.list.size > 1
239
- warn "WARN: tilt autoloading '#{file}' in a non thread-safe way; " +
240
- "explicit require '#{file}' suggested."
241
- end
242
-
243
334
  # It's safe to eval() here because constant_defined? will
244
335
  # raise NameError on invalid constant names
245
336
  template_class = eval(class_name)
@@ -251,15 +342,71 @@ module Tilt
251
342
  end
252
343
  end
253
344
 
254
- raise first_failure if first_failure
345
+ raise first_failure
255
346
  end
256
347
 
348
+ # The proper behavior (in MRI) for autoload? is to
349
+ # return `false` when the constant/file has been
350
+ # explicitly required.
351
+ #
352
+ # However, in JRuby it returns `true` even after it's
353
+ # been required. In that case it turns out that `defined?`
354
+ # returns `"constant"` if it exists and `nil` when it doesn't.
355
+ # This is actually a second bug: `defined?` should resolve
356
+ # autoload (aka. actually try to require the file).
357
+ #
358
+ # We use the second bug in order to resolve the first bug.
359
+
257
360
  def constant_defined?(name)
258
361
  name.split('::').inject(Object) do |scope, n|
259
- return false unless scope.const_defined?(n)
260
- return false if scope.autoload?(n) # skip autload
362
+ return false if scope.autoload?(n) || !scope.const_defined?(n)
261
363
  scope.const_get(n)
262
364
  end
263
365
  end
264
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
265
412
  end
data/lib/tilt/markaby.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'tilt/template'
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__, &data)
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
data/lib/tilt/maruku.rb CHANGED
@@ -1,22 +1,10 @@
1
- require 'tilt/template'
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
2
3
  require 'maruku'
3
4
 
4
- module Tilt
5
- # Maruku markdown implementation. See:
6
- # http://maruku.rubyforge.org/
7
- class MarukuTemplate < Template
8
- def prepare
9
- @engine = Maruku.new(data, options)
10
- @output = nil
11
- end
5
+ warn 'tilt/maruku is deprecated, as maruku requires modifying string literals', uplevel: 1
12
6
 
13
- def evaluate(scope, locals, &block)
14
- @output ||= @engine.to_html
15
- end
16
-
17
- def allows_script?
18
- false
19
- end
20
- end
7
+ # Maruku markdown implementation. See: https://github.com/bhollis/maruku
8
+ Tilt::MarukuTemplate = Tilt::StaticTemplate.subclass do
9
+ Maruku.new(@data, @options).to_html
21
10
  end
22
-
data/lib/tilt/nokogiri.rb CHANGED
@@ -1,21 +1,23 @@
1
- require 'tilt/template'
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
2
3
  require 'nokogiri'
3
4
 
4
5
  module Tilt
5
6
  # Nokogiri template implementation. See:
6
7
  # http://nokogiri.org/
7
8
  class NokogiriTemplate < Template
8
- DOCUMENT_HEADER = /^<\?xml version=\"1\.0\"\?>\n?/
9
+ DOCUMENT_HEADER = /\A<\?xml version=\"1\.0\"\?>\n?/
9
10
  self.default_mime_type = 'text/xml'
10
11
 
11
- def prepare; end
12
-
13
12
  def evaluate(scope, locals)
14
- if data.respond_to?(:to_str)
15
- wrapper = proc { yield.sub(DOCUMENT_HEADER, "") } if block_given?
16
- super(scope, locals, &wrapper)
13
+ if @data.respond_to?(:to_str)
14
+ if block_given?
15
+ super(scope, locals){yield.sub(DOCUMENT_HEADER, "")}
16
+ else
17
+ super
18
+ end
17
19
  else
18
- ::Nokogiri::XML::Builder.new.tap(&data).to_xml
20
+ ::Nokogiri::XML::Builder.new(&@data).to_xml
19
21
  end
20
22
  end
21
23
 
@@ -29,8 +31,7 @@ module Tilt
29
31
  end
30
32
 
31
33
  def precompiled_template(locals)
32
- data.to_str
34
+ @data.to_str
33
35
  end
34
36
  end
35
37
  end
36
-
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
3
+ require 'pandoc-ruby'
4
+
5
+ # Pandoc markdown implementation. See: http://pandoc.org/
6
+ Tilt::PandocTemplate = Tilt::StaticTemplate.subclass do
7
+ # turn options hash into an array
8
+ # Map tilt options to pandoc options
9
+ # Replace hash keys with value true with symbol for key
10
+ # Remove hash keys with value false
11
+ # Leave other hash keys untouched
12
+ pandoc_options = []
13
+ from = "markdown"
14
+ smart_extension = "-smart"
15
+ @options.each do |k,v|
16
+ case k
17
+ when :smartypants
18
+ smart_extension = "+smart" if v
19
+ when :escape_html
20
+ from = "markdown-raw_html" if v
21
+ when :commonmark
22
+ from = "commonmark" if v
23
+ when :markdown_strict
24
+ from = "markdown_strict" if v
25
+ else
26
+ case v
27
+ when true
28
+ pandoc_options << k
29
+ when false
30
+ # do nothing
31
+ else
32
+ pandoc_options << { k => v }
33
+ end
34
+ end
35
+ end
36
+ pandoc_options << { :f => from + smart_extension }
37
+
38
+ PandocRuby.new(@data, *pandoc_options).to_html.strip
39
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
3
+
4
+ module Tilt
5
+ # Superclass used for pipeline templates. Should not be used directly.
6
+ class Pipeline < Template
7
+ def prepare
8
+ @pipeline = self.class::TEMPLATES.inject(proc{|*| data}) do |data, (klass, options)|
9
+ proc do |s,l,&sb|
10
+ klass.new(file, line, options, &proc{|*| data.call(s, l, &sb)}).render(s, l, &sb)
11
+ end
12
+ end
13
+ end
14
+
15
+ def evaluate(scope, locals, &block)
16
+ @pipeline.call(scope, locals, &block)
17
+ end
18
+ end
19
+ end
data/lib/tilt/plain.rb CHANGED
@@ -1,20 +1,5 @@
1
- require 'tilt/template'
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
2
3
 
3
-
4
- module Tilt
5
- # Raw text (no template functionality).
6
- class PlainTemplate < Template
7
- self.default_mime_type = 'text/html'
8
-
9
- def self.engine_initialized?
10
- true
11
- end
12
-
13
- def prepare
14
- end
15
-
16
- def evaluate(scope, locals, &block)
17
- @output ||= data
18
- end
19
- end
20
- end
4
+ # Raw text (no template functionality).
5
+ Tilt::PlainTemplate = Tilt::StaticTemplate.subclass{@data}
data/lib/tilt/prawn.rb ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'template'
3
+ require 'prawn'
4
+
5
+ module Tilt
6
+ # Prawn template implementation. See: http://prawnpdf.org
7
+ class PrawnTemplate < Template
8
+ self.default_mime_type = 'application/pdf'
9
+
10
+ def prepare
11
+ @options[:page_size] = 'A4' unless @options.has_key?(:page_size)
12
+ @options[:page_layout] = :portrait unless @options.has_key?(:page_layout)
13
+ @engine = ::Prawn::Document.new(@options)
14
+ end
15
+
16
+ def evaluate(scope, locals, &block)
17
+ pdf = @engine
18
+ locals = locals.dup
19
+ locals[:pdf] = pdf
20
+ super
21
+ pdf.render
22
+ end
23
+
24
+ def precompiled_template(locals)
25
+ @data.to_str
26
+ end
27
+ end
28
+ end