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 +4 -4
- data/README.org +116 -5
- data/ext/berns/berns.c +20 -25
- data/ext/berns/extconf.rb +1 -0
- data/ext/berns/sds.c +1300 -0
- data/ext/berns/sds.h +274 -0
- data/ext/berns/sdsalloc.h +42 -0
- data/lib/berns/berns.bundle +0 -0
- data/lib/berns/builder.rb +59 -0
- data/lib/berns/version.rb +1 -1
- data/lib/berns.rb +23 -0
- metadata +11 -145
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cfbcf19e2450ffa23b283ad0bb24717cde0bf6191bd8db538bf2cbb3936f205
|
4
|
+
data.tar.gz: f2639cdade9f1a3ee7b55a66666d23ce9843f5988567d3a630fc7403476825e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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]],
|
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 (
|
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 (
|
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
|
-
|
457
|
-
|
458
|
-
|
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
|
-
|
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
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
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
|
-
|
473
|
-
|
474
|
-
|
475
|
-
char *end = string + total;
|
467
|
+
char *dest = malloc(total);
|
468
|
+
char *ptr = NULL;
|
469
|
+
char *end = dest + total;
|
476
470
|
|
477
|
-
|
478
|
-
|
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
|
-
|
477
|
+
}
|
482
478
|
|
483
|
-
|
479
|
+
ptr = stecpy(ptr, tag_close, end);
|
484
480
|
|
485
|
-
|
486
|
-
}
|
481
|
+
return dest;
|
487
482
|
}
|
488
483
|
|
489
484
|
/*
|