antlers 1.1.0 → 1.1.1

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
2
  SHA256:
3
- metadata.gz: 375ebfb2e841c81843bb17b1025d8cd43dbe851f803f4845afb73f6d24f8ef30
4
- data.tar.gz: a7db1372364cb6633b6ce6ae2492966ecf1c6d2a20f3d7af214ce14e18feda21
3
+ metadata.gz: 3c1e20787d49349b0f3df0f6df128650c7214ec53cd697ec66840d6f3884d9e8
4
+ data.tar.gz: 3048610d15b4fe61ff67123aba2b6f81a5ef9019e4ac03dea657995c30501b17
5
5
  SHA512:
6
- metadata.gz: c0b9b231ebe71d01f50443bebcec9210c3f97fe238138d172974ef5c298d5c543af1371a3806f45e54cc8e5a6a8cb32d6e51e17547465ed96682a633393c0ca4
7
- data.tar.gz: d7c42c19f7c1aa9a5bcb27d30fe2fe0118054897bb5e2388f266b7127bf6c89bdc35b7da4fa20e39f969a20f6a7a2ce9c6e8325ac32e0a9f78720b85a06bb21c
6
+ metadata.gz: bc0ff003117d8d08b22146b15a32f32288aef44191ba401080db525ed3125e6a7cc38fd278b64eb96eda1659d7b608cbf41f4b9a1879c8641eecf0f3fa4fc83d
7
+ data.tar.gz: e0a5d0d1c71721a4727b3f6134a1eafb40b75b34cff799cc5f2d94677cbf84b6e41dad3b6d8ad5bee5293ca1b1de10969d8e6af1d8cc19c6889b0dc0dbaca71b
data/lib/antlers/lexer.rb CHANGED
@@ -73,7 +73,7 @@ module Antlers
73
73
 
74
74
  while (keyword = keywords.shift)
75
75
  keyword.strip!
76
- value = keyword.end_with?(':') && value?(keywords.first.strip) ? keywords.shift.strip : nil
76
+ value = keyword.end_with?(':') && value?(keywords.first) ? keywords.shift.strip : nil
77
77
  key_values[keyword] = value
78
78
  end
79
79
 
@@ -81,7 +81,9 @@ module Antlers
81
81
  end
82
82
 
83
83
  def value?(string)
84
- !(string.start_with?(':') || string.end_with?(':'))
84
+ # Support keywords without a value like "<{ form: }>" whose value will become an empty string.
85
+ string = string.to_s.strip
86
+ !string.empty? && !(string.start_with?(':') || string.end_with?(':'))
85
87
  end
86
88
 
87
89
  def brackets?(segments:)
@@ -36,7 +36,13 @@ module Antlers
36
36
 
37
37
  def sub_branch(node:, sequence:, end_key:, end_name: nil)
38
38
  sub_sequence = []
39
- sub_sequence << sequence.shift until sequence.first.is_a?(Hash) && sequence.first[end_key] == end_name
39
+
40
+ until sequence.first.is_a?(Hash) && sequence.first[end_key] == end_name
41
+ raise ParserError, "Missing end tag for #{node.class}" if sequence.empty?
42
+
43
+ sub_sequence << sequence.shift
44
+ end
45
+
40
46
  # Remove the end tag we just stopped before.
41
47
  sequence.shift
42
48
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Antlers
4
- VERSION = '1.1.0'
4
+ VERSION = '1.1.1'
5
5
  end
data/lib/antlers.rb CHANGED
@@ -7,7 +7,7 @@ require_relative 'antlers/parser'
7
7
  module Antlers
8
8
  module_function
9
9
 
10
- DEFAULT_ELEMENTS = %i[root html form for if prop slot yield var]
10
+ DEFAULT_ELEMENTS = %i[root html form for if prop slot yield var].freeze
11
11
 
12
12
  def ast(template:, namespace: nil, elements: Elements[*DEFAULT_ELEMENTS])
13
13
  sequence = Lexer.new(lexeme_types: elements[:lexeme]).parse(template:)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Antlers
4
4
  module Lexeme
5
- KEYWORDS = []
5
+ KEYWORDS = [].freeze
6
6
 
7
7
  def match?(name: nil, keywords: {}) = false
8
8
 
@@ -14,10 +14,7 @@ module Antlers
14
14
  end
15
15
 
16
16
  def lexeme(keywords:, **)
17
- if keywords.key?('form:')
18
- action = keywords['form:'] ? keywords['form:'][1...-1] : nil
19
- return { form_def: action }
20
- end
17
+ return { form_def: keywords['form:'] } if keywords.key?('form:')
21
18
 
22
19
  { form_end: 'level_1' }
23
20
  end
@@ -9,15 +9,12 @@ module Antlers
9
9
  extend Queries
10
10
  extend self
11
11
 
12
- # Variables are special and are matched by the lexer.
12
+ # Variables are special and are matched by the lexer in a hard-coded fashion.
13
13
  def match?(**)
14
14
  false
15
15
  end
16
16
 
17
17
  def lexeme(segment:, raw:, **)
18
- # String is already interpolated or not depending on user input on the template layer, now we store it without those template quotes.
19
- segment = segment[1..-2] if Queries.user_defined_string?(segment)
20
-
21
18
  return { raw_var: segment } if raw
22
19
 
23
20
  { var: segment }
data/lib/modules/props.rb CHANGED
@@ -22,7 +22,7 @@ module Antlers
22
22
  evaluated_props = {}
23
23
 
24
24
  props.each do |name, value|
25
- evaluated_props[name] = evaluate(name: value, current_binding:) || fallback(value)
25
+ evaluated_props[name] = evaluate(value:, current_binding:)
26
26
  end
27
27
 
28
28
  evaluated_props
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'erb'
3
4
  require_relative '../support/queries'
4
5
 
5
6
  module Antlers
@@ -7,28 +8,29 @@ module Antlers
7
8
  extend Queries
8
9
 
9
10
  # Evaluation limited to the following for security and to stop a templating language becoming a programming language.
10
- # 1. An instance variable
11
- # 2. A method call/local variable
12
- # 3. A method chain
13
- # 4. A static string
14
- def evaluate(name:, current_binding:)
15
- return name.to_s unless current_binding
11
+ # 1. A static string
12
+ # 2. An instance variable
13
+ # 3. A method call/local variable
14
+ # 4. A method chain
15
+ def evaluate(value:, current_binding:, escape: true)
16
+ result = result(value:, current_binding:)
16
17
 
17
- name, *chain = name.split('.')
18
+ return ERB::Util.html_escape(result) if escape
19
+
20
+ result
21
+ end
22
+
23
+ def result(value:, current_binding:)
24
+ return value[1..-2] if Queries.user_defined_string?(value)
25
+ return value unless current_binding
26
+
27
+ name, *chain = value.split('.')
18
28
 
19
29
  result = method_var(name:, current_binding:)
20
30
  return method_chain(result:, chain:) if chain.count > 0
21
31
  return result if result
22
32
 
23
33
  nil
24
- rescue StandardError
25
- nil
26
- end
27
-
28
- def fallback(value)
29
- return value[1..-2] if Queries.user_defined_string?(value)
30
-
31
- value
32
34
  end
33
35
 
34
36
  private
@@ -23,7 +23,7 @@ module Antlers
23
23
  def render(current_binding: nil, parent_binding: nil, slot_node: nil, metadata: {})
24
24
  output = ''
25
25
 
26
- evaluate(name: @items, current_binding:).each do |value|
26
+ evaluate(value: @items, current_binding:, escape: false).each do |value|
27
27
  key, value = value if @key
28
28
 
29
29
  # TODO: Parallelize by creating new bindings and ensuring children have any args they need via RenderEvent.
@@ -20,7 +20,7 @@ module Antlers
20
20
  end
21
21
 
22
22
  def render(current_binding: nil, parent_binding: nil, slot_node: nil, metadata: {})
23
- output = "<form action='#{@action}' method='#{@method}'>"
23
+ output = "<form action='#{action(current_binding:)}' method='#{@method}'>"
24
24
 
25
25
  @children.each do |child|
26
26
  output += child.render(current_binding:, parent_binding:, slot_node:, metadata:) || ''
@@ -30,9 +30,17 @@ module Antlers
30
30
  output
31
31
  end
32
32
 
33
+ private
34
+
35
+ def action(current_binding:)
36
+ return if @action.nil?
37
+
38
+ evaluate(value: @action, current_binding:)
39
+ end
40
+
33
41
  class << self
34
42
  def match?(segment:)
35
- segment[DEF_KEY]
43
+ segment.is_a?(Hash) && segment.key?(DEF_KEY)
36
44
  end
37
45
 
38
46
  def build(segment:, **)
data/lib/nodes/if_node.rb CHANGED
@@ -21,7 +21,7 @@ module Antlers
21
21
  def render(current_binding: nil, parent_binding: nil, slot_node: nil, metadata: {})
22
22
  output = ''.dup
23
23
 
24
- if evaluate(name: @value, current_binding:)
24
+ if evaluate(value: @value, current_binding:, escape: false)
25
25
  @children.each do |child|
26
26
  output += child.render(current_binding:, parent_binding:, slot_node:, metadata:) || ''
27
27
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erb'
4
-
5
3
  require_relative '../interfaces/leaf_node'
6
4
  require_relative '../modules/variables'
7
5
 
@@ -19,11 +17,7 @@ module Antlers
19
17
  end
20
18
 
21
19
  def render(current_binding: nil, parent_binding: nil, slot_node: nil, metadata: {})
22
- result = evaluate(name: @value, current_binding:) || fallback(@value)
23
-
24
- return result if @raw
25
-
26
- ERB::Util.html_escape(result)
20
+ evaluate(value: @value, current_binding:, escape: !@raw)
27
21
  end
28
22
 
29
23
  class << self
@@ -32,7 +26,7 @@ module Antlers
32
26
  end
33
27
 
34
28
  def build(segment:, **)
35
- new(value: segment[:var] || segment[:raw_var], raw: !!segment[:raw_var])
29
+ new(value: segment[:var] || segment[:raw_var], raw: !segment[:raw_var].nil?)
36
30
  end
37
31
  end
38
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: antlers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi