antlers 0.7.0 → 0.8.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
2
  SHA256:
3
- metadata.gz: 4e01a292dd41ce2f99fd7a6bdd5a375d3d2c36a3e4d5280ccaaaf91be9bcde38
4
- data.tar.gz: 84227a375d02da8663bfdf04efaf496be097f7898840d25bc4f02b0c62bc2fff
3
+ metadata.gz: b0d88855d8351d4ce9b4ebf2bfeaf0fc05faef8a33a882ffd206fa1c8241ec9e
4
+ data.tar.gz: e72f72db347e9f0f442e0a15cb4dce3f2c7405bf1bd7da6b33ab919a7003785b
5
5
  SHA512:
6
- metadata.gz: c449e355a550e43aa65e1e00ba482e858b07a1fb0f983325808a538769d6e8eb78ed5dad4a5a3fdd3f24348db7001e59876894b2a98d882e38dd9fa10078104a
7
- data.tar.gz: 5f71032b3da08b3675f52045f513a810bf2228a1c3308ce7dcde2c53596f7525060dbbd34d05ffb1b04cf8672c045a9e117b727f58a972361a32603e53c2d6ff
6
+ metadata.gz: 6f1e6d6f8f512d327ee25068a3286d8f1e557407bf99f4ec274cd8c8e7336ef9c2d9db9980e66d13ce58b8055d07f6908108afcb8cd91d2da65224ac567946d4
7
+ data.tar.gz: 27520e044188ae13cde780d7438286e510dae3874cd2218debf2901a1b3c7e9909847c44ae38ce4353e8b0482afa2516fa47857836070a58e8683934865a58c7
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../nodes/if_node'
3
4
  require_relative '../nodes/for_node'
4
5
  require_relative '../nodes/form_node'
5
6
  require_relative '../nodes/prop_node'
@@ -13,6 +14,10 @@ module Antlers
13
14
  @namespace = namespace
14
15
  end
15
16
 
17
+ def if_node(segment:)
18
+ IfNode.new(name: segment[:if_def], value: segment[:if_def])
19
+ end
20
+
16
21
  def for_node(segment:)
17
22
  value, key, items = segment.values_at(:for_def, :key, :in)
18
23
  ForNode.new(name: value, key:, value:, items:)
@@ -37,6 +42,10 @@ module Antlers
37
42
  VarNode.new(value: segment[:var])
38
43
  end
39
44
 
45
+ def raw_var_node(segment:)
46
+ VarNode.new(value: segment[:raw_var], raw: true)
47
+ end
48
+
40
49
  def yield_node(segment:)
41
50
  YieldNode.new(name: segment[:slot])
42
51
  end
data/lib/lexer.rb CHANGED
@@ -8,12 +8,13 @@ module Antlers
8
8
  class LexerParseError < StandardError; end
9
9
 
10
10
  class Lexer
11
+ IF_KEYWORDS = ['if:', ':if'].freeze
11
12
  FOR_KEYWORDS = ['for:', 'in:', ':for'].freeze
12
13
  FORM_KEYWORDS = ['form:', ':form'].freeze
13
14
 
14
15
  def initialize
15
16
  @delimiters = ['<{', '}>', '{', '}']
16
- @keywords = ['if:', *FORM_KEYWORDS, *FOR_KEYWORDS, 'slot:', ':slot']
17
+ @keywords = [*IF_KEYWORDS, *FORM_KEYWORDS, *FOR_KEYWORDS, 'slot:', ':slot']
17
18
  @cursor = 0
18
19
  end
19
20
 
@@ -44,21 +45,23 @@ module Antlers
44
45
 
45
46
  def antlers_segment(segments:)
46
47
  next_segment = segments[@cursor + 1]
47
- return nil unless next_segment && (segments[@cursor] == '<{' || var?(segments:))
48
+ return nil unless next_segment && (segments[@cursor] == '<{' || brackets?(segments:))
48
49
 
49
50
  next_segment
50
51
  end
51
52
 
52
53
  def antlers_lexeme(antlers_segment:, segments:)
53
- return var(antlers_segment:) if var?(segments:)
54
+ return var(antlers_segment:) if brackets?(segments:)
54
55
 
55
56
  name, props, keywords = parse_segment(antlers_segment:)
56
57
 
57
58
  return slot_yield if slot_yield?(keywords:)
58
59
  return slot(name:, props:) if slot?(name)
59
60
  return prop(name:, props:) if prop?(name)
61
+ return if_block(keywords:) if if_block?(keywords:)
60
62
  return for_loop(keywords:) if for_loop?(keywords:)
61
63
  return form(keywords:) if form?(keywords:)
64
+ return var(antlers_segment:, raw: true) if deerheads?(segments:)
62
65
 
63
66
  raise LexerParseError, "Unrecognised syntax: '#{antlers_segment}'"
64
67
  end
@@ -87,11 +90,20 @@ module Antlers
87
90
 
88
91
  # TODO: Refactor every constant, match and result method into its own class. Loop through every class and return the first match.
89
92
 
90
- def var?(segments:)
93
+ def brackets?(segments:)
91
94
  first, _, last = segments[@cursor..@cursor + 3].map(&:strip)
92
95
  first == '{' && last == '}'
93
96
  end
94
97
 
98
+ def deerheads?(segments:)
99
+ first, _, last = segments[@cursor..@cursor + 3].map(&:strip)
100
+ first == '<{' && last == '}>'
101
+ end
102
+
103
+ def if_block?(keywords:)
104
+ IF_KEYWORDS.include?(keywords.keys.first)
105
+ end
106
+
95
107
  def for_loop?(keywords:)
96
108
  FOR_KEYWORDS.include?(keywords.keys.first)
97
109
  end
@@ -112,13 +124,21 @@ module Antlers
112
124
  name && [*'A'..'Z'].include?(name[0])
113
125
  end
114
126
 
115
- def var(antlers_segment:)
127
+ def var(antlers_segment:, raw: false)
116
128
  # String is already interpolated or not depending on user input on the template layer, now we store it without those template quotes.
117
129
  antlers_segment = antlers_segment[1..-2] if Queries.user_defined_string?(antlers_segment)
118
130
 
131
+ return { raw_var: antlers_segment } if raw
132
+
119
133
  { var: antlers_segment }
120
134
  end
121
135
 
136
+ def if_block(keywords:)
137
+ return { if_def: keywords['if:'] } if keywords.key?('if:')
138
+
139
+ { if_end: 'level_1' }
140
+ end
141
+
122
142
  def for_loop(keywords:)
123
143
  if keywords['for:']
124
144
  *key, value = keywords['for:'].split(',').map(&:strip)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../interfaces/branch_node'
4
+ require_relative '../modules/props'
5
+ require_relative '../modules/variables'
6
+
7
+ module Antlers
8
+ class IfNode < BranchNode
9
+ include Props
10
+ include Variables
11
+
12
+ def initialize(name:, value:, props: [], children: [])
13
+ super(name:, props:, children:)
14
+
15
+ @value = value
16
+ end
17
+
18
+ def render(current_binding: nil, parent_binding: nil, slot_node: nil)
19
+ output = ''.dup
20
+
21
+ if evaluate(name: @value, current_binding:)
22
+ @children.each do |child|
23
+ # Antlers nodes respond to "render", whereas HTML is stored as a string and output as is.
24
+ output += (child.respond_to?(:render) ? child.render(current_binding:, parent_binding:, slot_node:) : child) || ''
25
+ end
26
+ end
27
+
28
+ output
29
+ end
30
+ end
31
+ end
@@ -11,14 +11,19 @@ module Antlers
11
11
 
12
12
  attr_reader :value
13
13
 
14
- def initialize(value:, name: :var)
14
+ def initialize(value:, name: :var, raw: false)
15
15
  super(name:)
16
16
 
17
17
  @value = value
18
+ @raw = raw
18
19
  end
19
20
 
20
21
  def render(current_binding: nil, parent_binding: nil, slot_node: nil)
21
- ERB::Util.html_escape(evaluate(name: @value, current_binding:) || fallback(@value))
22
+ result = evaluate(name: @value, current_binding:) || fallback(@value)
23
+
24
+ return result if @raw
25
+
26
+ ERB::Util.html_escape(result)
22
27
  end
23
28
  end
24
29
  end
data/lib/parser.rb CHANGED
@@ -21,6 +21,8 @@ module Antlers
21
21
  node.children << segment
22
22
  elsif segment[:var]
23
23
  node.children << @factory.var_node(segment:)
24
+ elsif segment[:raw_var]
25
+ node.children << @factory.raw_var_node(segment:)
24
26
  elsif segment[:prop]
25
27
  node.children << @factory.prop_node(segment:)
26
28
  elsif segment[:slot]
@@ -29,6 +31,10 @@ module Antlers
29
31
  slot_node = @factory.slot_node(segment:)
30
32
  node.children << slot_node
31
33
  sub_branch(node: slot_node, sequence:, end_key: :slot_end, end_name: slot_node.name)
34
+ elsif segment[:if_def]
35
+ if_node = @factory.if_node(segment:)
36
+ node.children << if_node
37
+ sub_branch(node: if_node, sequence:, end_key: :if_end, end_name: 'level_1')
32
38
  elsif segment[:for_def]
33
39
  for_node = @factory.for_node(segment:)
34
40
  node.children << for_node
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Antlers
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  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: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi
@@ -70,6 +70,7 @@ files:
70
70
  - lib/modules/variables.rb
71
71
  - lib/nodes/for_node.rb
72
72
  - lib/nodes/form_node.rb
73
+ - lib/nodes/if_node.rb
73
74
  - lib/nodes/prop_node.rb
74
75
  - lib/nodes/root_node.rb
75
76
  - lib/nodes/slot_node.rb