berns 3.2.0 → 3.4.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: 0d9597d10ff728258b758e65aca73ec692374d3d359acb976677f0e143800978
4
- data.tar.gz: 8eb851e88a7674a5d9e9af5f111085af87bb958db03f0539574bdd9358dad9be
3
+ metadata.gz: 844af14032659e36711f21b482d7e07ba1627cdca43045ec1fb30869171ee21a
4
+ data.tar.gz: 828da05830d2d5c1a516fe51bcc2a5c5c9c346359f9eedde4b3ee5bd60a6bf25
5
5
  SHA512:
6
- metadata.gz: 6e62bb1798243beab62f44e1ba7a3fc211b53997ce44e4ba37e6c46303974a96d4391d3fcdb9c807f3b894f097e9d3c823831026d4dca645362b21f4cab050da
7
- data.tar.gz: 047c09ea060864337ee852e51b85964bfed265009123e290e17d0f3b51782aca5ad3ca877ea45195536e8a93258dd5536e66c6e553d6afc5dfcbf970bccf7807
6
+ metadata.gz: 93e0a7fc35666b0395d338cafc5a7aa9bb8aa3d1467158cdb1fc325640d275b3cfa0033921edfd62f0d6a52cbf8728842b45c31ea4d19552d18ee6440c135b59
7
+ data.tar.gz: 6bc2ea5f4749e09d8bbc4dacd2fac2981ad66dfdc649cb14f78a50ed21af5705d057228764edf6bdd32e4eb4dc8e848f6a42ffbab157ec9bf78f05c94899be6c
data/LICENSE.txt CHANGED
@@ -1,21 +1,20 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Taylor Beck
3
+ Copyright © 2021 Taylor Beck and Evan Lecklider
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the Software), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
11
 
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
14
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
15
+ THE SOFTWARE IS PROVIDED AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.org CHANGED
@@ -95,10 +95,84 @@ Note that this is an extremely naive implementation of HTML sanitization that
95
95
  literally just looks for "<" and ">" characters and removes the contents between
96
96
  them. This should probably only be used on trusted strings.
97
97
 
98
+ *** =build { content }=
99
+
100
+ The =build= method uses =Berns::Builder= to let you create HTML strings using a DSL.
101
+
102
+ #+begin_src ruby
103
+ Berns.build { h1 { 'Heading' } } # => '<h1>Heading</h1>'
104
+ #+end_src
105
+
106
+ See below for more on =Berns::Builder=.
107
+
108
+ *** =Berns::Builder= HTML DSL
109
+
110
+ Added in version 3.4.0 and heavily inspired by the likes of [[https://github.com/digital-fabric/papercraft][Papercraft]], [[https://github.com/markaby/markaby][Markaby]],
111
+ and [[https://github.com/activeadmin/arbre][Arbre]], the =Berns::Builder= class lets you create HTML strings using a DSL.
112
+
113
+ #+begin_src ruby
114
+ template = Berns::Builder.new do
115
+ h1 { 'Heading' }
116
+ p(class: 'paragraph') do
117
+ text 'Bare text here.'
118
+
119
+ b { 'Bold text here' }
120
+ end
121
+ end
122
+ #+end_src
123
+
124
+ Within the block provided to =Berns::Builder.new= every standard and void
125
+ element is available as a method and each time you use one of those methods the
126
+ result is appended to an internal buffer. In addition, the =#text= method can be
127
+ used to append a plain text string to the buffer and that text will be HTML
128
+ escaped, so it's good for untrusted content.
129
+
130
+ Once initialized, rendering the template to a string can be done with the
131
+ =#call= method and any arguments, positional or keyword, will be passed through
132
+ as-is to the block provided to =#new=.
133
+
134
+ #+begin_src ruby
135
+ string = template.call # =>
136
+ # <h1>
137
+ # Heading
138
+ # </h1>
139
+ # <p class='paragraph'>
140
+ # Bare text here.
141
+ # <b>
142
+ # Bold text here.
143
+ # </b>
144
+ # </p>
145
+ #+end_src
146
+
147
+ In addition to initializing a new instance of =Berns::Builder=, you can
148
+ construct and render a template to a string all at once with =Berns.build=.
149
+
150
+ #+begin_src ruby
151
+ Berns.build do
152
+ h1 { 'Heading' }
153
+ p(class: 'paragraph') do
154
+ text 'Bare text here.'
155
+
156
+ b { 'Bold text here' }
157
+ end
158
+ end # =>
159
+ # <h1>
160
+ # Heading
161
+ # </h1>
162
+ # <p class='paragraph'>
163
+ # Bare text here.
164
+ # <b>
165
+ # Bold text here.
166
+ # </b>
167
+ # </p>
168
+ #+end_src
169
+
98
170
  *** Standard and void elements
99
171
 
100
172
  All standard and void HTML elements are defined as methods on Berns, so you can
101
- create e.g. a link with =Berns.a=. Below is the full list of standard elements.
173
+ create e.g. a link with =Berns.a=. Below is the full list of standard elements
174
+ which are also available in the constant =Berns::STANDARD= as an array of
175
+ symbols.
102
176
 
103
177
  #+begin_example
104
178
  a abbr address article aside audio b bdi bdo blockquote body button
@@ -111,10 +185,33 @@ table tbody td template textarea tfoot th thead time title tr u ul var
111
185
  video
112
186
  #+end_example
113
187
 
114
-
115
188
  Below is the full list of void elements that are defined as singleton methods on
116
- Berns.
189
+ Berns which are also available in the constant =Berns::VOID= as an array of
190
+ symbols.
117
191
 
118
192
  #+begin_example
119
193
  area base br col embed hr img input link menuitem meta param source track wbr
120
194
  #+end_example
195
+
196
+ ** Performance
197
+
198
+ Berns 3 is about three times faster than the pure Ruby implementation used in
199
+ version 2. See the file [[file:benchmarks/performance.rb][benchmarks/performance.rb]] for the benchmark code.
200
+
201
+ #+begin_example
202
+ Warming up --------------------------------------
203
+ element 27.373k i/100ms
204
+ berns 94.118k i/100ms
205
+ Calculating -------------------------------------
206
+ element 314.078k (± 4.5%) i/s - 1.588M in 5.065539s
207
+ berns 935.528k (± 6.1%) i/s - 4.706M in 5.049718s
208
+
209
+ Comparison:
210
+ berns: 935527.9 i/s
211
+ element: 314078.4 i/s - 2.98x (± 0.00) slower
212
+ #+end_example
213
+
214
+ ** Trivia
215
+
216
+ The name "Berns" is taken from the name of [[https://en.wikipedia.org/wiki/HTML#Development][the inventor of HTML]],
217
+ [[https://en.wikipedia.org/wiki/Tim_Berners-Lee][Sir Tim Berners-Lee]].
data/ext/berns/berns.c CHANGED
@@ -64,7 +64,7 @@ static const size_t sllen = 1;
64
64
  static VALUE external_##element_name##_element(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self)) { \
65
65
  rb_check_arity(argc, 0, 1); \
66
66
  \
67
- CONTENT_FROM_BLOCK; \
67
+ CONTENT_FROM_BLOCK \
68
68
  const char *tag = #element_name; \
69
69
  char *string = element(tag, strlen(tag), RSTRING_PTR(content), RSTRING_LEN(content), argv[0]); \
70
70
  VALUE rstring = rb_utf8_str_new_cstr(string); \
@@ -110,22 +110,39 @@ static VALUE external_sanitize(RB_UNUSED_VAR(VALUE self), VALUE string) {
110
110
  char *str = RSTRING_PTR(string);
111
111
 
112
112
  char dest[slen + 1];
113
- int index = 0;
114
- int open = 0;
113
+
114
+ unsigned int index = 0;
115
+ unsigned int open = 0;
116
+ unsigned int modified = 0;
117
+ unsigned int entity = 0;
115
118
 
116
119
  for (unsigned int i = 0; i < slen; i++) {
117
120
  if (str[i] == '<') {
118
121
  open = 1;
122
+ modified = 1;
119
123
  } else if (str[i] == '>') {
120
124
  open = 0;
121
- } else if (!open) {
125
+ } else if (str[i] == '&') {
126
+ entity = 1;
127
+ modified = 1;
128
+ } else if (str[i] == ';') {
129
+ entity = 0;
130
+ } else if (!open && !entity) {
122
131
  dest[index++] = str[i];
123
132
  }
124
133
  }
125
134
 
126
135
  dest[index] = '\0';
127
136
 
128
- return rb_utf8_str_new_cstr(dest);
137
+ /*
138
+ * If the string was never modified, return the original string, otherwise
139
+ * create a new string from our destination buffer.
140
+ */
141
+ if (modified) {
142
+ return rb_utf8_str_new_cstr(dest);
143
+ } else {
144
+ return string;
145
+ }
129
146
  }
130
147
 
131
148
  /*
@@ -561,7 +578,7 @@ static VALUE external_element(int argc, VALUE *arguments, RB_UNUSED_VAR(VALUE se
561
578
 
562
579
  StringValue(tag);
563
580
 
564
- CONTENT_FROM_BLOCK;
581
+ CONTENT_FROM_BLOCK
565
582
 
566
583
  char *string = element(RSTRING_PTR(tag), RSTRING_LEN(tag), RSTRING_PTR(content), RSTRING_LEN(content), attributes);
567
584
  VALUE rstring = rb_utf8_str_new_cstr(string);
data/ext/berns/extconf.rb CHANGED
@@ -9,6 +9,5 @@ append_cflags '-Wstrict-overflow'
9
9
  append_cflags '-flto'
10
10
  append_cflags '-fno-strict-aliasing'
11
11
  append_cflags '-msse4'
12
- append_cflags '-std=c99'
13
12
 
14
13
  create_makefile 'berns/berns'
Binary file
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require 'berns'
3
+
4
+ module Berns
5
+ # An HTML builder DSL using Berns' HTML methods.
6
+ class Builder
7
+ def initialize(&block)
8
+ @block = block
9
+ @buffer = +''
10
+ end
11
+
12
+ # @return [String]
13
+ def call(*args, **opts)
14
+ instance_exec(*args, **opts, &@block)
15
+ to_s
16
+ end
17
+
18
+ # @return [String]
19
+ def to_s
20
+ @buffer.freeze
21
+ end
22
+
23
+ # Append text to the buffer.
24
+ #
25
+ # @param string [String]
26
+ # @return [String]
27
+ def text(string)
28
+ @buffer << Berns.escape_html(string.to_s)
29
+ end
30
+
31
+ Berns::STANDARD.each do |meth|
32
+ define_method(meth) do |*args, **opts, &block|
33
+ content = Builder.new.instance_exec(*args, **opts, &block) if block
34
+ @buffer << Berns.send(meth, *args, **opts) { content }
35
+ end
36
+ end
37
+
38
+ Berns::VOID.each do |meth|
39
+ define_method(meth) do |*args, **opts|
40
+ @buffer << Berns.send(meth, *args, **opts)
41
+ end
42
+ end
43
+ end
44
+ end
data/lib/berns/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Berns
3
- VERSION = '3.2.0'
3
+ VERSION = '3.4.0'
4
4
  end
data/lib/berns.rb CHANGED
@@ -1,3 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
  require 'berns/berns'
3
3
  require 'berns/version'
4
+
5
+ module Berns # :nodoc:
6
+ autoload :Builder, 'berns/builder'
7
+
8
+ STANDARD = %i[
9
+ a abbr address article aside audio b bdi bdo blockquote body button canvas
10
+ caption cite code colgroup datalist dd del details dfn dialog div dl dt em
11
+ fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header html i
12
+ iframe ins kbd label legend li main map mark menu meter nav noscript object
13
+ ol optgroup option output p picture pre progress q rp rt ruby s samp script
14
+ section select small span strong style sub summary table tbody td template
15
+ textarea tfoot th thead time title tr u ul var video
16
+ ].freeze
17
+
18
+ VOID = %i[
19
+ area base br col embed hr img input link menuitem meta param source track wbr
20
+ ].freeze
21
+
22
+ # @return [String]
23
+ def self.build(*args, **opts, &block)
24
+ Builder.new(&block).call(*args, **opts)
25
+ end
26
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berns
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taylor Beck
8
8
  - Evan Lecklider
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-06-14 00:00:00.000000000 Z
12
+ date: 2022-02-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: benchmark-ips
@@ -167,15 +167,17 @@ files:
167
167
  - ext/berns/hescape.c
168
168
  - ext/berns/hescape.h
169
169
  - lib/berns.rb
170
- - lib/berns/berns.so
170
+ - lib/berns/berns.bundle
171
+ - lib/berns/builder.rb
171
172
  - lib/berns/version.rb
172
173
  homepage: https://github.com/evanleck/berns
173
174
  licenses:
174
175
  - MIT
175
176
  metadata:
176
177
  bug_tracker_uri: https://github.com/evanleck/berns/issues
178
+ rubygems_mfa_required: 'true'
177
179
  source_code_uri: https://github.com/evanleck/berns
178
- post_install_message:
180
+ post_install_message:
179
181
  rdoc_options: []
180
182
  require_paths:
181
183
  - lib
@@ -188,10 +190,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
190
  requirements:
189
191
  - - ">="
190
192
  - !ruby/object:Gem::Version
191
- version: '0'
193
+ version: '2.0'
192
194
  requirements: []
193
- rubygems_version: 3.2.15
194
- signing_key:
195
+ rubygems_version: 3.3.3
196
+ signing_key:
195
197
  specification_version: 4
196
198
  summary: A utility library for generating HTML strings.
197
199
  test_files: []
data/lib/berns/berns.so DELETED
Binary file