tilt 2.0.1 → 2.0.2

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.
@@ -7,14 +7,6 @@ module Tilt
7
7
  class KramdownTemplate < Template
8
8
  DUMB_QUOTES = [39, 39, 34, 34]
9
9
 
10
- def self.engine_initialized?
11
- defined? ::Kramdown
12
- end
13
-
14
- def initialize_engine
15
- require_template_library 'kramdown'
16
- end
17
-
18
10
  def prepare
19
11
  options[:smart_quotes] = DUMB_QUOTES unless options[:smartypants]
20
12
  @engine = Kramdown::Document.new(data, options)
@@ -9,14 +9,6 @@ module Tilt
9
9
  class LessTemplate < Template
10
10
  self.default_mime_type = 'text/css'
11
11
 
12
- def self.engine_initialized?
13
- defined? ::Less
14
- end
15
-
16
- def initialize_engine
17
- require_template_library 'less'
18
- end
19
-
20
12
  def prepare
21
13
  if ::Less.const_defined? :Engine
22
14
  @engine = ::Less::Engine.new(data)
@@ -3,7 +3,7 @@ require 'liquid'
3
3
 
4
4
  module Tilt
5
5
  # Liquid template implementation. See:
6
- # http://liquid.rubyforge.org/
6
+ # http://liquidmarkup.org/
7
7
  #
8
8
  # Liquid is designed to be a *safe* template system and threfore
9
9
  # does not provide direct access to execuatable scopes. In order to
@@ -6,10 +6,6 @@ module Tilt
6
6
  class PlainTemplate < Template
7
7
  self.default_mime_type = 'text/html'
8
8
 
9
- def self.engine_initialized?
10
- true
11
- end
12
-
13
9
  def prepare
14
10
  end
15
11
 
@@ -0,0 +1,43 @@
1
+ require 'tilt/template'
2
+ require 'prawn'
3
+
4
+ module Tilt
5
+ # Prawn template implementation. See: http://prawnpdf.org
6
+ #
7
+ class PrawnTemplate < Template
8
+ self.default_mime_type = 'application/pdf'
9
+
10
+ def prepare
11
+ @engine = ::Prawn::Document.new(prawn_options)
12
+ end
13
+
14
+ def evaluate(scope, locals, &block)
15
+ pdf = @engine
16
+ if data.respond_to?(:to_str)
17
+ locals[:pdf] = pdf
18
+ super(scope, locals, &block)
19
+ elsif data.kind_of?(Proc)
20
+ data.call(pdf)
21
+ end
22
+ @output ||= pdf.render
23
+ end
24
+
25
+ def allows_script?
26
+ false
27
+ end
28
+
29
+ def precompiled_template(locals)
30
+ data.to_str
31
+ end
32
+
33
+
34
+ private
35
+
36
+ def prawn_options
37
+ # defaults to A4 instead of crazy US Letter format.
38
+ { :page_size => "A4", :page_layout => :portrait }.merge(options)
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -35,12 +35,8 @@ module Tilt
35
35
  class Redcarpet2Template < Template
36
36
  self.default_mime_type = 'text/html'
37
37
 
38
- def self.engine_initialized?
39
- defined? ::Redcarpet::Render and defined? ::Redcarpet::Markdown
40
- end
41
-
42
38
  def generate_renderer
43
- renderer = options.delete(:renderer) || ::Redcarpet::Render::HTML
39
+ renderer = options.delete(:renderer) || ::Redcarpet::Render::HTML.new(options)
44
40
  return renderer unless options.delete(:smartypants)
45
41
  return renderer if renderer.is_a?(Class) && renderer <= ::Redcarpet::Render::SmartyPants
46
42
 
@@ -78,27 +74,10 @@ module Tilt
78
74
  end
79
75
  end
80
76
 
81
- # Upskirt Markdown implementation. See:
82
- # https://github.com/tanoku/redcarpet
83
- #
84
- # Supports both Redcarpet 1.x and 2.x
85
- class RedcarpetTemplate < Template
86
- Redcarpet1 = Redcarpet1Template
87
- Redcarpet2 = Redcarpet2Template
88
-
89
- def prepare
90
- klass = Redcarpet2.engine_initialized? ? Redcarpet2 : Redcarpet1
91
- @engine = klass.new(file, line, options) { data }
92
- end
93
-
94
- def evaluate(scope, locals, &block)
95
- @engine.evaluate(scope, locals, &block)
96
- end
97
-
98
- def allows_script?
99
- false
100
- end
77
+ if defined? ::Redcarpet::Render and defined? ::Redcarpet::Markdown
78
+ RedcarpetTemplate = Redcarpet2Template
79
+ else
80
+ RedcarpetTemplate = Redcarpet1Template
101
81
  end
102
-
103
82
  end
104
83
 
@@ -5,6 +5,8 @@ module Tilt
5
5
  TOPOBJECT = Object.superclass || Object
6
6
  # @private
7
7
  LOCK = Mutex.new
8
+ # @private
9
+ SYMBOL_ARRAY_SORTABLE = RUBY_VERSION >= '1.9'
8
10
 
9
11
  # Base class for template implementations. Subclasses must implement
10
12
  # the #prepare method and one of the #evaluate or #precompiled_template
@@ -90,7 +92,8 @@ module Tilt
90
92
  # Render the template in the given scope with the locals specified. If a
91
93
  # block is given, it is typically available within the template via
92
94
  # +yield+.
93
- def render(scope=Object.new, locals={}, &block)
95
+ def render(scope=nil, locals={}, &block)
96
+ scope ||= Object.new
94
97
  current_template = Thread.current[:tilt_current_template]
95
98
  Thread.current[:tilt_current_template] = self
96
99
  evaluate(scope, locals || {}, &block)
@@ -151,7 +154,13 @@ module Tilt
151
154
  # This method is only used by source generating templates. Subclasses that
152
155
  # override render() may not support all features.
153
156
  def evaluate(scope, locals, &block)
154
- method = compiled_method(locals.keys)
157
+ locals_keys = locals.keys
158
+ if SYMBOL_ARRAY_SORTABLE
159
+ locals_keys.sort!
160
+ else
161
+ locals_keys.sort!{|x, y| x.to_s <=> y.to_s}
162
+ end
163
+ method = compiled_method(locals_keys)
155
164
  method.bind(scope).call(locals, &block)
156
165
  end
157
166
 
@@ -0,0 +1,2 @@
1
+ m4(1) http://man.cx/m4(1)
2
+ mustache(1) https://mustache.github.io/mustache.1.html
@@ -0,0 +1,59 @@
1
+ tilt(1) -- process templates
2
+ ============================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `tilt` `-l`<br>
7
+ `tilt` [`-t` <pattern>] [`-y` <file>] [`-D` <name>=<value>] [`-d` <file>]
8
+ [`--vars=`<ruby>] <file>
9
+
10
+ ## DESCRIPTION
11
+
12
+ Process template <file> and write output to stdout. With no <file> or
13
+ when <file> is '-', read template from stdin and use the --type option
14
+ to determine the template's type.
15
+
16
+ ## OPTIONS
17
+
18
+ * `-l`, `--list`:
19
+ List template engines + file patterns and exit
20
+ * `-t`, `--type`=<pattern>:
21
+ Use this template engine; required if no <file>
22
+ * `-y`, `--layout`=<file>:
23
+ Use <file> as a layout template
24
+ * `-D`<name>=<value>:
25
+ Define variable <name> as <value>
26
+ * `-d`, `--define-file`=<file>:
27
+ Load YAML or JSON from <file> and use for variables
28
+ * `--vars`=<ruby>:
29
+ Evaluate <ruby> to Hash and use for variables
30
+ * `-h`, `--help`:
31
+ Show this help message
32
+
33
+ ## EXAMPLES
34
+
35
+ Convert markdown to HTML:
36
+
37
+ $ tilt foo.markdown > foo.html
38
+
39
+ Process ERB template:
40
+
41
+ $ echo "Answer: <%= 2 + 2 %>" | tilt -t erb
42
+ Answer: 4
43
+
44
+ Define variables:
45
+
46
+ $ echo '{"n":40}' > data.json
47
+ $ echo "Answer: <%= 2 + n %>" | tilt -t erb -d data.json
48
+ Answer: 42
49
+
50
+ $ echo "Answer: <%= 2 + n %>" | tilt -t erb --vars="{:n=>40}"
51
+ Answer: 42
52
+ $ echo "Answer: <%= 2 + n.to_i %>" | tilt -t erb -Dn=40
53
+ Answer: 42
54
+
55
+ ## SEE ALSO
56
+
57
+ m4(1), mustache(1)
58
+
59
+
@@ -6,7 +6,8 @@ begin
6
6
 
7
7
  class AsciidoctorTemplateTest < Minitest::Test
8
8
  HTML5_OUTPUT = "<div class=\"sect1\"><h2 id=\"_hello_world\">Hello World!</h2><div class=\"sectionbody\"></div></div>"
9
- DOCBOOK_OUTPUT = "<section id=\"_hello_world\"><title>Hello World!</title></section>"
9
+ DOCBOOK45_OUTPUT = "<section id=\"_hello_world\"><title>Hello World!</title></section>"
10
+ DOCBOOK5_OUTPUT = "<section xml:id=\"_hello_world\"><title>Hello World!</title></section>"
10
11
 
11
12
  def strip_space(str)
12
13
  str.gsub(/>\s+</, '><').strip
@@ -29,9 +30,14 @@ begin
29
30
  assert_equal HTML5_OUTPUT, strip_space(template.render)
30
31
  end
31
32
 
32
- test "preparing and evaluating docbook templates on #render" do
33
- template = Tilt::AsciidoctorTemplate.new(:attributes => {"backend" => 'docbook'}) { |t| "== Hello World!" }
34
- assert_equal DOCBOOK_OUTPUT, strip_space(template.render)
33
+ test "preparing and evaluating docbook 4.5 templates on #render" do
34
+ template = Tilt::AsciidoctorTemplate.new(:attributes => {"backend" => 'docbook45'}) { |t| "== Hello World!" }
35
+ assert_equal DOCBOOK45_OUTPUT, strip_space(template.render)
36
+ end
37
+
38
+ test "preparing and evaluating docbook 5 templates on #render" do
39
+ template = Tilt::AsciidoctorTemplate.new(:attributes => {"backend" => 'docbook5'}) { |t| "== Hello World!" }
40
+ assert_equal DOCBOOK5_OUTPUT, strip_space(template.render)
35
41
  end
36
42
 
37
43
  test "can be rendered more than once" do
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+ require 'tilt'
3
+
4
+ begin
5
+ require 'tilt/babel'
6
+
7
+ class BabelTemplateTest < Minitest::Test
8
+ test "registered for '.es6' files" do
9
+ assert_equal Tilt::BabelTemplate, Tilt['es6']
10
+ end
11
+
12
+ test "registered for '.babel' files" do
13
+ assert_equal Tilt::BabelTemplate, Tilt['babel']
14
+ end
15
+
16
+ test "registered for '.jsx' files" do
17
+ assert_equal Tilt::BabelTemplate, Tilt['jsx']
18
+ end
19
+
20
+ test "basic ES6 features" do
21
+ template = Tilt::BabelTemplate.new { "square = (x) => x * x" }
22
+ assert_match "function", template.render
23
+ end
24
+
25
+ test "JSX support" do
26
+ template = Tilt::BabelTemplate.new { "<Awesome ness={true} />" }
27
+ assert_match "React.createElement", template.render
28
+ end
29
+ end
30
+ rescue LoadError => boom
31
+ warn "Tilt::BabelTemplate (disabled)"
32
+ end
33
+
@@ -20,6 +20,17 @@ class TiltCacheTest < Minitest::Test
20
20
  assert_same template, result
21
21
  end
22
22
 
23
+ test "caching nil" do
24
+ called = false
25
+ result = @cache.fetch("blah") {called = true; nil}
26
+ assert_equal true, called
27
+ assert_nil result
28
+ called = false
29
+ result = @cache.fetch("blah") {called = true; :blah}
30
+ assert_equal false, called
31
+ assert_nil result
32
+ end
33
+
23
34
  test "clearing the cache with #clear" do
24
35
  template, other = nil
25
36
  result = @cache.fetch('hello') { template = Tilt::StringTemplate.new {''} }
@@ -4,98 +4,135 @@ require 'tilt'
4
4
  begin
5
5
  require 'tilt/coffee'
6
6
 
7
- class CoffeeScriptTemplateTest < Minitest::Test
8
-
9
- test "is registered for '.coffee' files" do
10
- assert_equal Tilt::CoffeeScriptTemplate, Tilt['test.coffee']
7
+ module CoffeeScriptTests
8
+ def self.included(mod)
9
+ mod.class_eval do
10
+ test "bare is disabled by default" do
11
+ assert_equal false, @renderer.default_bare
12
+ end
13
+
14
+ test "compiles and evaluates the template on #render" do
15
+ template = @renderer.new { |t| @code_without_variables }
16
+ assert_match "puts('Hello, World!');", template.render
17
+ end
18
+
19
+ test "can be rendered more than once" do
20
+ template = @renderer.new { |t| @code_without_variables }
21
+ 3.times { assert_match "puts('Hello, World!');", template.render }
22
+ end
23
+
24
+ test "disabling coffee-script wrapper" do
25
+ template = @renderer.new { @code_with_variables }
26
+ assert_match "(function() {", template.render
27
+ assert_match "puts(\"Hello, \" + name);\n", template.render
28
+
29
+ template = @renderer.new(:bare => true) { @code_with_variables }
30
+ refute_match "(function() {", template.render
31
+ assert_equal "var name;\n\nname = \"Josh\";\n\nputs(\"Hello, \" + name);\n", template.render
32
+
33
+ template2 = @renderer.new(:no_wrap => true) { @code_with_variables}
34
+ refute_match "(function() {", template.render
35
+ assert_equal "var name;\n\nname = \"Josh\";\n\nputs(\"Hello, \" + name);\n", template.render
36
+ end
37
+
38
+ context "wrapper globally enabled" do
39
+ setup do
40
+ @bare = @renderer.default_bare
41
+ @renderer.default_bare = false
42
+ end
43
+
44
+ teardown do
45
+ @renderer.default_bare = @bare
46
+ end
47
+
48
+ test "no options" do
49
+ template = @renderer.new { |t| @code_with_variables }
50
+ assert_match "puts(\"Hello, \" + name);", template.render
51
+ assert_match "(function() {", template.render
52
+ end
53
+
54
+ test "overridden by :bare" do
55
+ template = @renderer.new(:bare => true) { |t| @code_with_variables }
56
+ assert_match "puts(\"Hello, \" + name);", template.render
57
+ refute_match "(function() {", template.render
58
+ end
59
+
60
+ test "overridden by :no_wrap" do
61
+ template = @renderer.new(:no_wrap => true) { |t| @code_with_variables }
62
+ assert_match "puts(\"Hello, \" + name);", template.render
63
+ refute_match "(function() {", template.render
64
+ end
65
+ end
66
+
67
+ context "wrapper globally disabled" do
68
+ setup do
69
+ @bare = @renderer.default_bare
70
+ @renderer.default_bare = true
71
+ end
72
+
73
+ teardown do
74
+ @renderer.default_bare = @bare
75
+ end
76
+
77
+ test "no options" do
78
+ template = @renderer.new { |t| @code_with_variables }
79
+ assert_match "puts(\"Hello, \" + name);", template.render
80
+ refute_match "(function() {", template.render
81
+ end
82
+
83
+ test "overridden by :bare" do
84
+ template = @renderer.new(:bare => false) { |t| @code_with_variables }
85
+ assert_match "puts(\"Hello, \" + name);", template.render
86
+ assert_match "(function() {", template.render
87
+ end
88
+
89
+ test "overridden by :no_wrap" do
90
+ template = @renderer.new(:no_wrap => false) { |t| @code_with_variables }
91
+ assert_match "puts(\"Hello, \" + name);", template.render
92
+ assert_match "(function() {", template.render
93
+ end
94
+ end
95
+ end
11
96
  end
97
+ end
12
98
 
13
- test "bare is disabled by default" do
14
- assert_equal false, Tilt::CoffeeScriptTemplate.default_bare
99
+ class CoffeeScriptTemplateTest < Minitest::Test
100
+ setup do
101
+ @code_without_variables = "puts 'Hello, World!'\n"
102
+ @code_with_variables = 'name = "Josh"; puts "Hello, #{name}"'
103
+ @renderer = Tilt::CoffeeScriptTemplate
15
104
  end
16
105
 
17
- test "compiles and evaluates the template on #render" do
18
- template = Tilt::CoffeeScriptTemplate.new { |t| "puts 'Hello, World!'\n" }
19
- assert_match "puts('Hello, World!');", template.render
20
- end
106
+ include CoffeeScriptTests
21
107
 
22
- test "can be rendered more than once" do
23
- template = Tilt::CoffeeScriptTemplate.new { |t| "puts 'Hello, World!'\n" }
24
- 3.times { assert_match "puts('Hello, World!');", template.render }
108
+ test "is registered for '.coffee' files" do
109
+ assert_equal @renderer, Tilt['test.coffee']
25
110
  end
111
+ end
26
112
 
27
- test "disabling coffee-script wrapper" do
28
- str = 'name = "Josh"; puts "Hello #{name}"'
29
-
30
- template = Tilt::CoffeeScriptTemplate.new { str }
31
- assert_match "(function() {", template.render
32
- assert_match "puts(\"Hello \" + name);\n", template.render
113
+ class LiterateCoffeeScriptTemplateTest < Minitest::Test
114
+ setup do
115
+ @code_without_variables = <<EOLIT
116
+ This is some comment.
33
117
 
34
- template = Tilt::CoffeeScriptTemplate.new(:bare => true) { str }
35
- refute_match "(function() {", template.render
36
- assert_equal "var name;\n\nname = \"Josh\";\n\nputs(\"Hello \" + name);\n", template.render
118
+ puts 'Hello, World!'
37
119
 
38
- template2 = Tilt::CoffeeScriptTemplate.new(:no_wrap => true) { str}
39
- refute_match "(function() {", template.render
40
- assert_equal "var name;\n\nname = \"Josh\";\n\nputs(\"Hello \" + name);\n", template.render
41
- end
120
+ This is a comment too.
121
+ EOLIT
122
+ @code_with_variables = <<EOLIT
123
+ This is some comment.
42
124
 
43
- context "wrapper globally enabled" do
44
- setup do
45
- @bare = Tilt::CoffeeScriptTemplate.default_bare
46
- Tilt::CoffeeScriptTemplate.default_bare = false
47
- end
48
-
49
- teardown do
50
- Tilt::CoffeeScriptTemplate.default_bare = @bare
51
- end
125
+ name = "Josh"; puts "Hello, \#{name}"
52
126
 
53
- test "no options" do
54
- template = Tilt::CoffeeScriptTemplate.new { |t| 'name = "Josh"; puts "Hello, #{name}"' }
55
- assert_match "puts(\"Hello, \" + name);", template.render
56
- assert_match "(function() {", template.render
57
- end
58
-
59
- test "overridden by :bare" do
60
- template = Tilt::CoffeeScriptTemplate.new(:bare => true) { |t| 'name = "Josh"; puts "Hello, #{name}"' }
61
- assert_match "puts(\"Hello, \" + name);", template.render
62
- refute_match "(function() {", template.render
63
- end
64
-
65
- test "overridden by :no_wrap" do
66
- template = Tilt::CoffeeScriptTemplate.new(:no_wrap => true) { |t| 'name = "Josh"; puts "Hello, #{name}"' }
67
- assert_match "puts(\"Hello, \" + name);", template.render
68
- refute_match "(function() {", template.render
69
- end
127
+ This is a comment too.
128
+ EOLIT
129
+ @renderer = Tilt::CoffeeScriptLiterateTemplate
70
130
  end
71
131
 
72
- context "wrapper globally disabled" do
73
- setup do
74
- @bare = Tilt::CoffeeScriptTemplate.default_bare
75
- Tilt::CoffeeScriptTemplate.default_bare = true
76
- end
132
+ include CoffeeScriptTests
77
133
 
78
- teardown do
79
- Tilt::CoffeeScriptTemplate.default_bare = @bare
80
- end
81
-
82
- test "no options" do
83
- template = Tilt::CoffeeScriptTemplate.new { |t| 'name = "Josh"; puts "Hello, #{name}"' }
84
- assert_match "puts(\"Hello, \" + name);", template.render
85
- refute_match "(function() {", template.render
86
- end
87
-
88
- test "overridden by :bare" do
89
- template = Tilt::CoffeeScriptTemplate.new(:bare => false) { |t| 'name = "Josh"; puts "Hello, #{name}"' }
90
- assert_match "puts(\"Hello, \" + name);", template.render
91
- assert_match "(function() {", template.render
92
- end
93
-
94
- test "overridden by :no_wrap" do
95
- template = Tilt::CoffeeScriptTemplate.new(:no_wrap => false) { |t| 'name = "Josh"; puts "Hello, #{name}"' }
96
- assert_match "puts(\"Hello, \" + name);", template.render
97
- assert_match "(function() {", template.render
98
- end
134
+ test "is registered for '.litcoffee' files" do
135
+ assert_equal @renderer, Tilt['test.litcoffee']
99
136
  end
100
137
  end
101
138