slim-mustache 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eceda48db1bdc2a3923f662fe2631a9e73d289b9
4
+ data.tar.gz: 892b6783b80e955bf2cf4b75d4fae5a98f8db441
5
+ SHA512:
6
+ metadata.gz: 8758c648a3215a7044e5f6632340b5836f2bbd779ebf66c901e2ae99c8944beef74a4da036b5b0f95b899c61fe7e35f7d6ce4a3cb718d6faf39992dd0a3f0976
7
+ data.tar.gz: 6dd93b91ed571966959318c3112666e88d4f9fc0c6063356c0fa36e618c9151fd6b5bd1e2f33941bea6640642b6cd4e407288d636604e5ce5d1fa1cfb00af944
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "slim", "~> 3.0"
4
+
5
+ group :development do
6
+ gem "minitest", "~> 5.7"
7
+ gem "bundler", "~> 1.0"
8
+ gem "jeweler", "~> 2.0.1"
9
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Michel Benevento
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,33 @@
1
+ = slim-mustache
2
+
3
+ Adding mustache/handlebars support to slim.
4
+
5
+
6
+ gem "slim-mustache"
7
+
8
+
9
+ require "slim/mustache"
10
+
11
+ ~#products # {{#products}}name: {{name}}, price: {{price}}{{/products}}
12
+ name: ~name, price: ~price
13
+
14
+ ~#if user.active # {{#if user.active}}<p>active</p>{{/if}}
15
+ p active
16
+
17
+ this is ~(group syntax) # this is {{group syntax}}
18
+
19
+ == Contributing to slim-mustache
20
+
21
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
22
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
23
+ * Fork the project.
24
+ * Start a feature/bugfix branch.
25
+ * Commit and push until you are happy with your contribution.
26
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
27
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
28
+
29
+ == Copyright
30
+
31
+ Copyright (c) 2015 Michel Benevento. See LICENSE.txt for
32
+ further details.
33
+
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "slim-mustache"
18
+ gem.homepage = "http://github.com/beno/slim-mustache"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{mustache/handlebars support for slim}
21
+ gem.description = %Q{use a ~tilde to generate \{\{mustache\}\} syntax}
22
+ gem.email = "michelbenevento@yahoo.com"
23
+ gem.authors = ["Michel Benevento"]
24
+ gem.version = "1.0.0"
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ desc "Code coverage detail"
37
+ task :simplecov do
38
+ ENV['COVERAGE'] = "true"
39
+ Rake::Task['test'].execute
40
+ end
41
+
42
+ task :default => :test
43
+
44
+ require 'rdoc/task'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "slim-mustache #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
@@ -0,0 +1,8 @@
1
+ require 'slim'
2
+ require 'slim/mustache/filter'
3
+ require 'slim/mustache/parser'
4
+ require 'slim/mustache/grammar'
5
+
6
+ Slim::Engine.replace Slim::Parser, Slim::Mustache::Parser
7
+ Slim::Engine.before Slim::Interpolation, Slim::Mustache::Filter
8
+
@@ -0,0 +1,32 @@
1
+ module Slim
2
+ module Mustache
3
+ # Handle ~mustache syntax
4
+ class Filter < ::Slim::Filter
5
+
6
+ def on_slim_mustache(line, content)
7
+ if match = line.match(/\A~([#\^]([^ ]*).*)/)
8
+ [:multi, [:static, "{{#{match[1]}}}"], compile(content), [:static, "{{/#{match[2]}}}"]]
9
+ else
10
+ on_slim_interpolate(line)
11
+ end
12
+ end
13
+
14
+ def on_slim_interpolate(string)
15
+ matches = string.scan(/([^~]*)~([!>])?(\((.*)\)|([^ ]*[\w}]))([^~]*)/)
16
+ if matches.any?
17
+ stack = [:multi]
18
+ matches.each do |first, prefix, text, clean_text, _, last|
19
+ prefix = "#{prefix} " if prefix
20
+ text = clean_text if clean_text
21
+ stack << [:multi, [:static, "{{#{prefix}"], [:slim, :interpolate, text], [:static, "}}"], [:slim, :interpolate, last]]
22
+ end
23
+ stack
24
+ else
25
+ [:slim, :interpolate, string]
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,8 @@
1
+ require 'slim/grammar'
2
+
3
+ module Slim::Grammar
4
+
5
+ HTMLAttr <<
6
+ [:slim, :mustache, String, Expression]
7
+
8
+ end
@@ -0,0 +1,27 @@
1
+ module Slim
2
+
3
+ module Mustache
4
+
5
+ class Parser < ::Slim::Parser
6
+
7
+ def parse_line_indicators
8
+ case @line
9
+ when /\A~/
10
+ # Mustache block
11
+ @line = $' if $1
12
+ parse_mustache
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def parse_mustache
19
+ block = [:multi]
20
+ @stacks.last << [:slim, :mustache, @line, block]
21
+ @stacks << block
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,211 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'codeclimate-test-reporter'
5
+ CodeClimate::TestReporter.start
6
+ rescue LoadError
7
+ end
8
+
9
+ require 'minitest/autorun'
10
+ require 'slim'
11
+ require 'slim/grammar'
12
+
13
+ Slim::Engine.after Slim::Parser, Temple::Filters::Validator, grammar: Slim::Grammar
14
+ Slim::Engine.before :Pretty, Temple::Filters::Validator
15
+
16
+ class TestSlim < Minitest::Test
17
+ def setup
18
+ @env = Env.new
19
+ end
20
+
21
+ def render(source, options = {}, &block)
22
+ scope = options.delete(:scope)
23
+ locals = options.delete(:locals)
24
+ Slim::Template.new(options[:file], options) { source }.render(scope || @env, locals, &block)
25
+ end
26
+
27
+ class HtmlSafeString < String
28
+ def html_safe?
29
+ true
30
+ end
31
+
32
+ def to_s
33
+ self
34
+ end
35
+ end
36
+
37
+ def with_html_safe
38
+ String.send(:define_method, :html_safe?) { false }
39
+ String.send(:define_method, :html_safe) { HtmlSafeString.new(self) }
40
+ yield
41
+ ensure
42
+ String.send(:undef_method, :html_safe?) if String.method_defined?(:html_safe?)
43
+ String.send(:undef_method, :html_safe) if String.method_defined?(:html_safe)
44
+ end
45
+
46
+ def assert_html(expected, source, options = {}, &block)
47
+ assert_equal expected, render(source, options, &block)
48
+ end
49
+
50
+ def assert_syntax_error(message, source, options = {})
51
+ render(source, options)
52
+ raise 'Syntax error expected'
53
+ rescue Slim::Parser::SyntaxError => ex
54
+ assert_equal message, ex.message
55
+ message =~ /([^\s]+), Line (\d+)/
56
+ assert_backtrace ex, "#{$1}:#{$2}"
57
+ end
58
+
59
+ def assert_ruby_error(error, from, source, options = {})
60
+ render(source, options)
61
+ raise 'Ruby error expected'
62
+ rescue error => ex
63
+ assert_backtrace(ex, from)
64
+ end
65
+
66
+ def assert_backtrace(ex, from)
67
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
68
+ # HACK: Rubinius stack trace sometimes has one entry more
69
+ if ex.backtrace[0] !~ /^#{Regexp.escape from}/
70
+ ex.backtrace[1] =~ /([^\s]+:\d+)/
71
+ assert_equal from, $1
72
+ end
73
+ else
74
+ ex.backtrace[0] =~ /([^\s]+:\d+)/
75
+ assert_equal from, $1
76
+ end
77
+ end
78
+
79
+ def assert_ruby_syntax_error(from, source, options = {})
80
+ render(source, options)
81
+ raise 'Ruby syntax error expected'
82
+ rescue SyntaxError => ex
83
+ ex.message =~ /([^\s]+:\d+):/
84
+ assert_equal from, $1
85
+ end
86
+
87
+ def assert_runtime_error(message, source, options = {})
88
+ render(source, options)
89
+ raise Exception, 'Runtime error expected'
90
+ rescue RuntimeError => ex
91
+ assert_equal message, ex.message
92
+ end
93
+ end
94
+
95
+ class Env
96
+ attr_reader :var, :x
97
+
98
+ def initialize
99
+ @var = 'instance'
100
+ @x = 0
101
+ end
102
+
103
+ def id_helper
104
+ "notice"
105
+ end
106
+
107
+ def hash
108
+ {a: 'The letter a', b: 'The letter b'}
109
+ end
110
+
111
+ def show_first?(show = false)
112
+ show
113
+ end
114
+
115
+ def define_macro(name, &block)
116
+ @macro ||= {}
117
+ @macro[name.to_s] = block
118
+ ''
119
+ end
120
+
121
+ def call_macro(name, *args)
122
+ @macro[name.to_s].call(*args)
123
+ end
124
+
125
+ def hello_world(text = "Hello World from @env", opts = {})
126
+ text << opts.to_a * " " if opts.any?
127
+ if block_given?
128
+ "#{text} #{yield} #{text}"
129
+ else
130
+ text
131
+ end
132
+ end
133
+
134
+ def message(*args)
135
+ args.join(' ')
136
+ end
137
+
138
+ def action_path(*args)
139
+ "/action-#{args.join('-')}"
140
+ end
141
+
142
+ def in_keyword
143
+ "starts with keyword"
144
+ end
145
+
146
+ def evil_method
147
+ "<script>do_something_evil();</script>"
148
+ end
149
+
150
+ def output_number
151
+ 1337
152
+ end
153
+
154
+ def succ_x
155
+ @x = @x.succ
156
+ end
157
+
158
+ end
159
+
160
+ class ViewEnv
161
+ def output_number
162
+ 1337
163
+ end
164
+
165
+ def person
166
+ [{name: 'Joe'}, {name: 'Jack'}]
167
+ end
168
+
169
+ def people
170
+ %w(Andy Fred Daniel).collect{|n| Person.new(n)}
171
+ end
172
+
173
+ def cities
174
+ %w{Atlanta Melbourne Karlsruhe}
175
+ end
176
+
177
+ def people_with_locations
178
+ array = []
179
+ people.each_with_index do |p,i|
180
+ p.location = Location.new cities[i]
181
+ array << p
182
+ end
183
+ array
184
+ end
185
+ end
186
+
187
+ require 'forwardable'
188
+
189
+ class Person
190
+ extend Forwardable
191
+
192
+ attr_accessor :name
193
+
194
+ def initialize(name)
195
+ @name = name
196
+ end
197
+
198
+ def location=(location)
199
+ @location = location
200
+ end
201
+
202
+ def_delegators :@location, :city
203
+ end
204
+
205
+ class Location
206
+ attr_accessor :city
207
+
208
+ def initialize(city)
209
+ @city = city
210
+ end
211
+ end
@@ -0,0 +1,146 @@
1
+ require 'helper'
2
+ require 'slim/mustache'
3
+
4
+ class TestSlimMustache < TestSlim
5
+
6
+ def test_line
7
+ source = %q{
8
+ ~foo bar baz
9
+ }
10
+ assert_html '{{foo}} bar baz', source
11
+ end
12
+
13
+ def test_line_two
14
+ source = %q{
15
+ ~foo bar ~baz
16
+ }
17
+ assert_html '{{foo}} bar {{baz}}', source
18
+ end
19
+
20
+ def test_dots
21
+ source = %q{
22
+ ~foo.bar. baz
23
+ }
24
+ assert_html '{{foo.bar}}. baz', source
25
+ end
26
+
27
+ def test_dots_section
28
+ source = %q{
29
+ ~#if user.active
30
+ p active
31
+ }
32
+ assert_html '{{#if user.active}}<p>active</p>{{/if}}', source
33
+ end
34
+
35
+ def test_punctuate
36
+ source = %q{
37
+ ~foo, bar ~baz: foo
38
+ }
39
+ assert_html '{{foo}}, bar {{baz}}: foo', source
40
+ end
41
+
42
+
43
+ def test_line_braced
44
+ source = %q{
45
+ p ~(foo * bar). baz
46
+ }
47
+ assert_html '<p>{{foo * bar}}. baz</p>', source
48
+ end
49
+
50
+ def test_section
51
+ source = %q{
52
+ ~#foo
53
+ p bar
54
+ }
55
+ assert_html '{{#foo}}<p>bar</p>{{/foo}}', source
56
+ end
57
+
58
+ def test_each
59
+ source = %q{
60
+ ~#each products
61
+ h1 product
62
+ | nice
63
+ }
64
+ assert_html '{{#each products}}<h1>product</h1>nice{{/each}}', source
65
+ end
66
+
67
+ def test_if
68
+ source = %q{
69
+ ~#if foo
70
+ 'bar
71
+ }
72
+ assert_html '{{#if foo}}bar {{/if}}', source
73
+ end
74
+
75
+ def test_not
76
+ source = %q{
77
+ ~^barz
78
+ | fooz
79
+ }
80
+ assert_html '{{^barz}}fooz{{/barz}}', source
81
+ end
82
+
83
+ def test_ignore
84
+ source = %q{
85
+ ~#bar
86
+ ~!ignore
87
+ }
88
+ assert_html '{{#bar}}{{! ignore}}{{/bar}}', source
89
+ end
90
+
91
+ def test_include
92
+ source = %q{
93
+ ~>bar
94
+ }
95
+ assert_html '{{> bar}}', source
96
+ end
97
+
98
+ def test_inline
99
+ source = %q{
100
+ h1 ~title here
101
+ }
102
+ assert_html '<h1>{{title}} here</h1>', source
103
+ end
104
+
105
+ def test_inline_two
106
+ source = %q{
107
+ h1 ~title here ~name here
108
+ }
109
+ assert_html '<h1>{{title}} here {{name}} here</h1>', source
110
+ end
111
+
112
+
113
+ def test_attribute
114
+ source = %q{
115
+ a href="~link.url" ~link.text
116
+ }
117
+ assert_html '<a href="{{link.url}}">{{link.text}}</a>', source
118
+ end
119
+
120
+
121
+ def test_interpolate_simple
122
+ source = %q{
123
+ p ~#{hello_world}
124
+ }
125
+ assert_html '<p>{{Hello World from @env}}</p>', source
126
+ end
127
+
128
+ def test_interpolate_complex
129
+ source = %q{
130
+ ~(#{'foo' + ' bar'}) baz
131
+ }
132
+ assert_html '{{foo bar}} baz', source
133
+ end
134
+
135
+ def test_all
136
+ source = %q{
137
+ ul
138
+ ~#each objects
139
+ li
140
+ a href="~link" ~name #{hello_world} and ~another
141
+ }
142
+ assert_html '<ul>{{#each objects}}<li><a href="{{link}}">{{name}} Hello World from @env and {{another}}</a></li>{{/each}}</ul>', source
143
+ end
144
+
145
+
146
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slim-mustache
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michel Benevento
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: slim
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jeweler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.1
69
+ description: use a ~tilde to generate {{mustache}} syntax
70
+ email: michelbenevento@yahoo.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files:
74
+ - LICENSE.txt
75
+ - README.rdoc
76
+ files:
77
+ - ".document"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.rdoc
81
+ - Rakefile
82
+ - lib/slim/mustache.rb
83
+ - lib/slim/mustache/filter.rb
84
+ - lib/slim/mustache/grammar.rb
85
+ - lib/slim/mustache/parser.rb
86
+ - test/helper.rb
87
+ - test/test_slim-mustache.rb
88
+ homepage: http://github.com/beno/slim-mustache
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.4.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: mustache/handlebars support for slim
112
+ test_files: []