flavour_saver 0.3.6 → 1.0.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.
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