tilt-handlebars 1.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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tilt-handlebars.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jim Cushing
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Tilt::Handlebars
2
+
3
+ Adds support for [Handlebars.rb](https://github.com/cowboyd/handlebars.rb) template
4
+ engine to [Tilt](https://github.com/rtomayko/tilt).
5
+
6
+ See the [Handlebars.js](http://handlebarsjs.com) site for syntax.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'tilt-handlebars'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install tilt-handlebars
21
+
22
+ ## Usage
23
+
24
+ Create a Handlebars template file with either a `.hbs` or `.handlebars` extension.
25
+
26
+ Example, in `hello.hbs`:
27
+
28
+ ```
29
+ Hello, {{name}}. I'm {{emotion}} to meet you.
30
+ ```
31
+
32
+ Then, render the template with Ruby:
33
+
34
+ ```ruby
35
+ require 'tilt/handlebars'
36
+
37
+ template = Tilt.new('hello.hbs')
38
+ puts template.render(nil, name: "Joe", emotion: "happy")
39
+ ```
40
+
41
+ Output:
42
+
43
+ Hello, Joe. I'm happy to meet you.
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ desc 'Run tests (default)'
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.ruby_opts = ['-Itest']
8
+ t.ruby_opts << '-rubygems' if defined? Gem
9
+ end
@@ -0,0 +1,67 @@
1
+ require 'tilt' unless defined? Tilt
2
+ require 'handlebars'
3
+
4
+ module Tilt
5
+
6
+ # Handlebars.rb template implementation. See:
7
+ # https://github.com/cowboyd/handlebars.rb
8
+ # and http://handlebarsjs.com
9
+ #
10
+ # Handlebars is a logic-less template rendered with JavaScript.
11
+ # Handlebars.rb is a Ruby wrapper around Handlebars, that allows
12
+ # Handlebars templates to be rendered server side.
13
+ #
14
+ class HandlebarsTemplate < Template
15
+ def initialize_engine
16
+ @context = ::Handlebars::Context.new
17
+ end
18
+
19
+ def self.engine_initialized?
20
+ true
21
+ end
22
+
23
+ def prepare
24
+ @context = ::Handlebars::Context.new
25
+ @template = @context.compile(data)
26
+ end
27
+
28
+ def evaluate(scope, locals = {}, &block)
29
+ # Based on LiquidTemplate
30
+ locals = locals.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
31
+ if scope.respond_to?(:to_h)
32
+ scope = scope.to_h.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
33
+ locals = scope.merge(locals)
34
+ else
35
+ scope.instance_variables.each do |var|
36
+ key = var.to_s.delete("@")
37
+ locals[key] = scope.instance_variable_get(var) unless locals.has_key? key
38
+ end
39
+ end
40
+
41
+ locals['yield'] = block.nil? ? '' : yield
42
+ locals['content'] = locals['yield']
43
+
44
+ @template.call(locals);
45
+ end
46
+
47
+ def register_helper(name, &fn)
48
+ @context.register_helper(name, &fn)
49
+ end
50
+
51
+ def register_partial(*args)
52
+ @context.register_partial(*args)
53
+ end
54
+
55
+ def partial_missing(&fn)
56
+ @context.partial_missing(&fn)
57
+ end
58
+
59
+ def allows_script?
60
+ false
61
+ end
62
+ end
63
+
64
+ register HandlebarsTemplate, 'handlebars', 'hbs'
65
+ end
66
+
67
+
data/test/hello.hbs ADDED
@@ -0,0 +1 @@
1
+ Hello, {{ name }}. I'm {{ emotion }} to meet you.
@@ -0,0 +1,222 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+
7
+ require 'tilt'
8
+ require 'tilt/handlebars'
9
+
10
+ def make_template(text)
11
+ Tilt::HandlebarsTemplate.new { |t| text }
12
+ end
13
+
14
+ describe Tilt::HandlebarsTemplate do
15
+ it 'renders from file' do
16
+ template = Tilt.new('test/hello.hbs')
17
+ template.render(nil, name: 'Joe', emotion: 'happy').must_equal "Hello, Joe. I'm happy to meet you.\n"
18
+ end
19
+
20
+ it 'is registered for .hbs files' do
21
+ Tilt['test.hbs'].must_equal Tilt::HandlebarsTemplate
22
+ end
23
+
24
+ it 'is registered for .handlebars files' do
25
+ Tilt['test.handlebars'].must_equal Tilt::HandlebarsTemplate
26
+ end
27
+
28
+ it 'renders static template' do
29
+ template = make_template "Hello World!"
30
+ template.render.must_equal "Hello World!"
31
+ end
32
+
33
+ it "can be rendered more than once" do
34
+ template = make_template "Hello World!"
35
+ 3.times { template.render.must_equal "Hello World!" }
36
+ end
37
+
38
+ it "substitutes locals in template" do
39
+ template = make_template "Hey {{ name }}!"
40
+ template.render(nil, :name => 'Joe').must_equal "Hey Joe!"
41
+ end
42
+
43
+ it "displays nested properties" do
44
+ template = make_template "Hey {{ person.name }}!"
45
+ template.render(nil, :person => { :name => 'Joe' }).must_equal "Hey Joe!"
46
+ end
47
+
48
+ it "displays text from block" do
49
+ template = make_template "Deck the halls. Fa {{ yield }}."
50
+ rendered = template.render(nil) { "la la la la"}
51
+ rendered.must_equal "Deck the halls. Fa la la la la."
52
+ end
53
+
54
+
55
+ describe "arrays" do
56
+ shopping_list = %w[milk eggs flour sugar]
57
+
58
+ it "displays element from array" do
59
+ template = make_template "Don't forget the {{ shopping_list.[1] }}!"
60
+ template.render(nil, :shopping_list => shopping_list).must_equal "Don't forget the eggs!"
61
+ end
62
+
63
+ it "displays elements in an array in a loop" do
64
+ template = make_template 'Items to buy:{{#each shopping_list}} {{ this }}{{/each}}'
65
+ template.render(nil, :shopping_list => shopping_list).must_equal "Items to buy: milk eggs flour sugar"
66
+ end
67
+
68
+ it "displays alternate text when array is empty" do
69
+ template = make_template 'Items to buy:{{#each shopping_list}} {{ this }}{{else}} All done!{{/each}}'
70
+ template.render(nil, :shopping_list => []).must_equal "Items to buy: All done!"
71
+ end
72
+ end
73
+
74
+ describe "conditionals" do
75
+ template = make_template '{{#if morning}}Good morning{{else}}Hello{{/if}}, {{ name }}'
76
+
77
+ it "displays text if value is true" do
78
+ template.render(nil, :name => 'Joe', :morning => true).must_equal "Good morning, Joe"
79
+ end
80
+
81
+ it "displays alternate text if value is false" do
82
+ template.render(nil, :name => 'Joe', :morning => false).must_equal "Hello, Joe"
83
+ end
84
+
85
+ it "displays alternate text if value is missing" do
86
+ template.render(nil, :name => 'Joe').must_equal "Hello, Joe"
87
+ end
88
+ end
89
+
90
+ describe "unless expressions" do
91
+ template = make_template 'Hello, {{ name }}.{{#unless weekend}} Time to go to work.{{/unless}}'
92
+
93
+ it "displays text if value is false" do
94
+ template.render(nil, :name => 'Joe', :weekend => false).must_equal "Hello, Joe. Time to go to work."
95
+ end
96
+
97
+ it "does not display text if value is true" do
98
+ template.render(nil, :name => 'Joe', :weekend => true).must_equal "Hello, Joe."
99
+ end
100
+
101
+ it "displays text if value is missing" do
102
+ template.render(nil, :name => 'Joe').must_equal "Hello, Joe. Time to go to work."
103
+ end
104
+ end
105
+
106
+ describe "escape HTML" do
107
+ it "escapes HTML characters" do
108
+ template = make_template "Hey {{ name }}!"
109
+ template.render(nil, :name => '<b>Joe</b>' ).must_equal "Hey &lt;b&gt;Joe&lt;/b&gt;!"
110
+ end
111
+
112
+ it "does not escape HTML characters in triple-stash" do
113
+ template = make_template "Hey {{{ name }}}!"
114
+ template.render(nil, :name => '<b>Joe</b>' ).must_equal "Hey <b>Joe</b>!"
115
+ end
116
+ end
117
+
118
+ describe "helpers" do
119
+ it "applies helper to static text" do
120
+ template = make_template '{{#upper}}Hello, World.{{/upper}}'
121
+ template.register_helper(:upper) do |this, block|
122
+ block.fn(this).upcase
123
+ end
124
+
125
+ template.render.must_equal "HELLO, WORLD."
126
+ end
127
+
128
+ it "applies helper to nested values" do
129
+ template = make_template '{{#upper}}Hey {{name}}{{/upper}}!'
130
+ template.register_helper(:upper) do |this, block|
131
+ block.fn(this).upcase
132
+ end
133
+
134
+ template.render(nil, :name => 'Joe').must_equal "HEY JOE!"
135
+ end
136
+
137
+ it "displays properties from object using 'with' helper" do
138
+ template = make_template '{{#with person}}Hello, {{ first_name }} {{ last_name }}{{/with}}'
139
+ joe = Person.new "Joe", "Blow"
140
+ template.render(nil, :person => joe).must_equal "Hello, Joe Blow"
141
+ end
142
+
143
+ end
144
+
145
+ describe "using scope object to render template" do
146
+ class Person
147
+ attr_reader :first_name, :last_name
148
+
149
+ def initialize(first_name, last_name)
150
+ @first_name = first_name
151
+ @last_name = last_name
152
+ end
153
+ end
154
+
155
+ class HashPerson
156
+ attr_reader :first_name, :last_name
157
+
158
+ def initialize(first_name, last_name)
159
+ @first_name = first_name
160
+ @last_name = last_name
161
+ end
162
+
163
+ def to_h
164
+ { first_name: @first_name, last_name: @last_name }
165
+ end
166
+ end
167
+
168
+ joe = Person.new "John", "Doe"
169
+
170
+ it "displays properties of object passed as scope" do
171
+ template = make_template "Hello, {{ first_name }} {{ last_name }}."
172
+ template.render(joe).must_equal "Hello, John Doe."
173
+ end
174
+
175
+ it "merges scope object properties with locals" do
176
+ template = make_template "{{ greeting }}, {{ first_name }} {{ last_name }}."
177
+ template.render(joe, :greeting => "Salut").must_equal "Salut, John Doe."
178
+ end
179
+
180
+ it "prefers locals over scope object properties with same name" do
181
+ template = make_template "Hello, {{ first_name }} {{ last_name }}."
182
+ template.render(joe, :first_name => "Jane").must_equal "Hello, Jane Doe."
183
+ end
184
+
185
+ it "prefers locals over scope object properties with same name when object defines to_h" do
186
+ joe_hash = HashPerson.new "John", "Doe"
187
+
188
+ template = make_template "Hello, {{ first_name }} {{ last_name }}."
189
+ template.render(joe_hash, :first_name => "Jane").must_equal "Hello, Jane Doe."
190
+ end
191
+ end
192
+
193
+ describe "comments" do
194
+ it "does not render comments" do
195
+ template = make_template "Hello world{{! what a wonderful world }}"
196
+ template.render.must_equal "Hello world"
197
+ end
198
+
199
+ it "does not render comments, alternative syntax" do
200
+ template = make_template "Hello world{{!-- what a wonderful world --}}"
201
+ template.render.must_equal "Hello world"
202
+ end
203
+ end
204
+
205
+ describe "partials" do
206
+ it "displays content of partial" do
207
+ template = make_template "{{> greeting}}. Nice to meet you."
208
+ template.register_partial :greeting, "Hey, {{name}}"
209
+ template.render(nil, :name => "Joe").must_equal "Hey, Joe. Nice to meet you."
210
+ end
211
+
212
+ it "calls registeded method if partial is missing" do
213
+ template = make_template "{{> where}} I've been looking for you."
214
+ template.partial_missing do |partial_name|
215
+ "Where have you been, {{name}}?" if partial_name == 'where'
216
+ end
217
+ template.render(nil, :name => "Joe").must_equal "Where have you been, Joe? I've been looking for you."
218
+ end
219
+ end
220
+ end
221
+
222
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "tilt-handlebars"
7
+ spec.version = "1.0"
8
+ spec.authors = ["Jim Cushing"]
9
+ spec.email = ["jimothy@mac.com"]
10
+ spec.description = "Use Handlebars.rb with Tilt"
11
+ spec.summary = spec.description
12
+ spec.homepage = "https://github.com/jimothyGator/tilt-handlebars"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "minitest", "~> 5.0"
23
+ spec.add_dependency "tilt", "~> 1.4"
24
+ spec.add_dependency "handlebars", "~> 0.4"
25
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tilt-handlebars
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jim Cushing
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '5.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: tilt
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.4'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.4'
78
+ - !ruby/object:Gem::Dependency
79
+ name: handlebars
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.4'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.4'
94
+ description: Use Handlebars.rb with Tilt
95
+ email:
96
+ - jimothy@mac.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - lib/tilt/handlebars.rb
107
+ - test/hello.hbs
108
+ - test/tilt_handlebarstemplate_test.rb
109
+ - tilt-handlebars.gemspec
110
+ homepage: https://github.com/jimothyGator/tilt-handlebars
111
+ licenses:
112
+ - MIT
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ segments:
124
+ - 0
125
+ hash: -129076644092719377
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ segments:
133
+ - 0
134
+ hash: -129076644092719377
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 1.8.25
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Use Handlebars.rb with Tilt
141
+ test_files:
142
+ - test/hello.hbs
143
+ - test/tilt_handlebarstemplate_test.rb