berns 3.2.0 → 3.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: 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