serbea 2.3.0 → 2.4.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: 8aebfee6e539271599cc9d84ec8c5220a13cd7746c82b687d257fc431b60fb5c
4
- data.tar.gz: c61b07f0c4402f067e354fa652cd32eaec060768bcfdf0228ca2d208d7402c77
3
+ metadata.gz: 16a4fb4aa837acca31f21651fb20a6eb9390b2f1fe71b17dcb5da1a6bea4648a
4
+ data.tar.gz: 37bdc48cd38eae83c124c7c290b6340aeac3e5e0f0e9739a627c5b543cba4b30
5
5
  SHA512:
6
- metadata.gz: 7a3372bddc2a463c1d3dd631ff3777ae60671bb2a20463a7fea9db3da8fb5a2b28cd5338fb251c454358ff33ddf58f7fe6e40ce5c4e320e6df2c042000463ae9
7
- data.tar.gz: 8cf230f8b0aa7fafb00c73ca80ff4805952ce6b3aa3cb3a7a781d8a1621bb7b1299ced2d30aa03dda2604e350fba7a6109861be90267f3c579a9d9bd8a3bd5c7
6
+ metadata.gz: beeb54542ca3610c6f70b166ad8a072d2dced0ff54b141de82102f8dd49c67b539773fdae7fd1620c2f09915be926faa5c4661352a93044de00c42f6152522ea
7
+ data.tar.gz: d72e6d3a26cd13119c257706f07451ef6122f4179a6a3100c508992ebfb19e0a008a50c1b406ef7409ebc75d0cc6e2f8c06ce83c5960f15541451c2113740891
data/.rubocop.yml ADDED
@@ -0,0 +1,29 @@
1
+ require: rubocop-bridgetown
2
+ inherit_gem:
3
+ rubocop-bridgetown: .rubocop.yml
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 3.1
7
+ Exclude:
8
+ - bin/**/*
9
+ - exe/**/*
10
+ - test/**/*
11
+ - tmp/**/*
12
+ - Gemfile
13
+ - Rakefile
14
+ - docs/**/*
15
+ - lib/rouge/**/*
16
+ - serbea-rails/**/*
17
+ - serbea.gemspec
18
+
19
+ Bridgetown/NoPutsAllowed:
20
+ Enabled: false
21
+
22
+ Bridgetown/InsecureHeredoc:
23
+ Enabled: false
24
+
25
+ Layout/LineLength:
26
+ Enabled: false
27
+
28
+ Metrics/BlockNesting:
29
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ .
6
+
7
+ ## 2.4.0
8
+
9
+ - Convert to using new `Erubi::CaptureBlockEngine`
10
+ - Add RuboCop to repoi and apply many suggested fixes
11
+
3
12
  ## 2.3.0
4
13
 
5
14
  - Migrate repo to Codeberg
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require "rubocop/rake_task"
3
4
  require "bundler"
4
5
 
5
6
  Bundler.setup
@@ -9,4 +10,6 @@ Rake::TestTask.new(:test) do |t|
9
10
  t.warning = false
10
11
  end
11
12
 
12
- task :default => :test
13
+ RuboCop::RakeTask.new
14
+
15
+ task :default => [:rubocop, :test]
data/bin/rubocop ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rubocop", "rubocop")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  unless "".respond_to?(:html_safe)
2
4
  # The simplest HTML safety "polyfill" around
3
5
  class String
@@ -13,7 +15,7 @@ end
13
15
 
14
16
  module Serbea
15
17
  module Helpers
16
- def self.included(mod)
18
+ def self.included(_mod)
17
19
  Serbea::Pipeline.deny_value_method %i(escape h prepend append assign_to)
18
20
  end
19
21
 
@@ -21,10 +23,10 @@ module Serbea
21
23
  previous_buffer_state = @_erbout
22
24
  @_erbout = Serbea::OutputBuffer.new
23
25
  result = yield(*args)
24
- result = @_erbout.empty? ? result : @_erbout
26
+ result = @_erbout unless @_erbout.empty?
25
27
  @_erbout = previous_buffer_state
26
28
 
27
- Serbea::OutputBuffer === result ? result.html_safe : result
29
+ result.is_a?(Serbea::OutputBuffer) ? result.html_safe : result
28
30
  end
29
31
 
30
32
  def pipeline(context, value)
@@ -38,11 +40,15 @@ module Serbea
38
40
  end
39
41
  alias_method :macro, :helper
40
42
 
41
- def import(*args, **kwargs, &block)
43
+ def import(...)
42
44
  helper_names = %i(partial render)
43
45
  available_helper = helper_names.find { |meth| respond_to?(meth) }
44
- raise Serbea::Error, "Serbea Error: no `render' or `partial' helper available in #{self.class}" unless available_helper
45
- available_helper == :partial ? partial(*args, **kwargs, &block) : render(*args, **kwargs, &block)
46
+ unless available_helper
47
+ raise Serbea::Error,
48
+ "Serbea Error: no `render' or `partial' helper available in #{self.class}"
49
+ end
50
+
51
+ available_helper == :partial ? partial(...) : render(...)
46
52
  nil
47
53
  end
48
54
 
@@ -65,7 +71,7 @@ module Serbea
65
71
  end
66
72
 
67
73
  def assign_to(input, varname, preserve: false)
68
- self.instance_variable_set("@#{varname}", input)
74
+ instance_variable_set("@#{varname}", input)
69
75
  preserve ? input : nil
70
76
  end
71
77
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
 
3
5
  module Serbea
@@ -25,9 +27,7 @@ module Serbea
25
27
  attr_accessor :output
26
28
  end
27
29
 
28
- if include_helpers
29
- anon.include include_helpers
30
- end
30
+ anon.include include_helpers if include_helpers
31
31
 
32
32
  pipeline_obj = anon.new
33
33
 
@@ -40,27 +40,29 @@ module Serbea
40
40
  end
41
41
 
42
42
  # @param processor [Proc]
43
- def self.output_processor=(processor)
44
- @output_processor = processor
43
+ class << self
44
+ attr_writer :output_processor
45
45
  end
46
46
 
47
47
  # @return [Proc]
48
48
  def self.output_processor
49
- @output_processor ||= lambda do |input|
50
- (!input.html_safe? && self.autoescape) ? Erubi.h(input) : input.html_safe
49
+ @output_processor ||= ->(input) do
50
+ !input.html_safe? && autoescape ? Erubi.h(input) : input.html_safe
51
51
  end
52
52
  end
53
53
 
54
- def self.autoescape=(config_boolean)
55
- @autoescape = config_boolean
54
+ class << self
55
+ attr_writer :autoescape
56
56
  end
57
+
57
58
  def self.autoescape
58
- @autoescape.nil? ? true : @autoescape
59
+ @autoescape.nil? || @autoescape
59
60
  end
60
61
 
61
- def self.raise_on_missing_filters=(config_boolean)
62
- @raise_on_missing_filters = config_boolean
62
+ class << self
63
+ attr_writer :raise_on_missing_filters
63
64
  end
65
+
64
66
  def self.raise_on_missing_filters
65
67
  @raise_on_missing_filters ||= false
66
68
  end
@@ -68,6 +70,7 @@ module Serbea
68
70
  def self.deny_value_method(name)
69
71
  value_methods_denylist.merge Array(name)
70
72
  end
73
+
71
74
  def self.value_methods_denylist
72
75
  @value_methods_denylist ||= Set.new
73
76
  end
@@ -87,6 +90,7 @@ module Serbea
87
90
  def self.polluted_method(name)
88
91
  polluted_methods_list.merge Array(name)
89
92
  end
93
+
90
94
  def self.polluted_methods_list
91
95
  @polluted_methods_list ||= Set.new(%i(select to_json))
92
96
  end
@@ -98,6 +102,7 @@ module Serbea
98
102
  @value = value
99
103
  end
100
104
 
105
+ # rubocop:disable Metrics
101
106
  def filter(name, *args, **kwargs)
102
107
  if @value.respond_to?(name) && !self.class.value_methods_denylist.include?(name)
103
108
  if args.last.is_a?(Proc)
@@ -115,27 +120,32 @@ module Serbea
115
120
  @value = var.call(@value, *args, **kwargs)
116
121
  else
117
122
  "Serbea warning: Filter '#{name}' does not respond to call".tap do |warning|
118
- self.class.raise_on_missing_filters ? raise(Serbea::FilterMissing, warning) : STDERR.puts(warning)
123
+ self.class.raise_on_missing_filters ? raise(
124
+ Serbea::FilterMissing, warning
125
+ ) : warn(warning)
119
126
  end
120
127
  end
121
128
  else
122
129
  "Serbea warning: Filter `#{name}' not found".tap do |warning|
123
- self.class.raise_on_missing_filters ? raise(Serbea::FilterMissing, warning) : STDERR.puts(warning)
130
+ self.class.raise_on_missing_filters ? raise(
131
+ Serbea::FilterMissing, warning
132
+ ) : warn(warning)
124
133
  end
125
134
  end
126
135
 
127
136
  self
128
137
  end
138
+ # rubocop:enable Metrics
129
139
 
130
140
  def to_s
131
141
  self.class.output_processor.call(@value.is_a?(String) ? @value : @value.to_s)
132
142
  end
133
-
143
+
134
144
  def |(*)
135
145
  self
136
146
  end
137
147
 
138
- def method_missing(...)
148
+ def method_missing(...) # rubocop:disable Style/MissingRespondToMissing
139
149
  filter(...)
140
150
  end
141
151
 
@@ -1,28 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "strscan"
2
4
 
3
5
  module Serbea
4
- class OutputBuffer < String
5
- def concat_to_s(input)
6
- concat input.to_s
7
- end
8
-
9
- alias_method :safe_append=, :concat_to_s
10
- alias_method :append=, :concat_to_s
11
- alias_method :safe_expr_append=, :concat_to_s
6
+ class OutputBuffer < Erubi::CaptureBlockEngine::Buffer
12
7
  end
13
8
 
14
- class TemplateEngine < Erubi::Engine
15
- FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m.freeze
9
+ class TemplateEngine < Erubi::CaptureBlockEngine
10
+ FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
16
11
 
17
12
  def self.directive(new_directive, directive_resolution)
18
13
  directives[new_directive.to_s] = directive_resolution
19
14
  end
20
15
 
16
+ # rubocop:disable Metrics
21
17
  def self.directives
22
18
  @directives ||= {
23
19
  "@" => ->(code, buffer) do
24
- pieces = code.split(" ")
25
- if pieces[0].start_with?(/[A-Z]/) # Ruby class name
20
+ pieces = code.split
21
+ if pieces[0].start_with?(%r{[A-Z]}) # Ruby class name
26
22
  pieces[0].prepend " "
27
23
  pieces[0] << ".new("
28
24
  else # string or something else
@@ -31,194 +27,176 @@ module Serbea
31
27
 
32
28
  includes_block = false
33
29
  pieces.reverse.each do |piece|
34
- if piece == "do" && (pieces.last == "do" || pieces.last.end_with?("|"))
35
- piece.prepend(") ")
36
- includes_block = true
37
- break
38
- end
39
- end
30
+ next unless piece == "do" && (pieces.last == "do" || pieces.last.end_with?("|"))
40
31
 
41
- if includes_block
42
- buffer << "{%= render#{pieces.join(" ")} %}"
43
- else
44
- pieces.last << ")"
45
- buffer << "{%= render#{pieces.join(" ")} %}"
32
+ piece.prepend(") ")
33
+ includes_block = true
34
+ break
46
35
  end
36
+
37
+ pieces.last << ")" unless includes_block
38
+ buffer << "{%= render#{pieces.join(" ")} %}"
47
39
  end,
48
40
  "`" => ->(code, buffer) do
49
41
  buffer << "{%= %`"
50
42
  buffer << code.gsub(%r("([^\\]?)\#{(.*?)}"), "\"\\1\#{h(\\2)}\"")
51
43
  buffer << ".strip %}"
52
- end
44
+ end,
53
45
  }
54
46
  end
47
+ # rubocop:enable Metrics
55
48
 
56
- def self.front_matter_preamble=(varname)
57
- @front_matter_preamble = varname
58
- end
49
+ class << self
50
+ attr_writer :front_matter_preamble
59
51
 
60
- def self.front_matter_preamble
61
- @front_matter_preamble ||= "frontmatter = YAML.load"
62
- end
52
+ def front_matter_preamble
53
+ @front_matter_preamble ||= "frontmatter = YAML.load"
54
+ end
63
55
 
64
- def self.has_yaml_header?(template)
65
- template.lines.first&.match? %r!\A---\s*\r?\n!
56
+ def yaml_header?(template)
57
+ template.lines.first&.match? %r!\A---\s*\r?\n!
58
+ end
59
+ alias_method :has_yaml_header?, :yaml_header?
66
60
  end
67
61
 
68
- def initialize(input, properties={})
69
- properties[:regexp] = /{%(={1,2}|-|\#|%)?(.*?)([-=])?%}([ \t]*\r?\n)?/m
62
+ def initialize(input, properties = {})
63
+ properties[:regexp] = %r{{%(={1,2}|-|\#|%)?(.*?)([-=])?%}([ \t]*\r?\n)?}m
70
64
  properties[:strip_front_matter] = true unless properties.key?(:strip_front_matter)
71
- super process_serbea_input(input, properties), properties
65
+ super(process_serbea_input(input, properties), properties)
72
66
  end
73
67
 
68
+ # rubocop:disable Metrics
74
69
  def process_serbea_input(template, properties)
75
- buff = ""
76
-
70
+ buff = +""
71
+
77
72
  string = template.dup
78
- if properties[:strip_front_matter] && self.class.has_yaml_header?(string)
79
- if string = string.match(FRONT_MATTER_REGEXP)
80
- require "yaml" if self.class.front_matter_preamble.include?(" = YAML.load")
81
-
82
- string = "{% #{self.class.front_matter_preamble} <<~YAMLDATA\n" +
83
- string[1].sub(/^---\n/,'') +
84
- "YAMLDATA\n%}" +
85
- string[2].sub(/^---\n/, '') +
86
- string.post_match
87
- end
73
+ if properties[:strip_front_matter] && self.class.yaml_header?(string) && (string = string.match(FRONT_MATTER_REGEXP))
74
+ require "yaml" if self.class.front_matter_preamble.include?(" = YAML.load")
75
+
76
+ string = "{% #{self.class.front_matter_preamble} <<~YAMLDATA\n#{
77
+ string[1].sub(%r{^---\n}, "")
78
+ }YAMLDATA\n%}#{
79
+ string[2].sub(%r{^---\n}, "")
80
+ }#{string.post_match}"
88
81
  end
89
-
82
+
90
83
  # Ensure the raw "tag" will strip out all ERB-style processing
91
84
  until string.empty?
92
- text, code, string = string.partition(/{% raw %}(.*?){% endraw %}/m)
93
-
85
+ text, code, string = string.partition(%r{{% raw %}(.*?){% endraw %}}m)
86
+
94
87
  buff << text
95
- if code.length > 0
96
- buff << $1.
97
- gsub("{{", "__RAW_START_PRINT__").
98
- gsub("}}", "__RAW_END_PRINT__").
99
- gsub("{%", "__RAW_START_EVAL__").
100
- gsub("%}", "__RAW_END_EVAL__")
101
- end
88
+ next unless code.length.positive?
89
+
90
+ buff << ::Regexp.last_match(1)
91
+ .gsub("{{", "__RAW_START_PRINT__")
92
+ .gsub("}}", "__RAW_END_PRINT__")
93
+ .gsub("{%", "__RAW_START_EVAL__")
94
+ .gsub("%}", "__RAW_END_EVAL__")
102
95
  end
103
96
 
104
97
  # Process any pipelines
105
98
  string = buff
106
- buff = ""
99
+ buff = +""
107
100
  until string.empty?
108
- text, code, string = string.partition(/{{(.*?)}}/m)
109
-
101
+ text, code, string = string.partition(%r{{{(.*?)}}}m)
102
+
110
103
  buff << text
111
- if code.length > 0
112
- original_line_length = code.lines.size
113
-
114
- s = StringScanner.new($1)
115
- escaped_segment = ""
116
- segments = []
117
- until s.eos?
118
- portion = s.scan_until(/\|>?/)
119
- if portion
120
- if portion.end_with?('\|')
121
- # the pipe is escaped, so save that for later
122
- escaped_segment += portion.sub(/\\\|$/, "|")
123
- elsif escaped_segment.length > 0
124
- # we already have escaped content, so finish that up
125
- segments << escaped_segment + portion.sub(/\|>?$/, "")
126
- escaped_segment = ""
127
- else
128
- # let's find out if this is actionable now
129
- if s.check(/\|/)
130
- # nope, the next character is another pipe, so let's escape
131
- s.pos += 1
132
- escaped_segment += portion + "|"
133
- else
134
- # finally, we have liftoff!
135
- segments << portion.sub(/\|>?$/, "")
136
- end
137
- end
104
+ next unless code.length.positive?
105
+
106
+ original_line_length = code.lines.size
107
+
108
+ s = StringScanner.new(::Regexp.last_match(1))
109
+ escaped_segment = ""
110
+ segments = []
111
+ until s.eos?
112
+ portion = s.scan_until(%r{\|>?})
113
+ if portion
114
+ if portion.end_with?('\|')
115
+ # the pipe is escaped, so save that for later
116
+ escaped_segment += portion.sub(%r{\\\|$}, "|")
117
+ elsif escaped_segment.length.positive?
118
+ # we already have escaped content, so finish that up
119
+ segments << (escaped_segment + portion.sub(%r{\|>?$}, ""))
120
+ escaped_segment = ""
121
+ elsif s.check(%r{\|})
122
+ # let's find out if this is actionable now
123
+ s.pos += 1
124
+ escaped_segment += "#{portion}|"
125
+ # nope, the next character is another pipe, so let's escape
138
126
  else
139
- # we've reached the last bit of the code
140
- if escaped_segment.length > 0
141
- # escape and get the rest
142
- segments << escaped_segment + s.rest
143
- else
144
- # or just the rest will do
145
- segments << s.rest
146
- end
147
- s.terminate
127
+ # finally, we have liftoff!
128
+ segments << portion.sub(%r{\|>?$}, "")
148
129
  end
130
+ else
131
+ # we've reached the last bit of the code
132
+ segments << if escaped_segment.length.positive?
133
+ # escape and get the rest
134
+ (escaped_segment + s.rest)
135
+ else
136
+ # or just the rest will do
137
+ s.rest
138
+ end
139
+ s.terminate
149
140
  end
141
+ end
150
142
 
151
- segments[0] = "pipeline(binding, (#{segments[0].strip}))"
152
- segments[1..-1].each_with_index do |segment, index|
153
- filter, args = segment.strip.match(/([^ :]*)(.*)/m).captures
154
- segments[index + 1] = ".filter(:" + filter
155
- if args == ""
156
- segments[index + 1] += ")"
157
- else
158
- segments[index + 1] += "," + args.sub(/^:/, "") + ")"
159
- end
160
- end
143
+ segments[0] = "pipeline(binding, (#{segments[0].strip}))"
144
+ segments[1..].each_with_index do |segment, index|
145
+ filter, args = segment.strip.match(%r{([^ :]*)(.*)}m).captures
146
+ segments[index + 1] = ".filter(:#{filter}"
147
+ segments[index + 1] += if args == ""
148
+ ")"
149
+ else
150
+ ",#{args.sub(%r{^:}, "")})"
151
+ end
152
+ end
161
153
 
162
- subs = "{%= #{segments.join} %}"
163
- buff << subs
154
+ subs = "{%= #{segments.join} %}"
155
+ buff << subs
164
156
 
165
- (original_line_length - subs.lines.size).times do
166
- buff << "\n{% %}" # preserve original line length
167
- end
157
+ (original_line_length - subs.lines.size).times do
158
+ buff << "\n{% %}" # preserve original line length
168
159
  end
169
160
  end
170
161
 
171
162
  # Process any render directives
172
163
  string = buff
173
- buff = ""
164
+ buff = +""
165
+ end_matches = ["end", ""]
174
166
  until string.empty?
175
- text, code, string = string.partition(/{%@([a-z_`]+)?(.*?)%}/m)
167
+ text, code, string = string.partition(%r{{%@([a-z_`]+)?(.*?)%}}m)
176
168
 
177
169
  buff << text
178
- if code.length > 0
179
- directive = $1
180
- code = $2
181
- unless ["end", ""].include? code.strip
182
- directive = $1 ? self.class.directives[$1] : self.class.directives["@"]
183
-
184
- if directive
185
- additional_length = "#{buff}#{code}".lines.size
186
- directive.(code, buff)
187
- (additional_length - buff.lines.size).times do
188
- buff << "{% %}\n" # preserve original directive line length
189
- end
190
- else
191
- raise Serbea::Error, "Handler for Serbea template directive `#{$1}' not found"
192
- end
193
- else
194
- buff << "{% end %}"
170
+ next unless code.length.positive?
171
+
172
+ code = ::Regexp.last_match(2)
173
+ if end_matches.include? code.strip
174
+ buff << "{% end %}"
175
+ else
176
+ directive = ::Regexp.last_match(1) ? self.class.directives[::Regexp.last_match(1)] : self.class.directives["@"]
177
+
178
+ unless directive
179
+ raise Serbea::Error,
180
+ "Handler for Serbea template directive `#{::Regexp.last_match(1)}' not found"
195
181
  end
182
+
183
+ additional_length = "#{buff}#{code}".lines.size
184
+ directive.(code, buff)
185
+ (additional_length - buff.lines.size).times do
186
+ buff << "{% %}\n" # preserve original directive line length
187
+ end
188
+
196
189
  end
197
190
  end
198
191
 
199
192
  buff
200
193
  end
194
+ # rubocop:enable Metrics
201
195
 
202
196
  private
203
197
 
204
- def add_code(code)
205
- @src << code
206
- @src << ";#{@bufvar};" if code.strip.split(".").first == "end"
207
- @src << ';' unless code[Erubi::RANGE_LAST] == "\n"
208
- end
209
-
210
- # pulled from Rails' ActionView
211
- BLOCK_EXPR = %r!\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z!.freeze
212
-
213
- def add_expression(indicator, code)
214
- if BLOCK_EXPR.match?(code)
215
- src << "#{@bufvar}.append= " << code
216
- else
217
- super
218
- end
219
- end
220
-
221
- # Don't allow == to output escaped strings, as that's the opposite of Rails
198
+ # Don't allow `{%==` to output escaped strings, it should be identical
199
+ # to `{%=`
222
200
  def add_expression_result_escaped(code)
223
201
  add_expression_result(code)
224
202
  end
@@ -226,11 +204,11 @@ module Serbea
226
204
  def add_postamble(postamble)
227
205
  src << postamble
228
206
  src << "#{@bufvar}.html_safe"
229
-
207
+
230
208
  src.gsub!("__RAW_START_PRINT__", "{{")
231
209
  src.gsub!("__RAW_END_PRINT__", "}}")
232
210
  src.gsub!("__RAW_START_EVAL__", "{%")
233
211
  src.gsub!("__RAW_END_EVAL__", "%}")
234
212
  end
235
213
  end
236
- end
214
+ end
data/lib/serbea.rb CHANGED
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tilt"
2
4
  require "tilt/erubi"
5
+ require "erubi/capture_block"
3
6
 
4
7
  module Serbea
5
8
  class Error < StandardError; end
@@ -16,7 +19,7 @@ module Tilt
16
19
  def prepare
17
20
  @options.merge!(
18
21
  outvar: "@_erbout",
19
- bufval: "Serbea::OutputBuffer.new",
22
+ bufval: "Serbea::OutputBuffer.new",
20
23
  literal_prefix: "{%",
21
24
  literal_postfix: "%}",
22
25
  engine_class: Serbea::TemplateEngine
data/lib/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Serbea
2
- VERSION = "2.3.0"
3
- end
4
+ VERSION = "2.4.0"
5
+ end
data/serbea.gemspec CHANGED
@@ -16,8 +16,9 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|script|spec|features|docs|serbea-rails)/!) }
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.add_runtime_dependency("erubi", ">= 1.11")
20
- spec.add_runtime_dependency("tilt", ">= 2.1")
19
+ spec.add_runtime_dependency("erubi", ">= 1.13")
20
+ spec.add_runtime_dependency("tilt", ">= 2.6")
21
21
 
22
22
  spec.add_development_dependency("rake", "~> 13.0")
23
+ spec.add_development_dependency("rubocop-bridgetown", "~> 0.7")
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serbea
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bridgetown Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-11 00:00:00.000000000 Z
11
+ date: 2025-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubi
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.11'
19
+ version: '1.13'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: '1.13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: tilt
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.1'
33
+ version: '2.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '2.1'
40
+ version: '2.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-bridgetown
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.7'
55
69
  description:
56
70
  email: maintainers@bridgetownrb.com
57
71
  executables: []
@@ -60,6 +74,7 @@ extra_rdoc_files: []
60
74
  files:
61
75
  - ".github/workflows/ci.yml"
62
76
  - ".gitignore"
77
+ - ".rubocop.yml"
63
78
  - ".ruby-version"
64
79
  - CHANGELOG.md
65
80
  - Gemfile
@@ -67,6 +82,7 @@ files:
67
82
  - README.md
68
83
  - Rakefile
69
84
  - bin/rake
85
+ - bin/rubocop
70
86
  - lib/rouge/lexers/serbea.rb
71
87
  - lib/serbea.rb
72
88
  - lib/serbea/helpers.rb