rblade 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/TODO.md ADDED
@@ -0,0 +1,2 @@
1
+ Add @shouldRender? Or say you can use return (return _out) to exit early? @return? @exitComponent?
2
+
@@ -11,7 +11,7 @@ module RBlade
11
11
  # <%% and %%> are escape ERB style tags
12
12
  (<%%)(.+?)(%%>)
13
13
  |
14
- (?:^|[\b\s])(@ruby)\s+(.+?)[\s;]*(@endruby)(?:$|[\b\s])
14
+ \s?(?<!\w)(@ruby)\s+(.+?)[\s;]*(@endruby)(?!\w)\s?
15
15
  |
16
16
  (<%)\s+(.+?)[\s;]*(%>)
17
17
  /xm)
@@ -1,6 +1,8 @@
1
1
  require "rblade/compiler/statements/compiles_conditionals"
2
+ require "rblade/compiler/statements/compiles_html_attributes"
2
3
  require "rblade/compiler/statements/compiles_inline_ruby"
3
4
  require "rblade/compiler/statements/compiles_loops"
5
+ require "rblade/compiler/statements/compiles_once"
4
6
  require "rblade/compiler/statements/compiles_props"
5
7
  require "rblade/compiler/statements/compiles_stacks"
6
8
 
@@ -43,7 +45,7 @@ module RBlade
43
45
  private
44
46
 
45
47
  def getHandler(name)
46
- handler_class, handler_method = @@statement_handlers[name]
48
+ handler_class, handler_method = @@statement_handlers[name.tr("_", "").downcase]
47
49
 
48
50
  if !handler_class&.method_defined?(handler_method)
49
51
  raise StandardError.new "Unhandled statement: @#{name}"
@@ -65,6 +67,7 @@ module RBlade
65
67
  "breakif" => [CompilesLoops, :compileBreakIf],
66
68
  "case" => [CompilesConditionals, :compileCase],
67
69
  "checked" => [CompilesConditionals, :compileChecked],
70
+ "class" => [CompilesHtmlAttributes, :compileClass],
68
71
  "disabled" => [CompilesConditionals, :compileDisabled],
69
72
  "else" => [CompilesConditionals, :compileElse],
70
73
  "elsif" => [CompilesConditionals, :compileElsif],
@@ -75,27 +78,38 @@ module RBlade
75
78
  "endcase" => [CompilesStatements, :compileEnd],
76
79
  "endeach" => [CompilesStatements, :compileEnd],
77
80
  "endeachelse" => [CompilesStatements, :compileEnd],
81
+ "endenv" => [CompilesStatements, :compileEnd],
78
82
  "endfor" => [CompilesStatements, :compileEnd],
79
83
  "endforelse" => [CompilesStatements, :compileEnd],
80
84
  "endif" => [CompilesStatements, :compileEnd],
85
+ "endonce" => [CompilesStatements, :compileEnd],
81
86
  "endprepend" => [CompilesStacks, :compileEndPrepend],
87
+ "endprependonce" => [CompilesOnce, :compileEndPrependOnce],
88
+ "endproduction" => [CompilesStatements, :compileEnd],
82
89
  "endpush" => [CompilesStacks, :compileEndPush],
90
+ "endpushonce" => [CompilesOnce, :compileEndPushOnce],
83
91
  "endunless" => [CompilesStatements, :compileEnd],
84
92
  "enduntil" => [CompilesStatements, :compileEnd],
85
93
  "endwhile" => [CompilesStatements, :compileEnd],
94
+ "env" => [CompilesConditionals, :compileEnv],
86
95
  "for" => [CompilesLoops, :compileFor],
87
96
  "forelse" => [CompilesLoops, :compileForElse],
88
97
  "if" => [CompilesConditionals, :compileIf],
89
98
  "next" => [CompilesLoops, :compileNext],
90
99
  "nextif" => [CompilesLoops, :compileNextIf],
100
+ "once" => [CompilesOnce, :compileOnce],
91
101
  "prepend" => [CompilesStacks, :compilePrepend],
102
+ "prependonce" => [CompilesOnce, :compilePrependOnce],
103
+ "production" => [CompilesConditionals, :compileProduction],
92
104
  "props" => [CompilesProps, :compileProps],
93
105
  "push" => [CompilesStacks, :compilePush],
106
+ "pushonce" => [CompilesOnce, :compilePushOnce],
94
107
  "readonly" => [CompilesConditionals, :compileReadonly],
95
108
  "required" => [CompilesConditionals, :compileRequired],
96
109
  "ruby" => [CompilesInlineRuby, :compile],
97
110
  "selected" => [CompilesConditionals, :compileSelected],
98
111
  "stack" => [CompilesStacks, :compileStack],
112
+ "style" => [CompilesHtmlAttributes, :compileStyle],
99
113
  "unless" => [CompilesConditionals, :compileUnless],
100
114
  "until" => [CompilesLoops, :compileUntil],
101
115
  "when" => [CompilesConditionals, :compileWhen],
@@ -0,0 +1,29 @@
1
+ module RBlade
2
+ class CompilesVerbatim
3
+ def compile!(tokens)
4
+ tokens.map! do |token|
5
+ next(token) if token.type != :unprocessed
6
+
7
+ segments = token.value.split(/\s?(?<!\w)(@verbatim)(?!\w)\s?(.+?)\s?(?<!\w)@end_?verbatim(?!\w)\s?/mi)
8
+
9
+ i = 0
10
+ while i < segments.count
11
+ if segments[i] == "@verbatim"
12
+ segments.delete_at i
13
+ segments[i] = Token.new(type: :raw_text, value: segments[i])
14
+
15
+ i += 1
16
+ elsif !segments[i].nil? && segments[i] != ""
17
+ segments[i] = Token.new(type: :unprocessed, value: segments[i])
18
+
19
+ i += 1
20
+ else
21
+ segments.delete_at i
22
+ end
23
+ end
24
+
25
+ segments
26
+ end.flatten!
27
+ end
28
+ end
29
+ end
@@ -88,6 +88,32 @@ module RBlade
88
88
 
89
89
  "if #{args[0]};_out<<'selected';end;"
90
90
  end
91
+
92
+ def compileEnv args
93
+ if args&.count != 1
94
+ raise StandardError.new "Env statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
95
+ end
96
+
97
+ environments = args[0].strip
98
+
99
+ "if Array.wrap(#{environments}).include?(Rails.env);"
100
+ end
101
+
102
+ def compileProduction args
103
+ unless args.nil?
104
+ raise StandardError.new "Production statement: wrong number of arguments (given #{args.count}, expecting 1)"
105
+ end
106
+
107
+ "if Rails.env.production?;"
108
+ end
109
+
110
+ def compileOnce args
111
+ if args&.count&.> 1
112
+ raise StandardError.new "Production statement: wrong number of arguments (given #{args.count}, expecting 0 or 1)"
113
+ end
114
+
115
+ args[0].nil? ? "" : args[0]
116
+ end
91
117
  end
92
118
  end
93
119
  end
@@ -0,0 +1,21 @@
1
+ module RBlade
2
+ class CompilesStatements
3
+ class CompilesHtmlAttributes
4
+ def compileClass args
5
+ if args&.count != 1
6
+ raise StandardError.new "Class statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
7
+ end
8
+
9
+ "_out<<'class=\"'<<RBlade::ClassManager.new(#{args[0]})<<'\"';"
10
+ end
11
+
12
+ def compileStyle args
13
+ if args&.count != 1
14
+ raise StandardError.new "Style statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
15
+ end
16
+
17
+ "_out<<'style=\"'<<RBlade::StyleManager.new(#{args[0]})<<'\"';"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,19 +6,15 @@ module RBlade
6
6
  end
7
7
 
8
8
  def compileBreak args
9
- if !args.nil?
10
- raise StandardError.new "Break statement: wrong number of arguments (given #{args&.count}, expecting 0)"
9
+ if args&.count&.> 1
10
+ raise StandardError.new "Break statement: wrong number of arguments (given #{args&.count}, expecting 0 or 1)"
11
11
  end
12
12
 
13
- "break;"
14
- end
15
-
16
- def compileBreakIf args
17
- if args&.count != 1
18
- raise StandardError.new "Break statement: wrong number of arguments (given #{args&.count}, expecting 1)"
13
+ if args.nil?
14
+ "break;"
15
+ else
16
+ "if #{args[0]};break;end;"
19
17
  end
20
-
21
- "if #{args[0]};break;end;"
22
18
  end
23
19
 
24
20
  def compileEach args
@@ -77,19 +73,7 @@ module RBlade
77
73
  if args.nil?
78
74
  "next;"
79
75
  else
80
- "next #{args[0]};"
81
- end
82
- end
83
-
84
- def compileNextIf args
85
- if args.nil? || args.count > 2
86
- raise StandardError.new "For statement: wrong number of arguments (given #{args&.count || 0}, expecting 1 or 2)"
87
- end
88
-
89
- if args.count == 1
90
76
  "if #{args[0]};next;end;"
91
- else
92
- "if #{args[0]};next #{args[1]};end;"
93
77
  end
94
78
  end
95
79
 
@@ -0,0 +1,57 @@
1
+ module RBlade
2
+ class CompilesStatements
3
+ class CompilesOnce
4
+ def initialize
5
+ @once_counter = 0
6
+ end
7
+
8
+ def compileOnce args
9
+ if args&.count&.> 1
10
+ raise StandardError.new "Once statement: wrong number of arguments (given #{args.count}, expecting 0 or 1)"
11
+ end
12
+
13
+ once_id = args.nil? ? ":_#{@once_counter += 1}" : args[0]
14
+
15
+ "unless $_once_tokens.include? #{once_id};$_once_tokens<<#{once_id};"
16
+ end
17
+
18
+ def compilePushOnce args
19
+ if args&.count != 1 && args&.count != 2
20
+ raise StandardError.new "Push once statement: wrong number of arguments (given #{args.count}, expecting 1 or 2)"
21
+ end
22
+ @once_counter += 1
23
+ once_id = args[1].nil? ? ":_#{@once_counter}" : args[1]
24
+
25
+ "unless $_once_tokens.include? #{once_id};$_once_tokens<<#{once_id};" \
26
+ << "_p1_#{@once_counter}=#{args[0]};_p1_#{@once_counter}_b=_out;_out='';"
27
+ end
28
+
29
+ def compileEndPushOnce args
30
+ if !args.nil?
31
+ raise StandardError.new "End push once statement: wrong number of arguments (given #{args&.count}, expecting 0)"
32
+ end
33
+
34
+ "RBlade::StackManager.push(_p1_#{@once_counter}, _out);_out=_p1_#{@once_counter}_b;end;"
35
+ end
36
+
37
+ def compilePrependOnce args
38
+ if args&.count != 1 && args&.count != 2
39
+ raise StandardError.new "Prepend once statement: wrong number of arguments (given #{args.count}, expecting 1 or 2)"
40
+ end
41
+ @once_counter += 1
42
+ once_id = args[1].nil? ? ":_#{@once_counter}" : args[1]
43
+
44
+ "unless $_once_tokens.include? #{once_id};$_once_tokens<<#{once_id};" \
45
+ << "_p1_#{@once_counter}=#{args[0]};_p1_#{@once_counter}_b=_out;_out='';"
46
+ end
47
+
48
+ def compileEndPrependOnce args
49
+ if !args.nil?
50
+ raise StandardError.new "End prepend once statement: wrong number of arguments (given #{args&.count}, expecting 0)"
51
+ end
52
+
53
+ "RBlade::StackManager.prepend(_p1_#{@once_counter}, _out);_out=_p1_#{@once_counter}_b;end;"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -23,7 +23,7 @@ module RBlade
23
23
  else
24
24
  @push_counter += 1
25
25
 
26
- "_push_#{@push_counter}_name=#{args[0]};_push_#{@push_counter}_buffer=_out;_out='';"
26
+ "_p_#{@push_counter}=#{args[0]};_p_#{@push_counter}_b=_out;_out='';"
27
27
  end
28
28
  end
29
29
 
@@ -34,7 +34,7 @@ module RBlade
34
34
 
35
35
  @push_counter -= 1
36
36
 
37
- "RBlade::StackManager.prepend(_push_#{@push_counter + 1}_name, _out);_out=_push_#{@push_counter + 1}_buffer;"
37
+ "RBlade::StackManager.prepend(_p_#{@push_counter + 1}, _out);_out=_p_#{@push_counter + 1}_b;"
38
38
  end
39
39
 
40
40
  def compilePush args
@@ -47,7 +47,7 @@ module RBlade
47
47
  else
48
48
  @push_counter += 1
49
49
 
50
- "_push_#{@push_counter}_name=#{args[0]};_push_#{@push_counter}_buffer=_out;_out='';"
50
+ "_p_#{@push_counter}=#{args[0]};_p_#{@push_counter}_b=_out;_out='';"
51
51
  end
52
52
  end
53
53
 
@@ -58,7 +58,7 @@ module RBlade
58
58
 
59
59
  @push_counter -= 1
60
60
 
61
- "RBlade::StackManager.push(_push_#{@push_counter + 1}_name, _out);_out=_push_#{@push_counter + 1}_buffer;"
61
+ "RBlade::StackManager.push(_p_#{@push_counter + 1}, _out);_out=_p_#{@push_counter + 1}_b;"
62
62
  end
63
63
  end
64
64
  end
@@ -8,12 +8,23 @@ module RBlade
8
8
  next(token) if token.type != :unprocessed
9
9
 
10
10
  segments = token.value.split(/
11
- (?:^|[\b\s])
12
- (@@?)
13
- (\w+(?:::\w+)?)
14
- (?:[ \t]*
15
- (\(.*?\))
16
- )?/mx)
11
+ \s?(?<!\w)
12
+ (?:
13
+ (?:
14
+ (@@)
15
+ (\w+(?!\w))
16
+ )
17
+ |
18
+ (?:
19
+ (@)
20
+ (\w+(?!\w))
21
+ (?:[ \t]*
22
+ (\(.*?\))
23
+ )?
24
+ )
25
+ )
26
+ \s?
27
+ /mx)
17
28
 
18
29
  parseSegments! segments
19
30
  end.flatten!
@@ -35,11 +46,6 @@ module RBlade
35
46
  elsif segment == "@"
36
47
  tokenizeStatement! segments, i
37
48
 
38
- # Remove trailing whitespace if it exists, but don't double dip when another statement follows
39
- if !segments[i + 1].nil? && segments[i + 1].match(/^\s/) && (segments[i + 1].length > 1 || segments[i + 2].nil?)
40
- segments[i + 1].slice! 0, 1
41
- end
42
-
43
49
  i += 1
44
50
  elsif !segments[i].nil? && segments[i] != ""
45
51
  segments[i] = Token.new(type: :unprocessed, value: segments[i])
@@ -2,6 +2,7 @@ require "rblade/compiler/compiles_comments"
2
2
  require "rblade/compiler/compiles_components"
3
3
  require "rblade/compiler/compiles_echos"
4
4
  require "rblade/compiler/compiles_ruby"
5
+ require "rblade/compiler/compiles_verbatim"
5
6
  require "rblade/compiler/compiles_statements"
6
7
  require "rblade/compiler/tokenizes_components"
7
8
  require "rblade/compiler/tokenizes_statements"
@@ -22,6 +23,7 @@ module RBlade
22
23
  def self.compileString(string_template)
23
24
  tokens = [Token.new(:unprocessed, string_template)]
24
25
 
26
+ CompilesVerbatim.new.compile! tokens
25
27
  CompilesComments.new.compile! tokens
26
28
  CompilesRuby.new.compile! tokens
27
29
  TokenizesComponents.new.tokenize! tokens
@@ -36,8 +38,8 @@ module RBlade
36
38
  def self.compileAttributeString(string_template)
37
39
  tokens = [Token.new(:unprocessed, string_template)]
38
40
 
39
- CompilesRuby.compile! tokens
40
41
  CompilesComments.compile!(tokens)
42
+ CompilesRuby.compile! tokens
41
43
  CompilesEchos.compile!(tokens)
42
44
 
43
45
  compileTokens tokens
@@ -19,5 +19,9 @@ module RBlade
19
19
  def to_s
20
20
  @classes
21
21
  end
22
+
23
+ def to_str
24
+ to_s
25
+ end
22
26
  end
23
27
  end
@@ -33,5 +33,9 @@ module RBlade
33
33
  def to_s
34
34
  @styles
35
35
  end
36
+
37
+ def to_str
38
+ to_s
39
+ end
36
40
  end
37
41
  end
@@ -9,19 +9,22 @@ require "rblade/helpers/style_manager"
9
9
  module RBlade
10
10
  class RailsTemplate
11
11
  def call(template, source = nil)
12
+ RBlade::ComponentStore.clear
13
+ RBlade::StackManager.clear
14
+
12
15
  unless template.nil?
13
16
  view_name = template.short_identifier
14
- .delete_prefix('app/views/')
15
- .delete_suffix('.rblade')
16
- .delete_suffix('.html')
17
- .tr('/', '.')
17
+ .delete_prefix("app/views/")
18
+ .delete_suffix(".rblade")
19
+ .delete_suffix(".html")
20
+ .tr("/", ".")
18
21
 
19
22
  # Let the component store know about the current view for relative components
20
23
  RBlade::ComponentStore.view_name(
21
24
  "view::#{view_name}"
22
25
  )
23
26
  end
24
- setup = "_out='';_stacks=[];"
27
+ setup = "_out='';_stacks=[];$_once_tokens=[];"
25
28
  code = RBlade::Compiler.compileString(source || template.source)
26
29
  setdown = "RBlade::StackManager.get(_stacks) + _out"
27
30
  setup + ComponentStore.get + code + setdown
data/rblade.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rblade"
3
- s.version = "0.3.0"
4
- s.summary = "Blade templates for ruby"
5
- s.description = "A port of the Laravel blade templating engine to ruby"
3
+ s.version = "0.4.0"
4
+ s.summary = "A component-first templating engine for Rails"
5
+ s.description = "RBlade is a simple, yet powerful templating engine for Ruby on Rails, inspired by Laravel Blade."
6
6
  s.authors = ["Simon J"]
7
7
  s.email = "2857218+mwnciau@users.noreply.github.com"
8
8
  s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|storage)/}) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rblade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon J
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-26 00:00:00.000000000 Z
11
+ date: 2024-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -66,7 +66,8 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '7.0'
69
- description: A port of the Laravel blade templating engine to ruby
69
+ description: RBlade is a simple, yet powerful templating engine for Ruby on Rails,
70
+ inspired by Laravel Blade.
70
71
  email: 2857218+mwnciau@users.noreply.github.com
71
72
  executables: []
72
73
  extensions: []
@@ -76,8 +77,10 @@ files:
76
77
  - ".standard.yml"
77
78
  - CHANGELOG.md
78
79
  - Gemfile
80
+ - LICENSE.md
79
81
  - README.md
80
82
  - Rakefile
83
+ - TODO.md
81
84
  - do
82
85
  - docker-compose.yml
83
86
  - lib/rblade.rb
@@ -87,9 +90,12 @@ files:
87
90
  - lib/rblade/compiler/compiles_echos.rb
88
91
  - lib/rblade/compiler/compiles_ruby.rb
89
92
  - lib/rblade/compiler/compiles_statements.rb
93
+ - lib/rblade/compiler/compiles_verbatim.rb
90
94
  - lib/rblade/compiler/statements/compiles_conditionals.rb
95
+ - lib/rblade/compiler/statements/compiles_html_attributes.rb
91
96
  - lib/rblade/compiler/statements/compiles_inline_ruby.rb
92
97
  - lib/rblade/compiler/statements/compiles_loops.rb
98
+ - lib/rblade/compiler/statements/compiles_once.rb
93
99
  - lib/rblade/compiler/statements/compiles_props.rb
94
100
  - lib/rblade/compiler/statements/compiles_stacks.rb
95
101
  - lib/rblade/compiler/tokenizes_components.rb
@@ -125,5 +131,5 @@ requirements: []
125
131
  rubygems_version: 3.5.11
126
132
  signing_key:
127
133
  specification_version: 4
128
- summary: Blade templates for ruby
134
+ summary: A component-first templating engine for Rails
129
135
  test_files: []