curlybars 1.12.0 → 1.13.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 +4 -4
- data/lib/curlybars/error/lex.rb +1 -1
- data/lib/curlybars/error/parse.rb +1 -1
- data/lib/curlybars/lexer.rb +3 -3
- data/lib/curlybars/node/path.rb +7 -10
- data/lib/curlybars/path_finder.rb +112 -0
- data/lib/curlybars/presenter.rb +3 -3
- data/lib/curlybars/rendering_support.rb +5 -5
- data/lib/curlybars/template_handler.rb +6 -3
- data/lib/curlybars/version.rb +1 -1
- data/lib/curlybars/visitor.rb +1 -1
- data/lib/curlybars.rb +17 -2
- metadata +9 -137
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ef985c46340022e337318774e4fcf8f36a1f0f7fc6d87788d70ffa3b214f16f
|
|
4
|
+
data.tar.gz: 1bd1f9195be76418bc0b416f6466aa73809f39037d93ccdde901d90ffca14baa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 443143ccfb796e5cc14f4cb4bf2f5c1958b8de9b271c95f8fdfccc07caa169d520e4563e70b5111109f6d914388d18c8c6bd519f837524371f235cb375b10389
|
|
7
|
+
data.tar.gz: fc72c19b12e2084f7e9dab5a01c51d6c6f7ab1614dde449f635356f40fc0841ef3305fd2fb6169763c6333e66324e3486d38f396516325794597b8184801e84a
|
data/lib/curlybars/error/lex.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Curlybars
|
|
|
9
9
|
|
|
10
10
|
error_line = source.split("\n")[line_number - 1]
|
|
11
11
|
before_error = error_line.first(line_offset).last(10)
|
|
12
|
-
after_error = error_line[line_offset + 1..].first(10)
|
|
12
|
+
after_error = error_line[(line_offset + 1)..].first(10)
|
|
13
13
|
error = error_line[line_offset]
|
|
14
14
|
|
|
15
15
|
details = [before_error, error, after_error]
|
|
@@ -16,7 +16,7 @@ module Curlybars
|
|
|
16
16
|
|
|
17
17
|
error_line = source.split("\n")[line_number - 1]
|
|
18
18
|
before_error = error_line.first(line_offset).last(10)
|
|
19
|
-
after_error = error_line[line_offset + length..].first(10)
|
|
19
|
+
after_error = error_line[(line_offset + length)..].first(10)
|
|
20
20
|
error = error_line.slice(line_offset, length)
|
|
21
21
|
|
|
22
22
|
details = [before_error, error, after_error]
|
data/lib/curlybars/lexer.rb
CHANGED
|
@@ -51,10 +51,10 @@ module Curlybars
|
|
|
51
51
|
r(/'(.*?)'/, :curly) { [:LITERAL, match[1].inspect] }
|
|
52
52
|
r(/"(.*?)"/, :curly) { [:LITERAL, match[1].inspect] }
|
|
53
53
|
|
|
54
|
-
r(/@((?:\.\.\/)*#{IDENTIFIER})
|
|
54
|
+
r(/@((?:\.\.\/)*#{IDENTIFIER})/o, :curly) { |variable| [:VARIABLE, match[1]] }
|
|
55
55
|
|
|
56
|
-
r(/(#{IDENTIFIER})\s
|
|
57
|
-
r(/(?:\.\.\/)*(?:#{IDENTIFIER}\.)*#{IDENTIFIER}
|
|
56
|
+
r(/(#{IDENTIFIER})\s*=/o, :curly) { [:KEY, match[1]] }
|
|
57
|
+
r(/(?:\.\.\/)*(?:#{IDENTIFIER}\.)*#{IDENTIFIER}/o, :curly) { |name| [:PATH, name] }
|
|
58
58
|
|
|
59
59
|
r(/\s/, :curly)
|
|
60
60
|
|
data/lib/curlybars/node/path.rb
CHANGED
|
@@ -87,15 +87,12 @@ module Curlybars
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def resolve(branches)
|
|
90
|
-
@value
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return :helper if dep_node.nil?
|
|
95
|
-
|
|
96
|
-
return [:helper, dep_node]
|
|
97
|
-
end
|
|
90
|
+
if !defined?(@value) && Curlybars.global_helpers_dependency_tree.key?(path.to_sym)
|
|
91
|
+
dep_node = Curlybars.global_helpers_dependency_tree[path.to_sym]
|
|
92
|
+
@value = dep_node.nil? ? :helper : [:helper, dep_node]
|
|
93
|
+
end
|
|
98
94
|
|
|
95
|
+
@value ||= begin
|
|
99
96
|
path_split_by_slashes = path.split('/')
|
|
100
97
|
backward_steps_on_branches = path_split_by_slashes.count - 1
|
|
101
98
|
base_tree_position = branches.length - backward_steps_on_branches
|
|
@@ -108,10 +105,10 @@ module Curlybars
|
|
|
108
105
|
dotted_path_side = path_split_by_slashes.last
|
|
109
106
|
|
|
110
107
|
offset_adjustment = 0
|
|
111
|
-
dotted_path_side.split(
|
|
108
|
+
dotted_path_side.split(".").map(&:to_sym).inject(base_tree) do |sub_tree, step|
|
|
112
109
|
if step == :this
|
|
113
110
|
next sub_tree
|
|
114
|
-
elsif step == :length &&
|
|
111
|
+
elsif step == :length && sub_tree.is_a?(Array) && sub_tree.first.is_a?(Hash)
|
|
115
112
|
next nil # :length is synthesised leaf
|
|
116
113
|
elsif !(sub_tree.is_a?(Hash) && sub_tree.key?(step))
|
|
117
114
|
message = step.to_s == path ? "'#{path}' does not exist" : "not possible to access `#{step}` in `#{path}`"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Curlybars
|
|
2
|
+
class PathFinder
|
|
3
|
+
def initialize(ast)
|
|
4
|
+
@ast = ast
|
|
5
|
+
@matches = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def find(target_path)
|
|
9
|
+
@matches = []
|
|
10
|
+
@target_segments = normalize_path(target_path)
|
|
11
|
+
traverse(@ast.template, [])
|
|
12
|
+
@matches
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def normalize_path(path)
|
|
18
|
+
return path if path.is_a?(Array)
|
|
19
|
+
|
|
20
|
+
path.to_s.split('.')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def traverse(node, context_stack)
|
|
24
|
+
return unless node
|
|
25
|
+
|
|
26
|
+
case node
|
|
27
|
+
when Curlybars::Node::Template
|
|
28
|
+
node.items.each { |item| traverse(item, context_stack) }
|
|
29
|
+
when Curlybars::Node::Item
|
|
30
|
+
traverse(node.item, context_stack)
|
|
31
|
+
when Curlybars::Node::Path
|
|
32
|
+
check_path_match(node, context_stack)
|
|
33
|
+
when Curlybars::Node::Output
|
|
34
|
+
traverse(node.value, context_stack)
|
|
35
|
+
when Curlybars::Node::Partial
|
|
36
|
+
traverse(node.path, context_stack)
|
|
37
|
+
when Curlybars::Node::SubExpression
|
|
38
|
+
traverse(node.helper, context_stack)
|
|
39
|
+
node.arguments&.each { |arg| traverse(arg, context_stack) }
|
|
40
|
+
node.options&.each { |opt| traverse(opt.expression, context_stack) }
|
|
41
|
+
when Curlybars::Node::BlockHelperElse
|
|
42
|
+
handle_block_helper(node, context_stack)
|
|
43
|
+
when Curlybars::Node::IfElse, Curlybars::Node::UnlessElse
|
|
44
|
+
handle_conditional(node, context_stack)
|
|
45
|
+
when Curlybars::Node::EachElse
|
|
46
|
+
handle_each(node, context_stack)
|
|
47
|
+
when Curlybars::Node::WithElse
|
|
48
|
+
handle_with(node, context_stack)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def check_path_match(path_node, context_stack)
|
|
53
|
+
path_segments = path_node.path.split('.')
|
|
54
|
+
resolved_segments = resolve_path(path_segments, context_stack)
|
|
55
|
+
|
|
56
|
+
@matches << path_node if resolved_segments == @target_segments
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def resolve_path(path_segments, context_stack)
|
|
60
|
+
full_path = path_segments.join('.')
|
|
61
|
+
stack = context_stack.dup
|
|
62
|
+
|
|
63
|
+
# Handle ../ parent navigation
|
|
64
|
+
while full_path.start_with?('../')
|
|
65
|
+
full_path = full_path[3..]
|
|
66
|
+
stack.pop unless stack.empty?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
remaining_segments = full_path.empty? ? [] : full_path.split('.')
|
|
70
|
+
stack + remaining_segments
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def handle_block_helper(node, context_stack)
|
|
74
|
+
traverse(node.helper, context_stack)
|
|
75
|
+
traverse(node.helper_template, context_stack)
|
|
76
|
+
traverse(node.else_template, context_stack) if node.else_template
|
|
77
|
+
node.arguments&.each { |arg| traverse(arg, context_stack) }
|
|
78
|
+
node.options&.each { |opt| traverse(opt.expression, context_stack) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def handle_conditional(node, context_stack)
|
|
82
|
+
traverse(node.expression, context_stack)
|
|
83
|
+
|
|
84
|
+
if node.is_a?(Curlybars::Node::IfElse)
|
|
85
|
+
traverse(node.if_template, context_stack)
|
|
86
|
+
elsif node.is_a?(Curlybars::Node::UnlessElse)
|
|
87
|
+
traverse(node.unless_template, context_stack)
|
|
88
|
+
end
|
|
89
|
+
traverse(node.else_template, context_stack) if node.else_template
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def handle_each(node, context_stack)
|
|
93
|
+
traverse(node.path, context_stack)
|
|
94
|
+
|
|
95
|
+
# EachElse changes context to the item being iterated
|
|
96
|
+
collection_path = node.path.respond_to?(:subexpression?) && node.path.subexpression? ? node.path.helper : node.path
|
|
97
|
+
new_context = context_stack + collection_path.path.split('.')
|
|
98
|
+
traverse(node.each_template, new_context)
|
|
99
|
+
traverse(node.else_template, context_stack) if node.else_template
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def handle_with(node, context_stack)
|
|
103
|
+
traverse(node.path, context_stack)
|
|
104
|
+
|
|
105
|
+
# WithElse changes context to the specified path
|
|
106
|
+
presenter_path = node.path.respond_to?(:subexpression?) && node.path.subexpression? ? node.path.helper : node.path
|
|
107
|
+
new_context = context_stack + presenter_path.path.split('.')
|
|
108
|
+
traverse(node.with_template, new_context)
|
|
109
|
+
traverse(node.else_template, context_stack) if node.else_template
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/curlybars/presenter.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Curlybars
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
instance_variable_set("@#{name}", value)
|
|
63
|
+
instance_variable_set(:"@#{name}", value)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
@@ -276,8 +276,8 @@ module Curlybars
|
|
|
276
276
|
# Delegates private method calls to the current view context.
|
|
277
277
|
#
|
|
278
278
|
# The view context, an instance of ActionView::Base, is set by Rails.
|
|
279
|
-
def method_missing(method,
|
|
280
|
-
@_context.public_send(method,
|
|
279
|
+
def method_missing(method, ...)
|
|
280
|
+
@_context.public_send(method, ...)
|
|
281
281
|
end
|
|
282
282
|
|
|
283
283
|
# Tells ruby (and developers) what methods we can accept.
|
|
@@ -140,15 +140,15 @@ module Curlybars
|
|
|
140
140
|
check_context_is_hash_or_enum_of_presenters(collection, path, position)
|
|
141
141
|
if collection.is_a?(Hash)
|
|
142
142
|
collection
|
|
143
|
-
elsif collection.respond_to?
|
|
144
|
-
collection.each_with_index.
|
|
143
|
+
elsif collection.respond_to?(:each_with_index)
|
|
144
|
+
collection.each_with_index.to_h { |value, index| [index, value] }
|
|
145
145
|
else
|
|
146
146
|
raise "Collection is not coerceable to hash"
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def presenter?(context)
|
|
151
|
-
context.respond_to?
|
|
151
|
+
context.respond_to?(:allows_method?)
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
def presenter_collection?(collection)
|
|
@@ -180,12 +180,12 @@ module Curlybars
|
|
|
180
180
|
|
|
181
181
|
attr_reader :contexts, :variables, :cached_calls, :file_name, :global_helpers, :start_time, :timeout, :cache
|
|
182
182
|
|
|
183
|
-
def instrument(meth, &
|
|
183
|
+
def instrument(meth, &)
|
|
184
184
|
# Instruments only callables that give enough details (eg. methods)
|
|
185
185
|
return yield unless meth.respond_to?(:name) && meth.respond_to?(:owner)
|
|
186
186
|
|
|
187
187
|
payload = { presenter: meth.owner, method: meth.name }
|
|
188
|
-
ActiveSupport::Notifications.instrument("call_to_presenter.curlybars", payload, &
|
|
188
|
+
ActiveSupport::Notifications.instrument("call_to_presenter.curlybars", payload, &)
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
def arguments_for_signature(helper, arguments, options)
|
|
@@ -43,6 +43,9 @@ module Curlybars
|
|
|
43
43
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
|
+
LEADING_ENCODING_REGEXP = /\A#{ActionView::ENCODING_FLAG}/
|
|
47
|
+
private_constant :LEADING_ENCODING_REGEXP
|
|
48
|
+
|
|
46
49
|
def compile(template, source)
|
|
47
50
|
# Template is empty, so there's no need to initialize a presenter.
|
|
48
51
|
return %("") if source.empty?
|
|
@@ -55,7 +58,7 @@ module Curlybars
|
|
|
55
58
|
# For security reason, we strip the encoding directive in order to avoid
|
|
56
59
|
# potential issues when rendering the template in another character
|
|
57
60
|
# encoding.
|
|
58
|
-
safe_source = source.
|
|
61
|
+
safe_source = source.sub(LEADING_ENCODING_REGEXP, '')
|
|
59
62
|
|
|
60
63
|
source = Curlybars.compile(safe_source, template.identifier)
|
|
61
64
|
|
|
@@ -84,9 +87,9 @@ module Curlybars
|
|
|
84
87
|
RUBY
|
|
85
88
|
end
|
|
86
89
|
|
|
87
|
-
def instrument(template, &
|
|
90
|
+
def instrument(template, &)
|
|
88
91
|
payload = { path: template.virtual_path }
|
|
89
|
-
ActiveSupport::Notifications.instrument("compile.curlybars", payload, &
|
|
92
|
+
ActiveSupport::Notifications.instrument("compile.curlybars", payload, &)
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
95
|
end
|
data/lib/curlybars/version.rb
CHANGED
data/lib/curlybars/visitor.rb
CHANGED
data/lib/curlybars.rb
CHANGED
|
@@ -63,8 +63,8 @@ module Curlybars
|
|
|
63
63
|
# identifier - The the file name of the template being checked (defaults to `nil`).
|
|
64
64
|
#
|
|
65
65
|
# Returns true if the template is valid, false otherwise.
|
|
66
|
-
def valid?(presenter_class, source, identifier = nil, **
|
|
67
|
-
errors = validate(presenter_class, source, identifier, **
|
|
66
|
+
def valid?(presenter_class, source, identifier = nil, **)
|
|
67
|
+
errors = validate(presenter_class, source, identifier, **)
|
|
68
68
|
errors.empty?
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -78,6 +78,20 @@ module Curlybars
|
|
|
78
78
|
visitor.accept(tree)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
# Find all path nodes in the AST that resolve to a given path.
|
|
82
|
+
# Takes into account contextual scope from block helpers like #with, #each, etc.
|
|
83
|
+
#
|
|
84
|
+
# target_path - The path String to search for (e.g., "user.name" or "user.organizations.id").
|
|
85
|
+
# source - The source HBS String used to generate an AST.
|
|
86
|
+
# identifier - The the file name of the template being checked (defaults to `nil`).
|
|
87
|
+
#
|
|
88
|
+
# Returns an Array of Curlybars::Node::Path instances that match the target path.
|
|
89
|
+
def find(target_path, source, identifier = nil)
|
|
90
|
+
tree = ast(transformed_source(source), identifier, run_processors: true)
|
|
91
|
+
finder = Curlybars::PathFinder.new(tree)
|
|
92
|
+
finder.find(target_path)
|
|
93
|
+
end
|
|
94
|
+
|
|
81
95
|
def global_helpers_dependency_tree
|
|
82
96
|
@global_helpers_dependency_tree ||= begin
|
|
83
97
|
classes = Curlybars.configuration.global_helpers_provider_classes
|
|
@@ -139,3 +153,4 @@ require 'curlybars/railtie' if defined?(Rails)
|
|
|
139
153
|
require 'curlybars/presenter'
|
|
140
154
|
require 'curlybars/method_whitelist'
|
|
141
155
|
require 'curlybars/visitor'
|
|
156
|
+
require 'curlybars/path_finder'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: curlybars
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Libo Cannici
|
|
@@ -12,10 +12,9 @@ authors:
|
|
|
12
12
|
- Andreas Garnæs
|
|
13
13
|
- Augusto Silva
|
|
14
14
|
- Attila Večerek
|
|
15
|
-
autorequire:
|
|
16
15
|
bindir: bin
|
|
17
16
|
cert_chain: []
|
|
18
|
-
date:
|
|
17
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
19
18
|
dependencies:
|
|
20
19
|
- !ruby/object:Gem::Dependency
|
|
21
20
|
name: actionpack
|
|
@@ -23,28 +22,28 @@ dependencies:
|
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
25
|
+
version: '7.2'
|
|
27
26
|
type: :runtime
|
|
28
27
|
prerelease: false
|
|
29
28
|
version_requirements: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - ">="
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
32
|
+
version: '7.2'
|
|
34
33
|
- !ruby/object:Gem::Dependency
|
|
35
34
|
name: activesupport
|
|
36
35
|
requirement: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
39
|
+
version: '7.2'
|
|
41
40
|
type: :runtime
|
|
42
41
|
prerelease: false
|
|
43
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
44
|
- - ">="
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
46
|
+
version: '7.2'
|
|
48
47
|
- !ruby/object:Gem::Dependency
|
|
49
48
|
name: ffi
|
|
50
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -73,132 +72,6 @@ dependencies:
|
|
|
73
72
|
- - ">="
|
|
74
73
|
- !ruby/object:Gem::Version
|
|
75
74
|
version: '0'
|
|
76
|
-
- !ruby/object:Gem::Dependency
|
|
77
|
-
name: bundler
|
|
78
|
-
requirement: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - ">="
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0'
|
|
83
|
-
type: :development
|
|
84
|
-
prerelease: false
|
|
85
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - ">="
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
90
|
-
- !ruby/object:Gem::Dependency
|
|
91
|
-
name: byebug
|
|
92
|
-
requirement: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - ">="
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0'
|
|
97
|
-
type: :development
|
|
98
|
-
prerelease: false
|
|
99
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - ">="
|
|
102
|
-
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0'
|
|
104
|
-
- !ruby/object:Gem::Dependency
|
|
105
|
-
name: railties
|
|
106
|
-
requirement: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - ">="
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '6.0'
|
|
111
|
-
type: :development
|
|
112
|
-
prerelease: false
|
|
113
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - ">="
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '6.0'
|
|
118
|
-
- !ruby/object:Gem::Dependency
|
|
119
|
-
name: rake
|
|
120
|
-
requirement: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - ">="
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '0'
|
|
125
|
-
type: :development
|
|
126
|
-
prerelease: false
|
|
127
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - ">="
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '0'
|
|
132
|
-
- !ruby/object:Gem::Dependency
|
|
133
|
-
name: rspec-rails
|
|
134
|
-
requirement: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - ">="
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: '0'
|
|
139
|
-
type: :development
|
|
140
|
-
prerelease: false
|
|
141
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - ">="
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0'
|
|
146
|
-
- !ruby/object:Gem::Dependency
|
|
147
|
-
name: rubocop
|
|
148
|
-
requirement: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - "~>"
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '1.57'
|
|
153
|
-
type: :development
|
|
154
|
-
prerelease: false
|
|
155
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - "~>"
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '1.57'
|
|
160
|
-
- !ruby/object:Gem::Dependency
|
|
161
|
-
name: rubocop-performance
|
|
162
|
-
requirement: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - "~>"
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '1.19'
|
|
167
|
-
type: :development
|
|
168
|
-
prerelease: false
|
|
169
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - "~>"
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: '1.19'
|
|
174
|
-
- !ruby/object:Gem::Dependency
|
|
175
|
-
name: rubocop-rake
|
|
176
|
-
requirement: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - "~>"
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: '0.6'
|
|
181
|
-
type: :development
|
|
182
|
-
prerelease: false
|
|
183
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
184
|
-
requirements:
|
|
185
|
-
- - "~>"
|
|
186
|
-
- !ruby/object:Gem::Version
|
|
187
|
-
version: '0.6'
|
|
188
|
-
- !ruby/object:Gem::Dependency
|
|
189
|
-
name: rubocop-rspec
|
|
190
|
-
requirement: !ruby/object:Gem::Requirement
|
|
191
|
-
requirements:
|
|
192
|
-
- - "~>"
|
|
193
|
-
- !ruby/object:Gem::Version
|
|
194
|
-
version: '2.25'
|
|
195
|
-
type: :development
|
|
196
|
-
prerelease: false
|
|
197
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
198
|
-
requirements:
|
|
199
|
-
- - "~>"
|
|
200
|
-
- !ruby/object:Gem::Version
|
|
201
|
-
version: '2.25'
|
|
202
75
|
description: |-
|
|
203
76
|
A view layer for your Rails apps that separates structure and logic, using Handlebars templates.
|
|
204
77
|
Strongly inspired by Curly Template gem by Daniel Schierbeck.
|
|
@@ -239,6 +112,7 @@ files:
|
|
|
239
112
|
- lib/curlybars/node/variable.rb
|
|
240
113
|
- lib/curlybars/node/with_else.rb
|
|
241
114
|
- lib/curlybars/parser.rb
|
|
115
|
+
- lib/curlybars/path_finder.rb
|
|
242
116
|
- lib/curlybars/position.rb
|
|
243
117
|
- lib/curlybars/presenter.rb
|
|
244
118
|
- lib/curlybars/processor/tilde.rb
|
|
@@ -253,7 +127,6 @@ homepage: https://github.com/zendesk/curlybars
|
|
|
253
127
|
licenses:
|
|
254
128
|
- Apache-2.0
|
|
255
129
|
metadata: {}
|
|
256
|
-
post_install_message:
|
|
257
130
|
rdoc_options:
|
|
258
131
|
- "--charset=UTF-8"
|
|
259
132
|
require_paths:
|
|
@@ -262,15 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
262
135
|
requirements:
|
|
263
136
|
- - ">="
|
|
264
137
|
- !ruby/object:Gem::Version
|
|
265
|
-
version: '3.
|
|
138
|
+
version: '3.2'
|
|
266
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
140
|
requirements:
|
|
268
141
|
- - ">="
|
|
269
142
|
- !ruby/object:Gem::Version
|
|
270
143
|
version: '0'
|
|
271
144
|
requirements: []
|
|
272
|
-
rubygems_version: 3.
|
|
273
|
-
signing_key:
|
|
145
|
+
rubygems_version: 3.6.9
|
|
274
146
|
specification_version: 4
|
|
275
147
|
summary: Create your views using Handlebars templates!
|
|
276
148
|
test_files: []
|