erubi 1.11.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0424c43d37611204a83153f9cffb1e259027a0f1a1edd16b3b5cfef09ec7b137
4
- data.tar.gz: 796b2b90f46c80297fdf05b3070f9bad10fc9199946878c0bfbfe7435ce5466c
3
+ metadata.gz: 9364047dc0b7365bae5a6f9ee75c748a0ef02bf4e516331c2d0533da9fe49e04
4
+ data.tar.gz: 9416aeee2c6c4556c3f19f7b918819cbe076493601efd9470815870fac1a2625
5
5
  SHA512:
6
- metadata.gz: 8833bc8ec00db215ef73c71271c97e668861f920c339de7df658f1cf464761b62b2811845a062b681bb30966b7797beec708674929aa9400159e1bfdce3c31dd
7
- data.tar.gz: 74fa7a9107f056dbcb3bb2efedb858a7f120d8c36d378da1eb425783c75e2a398ffd4b301c1e300cc684b98155d9b67abb07d1589f1be9786282756a0140449b
6
+ metadata.gz: ecd851eb258b2a0302d6a46b747722100aad3a145c4c22b6d1d14f856f094507ebbc84e151a1b9cd9795bb59b0154866e38a08798c75e9726c45b4d987ec48e5
7
+ data.tar.gz: 0c1f32494ca8a192de037c1497065e1f0901cf646fbb090972de215bf66f0fbf2e0774fa38309c50eab288d60dfe59a634e431395912275ec75a2aa3bf4c66be
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ === 1.13.0 (2024-06-13)
2
+
3
+ * Define Erubi.h as a module function (jeremyevans)
4
+
5
+ * Add erubi/capture_block, supporting capturing block output via standard <%= and <%== tags (jeremyevans)
6
+
7
+ === 1.12.0 (2022-12-22)
8
+
9
+ * Use erb/escape for faster html escaping if available (jeremyevans)
10
+
11
+ * Default :freeze_template_literals option to false if running with --enable-frozen-string-literal (casperisfine) (#35)
12
+
1
13
  === 1.11.0 (2022-08-02)
2
14
 
3
15
  * Support :freeze_template_literals option for configuring whether to add .freeze to template literal strings (casperisfine) (#33)
data/README.rdoc CHANGED
@@ -8,8 +8,8 @@ the same basic algorithm, with the following differences:
8
8
  * Works with ruby's <tt>--enable-frozen-string-literal</tt> option
9
9
  * Automatically freezes strings for template text when ruby optimizes it (on ruby 2.1+)
10
10
  * Escapes <tt>'</tt> (apostrophe) when escaping for better XSS protection
11
- * Has 6x faster escaping on ruby 2.3+ by using cgi/escape
12
- * Has 86% smaller memory footprint
11
+ * Has 15x-6x faster escaping by using erb/escape or cgi/escape
12
+ * Has 81% smaller memory footprint (calculated using +ObjectSpace.memsize_of_all+)
13
13
  * Does no monkey patching (Erubis adds a method to Kernel)
14
14
  * Uses an immutable design (all options passed to the constructor, which returns a frozen object)
15
15
  * Has simpler internals (1 file, <150 lines of code)
@@ -42,33 +42,75 @@ erb template handler in Tilt 2.0.6+ and Rails 5.1+.
42
42
  == Capturing
43
43
 
44
44
  Erubi does not support capturing block output into the template by default.
45
- However, it comes with an +erubi/capture_end+ file that supports capturing
46
- via <tt><%|=</tt> and <tt><%|==</tt> tags which are closed with a
47
- <tt><%|</tt> tag:
45
+ It currently ships with two implementations that allow it.
48
46
 
49
- <%|= form do %>
47
+ === Erubi::CaptureBlockEngine
48
+
49
+ The recommended implementation can be required via +erubi/capture_block+,
50
+ which allows capturing to work with normal <tt><%=</tt> and <tt><%==</tt>
51
+ tags.
52
+
53
+ <%= form do %>
50
54
  <input>
51
- <%| end %>
55
+ <% end %>
56
+
57
+ When using the capture_block support, capture methods should just return
58
+ the text it emit into the template, and call +capture+ on the buffer value.
59
+ Since the buffer variable is a local variable and not an instance variable
60
+ by default, you'll probably want to set the +:bufvar+ variable when using
61
+ the capture_block support to an instance variable, and have any methods
62
+ used call capture on that instance variable. Example:
63
+
64
+ def form(&block)
65
+ "<form>#{@_buf.capture(&block)}</form>"
66
+ end
52
67
 
53
- This offers similar functionality to that offered by Rails' <tt><%=</tt>
54
- tags, but without the corner cases with that approach (which are due to
55
- attempting to parse ruby code via a regexp). Similar to the <tt><%=</tt>
56
- and <tt><%==</tt> tags, <tt><%|=</tt> captures by default and
57
- <tt><%|==</tt> captures and escapes by default, but this can be reversed
58
- via the +:escape_capture+ or +:escape+ options.
68
+ puts eval(Erubi::CaptureBlockEngine.new(<<-END, bufvar: '@_buf', trim: false).src)
69
+ before
70
+ <%= form do %>
71
+ inside
72
+ <% end %>
73
+ after
74
+ END
75
+
76
+ # Output:
77
+ # before
78
+ # <form>
79
+ # inside
80
+ # </form>
81
+ # after
59
82
 
60
- To use the capture_end support with tilt:
83
+ To use the capture_block support with tilt:
61
84
 
62
85
  require 'tilt'
63
- require 'erubi/capture_end'
64
- Tilt.new("filename.erb", :engine_class=>Erubi::CaptureEndEngine).render
86
+ require 'erubi/capture_block'
87
+ Tilt.new("filename.erb", :engine_class=>Erubi::CaptureBlockEngine).render
88
+
89
+ Note that the capture_block support, while very compatible with the default
90
+ support, is not 100% compatible. One area where behavior differs is when
91
+ using multiple statements inside <tt><%=</tt> and <tt><%==</tt> tags:
92
+
93
+ <%= 1; 2 %>
94
+
95
+ The default support will output 2, but the capture_block support will output
96
+ 1.
97
+
98
+ === Erubi::CaptureEndEngine
99
+
100
+ An alternative capture implementation can be required via +erubi/capture_end+,
101
+ which supports it via <tt><%|=</tt> and <tt><%|==</tt> tags which are
102
+ closed with a <tt><%|</tt> tag:
103
+
104
+ <%|= form do %>
105
+ <input>
106
+ <%| end %>
107
+
108
+ It is only recommended to use +erubi/capture_end+ for backwards
109
+ compatibilty.
65
110
 
66
- When using the capture_end support, any methods (such as +form+ in the example
67
- above) should return the (potentially modified) buffer. Since the buffer
68
- variable is a local variable and not an instance variable by default, you'll
69
- probably want to set the +:bufvar+ variable when using the capture_end
70
- support to an instance variable, and have any methods used access that
71
- instance variable. Example:
111
+ When using the capture_end support, capture methods (such as +form+ in the example
112
+ above) should return the (potentially modified) buffer. Similar to the
113
+ capture_block support, using an instance variable is recommended. Example:
72
114
 
73
115
  def form
74
116
  @_buf << "<form>"
@@ -77,7 +119,7 @@ instance variable. Example:
77
119
  @_buf
78
120
  end
79
121
 
80
- puts eval(Erubi::CaptureEndEngine.new(<<-END, :bufvar=>:@_buf).src)
122
+ puts eval(Erubi::CaptureEndEngine.new(<<-END, bufvar: '@_buf').src)
81
123
  before
82
124
  <%|= form do %>
83
125
  inside
data/Rakefile CHANGED
@@ -16,7 +16,7 @@ end
16
16
  RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Erubi: Small ERB Implementation']
17
17
 
18
18
  begin
19
- gem 'hanna-nouveau'
19
+ gem 'hanna'
20
20
  RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
21
21
  rescue Gem::LoadError
22
22
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erubi'
4
+
5
+ module Erubi
6
+ # An engine class that supports capturing blocks via the <tt><%=</tt> and <tt><%==</tt> tags:
7
+ #
8
+ # <%= upcase_form do %>
9
+ # <%= 'foo' %>
10
+ # <% end %>
11
+ #
12
+ # Where +upcase_form+ is defined like:
13
+ #
14
+ # def upcase_form(&block)
15
+ # "<form>#{@bufvar.capture(&block).upcase}</form>"
16
+ # end
17
+ #
18
+ # With output being:
19
+ #
20
+ # <form>
21
+ # FOO
22
+ # </form>
23
+ #
24
+ # This requires using a string subclass as the buffer value, provided by the
25
+ # CaptureBlockEngine::Buffer class.
26
+ #
27
+ # This engine does not support the :escapefunc option. To change the escaping function,
28
+ # use a subclass of CaptureBlockEngine::Buffer and override the #| method.
29
+ #
30
+ # This engine does not support the :chain_appends option, and ignores it if present.
31
+ class CaptureBlockEngine < Engine
32
+ class Buffer < ::String
33
+
34
+ # Convert argument to string when concatening
35
+ def <<(v)
36
+ concat(v.to_s)
37
+ end
38
+
39
+ # Escape argument using Erubi.h then then concatenate it to the receiver.
40
+ def |(v)
41
+ concat(h(v))
42
+ end
43
+
44
+ # Temporarily clear the receiver before yielding to the block, yield the
45
+ # given args to the block, return any data captured by the receiver, and
46
+ # restore the original data the receiver contained before returning.
47
+ def capture(*args)
48
+ prev = dup
49
+ replace("") # 1.8 support!
50
+ yield(*args)
51
+ dup
52
+ ensure
53
+ replace(prev)
54
+ end
55
+
56
+ private
57
+
58
+ if RUBY_VERSION >= '2'
59
+ define_method(:h, ::Erubi.instance_method(:h))
60
+ # :nocov:
61
+ else
62
+ def h(v)
63
+ ::Erubi.h(v)
64
+ end
65
+ end
66
+ # :nocov:
67
+ end
68
+
69
+ def initialize(input, properties={})
70
+ properties = Hash[properties]
71
+ properties[:bufval] ||= '::Erubi::CaptureBlockEngine::Buffer.new'
72
+ properties[:chain_appends] = false
73
+ super
74
+ end
75
+
76
+ private
77
+
78
+ def add_expression_result(code)
79
+ add_expression_op(' <<= ', code)
80
+ end
81
+
82
+ def add_expression_result_escaped(code)
83
+ add_expression_op(' |= ', code)
84
+ end
85
+
86
+ def add_expression_op(op, code)
87
+ check = /\A\s*\z/.send(MATCH_METHOD, code) ? "''" : ''
88
+ with_buffer{@src << op << check << code}
89
+ end
90
+ end
91
+ end
data/lib/erubi.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Erubi
4
- VERSION = '1.11.0'
4
+ VERSION = '1.13.0'
5
5
 
6
6
  # :nocov:
7
7
  if RUBY_VERSION >= '1.9'
@@ -14,34 +14,39 @@ module Erubi
14
14
 
15
15
  MATCH_METHOD = RUBY_VERSION >= '2.4' ? :match? : :match
16
16
  SKIP_DEFINED_FOR_INSTANCE_VARIABLE = RUBY_VERSION > '3'
17
+ FREEZE_TEMPLATE_LITERALS = !eval("''").frozen? && RUBY_VERSION >= '2.1'
17
18
  # :nocov:
18
19
 
19
20
  begin
20
- require 'cgi/escape'
21
- # :nocov:
22
- unless CGI.respond_to?(:escapeHTML) # work around for JRuby 9.1
23
- CGI = Object.new
24
- CGI.extend(defined?(::CGI::Escape) ? ::CGI::Escape : ::CGI::Util)
25
- end
26
- # :nocov:
27
- # Escape characters with their HTML/XML equivalents.
28
- def self.h(value)
29
- CGI.escapeHTML(value.to_s)
30
- end
21
+ require 'erb/escape'
22
+ define_method(:h, ERB::Escape.instance_method(:html_escape))
23
+ # :nocov:
31
24
  rescue LoadError
32
- # :nocov:
33
- ESCAPE_TABLE = {'&' => '&amp;'.freeze, '<' => '&lt;'.freeze, '>' => '&gt;'.freeze, '"' => '&quot;'.freeze, "'" => '&#39;'.freeze}.freeze
34
- if RUBY_VERSION >= '1.9'
35
- def self.h(value)
36
- value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
25
+ begin
26
+ require 'cgi/escape'
27
+ unless CGI.respond_to?(:escapeHTML) # work around for JRuby 9.1
28
+ CGI = Object.new
29
+ CGI.extend(defined?(::CGI::Escape) ? ::CGI::Escape : ::CGI::Util)
30
+ end
31
+ # Escape characters with their HTML/XML equivalents.
32
+ def h(value)
33
+ CGI.escapeHTML(value.to_s)
37
34
  end
38
- else
39
- def self.h(value)
40
- value.to_s.gsub(/[&<>"']/){|s| ESCAPE_TABLE[s]}
35
+ rescue LoadError
36
+ ESCAPE_TABLE = {'&' => '&amp;'.freeze, '<' => '&lt;'.freeze, '>' => '&gt;'.freeze, '"' => '&quot;'.freeze, "'" => '&#39;'.freeze}.freeze
37
+ if RUBY_VERSION >= '1.9'
38
+ def h(value)
39
+ value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
40
+ end
41
+ else
42
+ def h(value)
43
+ value.to_s.gsub(/[&<>"']/){|s| ESCAPE_TABLE[s]}
44
+ end
41
45
  end
42
46
  end
43
- # :nocov:
44
47
  end
48
+ # :nocov:
49
+ module_function :h
45
50
 
46
51
  class Engine
47
52
  # The default regular expression used for scanning.
@@ -95,7 +100,7 @@ module Erubi
95
100
  preamble = properties[:preamble] || "#{bufvar} = #{bufval};"
96
101
  postamble = properties[:postamble] || "#{bufvar}.to_s\n"
97
102
  @chain_appends = properties[:chain_appends]
98
- @text_end = if properties.fetch(:freeze_template_literals, RUBY_VERSION >= '2.1')
103
+ @text_end = if properties.fetch(:freeze_template_literals, FREEZE_TEMPLATE_LITERALS)
99
104
  "'.freeze"
100
105
  else
101
106
  "'"
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erubi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  - kuwata-lab.com
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-08-02 00:00:00.000000000 Z
12
+ date: 2024-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -53,15 +53,17 @@ files:
53
53
  - README.rdoc
54
54
  - Rakefile
55
55
  - lib/erubi.rb
56
+ - lib/erubi/capture_block.rb
56
57
  - lib/erubi/capture_end.rb
57
58
  homepage: https://github.com/jeremyevans/erubi
58
59
  licenses:
59
60
  - MIT
60
61
  metadata:
61
62
  bug_tracker_uri: https://github.com/jeremyevans/erubi/issues
63
+ mailing_list_uri: https://github.com/jeremyevans/erubi/discussions
62
64
  changelog_uri: https://github.com/jeremyevans/erubi/blob/master/CHANGELOG
63
65
  source_code_uri: https://github.com/jeremyevans/erubi
64
- post_install_message:
66
+ post_install_message:
65
67
  rdoc_options:
66
68
  - "--quiet"
67
69
  - "--line-numbers"
@@ -83,8 +85,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
85
  - !ruby/object:Gem::Version
84
86
  version: '0'
85
87
  requirements: []
86
- rubygems_version: 3.3.7
87
- signing_key:
88
+ rubygems_version: 3.5.9
89
+ signing_key:
88
90
  specification_version: 4
89
91
  summary: Small ERB Implementation
90
92
  test_files: []