flavour_saver 0.3.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a79f853de54eb5d874990e16f9dfa613baecd6a6
4
- data.tar.gz: 9087954f3e3a7fe8d33fb174955702cf99572602
2
+ SHA256:
3
+ metadata.gz: 2874ca7f6ce28bbd9ed5f1ba887a0bc7244bdd448be995c2447078439e32bb82
4
+ data.tar.gz: cdae84ceb24202a2f03db262a973f254dc750a3de30efae7138e01a3ef6187cb
5
5
  SHA512:
6
- metadata.gz: 069c5cb0b6df25e7eaff653ab7f44b195dbe1447378eee9033f723205e500e9b57f8b9bfb0eaa6d2c6c36d693fef7057ab7f449a30596fece2f1c5f5c55a9efe
7
- data.tar.gz: faaf752ce94bb0ce1c29c3ae4f43703fffcb8ef9192d30bd5f335eddbd1f28e0f0330055c0c0746927830b7421901b9a89f0726d73ad15f3d2b74f14fae52ef7
6
+ metadata.gz: 404531d6a27b3c6e8739d98dc7ab9b5af81e8b29cc9260869784882704b58b4cd7ab2e2f3e741768cbe5386c326c66e1fc1be66d3ab1f6702a2902b9ee811017
7
+ data.tar.gz: b5ae4b6c36462dfc80a29e6eb25cca006330462aa44b1d38dd234e353a072ee906ac41943201ab5cce233b3812f14da697be6b29a189b4bf7b8820a98afecc7e
@@ -0,0 +1,26 @@
1
+ name: Continuous integration
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ ruby-version: ['2.6', '2.7', '3.0', '3.1']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true
24
+ - name: Run tests
25
+ run: bundle exec rspec
26
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2022-01-19
11
+
12
+ ### Added
13
+
14
+ * Ruby 3.0 and 3.1 support
15
+
16
+ ### Changed
17
+
18
+ * The gem is now maintained by the FlavourSaver organization
19
+
20
+ ### Removed
21
+
22
+ * Dropped support for Ruby 1.9, 2.0, 2.1, 2.2, 2.3, and 2.4
23
+
data/Gemfile.lock CHANGED
@@ -1,79 +1,54 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flavour_saver (0.3.6)
4
+ flavour_saver (1.0.0)
5
5
  rltk (~> 2.2.0)
6
6
  tilt
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (4.0.13)
12
- i18n (~> 0.6, >= 0.6.9)
13
- minitest (~> 4.2)
14
- multi_json (~> 1.3)
15
- thread_safe (~> 0.1)
16
- tzinfo (~> 0.3.37)
17
- coderay (1.0.9)
18
- diff-lcs (1.2.4)
19
- ffi (1.9.0)
20
- formatador (0.2.4)
21
- guard (1.8.3)
22
- formatador (>= 0.2.4)
23
- listen (~> 1.3)
24
- lumberjack (>= 1.0.2)
25
- pry (>= 0.9.10)
26
- thor (>= 0.14.6)
27
- guard-bundler (1.0.0)
28
- bundler (~> 1.0)
29
- guard (~> 1.1)
30
- guard-rspec (3.1.0)
31
- guard (>= 1.8)
32
- rspec (~> 2.13)
33
- i18n (0.7.0)
34
- listen (1.3.1)
35
- rb-fsevent (>= 0.9.3)
36
- rb-inotify (>= 0.9)
37
- rb-kqueue (>= 0.2)
38
- lumberjack (1.0.4)
39
- method_source (0.8.2)
40
- minitest (4.7.5)
41
- multi_json (1.10.1)
42
- pry (0.9.12.2)
43
- coderay (~> 1.0.5)
44
- method_source (~> 0.8)
45
- slop (~> 3.4)
46
- rake (10.1.0)
47
- rb-fsevent (0.9.3)
48
- rb-inotify (0.9.2)
49
- ffi (>= 0.5.0)
50
- rb-kqueue (0.2.0)
51
- ffi (>= 0.5.0)
11
+ activesupport (6.1.4.4)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
16
+ zeitwerk (~> 2.3)
17
+ concurrent-ruby (1.1.9)
18
+ diff-lcs (1.5.0)
19
+ ffi (1.15.5)
20
+ i18n (1.8.11)
21
+ concurrent-ruby (~> 1.0)
22
+ minitest (5.15.0)
23
+ rake (13.0.6)
52
24
  rltk (2.2.1)
53
25
  ffi (>= 1.0.0)
54
- rspec (2.14.1)
55
- rspec-core (~> 2.14.0)
56
- rspec-expectations (~> 2.14.0)
57
- rspec-mocks (~> 2.14.0)
58
- rspec-core (2.14.5)
59
- rspec-expectations (2.14.3)
60
- diff-lcs (>= 1.1.3, < 2.0)
61
- rspec-mocks (2.14.3)
62
- slop (3.4.6)
63
- thor (0.18.1)
64
- thread_safe (0.3.4)
65
- tilt (2.0.1)
66
- tzinfo (0.3.42)
26
+ rspec (3.10.0)
27
+ rspec-core (~> 3.10.0)
28
+ rspec-expectations (~> 3.10.0)
29
+ rspec-mocks (~> 3.10.0)
30
+ rspec-core (3.10.1)
31
+ rspec-support (~> 3.10.0)
32
+ rspec-expectations (3.10.2)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.10.0)
35
+ rspec-mocks (3.10.2)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.10.0)
38
+ rspec-support (3.10.3)
39
+ tilt (2.0.10)
40
+ tzinfo (2.0.4)
41
+ concurrent-ruby (~> 1.0)
42
+ zeitwerk (2.5.3)
67
43
 
68
44
  PLATFORMS
69
45
  ruby
70
46
 
71
47
  DEPENDENCIES
72
- activesupport (~> 4.0.2)
48
+ activesupport (< 7.0)
73
49
  flavour_saver!
74
- guard-bundler
75
- guard-rspec
76
50
  rake
77
- rspec-core
78
- rspec-expectations
79
- rspec-mocks
51
+ rspec
52
+
53
+ BUNDLED WITH
54
+ 2.2.17
data/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  [Handlebars.js](http://handlebarsjs.com) without the `.js`
4
4
 
5
- [![Build Status](https://travis-ci.org/jamesotron/FlavourSaver.png)](https://travis-ci.org/jamesotron/FlavourSaver)
6
- [![Dependency Status](https://gemnasium.com/jamesotron/FlavourSaver.png)](https://gemnasium.com/jamesotron/FlavourSaver)
7
- [![Code Climate](https://codeclimate.com/github/jamesotron/FlavourSaver.png)](https://codeclimate.com/github/jamesotron/FlavourSaver)
5
+ [![Gem Version](https://badge.fury.io/rb/flavour_saver.svg)](https://badge.fury.io/rb/flavour_saver)
6
+ ![Build Status](https://github.com/FlavourSaver/FlavourSaver/actions/workflows/ci.yml/badge.svg)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/89a99bec5bbf49359081/maintainability)](https://codeclimate.com/github/FlavourSaver/FlavourSaver/maintainability)
8
8
 
9
9
  ## WAT?
10
10
 
11
- FlavourSaver is a ruby-based implementation of the [Handlebars.js](http://handlebars.js)
11
+ FlavourSaver is a ruby-based implementation of the [Handlebars.js](http://handlebarsjs.com)
12
12
  templating language. FlavourSaver supports Handlebars template rendering natively on
13
13
  Rails and on other frameworks (such as Sinatra) via Tilt.
14
14
 
@@ -66,6 +66,8 @@ Currently supported:
66
66
  - Block expressions with inverse blocks
67
67
  - Inverse blocks
68
68
  - Partials
69
+ - Raw content (`{{{{raw}}}} not parsed or validated {{{{/raw}}}}`)
70
+ - Subexpressions (`{{sum 1 (sum 1 1)}}` returns `3`)
69
71
 
70
72
  ## Helpers
71
73
 
@@ -240,6 +242,35 @@ Which could be used like so:
240
242
  {{/isFemale}}
241
243
  ```
242
244
 
245
+ ### Subexpressions
246
+
247
+ You can use a subexpression as any value for a helper, and it will be executed before it is ran. You can also nest them, and use them in assignment of variables.
248
+
249
+ Below are some examples, utilizing a "sum" helper than adds together two numbers.
250
+
251
+ ```
252
+ {{sum (sum 5 10) (sum 2 (sum 1 4))}}
253
+ #=> 22
254
+
255
+ {{#if (sum 1 2) > 2}}its more{{/if}}
256
+ #=> its more
257
+
258
+ {{#student_heights size=(sum boys girls)}}
259
+ ```
260
+
261
+ ### Raw Content
262
+
263
+ Sometimes you don't want a section of content to be evaluted as handlebars, such as when you want to display it in a page that renders with handlebars. FlavourSaver offers a `raw` helper, that will allow you to pass anything through wrapped in those elements, and it will not be evaluated.
264
+
265
+ ```
266
+ {{{{raw}}}}
267
+ {{if} this tries to parse, it will break on syntax
268
+ {{{{/raw}}}}
269
+ => {{if} this tries to parse, it will break on syntax
270
+ ```
271
+
272
+ Its important to note that while this looks like a block helper, it is not in practice. This is why you must omit the use of a `#` when writing it.
273
+
243
274
  ### Using Partials
244
275
 
245
276
  Handlebars allows you to register a partial either as a function or a string template with
@@ -2,11 +2,18 @@
2
2
  require File.expand_path('../lib/flavour_saver/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["James Harton"]
6
- gem.email = ["james@resistor.io"]
5
+ gem.authors = ["Clayton Passmore", "James Harton"]
6
+ gem.email = ["ctpassmore+flavoursaver@gmail.com"]
7
7
  gem.description = %q{FlavourSaver is a pure-ruby implimentation of the Handlebars templating language}
8
8
  gem.summary = %q{Handlebars.js without the .js}
9
- gem.homepage = "http://jamesotron.github.com/FlavourSaver/"
9
+ gem.homepage = "http://github.com/FlavourSaver/FlavourSaver"
10
+ gem.license = "MIT"
11
+ gem.metadata = {
12
+ "bug_tracker_uri" => "http://github.com/FlavourSaver/FlavourSaver/issues",
13
+ "changelog_uri" => "http://github.com/FlavourSaver/FlavourSaver/blob/master/CHANGELOG.md",
14
+ "homepage_uri" => "http://github.com/FlavourSaver/FlavourSaver",
15
+ "source_code_uri" => "http://github.com/FlavourSaver/FlavourSaver",
16
+ }
10
17
 
11
18
  gem.files = `git ls-files`.split($\)
12
19
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -15,13 +22,11 @@ Gem::Specification.new do |gem|
15
22
  gem.require_paths = ["lib"]
16
23
  gem.version = FlavourSaver::VERSION
17
24
 
25
+ gem.required_ruby_version = ">= 2.6.0"
26
+
18
27
  gem.add_development_dependency 'rake'
19
- gem.add_development_dependency 'guard-rspec'
20
- gem.add_development_dependency 'rspec-core'
21
- gem.add_development_dependency 'rspec-mocks'
22
- gem.add_development_dependency 'rspec-expectations'
23
- gem.add_development_dependency 'guard-bundler'
24
- gem.add_development_dependency 'activesupport', '~> 4.0.2'
28
+ gem.add_development_dependency 'rspec'
29
+ gem.add_development_dependency 'activesupport', '< 7.0'
25
30
 
26
31
  gem.add_dependency 'rltk', '~> 2.2.0'
27
32
  gem.add_dependency 'tilt'
@@ -11,7 +11,10 @@ module FlavourSaver
11
11
  r = []
12
12
  count = 0
13
13
  collection.each do |element|
14
- r << yield.contents(element, 'index' => count)
14
+ r << yield.contents(element,
15
+ 'index' => count,
16
+ 'last' => count == collection.size - 1,
17
+ 'first' => count == 0)
15
18
  count += 1
16
19
  end
17
20
  yield.rendered!
@@ -59,7 +62,7 @@ module FlavourSaver
59
62
 
60
63
  def [](accessor)
61
64
  if array?
62
- if accessor.match /[0-9]+/
65
+ if accessor.match?(/[0-9]+/)
63
66
  return @source.at(accessor.to_i)
64
67
  end
65
68
  end
@@ -85,7 +88,7 @@ module FlavourSaver
85
88
  end
86
89
 
87
90
  def register_helper(method,&b)
88
- if method.respond_to? :name
91
+ if !method.is_a?(Symbol) && method.respond_to?(:name)
89
92
  registered_helpers[method.name.to_sym] = method
90
93
  elsif b
91
94
  registered_helpers[method.to_sym] = b
@@ -112,7 +115,5 @@ module FlavourSaver
112
115
  helpers = helpers.merge(locals)
113
116
  Decorator.new(helpers, context)
114
117
  end
115
-
116
118
  end
117
119
  end
118
-
@@ -3,6 +3,21 @@ require 'rltk'
3
3
  module FlavourSaver
4
4
  class Lexer < RLTK::Lexer
5
5
 
6
+ # seems to have problem with hash symbol in regex
7
+ rule /\{\{\{\{raw\}\}\}\}/, :default do
8
+ push_state :raw
9
+ :RAWSTART
10
+ end
11
+
12
+ rule /.*?(?=\{\{\{\{\/raw\}\}\}\})/m, :raw do |str|
13
+ [ :RAWSTRING, str ]
14
+ end
15
+
16
+ rule /\{\{\{\{\/raw\}\}\}\}/, :raw do
17
+ pop_state
18
+ :RAWEND
19
+ end
20
+
6
21
  rule /{{{/, :default do
7
22
  push_state :expression
8
23
  :TEXPRST
@@ -63,7 +78,7 @@ module FlavourSaver
63
78
  :ELSE
64
79
  end
65
80
 
66
- rule /([A-Za-z]\w*)/, :expression do |name|
81
+ rule /([A-Za-z_]\w*)/, :expression do |name|
67
82
  [ :IDENT, name ]
68
83
  end
69
84
 
@@ -71,6 +86,14 @@ module FlavourSaver
71
86
  :DOT
72
87
  end
73
88
 
89
+ rule /\(/, :expression do
90
+ :OPAR
91
+ end
92
+
93
+ rule /\)/, :expression do
94
+ :CPAR
95
+ end
96
+
74
97
  rule /\=/, :expression do
75
98
  :EQ
76
99
  end
@@ -99,10 +122,15 @@ module FlavourSaver
99
122
  pop_state
100
123
  end
101
124
 
102
- # Handlebars allows methods with hyphens in them. Ruby doesn't, so
103
- # we'll assume you're trying to index the context with the identifier
104
- # and call the result.
105
- rule /([A-Za-z][a-z0-9_-]*[a-z0-9])/, :expression do |str|
125
+ # Handlebars allows identifiers with characters in them which Ruby does not.
126
+ # These are mapped to the literal notation and accessed in this way.
127
+ #
128
+ # As per the http://handlebarsjs.com/expressions.html:
129
+ #
130
+ # Identifiers may be any unicode character except for the following:
131
+ # Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~
132
+ #
133
+ rule /([^\s!-#%-,.\/;->@\[-^`{-~]+)/, :expression do |str|
106
134
  [ :LITERAL, str ]
107
135
  end
108
136
 
@@ -95,7 +95,7 @@ module FlavourSaver
95
95
  end
96
96
 
97
97
  class ParentCallNode < CallNode
98
- value :depth, Fixnum
98
+ value :depth, Integer
99
99
 
100
100
  def to_callnode
101
101
  CallNode.new(name,arguments)
@@ -39,7 +39,8 @@ module FlavourSaver
39
39
  end
40
40
 
41
41
  production(:template_item) do
42
- clause('output') { |e| e }
42
+ clause('raw_bl') { |e| e }
43
+ clause('output') { |e| e }
43
44
  clause('expression') { |e| e }
44
45
  end
45
46
 
@@ -47,6 +48,10 @@ module FlavourSaver
47
48
  clause('OUT') { |o| OutputNode.new(o) }
48
49
  end
49
50
 
51
+ production(:raw_bl) do
52
+ clause('RAWSTART RAWSTRING RAWEND') { |_,e,_| OutputNode.new(e) }
53
+ end
54
+
50
55
  production(:expression) do
51
56
  clause('block_expression') { |e| e }
52
57
  clause('expr') { |e| ExpressionNode.new(e) }
@@ -81,6 +86,10 @@ module FlavourSaver
81
86
  clause('EXPRST expression_contents EXPRE') { |_,e,_| e }
82
87
  end
83
88
 
89
+ production(:subexpr) do
90
+ clause('OPAR expression_contents CPAR') { |_,e,_| e }
91
+ end
92
+
84
93
  production(:expr_comment) do
85
94
  clause('EXPRST BANG COMMENT EXPRE') { |_,_,e,_| e }
86
95
  end
@@ -121,11 +130,11 @@ module FlavourSaver
121
130
 
122
131
  production('arguments') do
123
132
  clause('argument_list') { |e| e }
124
- clause('argument_list hash') { |e0,e1| e0 + [e1] }
133
+ clause('argument_list WHITE hash') { |e0,_,e1| e0 + [e1] }
125
134
  clause('hash') { |e| [e] }
126
135
  end
127
-
128
- nonempty_list(:argument_list, [:object_path,:lit], :WHITE)
136
+
137
+ nonempty_list(:argument_list, [:object_path,:lit, :local, :subexpr], :WHITE)
129
138
 
130
139
  production(:lit) do
131
140
  clause('string') { |e| e }
@@ -152,6 +161,7 @@ module FlavourSaver
152
161
  end
153
162
 
154
163
  production(:hash_item) do
164
+ clause('IDENT EQ subexpr') { |e0,_,e1| { e0.to_sym => e1 } }
155
165
  clause('IDENT EQ string') { |e0,_,e1| { e0.to_sym => e1 } }
156
166
  clause('IDENT EQ number') { |e0,_,e1| { e0.to_sym => e1 } }
157
167
  clause('IDENT EQ object_path') { |e0,_,e1| { e0.to_sym => e1 } }
@@ -34,7 +34,7 @@ module FlavourSaver
34
34
  @privates = old_privates
35
35
  @context = old_context
36
36
  else
37
- result = evaluate_node(@ast)
37
+ result = evaluate_node(@ast).to_s.force_encoding(Encoding::default_external)
38
38
  end
39
39
  result
40
40
  end
@@ -46,13 +46,13 @@ module FlavourSaver
46
46
  def private_variable_get(name)
47
47
  begin
48
48
  @privates.fetch(name)
49
- rescue KeyError => e
49
+ rescue KeyError
50
50
  raise UndefinedPrivateVariableException, "private variable not found @#{name}"
51
51
  end
52
52
  end
53
53
 
54
54
  def strip(tmp_context = nil)
55
- self.to_s(tmp_context).gsub(/[\s\r\n]+/,' ').strip
55
+ self.to_s(tmp_context).gsub(/[\s]+/,' ').strip
56
56
  end
57
57
 
58
58
  def evaluate_node(node)
@@ -256,9 +256,9 @@ module FlavourSaver
256
256
  "&#x27;"
257
257
  when '"'
258
258
  "&quot;"
259
- when '`'
260
- "&#x60;"
261
- end
259
+ when '`'
260
+ "&#x60;"
261
+ end
262
262
  end
263
263
 
264
264
  # Mark it as already escaped if we're in Rails
@@ -1,3 +1,3 @@
1
1
  module FlavourSaver
2
- VERSION = "0.3.6"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -9,6 +9,6 @@ describe 'Fixture: backtrack.hbs' do
9
9
  it 'renders correctly' do
10
10
  context.person = Struct.new(:name).new('Alan')
11
11
  context.company = Struct.new(:name).new('Rad, Inc.')
12
- subject.should == "Alan - Rad, Inc."
12
+ expect(subject).to eq "Alan - Rad, Inc."
13
13
  end
14
14
  end
@@ -7,6 +7,6 @@ describe 'Fixture: comment.hbs' do
7
7
  let(:context) { double(:context) }
8
8
 
9
9
  it 'renders correctly' do
10
- subject.should == "I am a very nice person!"
10
+ expect(subject).to eq "I am a very nice person!"
11
11
  end
12
12
  end
@@ -18,7 +18,7 @@ describe 'Fixture: custom_block_helper.hbs' do
18
18
  end.join ''
19
19
  end
20
20
  FlavourSaver.register_helper(method(:three_times))
21
- subject.should == "1 time. 2 time. 3 time."
21
+ expect(subject).to eq "1 time. 2 time. 3 time."
22
22
  end
23
23
  end
24
24
 
@@ -29,7 +29,7 @@ describe 'Fixture: custom_block_helper.hbs' do
29
29
  b.call.contents i
30
30
  end.join ''
31
31
  }
32
- subject.should == "1 time. 2 time. 3 time."
32
+ expect(subject).to eq "1 time. 2 time. 3 time."
33
33
  end
34
34
  end
35
35
  end
@@ -10,6 +10,6 @@ describe 'Fixture: custom_helper.hbs' do
10
10
  FlavourSaver.register_helper(:say_what_again) do
11
11
  'What?'
12
12
  end
13
- subject.should == "What?"
13
+ expect(subject).to eq "What?"
14
14
  end
15
15
  end
@@ -8,7 +8,7 @@ describe "Can't call methods that the context doesn't respond to" do
8
8
 
9
9
  it 'renders correctly' do
10
10
  expect(Kernel).not_to receive(:system)
11
- expect { subject }.to raise_error
11
+ expect { subject }.to raise_error(RuntimeError)
12
12
  end
13
13
  end
14
14
 
@@ -19,7 +19,7 @@ describe "Can't eval arbitrary Ruby code" do
19
19
 
20
20
  it 'renders correctly' do
21
21
  expect(Kernel).not_to receive(:eval)
22
- expect { subject }.to raise_error
22
+ expect { subject }.to raise_error(RuntimeError)
23
23
  end
24
24
  end
25
25