berns 3.3.1 → 4.0.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: 8befdd27a627569fd4d81d583c107e97af40e9b8f29423c4178fffa1decb92e9
4
- data.tar.gz: e268d19c3fafd596d310fefddcda6e9ca2393f06f668d52c3d92a7d748e41c77
3
+ metadata.gz: 5cfbcf19e2450ffa23b283ad0bb24717cde0bf6191bd8db538bf2cbb3936f205
4
+ data.tar.gz: f2639cdade9f1a3ee7b55a66666d23ce9843f5988567d3a630fc7403476825e8
5
5
  SHA512:
6
- metadata.gz: d14dbff87be26716aa466fab088ac036e25e27e72fd2893c4fb67f02422560c88d8bd2d15c08b176c6c9b4fa706ed3a4098edcfe54af273a43eef5cacd295142
7
- data.tar.gz: 34c7b95ee33095ea4e8712e280ad90cfe7d79d983996c72c0c245bb63ee9c10c28150a8bfbc3da0f56236ec5ac7df35f61a11f1f4a5e5f0255c167896e4bae5c
6
+ metadata.gz: f36bec9a6378fa664cc254a24700c63fc4a44720cfd5aad2b7e882dc6aa6ffa523031ec165270cb50d792c85dbcf0e1c0942d3ad22b64b4ec47ee29572170c03
7
+ data.tar.gz: a520befecc81e00cb2ae6c4a8b973965ee10cbdca0adb003d49ee6464478302ac97391651412f3945a5e6d92f76eaa2f5b51c5d5ef186a3c463c5b6928de564c
data/README.org CHANGED
@@ -1,6 +1,7 @@
1
1
  * Berns
2
2
 
3
3
  [[https://badge.fury.io/rb/berns][https://badge.fury.io/rb/berns.svg]]
4
+ [[https://github.com/evanleck/berns/actions/workflows/main.yml][https://github.com/evanleck/berns/actions/workflows/main.yml/badge.svg]]
4
5
 
5
6
  A utility library for generating HTML strings.
6
7
 
@@ -95,10 +96,102 @@ Note that this is an extremely naive implementation of HTML sanitization that
95
96
  literally just looks for "<" and ">" characters and removes the contents between
96
97
  them. This should probably only be used on trusted strings.
97
98
 
99
+ *** =build { content }=
100
+
101
+ The =build= method uses =Berns::Builder= to let you create HTML strings using a DSL.
102
+
103
+ #+begin_src ruby
104
+ Berns.build { h1 { 'Heading' } } # => '<h1>Heading</h1>'
105
+ #+end_src
106
+
107
+ See below for more on =Berns::Builder=.
108
+
109
+ *** =Berns::Builder= HTML DSL
110
+
111
+ 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]],
112
+ and [[https://github.com/activeadmin/arbre][Arbre]], the =Berns::Builder= class lets you create HTML strings using a DSL.
113
+
114
+ #+begin_src ruby
115
+ template = Berns::Builder.new do
116
+ h1 { 'Heading' }
117
+ p(class: 'paragraph') do
118
+ text 'Bare text here.'
119
+
120
+ b { 'Bold text here' }
121
+ end
122
+ end
123
+ #+end_src
124
+
125
+ Within the block provided to =Berns::Builder.new= every standard element method,
126
+ void element method, =#element=, and =#void= are available as methods and each
127
+ time you use one of those methods the result is appended to an internal buffer.
128
+ In addition, the =#text= method can be used to append a plain text string to the
129
+ buffer and that text will be HTML escaped, so it's good for untrusted content.
130
+
131
+ Once initialized, rendering the template to a string can be done with the
132
+ =#call= method and any arguments, positional or keyword, will be passed through
133
+ as-is to the block provided to =#new=.
134
+
135
+ #+begin_src ruby
136
+ string = template.call # =>
137
+ # <h1>
138
+ # Heading
139
+ # </h1>
140
+ # <p class='paragraph'>
141
+ # Bare text here.
142
+ # <b>
143
+ # Bold text here.
144
+ # </b>
145
+ # </p>
146
+ #+end_src
147
+
148
+ In addition to initializing a new instance of =Berns::Builder=, you can
149
+ construct and render a template to a string all at once with =Berns.build=.
150
+
151
+ #+begin_src ruby
152
+ Berns.build do
153
+ h1 { 'Heading' }
154
+ p(class: 'paragraph') do
155
+ text 'Bare text here.'
156
+
157
+ b { 'Bold text here' }
158
+ end
159
+ end # =>
160
+ # <h1>
161
+ # Heading
162
+ # </h1>
163
+ # <p class='paragraph'>
164
+ # Bare text here.
165
+ # <b>
166
+ # Bold text here.
167
+ # </b>
168
+ # </p>
169
+ #+end_src
170
+
171
+ Lastly, the block provided to =Berns::Builder.new= can take both positional and
172
+ keyword arguments.
173
+
174
+ #+begin_src ruby
175
+ template = Berns::Builder.new do |content, title:|
176
+ h1 { title }
177
+ p(class: 'paragraph') { content }
178
+ end
179
+
180
+ template.call('Some text.', title: 'The title') # =>
181
+ # <h1>
182
+ # The title
183
+ # </h1>
184
+ # <p>
185
+ # Some text.
186
+ # </p>
187
+ #+end_src
188
+
98
189
  *** Standard and void elements
99
190
 
100
191
  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.
192
+ create e.g. a link with =Berns.a=. Below is the full list of standard elements
193
+ which are also available in the constant =Berns::STANDARD= as an array of
194
+ symbols.
102
195
 
103
196
  #+begin_example
104
197
  a abbr address article aside audio b bdi bdo blockquote body button
@@ -111,15 +204,33 @@ table tbody td template textarea tfoot th thead time title tr u ul var
111
204
  video
112
205
  #+end_example
113
206
 
114
-
115
207
  Below is the full list of void elements that are defined as singleton methods on
116
- Berns.
208
+ Berns which are also available in the constant =Berns::VOID= as an array of
209
+ symbols.
117
210
 
118
211
  #+begin_example
119
212
  area base br col embed hr img input link menuitem meta param source track wbr
120
213
  #+end_example
121
214
 
215
+ ** Performance
216
+
217
+ Berns 3 is about three times faster than the pure Ruby implementation used in
218
+ version 2. See the file [[file:benchmarks/performance.rb][benchmarks/performance.rb]] for the benchmark code.
219
+
220
+ #+begin_example
221
+ Warming up --------------------------------------
222
+ element 27.373k i/100ms
223
+ berns 94.118k i/100ms
224
+ Calculating -------------------------------------
225
+ element 314.078k (± 4.5%) i/s - 1.588M in 5.065539s
226
+ berns 935.528k (± 6.1%) i/s - 4.706M in 5.049718s
227
+
228
+ Comparison:
229
+ berns: 935527.9 i/s
230
+ element: 314078.4 i/s - 2.98x (± 0.00) slower
231
+ #+end_example
232
+
122
233
  ** Trivia
123
234
 
124
- The name "Berns" is taken from the name of [[https://en.wikipedia.org/wiki/HTML#Development][the inventor of HTML]], [[https://en.wikipedia.org/wiki/Tim_Berners-Lee][Sir Tim
125
- Berners-Lee]].
235
+ The name "Berns" is taken from the name of [[https://en.wikipedia.org/wiki/HTML#Development][the inventor of HTML]],
236
+ [[https://en.wikipedia.org/wiki/Tim_Berners-Lee][Sir Tim Berners-Lee]].
data/ext/berns/berns.c CHANGED
@@ -228,7 +228,7 @@ static char * hash_value_to_attribute(const char *attr, const size_t attrlen, VA
228
228
 
229
229
  Check_Type(value, T_HASH);
230
230
 
231
- if (rb_hash_size(value) == 1) {
231
+ if (RHASH_SIZE(value) == 0) {
232
232
  return strdup("");
233
233
  }
234
234
 
@@ -439,7 +439,7 @@ static VALUE external_to_attribute(RB_UNUSED_VAR(VALUE self), VALUE attr, VALUE
439
439
  static VALUE external_to_attributes(RB_UNUSED_VAR(VALUE self), VALUE attributes) {
440
440
  Check_Type(attributes, T_HASH);
441
441
 
442
- if (rb_hash_size(attributes) == 1) {
442
+ if (RHASH_SIZE(attributes) == 0) {
443
443
  return rb_utf8_str_new_cstr("");
444
444
  }
445
445
 
@@ -453,37 +453,32 @@ static VALUE external_to_attributes(RB_UNUSED_VAR(VALUE self), VALUE attributes)
453
453
  }
454
454
 
455
455
  static char * void_element(const char *tag, size_t tlen, VALUE attributes) {
456
- /* T_IMEMO is what we get if an optional argument was not passed. */
457
- if (TYPE(attributes) == T_IMEMO) {
458
- size_t total = tag_olen + tlen + tag_clen + 1;
459
- char *string = malloc(total);
460
- char *ptr;
461
- char *end = string + total;
456
+ const char *empty = "";
457
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
458
+ size_t alen = strlen(attrs);
462
459
 
463
- ptr = stecpy(string, tag_open, end);
464
- ptr = stecpy(ptr, tag, end);
465
- ptr = stecpy(ptr, tag_close, end);
460
+ size_t total = tag_olen + tlen + tag_clen + 1;
466
461
 
467
- return string;
468
- } else {
469
- const char *empty = "";
470
- char *attrs = hash_value_to_attribute(empty, 0, attributes);
462
+ /* If we have some attributes, add a space and the attributes' length. */
463
+ if (alen > 0) {
464
+ total += splen + alen;
465
+ }
471
466
 
472
- size_t total = tag_olen + tlen + splen + strlen(attrs) + tag_clen + 1;
473
- char *string = malloc(total);
474
- char *ptr;
475
- char *end = string + total;
467
+ char *dest = malloc(total);
468
+ char *ptr = NULL;
469
+ char *end = dest + total;
476
470
 
477
- ptr = stecpy(string, tag_open, end);
478
- ptr = stecpy(ptr, tag, end);
471
+ ptr = stecpy(dest, tag_open, end);
472
+ ptr = stecpy(ptr, tag, end);
473
+
474
+ if (alen > 0) {
479
475
  ptr = stecpy(ptr, space, end);
480
476
  ptr = stecpy(ptr, attrs, end);
481
- ptr = stecpy(ptr, tag_close, end);
477
+ }
482
478
 
483
- free(attrs);
479
+ ptr = stecpy(ptr, tag_close, end);
484
480
 
485
- return string;
486
- }
481
+ return dest;
487
482
  }
488
483
 
489
484
  /*
data/ext/berns/extconf.rb CHANGED
@@ -9,5 +9,6 @@ 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'
12
13
 
13
14
  create_makefile 'berns/berns'