tilt 2.0.1 → 2.0.2

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