berns 3.3.1 → 4.0.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 +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
|
/*
|