berns 3.0.3 → 3.1.1

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: a8cce0df8142c8a2057ccaebe098b64e250c11d57ec2c1a6ddaa90a965b8d9d1
4
- data.tar.gz: 367bc79f457574800fd20ec28a51a8a81fe8c45cfaa05bf94c4b47cdfdeac3ba
3
+ metadata.gz: eceee553d37bba81c69041a8b4df52d8d108edfeb40d23005d2045c2d10af24a
4
+ data.tar.gz: 176886a8d6d08a5c83624ca294ee3a62c30846dcbc359888f47f8e500fb539e5
5
5
  SHA512:
6
- metadata.gz: 9535d2513301b4b1a03eb0dd1105bdef5dc39b849c6964a5f79d218f695c7cfc40377147ef3262fc58290626b99b4d119698ae39812e37356a36315a0f3e95ab
7
- data.tar.gz: 48ee25901e3d204953472b4a9e1e4e1193c71dee33711e5a8160bdcd8e9322cdfde7721f15bcc50f0b4cea03d254130c44a55a03920ec389bb2c04638e84c18b
6
+ metadata.gz: 433c793484d7508edd1c376aae80d881425dbf76c5713e0d6aefed09be9d0f60a40ae7aa6279259c15a56835b46c95ec095dfea91b869b137ad97069f8f99480
7
+ data.tar.gz: e931debab26d70ec30977baf2abe7dd7ca43b3d4f32a2492120d409823936f93602efff0bedfb96f48688b33e11660bfd8c8ea49a071219f83ca5111458f151a
data/README.org CHANGED
@@ -26,10 +26,7 @@ gem install berns
26
26
 
27
27
  ** Usage
28
28
 
29
- All standard and void HTML elements are defined as methods on Berns, so you can
30
- create e.g. a link with =Berns.a=. In addition, there are methods to sanitize
31
- strings i.e. remove HTML from them, convert hashes into a string of HTML
32
- attributes, and more.
29
+ Note that all return string values will be UTF-8 encoded.
33
30
 
34
31
  *** =void(tag, attributes)=
35
32
 
@@ -64,7 +61,8 @@ Berns.to_attribute('class', 'my-class another-class') # => 'class="my-class anot
64
61
  Berns.to_attribute('data', { foo: 'bar' }) # => 'data-foo="bar"'
65
62
  #+end_src
66
63
 
67
- All attribute values are HTML-escaped using =CGI.escapeHTML=.
64
+ All attribute values are HTML-escaped using [[https://github.com/k0kubun/hescape][k0kubun/hescape]] written by Takashi
65
+ Kokubun.
68
66
 
69
67
  *** =to_attributes(attributes)=
70
68
 
@@ -77,8 +75,9 @@ Berns.to_attributes({ 'data' => { foo: 'bar' }, 'class' => 'my-class another-cla
77
75
 
78
76
  *** =escape_html(string)=
79
77
 
80
- The =escape_html= method is a passthrough to =CGI.escapeHTML= and does what it
81
- says on the tin.
78
+ The =escape_html= method escapes HTML entities in strings using [[https://github.com/k0kubun/hescape][k0kubun/hescape]]
79
+ written by Takashi Kokubun. As noted in the hescape repository, it should be the
80
+ same as =CGI.escapeHTML=.
82
81
 
83
82
  #+begin_src ruby
84
83
  Berns.escape_html('<"tag"') # => '&lt;&quot;tag&quot;'
@@ -94,8 +93,8 @@ Berns.sanitize('This <span>should be clean</span>') # => 'This should be clean'
94
93
 
95
94
  *** Standard and void elements
96
95
 
97
- As mentioned above, all standard and void HTML elements are defined as singleton
98
- methods on the Berns module. Below is the full list of standard elements.
96
+ All standard and void HTML elements are defined as methods on Berns, so you can
97
+ create e.g. a link with =Berns.a=. Below is the full list of standard elements.
99
98
 
100
99
  #+begin_example
101
100
  a abbr address article aside audio b bdi bdo blockquote body button
data/ext/berns/berns.c CHANGED
@@ -1,5 +1,79 @@
1
1
  #include "ruby.h"
2
2
  #include "extconf.h"
3
+ #include "hescape.h"
4
+
5
+ static const char *attr_close = "\"";
6
+ static const size_t attr_clen = 1;
7
+
8
+ static const char *attr_equals = "=\"";
9
+ static const size_t attr_eqlen = 2;
10
+
11
+ static const char *dash = "-";
12
+ static const size_t dlen = 1;
13
+
14
+ static const char *space = " ";
15
+ static const size_t splen = 1;
16
+
17
+ static const char *tag_open = "<";
18
+ static const size_t tag_olen = 1;
19
+
20
+ static const char *tag_close = ">";
21
+ static const size_t tag_clen = 1;
22
+
23
+ static const char *slash = "/";
24
+ static const size_t sllen = 1;
25
+
26
+
27
+ /*
28
+ * Macro to capture a block's content as a Ruby string into the local variable
29
+ * content.
30
+ */
31
+ #define CONTENT_FROM_BLOCK \
32
+ VALUE content; \
33
+ \
34
+ if (rb_block_given_p()) { \
35
+ content = rb_yield(Qnil); \
36
+ \
37
+ if (TYPE(content) == T_NIL || TYPE(content) == T_FALSE) { \
38
+ content = rb_utf8_str_new_cstr(""); \
39
+ } else if (TYPE(content) != T_STRING) { \
40
+ content = rb_funcall(content, rb_intern("to_s"), 0); \
41
+ } \
42
+ } else { \
43
+ content = rb_utf8_str_new_cstr(""); \
44
+ }
45
+
46
+ /*
47
+ * Macro to define a "dynamic" function that generates a void element.
48
+ */
49
+ #define VOID_ELEMENT(element_name) \
50
+ static VALUE external_##element_name##_element(int argc, VALUE* argv, RB_UNUSED_VAR(VALUE self)) { \
51
+ rb_check_arity(argc, 0, 1); \
52
+ \
53
+ char *tag = #element_name; \
54
+ char *string = void_element(tag, strlen(tag), &argv[0]); \
55
+ VALUE rstring = rb_utf8_str_new_cstr(string); \
56
+ free(string); \
57
+ \
58
+ return rstring; \
59
+ }
60
+
61
+ /*
62
+ * Macro to define a "dynamic" function that generates a standard element.
63
+ */
64
+ #define STANDARD_ELEMENT(element_name) \
65
+ static VALUE external_##element_name##_element(int argc, VALUE* argv, RB_UNUSED_VAR(VALUE self)) { \
66
+ rb_check_arity(argc, 0, 1); \
67
+ \
68
+ CONTENT_FROM_BLOCK; \
69
+ char *tag = #element_name; \
70
+ char *string = element(tag, strlen(tag), RSTRING_PTR(content), RSTRING_LEN(content), &argv[0]); \
71
+ VALUE rstring = rb_utf8_str_new_cstr(string); \
72
+ free(string); \
73
+ \
74
+ return rstring; \
75
+ }
76
+
3
77
 
4
78
  /*
5
79
  * "Safe strcpy" - https://twitter.com/hyc_symas/status/1102573036534972416?s=12
@@ -17,912 +91,570 @@ static char *stecpy(char *destination, const char *source, const char *end) {
17
91
  }
18
92
 
19
93
  /*
20
- * Berns.escape_html is effectively a proxy to CGI.escapeHTML so we limit the
21
- * type to strings.
94
+ * The external API for Berns.escape_html.
95
+ *
96
+ * string should be a string, anything else will raise an error.
97
+ *
22
98
  */
23
- static VALUE berns_escape_html(const VALUE self, VALUE string) {
99
+ static VALUE external_escape_html(const VALUE self, VALUE string) {
24
100
  StringValue(string);
25
101
 
26
- const VALUE cgi = rb_const_get(rb_cObject, rb_intern("CGI"));
27
- const VALUE escape = rb_intern("escapeHTML");
102
+ uint8_t *dest = NULL;
103
+ size_t slen = RSTRING_LEN(string);
104
+ size_t esclen = hesc_escape_html(&dest, RSTRING_PTR(string), slen);
28
105
 
29
- return rb_funcall(cgi, escape, 1, string);
30
- }
31
-
32
- static VALUE berns_to_attribute(const VALUE self, VALUE attribute, const VALUE value) {
33
- const VALUE empty = rb_utf8_str_new_cstr("");
34
-
35
- VALUE escaped;
36
- VALUE key;
37
- VALUE keys;
38
- VALUE length;
39
106
  VALUE rstring;
40
- VALUE subattr;
41
- VALUE subkey;
42
- VALUE subvalue;
43
107
 
44
- switch(TYPE(attribute)) {
45
- case T_STRING:
46
- break;
47
- case T_SYMBOL:
48
- attribute = rb_sym_to_s(attribute);
49
- break;
50
- default:
51
- rb_raise(rb_eTypeError, "Berns.to_attribute attributes must be Strings or Symbols.");
52
- break;
108
+ if (esclen > slen) {
109
+ rstring = rb_utf8_str_new_cstr(dest);
110
+ free(dest);
111
+ } else {
112
+ rstring = string;
53
113
  }
54
114
 
55
- const char *close = "\"";
56
- const char *dash = "-";
57
- const char *equals = "=\"";
58
- const char *space = " ";
115
+ return rstring;
116
+ }
59
117
 
60
- const size_t clen = strlen(close);
61
- const size_t dlen = strlen(dash);
62
- const size_t eqlen = strlen(equals);
63
- const size_t splen = strlen(space);
118
+ /*
119
+ * Return a freeable piece of memory with a copy of the attribute passed in it.
120
+ * Why does this exist? So we can free the memory created by this without having
121
+ * branch further in other places.
122
+ */
123
+ static char * empty_value_to_attribute(const char *attr, const size_t attrlen) {
124
+ size_t total_size = attrlen + 1;
125
+ char *dest = malloc(total_size);
126
+ char *ptr = NULL;
127
+ char *end = dest + total_size;
64
128
 
65
- switch(TYPE(value)) {
66
- case T_NIL:
67
- case T_TRUE:
68
- return attribute;
69
- case T_FALSE:
70
- return empty;
71
- case T_HASH:
72
- keys = rb_funcall(value, rb_intern("keys"), 0);
73
- length = RARRAY_LEN(keys);
129
+ stecpy(dest, attr, end);
74
130
 
75
- char *substring = NULL;
76
- size_t size = 0;
131
+ return dest;
132
+ }
77
133
 
78
- for (unsigned int i = 0; i < length; i++) {
79
- key = rb_ary_entry(keys, i);
80
- subvalue = rb_hash_aref(value, key);
134
+ /*
135
+ * Takes a string attribute name and value pair and converts them into a string ready to use in HTML
136
+ *
137
+ * "class" + "bg-primary" => 'class="bg-primary"'
138
+ */
139
+ static char * string_value_to_attribute(const char *attr, const size_t attrlen, const char *value, const size_t vallen) {
140
+ if (vallen == 0) {
141
+ size_t total_size = attrlen + 1;
142
+ char *dest = malloc(total_size);
143
+ char *ptr = NULL;
144
+ char *end = dest + total_size;
81
145
 
82
- switch(TYPE(key)) {
83
- case T_NIL:
84
- subkey = empty;
85
- break;
86
- case T_STRING:
87
- subkey = key;
88
- break;
89
- case T_SYMBOL:
90
- subkey = rb_sym_to_s(key);
91
- break;
92
- default:
93
- if (substring != NULL) {
94
- free(substring);
95
- }
146
+ stecpy(dest, attr, end);
96
147
 
97
- rb_raise(rb_eTypeError, "Berns.to_attribute value keys must be Strings or Symbols.");
98
- break;
99
- }
148
+ return dest;
149
+ } else {
150
+ uint8_t *edest = NULL;
151
+ size_t esclen = hesc_escape_html(&edest, value, vallen);
100
152
 
101
- size_t total = RSTRING_LEN(attribute) + 1;
153
+ size_t total_size = attrlen + attr_eqlen + esclen + attr_clen + 1;
154
+ char *dest = malloc(total_size);
155
+ char *ptr = NULL;
156
+ char *end = dest + total_size;
102
157
 
103
- if (RSTRING_LEN(subkey) > 0) {
104
- total = RSTRING_LEN(attribute) + dlen + RSTRING_LEN(subkey) + 1;
105
- }
158
+ ptr = stecpy(dest, attr, end);
159
+ ptr = stecpy(ptr, attr_equals, end);
160
+ ptr = stecpy(ptr, edest, end);
161
+ ptr = stecpy(ptr, attr_close, end);
106
162
 
107
- char subname[total];
108
- char *ptr;
109
- char *end = subname + sizeof(subname);
163
+ if (esclen > vallen) {
164
+ free(edest);
165
+ }
110
166
 
111
- ptr = stecpy(subname, RSTRING_PTR(attribute), end);
167
+ return dest;
168
+ }
169
+ }
112
170
 
113
- if (RSTRING_LEN(subkey) > 0) {
114
- ptr = stecpy(ptr, dash, end);
115
- }
171
+ static char * hash_value_to_attribute(char *attr, const size_t attrlen, VALUE *value) {
172
+ if (TYPE(*value) == T_IMEMO) {
173
+ return calloc(0, 1);
174
+ }
116
175
 
117
- stecpy(ptr, RSTRING_PTR(subkey), end);
176
+ Check_Type(*value, T_HASH);
118
177
 
119
- subattr = berns_to_attribute(self, rb_utf8_str_new_cstr(subname), subvalue);
120
- size_t subattrlen = RSTRING_LEN(subattr);
178
+ if (rb_hash_size(*value) == 1 ) {
179
+ return calloc(0, 1);
180
+ }
121
181
 
122
- if (i > 0) {
123
- size = size + splen + subattrlen;
182
+ VALUE subkey;
183
+ VALUE subvalue;
124
184
 
125
- char *tmp = realloc(substring, size + 1);
185
+ const VALUE keys = rb_funcall(*value, rb_intern("keys"), 0);
186
+ const VALUE length = RARRAY_LEN(keys);
126
187
 
127
- if (tmp == NULL) {
128
- rb_raise(rb_eNoMemError, "Berns.to_attribute could not allocate sufficient memory.");
129
- }
188
+ size_t allocated = 256;
189
+ size_t occupied = 0;
130
190
 
131
- substring = tmp;
191
+ char *destination = malloc(allocated);
192
+ char *position = destination;
193
+ char *end = destination + allocated;
132
194
 
133
- stecpy(substring + size - splen - subattrlen, space, substring + size);
134
- stecpy(substring + size - subattrlen, RSTRING_PTR(subattr), substring + size + 1);
135
- } else {
136
- size = size + subattrlen;
137
- char *tmp = realloc(substring, size + 1);
195
+ for (unsigned int i = 0; i < length; i++) {
196
+ subkey = rb_ary_entry(keys, i);
197
+ subvalue = rb_hash_aref(*value, subkey);
198
+
199
+ switch(TYPE(subkey)) {
200
+ case T_STRING:
201
+ break;
202
+ case T_NIL:
203
+ subkey = rb_utf8_str_new_cstr("");
204
+ break;
205
+ case T_SYMBOL:
206
+ subkey = rb_sym2str(subkey);
207
+ break;
208
+ default:
209
+ free(destination);
210
+ rb_raise(rb_eTypeError, "Berns.to_attribute value keys must be Strings, Symbols, or nil.");
211
+ break;
212
+ }
138
213
 
139
- if (tmp == NULL) {
140
- rb_raise(rb_eNoMemError, "Berns.to_attribute could not allocate sufficient memory.");
141
- }
214
+ size_t subattr_len = attrlen + 1;
215
+ size_t subkey_len = RSTRING_LEN(subkey);
142
216
 
143
- substring = tmp;
217
+ if (attrlen > 0 && subkey_len > 0) {
218
+ subattr_len += dlen;
219
+ }
144
220
 
145
- stecpy(substring + size - subattrlen, RSTRING_PTR(subattr), substring + size + 1);
146
- }
147
- }
221
+ if (subkey_len > 0) {
222
+ subattr_len += subkey_len;
223
+ }
148
224
 
149
- rstring = rb_utf8_str_new_cstr(substring);
150
- free(substring);
225
+ char subattr[subattr_len];
226
+ char *ptr = subattr;
227
+ char *end = subattr + sizeof(subattr);
151
228
 
152
- return rstring;
153
- default:
154
- switch (TYPE(value)) {
155
- case T_STRING:
156
- escaped = berns_escape_html(self, value);
157
- break;
158
- case T_SYMBOL:
159
- escaped = berns_escape_html(self, rb_sym_to_s(value));
160
- break;
161
- default:
162
- escaped = berns_escape_html(self, rb_funcall(value, rb_intern("to_s"), 0));
163
- break;
164
- }
229
+ if (attrlen > 0) {
230
+ ptr = stecpy(ptr, attr, end);
231
+ }
165
232
 
166
- char string[RSTRING_LEN(attribute) + eqlen + RSTRING_LEN(escaped) + clen + 1];
167
- char *ptr;
168
- char *end = string + sizeof(string);
233
+ if (attrlen > 0 && subkey_len > 0) {
234
+ ptr = stecpy(ptr, dash, end);
235
+ }
169
236
 
170
- ptr = stecpy(string, RSTRING_PTR(attribute), end);
171
- ptr = stecpy(ptr, equals, end);
172
- ptr = stecpy(ptr, RSTRING_PTR(escaped), end);
173
- stecpy(ptr, close, end);
237
+ stecpy(ptr, RSTRING_PTR(subkey), end);
174
238
 
175
- return rb_utf8_str_new_cstr(string);
176
- }
177
- }
239
+ char *combined;
178
240
 
179
- /* Expects a Ruby Hash as a single argument. */
180
- static VALUE berns_to_attributes(const VALUE self, const VALUE attributes) {
181
- Check_Type(attributes, T_HASH);
241
+ switch(TYPE(subvalue)) {
242
+ case T_FALSE:
243
+ combined = calloc(0, 1);
244
+ break;
182
245
 
183
- VALUE key;
184
- VALUE attribute;
185
- VALUE rstring;
246
+ case T_TRUE:
247
+ combined = string_value_to_attribute(subattr, subattr_len, "", 0);
248
+ break;
186
249
 
187
- const VALUE keys = rb_funcall(attributes, rb_intern("keys"), 0);
188
- const VALUE length = RARRAY_LEN(keys);
250
+ case T_STRING:
251
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
252
+ break;
189
253
 
190
- if (length == 0) {
191
- return rb_utf8_str_new_cstr("");
192
- }
254
+ case T_SYMBOL:
255
+ subvalue = rb_sym2str(subvalue);
256
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
257
+ break;
193
258
 
194
- char *string = NULL;
195
- size_t size = 0; /* IN BYTES */
259
+ case T_NIL:
260
+ subvalue = rb_utf8_str_new_cstr("");
261
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
262
+ break;
196
263
 
197
- const char *space = " ";
198
- const size_t splen = strlen(space);
264
+ case T_HASH:
265
+ combined = hash_value_to_attribute(subattr, subattr_len, &subvalue);
266
+ break;
199
267
 
200
- size_t alen;
268
+ default:
269
+ subvalue = rb_funcall(subvalue, rb_intern("to_s"), 0);
270
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
271
+ break;
272
+ }
201
273
 
202
- for (unsigned int i = 0; i < length; i++) {
203
- key = rb_ary_entry(keys, i);
204
- attribute = berns_to_attribute(self, key, rb_hash_aref(attributes, key));
205
- alen = RSTRING_LEN(attribute);
274
+ size_t combined_len = strlen(combined);
275
+ size_t size_to_append = combined_len;
206
276
 
207
277
  if (i > 0) {
208
- char *tmp = realloc(string, size + alen + splen + 1);
209
-
210
- if (tmp == NULL) {
211
- rb_raise(rb_eNoMemError, "Berns.to_attributes could not allocate sufficient memory.");
212
- }
278
+ size_to_append += splen;
279
+ }
213
280
 
214
- string = tmp;
281
+ if ((size_to_append + occupied) > allocated) {
282
+ /* To avoid an abundance of reallocations, this is a multiple of 256. */
283
+ double multiple = (double) (size_to_append + occupied) / 256;
284
+ size_t new_size_to_allocate = (unsigned int) ceil(multiple) * 256;
215
285
 
216
- stecpy(string + size, space, string + size + splen);
217
- stecpy(string + size + splen, RSTRING_PTR(attribute), string + size + splen + alen + 1);
218
- size = size + splen + alen;
219
- } else {
220
- char *tmp = realloc(string, size + alen + 1);
286
+ char *tmp = realloc(destination, new_size_to_allocate);
221
287
 
222
288
  if (tmp == NULL) {
223
- rb_raise(rb_eNoMemError, "Berns.to_attributes could not allocate sufficient memory.");
289
+ free(destination);
290
+ rb_raise(rb_eNoMemError, "Berns could not allocate sufficient memory.");
224
291
  }
225
292
 
226
- string = tmp;
293
+ allocated = new_size_to_allocate;
294
+ destination = tmp;
295
+ position = destination + occupied;
296
+ end = destination + allocated;
297
+ }
227
298
 
228
- stecpy(string + size, RSTRING_PTR(attribute), string + size + alen + 1);
229
- size = size + alen;
299
+ if (i > 0) {
300
+ position = stecpy(position, space, end);
301
+ occupied += splen;
230
302
  }
231
- }
232
303
 
233
- rstring = rb_utf8_str_new_cstr(string);
234
- free(string);
304
+ position = stecpy(position, combined, end);
305
+ occupied += combined_len;
235
306
 
236
- return rstring;
237
- }
307
+ free(combined);
308
+ }
238
309
 
239
- static VALUE berns_internal_void(VALUE tag, VALUE attributes) {
240
- const VALUE berns = rb_const_get(rb_cObject, rb_intern("Berns"));
310
+ return destination;
311
+ }
241
312
 
242
- switch(TYPE(tag)) {
243
- case T_STRING:
244
- break;
313
+ /*
314
+ * Convert an attribute name and value into a string.
315
+ */
316
+ static char * to_attribute(VALUE attr, VALUE *value) {
317
+ switch(TYPE(attr)) {
245
318
  case T_SYMBOL:
246
- tag = rb_sym_to_s(tag);
319
+ attr = rb_sym2str(attr);
247
320
  break;
248
321
  default:
249
- rb_raise(rb_eTypeError, "Berns.void elements must be a String or Symbol.");
250
322
  break;
251
323
  }
252
324
 
253
- const char *open = "<";
254
- const char *close = ">";
255
- const char *space = " ";
256
-
257
- const size_t olen = strlen(open);
258
- const size_t clen = strlen(close);
259
- const size_t slen = strlen(space);
260
-
261
- size_t tlen = RSTRING_LEN(tag);
262
- size_t total;
263
- size_t alen = 0;
264
-
265
- if (TYPE(attributes) != T_IMEMO) {
266
- attributes = berns_to_attributes(berns, attributes);
267
- alen = RSTRING_LEN(attributes);
268
-
269
- if (alen > 0) {
270
- total = olen + tlen + slen + alen + clen + 1;
271
- } else {
272
- total = olen + tlen + clen + 1;
273
- }
274
- } else {
275
- total = olen + tlen + clen + 1;
276
- }
277
-
278
- char string[total];
279
- char *ptr, *end = string + sizeof(string);
325
+ StringValue(attr);
280
326
 
281
- ptr = stecpy(string, open, end);
282
- ptr = stecpy(ptr, RSTRING_PTR(tag), end);
327
+ char *val = NULL;
328
+ VALUE str;
283
329
 
284
- if (TYPE(attributes) != T_IMEMO && alen > 0) {
285
- ptr = stecpy(ptr, space, end);
286
- ptr = stecpy(ptr, RSTRING_PTR(attributes), end);
287
- }
288
-
289
- stecpy(ptr, close, end);
290
-
291
- return rb_utf8_str_new_cstr(string);
292
- }
293
-
294
- static VALUE berns_internal_element(VALUE tag, VALUE attributes) {
295
- const VALUE berns = rb_const_get(rb_cObject, rb_intern("Berns"));
296
-
297
- VALUE content;
298
-
299
- switch(TYPE(tag)) {
330
+ switch(TYPE(*value)) {
331
+ case T_NIL:
332
+ case T_TRUE:
333
+ val = empty_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr));
334
+ break;
335
+ case T_FALSE:
336
+ val = calloc(0, 1);
337
+ break;
338
+ case T_HASH:
339
+ val = hash_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), value);
340
+ break;
300
341
  case T_STRING:
342
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(*value), RSTRING_LEN(*value));
301
343
  break;
302
344
  case T_SYMBOL:
303
- tag = rb_sym_to_s(tag);
345
+ str = rb_sym2str(*value);
346
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(str), RSTRING_LEN(str));
304
347
  break;
305
348
  default:
306
- rb_raise(rb_eTypeError, "Berns.element elements must be a String or Symbol.");
349
+ str = rb_funcall(*value, rb_intern("to_s"), 0);
350
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(str), RSTRING_LEN(str));
307
351
  break;
308
352
  }
309
353
 
310
- if (rb_block_given_p()) {
311
- content = rb_yield(Qnil);
312
-
313
- if (TYPE(content) == T_NIL) {
314
- content = rb_utf8_str_new_cstr("");
315
- }
316
- } else {
317
- content = rb_utf8_str_new_cstr("");
318
- }
319
-
320
- StringValue(content);
321
-
322
- const char *open = "<";
323
- const char *close = ">";
324
- const char *slash = "/";
325
- const char *space = " ";
326
-
327
- const size_t olen = strlen(open);
328
- const size_t clen = strlen(close);
329
- const size_t sllen = strlen(slash);
330
- const size_t slen = strlen(space);
331
-
332
- size_t tlen = RSTRING_LEN(tag);
333
- size_t conlen = RSTRING_LEN(content);
334
- size_t total = olen + tlen + clen + conlen + olen + sllen + tlen + clen + 1;
335
-
336
- if (TYPE(attributes) != T_IMEMO) {
337
- attributes = berns_to_attributes(berns, attributes);
338
- total = total + slen + RSTRING_LEN(attributes);
339
- }
340
-
341
- char string[total];
342
- char *ptr;
343
- char *end = string + sizeof(string);
344
-
345
- ptr = stecpy(string, open, end);
346
- ptr = stecpy(ptr, RSTRING_PTR(tag), end);
347
-
348
- if (TYPE(attributes) != T_IMEMO) {
349
- ptr = stecpy(ptr, space, end);
350
- ptr = stecpy(ptr, RSTRING_PTR(attributes), end);
351
- }
352
-
353
- ptr = stecpy(ptr, close, end);
354
- ptr = stecpy(ptr, RSTRING_PTR(content), end);
355
- ptr = stecpy(ptr, open, end);
356
- ptr = stecpy(ptr, slash, end);
357
- ptr = stecpy(ptr, RSTRING_PTR(tag), end);
358
- stecpy(ptr, close, end);
359
-
360
- return rb_utf8_str_new_cstr(string);
354
+ return val;
361
355
  }
362
356
 
363
- static VALUE berns_void_element(int argc, VALUE *argv, VALUE self) {
364
- rb_check_arity(argc, 1, 2);
365
- return berns_internal_void(argv[0], argv[1]);
366
- }
357
+ /*
358
+ * The external API for Berns.to_attribute.
359
+ *
360
+ * attr should be either a symbol or string, otherwise an error is raised.
361
+ * value can be anything to responds to #to_s
362
+ *
363
+ */
364
+ static VALUE external_to_attribute(RB_UNUSED_VAR(VALUE self), VALUE attr, VALUE value) {
365
+ switch(TYPE(attr)) {
366
+ case T_SYMBOL:
367
+ attr = rb_sym2str(attr);
368
+ break;
369
+ default:
370
+ break;
371
+ }
367
372
 
368
- static VALUE berns_area_element(int argc, VALUE *argv, VALUE self) {
369
- rb_check_arity(argc, 0, 1);
370
- return berns_internal_void(rb_utf8_str_new_cstr("area"), argv[0]);
371
- }
373
+ StringValue(attr);
372
374
 
373
- static VALUE berns_base_element(int argc, VALUE *argv, VALUE self) {
374
- rb_check_arity(argc, 0, 1);
375
- return berns_internal_void(rb_utf8_str_new_cstr("base"), argv[0]);
376
- }
375
+ char *val = to_attribute(attr, &value);
376
+ VALUE rstring = rb_utf8_str_new_cstr(val);
377
+ free(val);
377
378
 
378
- static VALUE berns_br_element(int argc, VALUE *argv, VALUE self) {
379
- rb_check_arity(argc, 0, 1);
380
- return berns_internal_void(rb_utf8_str_new_cstr("br"), argv[0]);
379
+ return rstring;
381
380
  }
382
381
 
383
- static VALUE berns_col_element(int argc, VALUE *argv, VALUE self) {
384
- rb_check_arity(argc, 0, 1);
385
- return berns_internal_void(rb_utf8_str_new_cstr("col"), argv[0]);
386
- }
382
+ /*
383
+ * The external API for Berns.to_attributes.
384
+ *
385
+ * attributes should be a hash, otherwise an error is raised.
386
+ *
387
+ */
388
+ static VALUE external_to_attributes(RB_UNUSED_VAR(VALUE self), VALUE attributes) {
389
+ Check_Type(attributes, T_HASH);
387
390
 
388
- static VALUE berns_embed_element(int argc, VALUE *argv, VALUE self) {
389
- rb_check_arity(argc, 0, 1);
390
- return berns_internal_void(rb_utf8_str_new_cstr("embed"), argv[0]);
391
- }
391
+ if (rb_hash_size(attributes) == 1) {
392
+ return rb_utf8_str_new_cstr("");
393
+ }
392
394
 
393
- static VALUE berns_hr_element(int argc, VALUE *argv, VALUE self) {
394
- rb_check_arity(argc, 0, 1);
395
- return berns_internal_void(rb_utf8_str_new_cstr("hr"), argv[0]);
396
- }
395
+ char *empty = "";
396
+ char *attrs = hash_value_to_attribute(empty, 0, &attributes);
397
397
 
398
- static VALUE berns_img_element(int argc, VALUE *argv, VALUE self) {
399
- rb_check_arity(argc, 0, 1);
400
- return berns_internal_void(rb_utf8_str_new_cstr("img"), argv[0]);
401
- }
398
+ VALUE rstring = rb_utf8_str_new_cstr(attrs);
399
+ free(attrs);
402
400
 
403
- static VALUE berns_input_element(int argc, VALUE *argv, VALUE self) {
404
- rb_check_arity(argc, 0, 1);
405
- return berns_internal_void(rb_utf8_str_new_cstr("input"), argv[0]);
401
+ return rstring;
406
402
  }
407
403
 
408
- static VALUE berns_link_element(int argc, VALUE *argv, VALUE self) {
409
- rb_check_arity(argc, 0, 1);
410
- return berns_internal_void(rb_utf8_str_new_cstr("link"), argv[0]);
411
- }
404
+ static char * void_element(char *tag, size_t tlen, VALUE *attributes) {
405
+ /* T_IMEMO is what we get if an optional argument was not passed. */
406
+ if (TYPE(*attributes) == T_IMEMO) {
407
+ size_t total = tag_olen + tlen + tag_clen + 1;
408
+ char *string = malloc(total);
409
+ char *ptr;
410
+ char *end = string + total;
412
411
 
413
- static VALUE berns_menuitem_element(int argc, VALUE *argv, VALUE self) {
414
- rb_check_arity(argc, 0, 1);
415
- return berns_internal_void(rb_utf8_str_new_cstr("menuitem"), argv[0]);
416
- }
412
+ ptr = stecpy(string, tag_open, end);
413
+ ptr = stecpy(ptr, tag, end);
414
+ ptr = stecpy(ptr, tag_close, end);
417
415
 
418
- static VALUE berns_meta_element(int argc, VALUE *argv, VALUE self) {
419
- rb_check_arity(argc, 0, 1);
420
- return berns_internal_void(rb_utf8_str_new_cstr("meta"), argv[0]);
421
- }
416
+ return string;
417
+ } else {
418
+ char *empty = "";
419
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
422
420
 
423
- static VALUE berns_param_element(int argc, VALUE *argv, VALUE self) {
424
- rb_check_arity(argc, 0, 1);
425
- return berns_internal_void(rb_utf8_str_new_cstr("param"), argv[0]);
426
- }
421
+ size_t total = tag_olen + tlen + splen + strlen(attrs) + tag_clen + 1;
422
+ char *string = malloc(total);
423
+ char *ptr;
424
+ char *end = string + total;
427
425
 
428
- static VALUE berns_source_element(int argc, VALUE *argv, VALUE self) {
429
- rb_check_arity(argc, 0, 1);
430
- return berns_internal_void(rb_utf8_str_new_cstr("source"), argv[0]);
431
- }
426
+ ptr = stecpy(string, tag_open, end);
427
+ ptr = stecpy(ptr, tag, end);
428
+ ptr = stecpy(ptr, space, end);
429
+ ptr = stecpy(ptr, attrs, end);
430
+ ptr = stecpy(ptr, tag_close, end);
432
431
 
433
- static VALUE berns_track_element(int argc, VALUE *argv, VALUE self) {
434
- rb_check_arity(argc, 0, 1);
435
- return berns_internal_void(rb_utf8_str_new_cstr("track"), argv[0]);
436
- }
432
+ free(attrs);
437
433
 
438
- static VALUE berns_wbr_element(int argc, VALUE *argv, VALUE self) {
439
- rb_check_arity(argc, 0, 1);
440
- return berns_internal_void(rb_utf8_str_new_cstr("wbr"), argv[0]);
434
+ return string;
435
+ }
441
436
  }
442
437
 
443
- static VALUE berns_element(int argc, VALUE* argv, VALUE self) {
438
+ /*
439
+ * The external API for Berns.void.
440
+ *
441
+ * The first argument should be a string or symbol, otherwise an error is raised.
442
+ * The second argument must be a hash if present.
443
+ *
444
+ */
445
+ static VALUE external_void_element(int argc, VALUE *arguments, RB_UNUSED_VAR(VALUE self)) {
444
446
  rb_check_arity(argc, 1, 2);
445
- return berns_internal_element(argv[0], argv[1]);
446
- }
447
-
448
- static VALUE berns_a_element(int argc, VALUE* argv, VALUE self) {
449
- rb_check_arity(argc, 0, 1);
450
- return berns_internal_element(rb_utf8_str_new_cstr("a"), argv[0]);
451
- }
452
447
 
453
- static VALUE berns_abbr_element(int argc, VALUE* argv, VALUE self) {
454
- rb_check_arity(argc, 0, 1);
455
- return berns_internal_element(rb_utf8_str_new_cstr("abbr"), argv[0]);
456
- }
448
+ VALUE tag = arguments[0];
449
+ VALUE attributes = arguments[1];
457
450
 
458
- static VALUE berns_address_element(int argc, VALUE* argv, VALUE self) {
459
- rb_check_arity(argc, 0, 1);
460
- return berns_internal_element(rb_utf8_str_new_cstr("address"), argv[0]);
461
- }
462
-
463
- static VALUE berns_article_element(int argc, VALUE* argv, VALUE self) {
464
- rb_check_arity(argc, 0, 1);
465
- return berns_internal_element(rb_utf8_str_new_cstr("article"), argv[0]);
466
- }
467
-
468
- static VALUE berns_aside_element(int argc, VALUE* argv, VALUE self) {
469
- rb_check_arity(argc, 0, 1);
470
- return berns_internal_element(rb_utf8_str_new_cstr("aside"), argv[0]);
471
- }
472
-
473
- static VALUE berns_audio_element(int argc, VALUE* argv, VALUE self) {
474
- rb_check_arity(argc, 0, 1);
475
- return berns_internal_element(rb_utf8_str_new_cstr("audio"), argv[0]);
476
- }
477
-
478
- static VALUE berns_b_element(int argc, VALUE* argv, VALUE self) {
479
- rb_check_arity(argc, 0, 1);
480
- return berns_internal_element(rb_utf8_str_new_cstr("b"), argv[0]);
481
- }
482
-
483
- static VALUE berns_bdi_element(int argc, VALUE* argv, VALUE self) {
484
- rb_check_arity(argc, 0, 1);
485
- return berns_internal_element(rb_utf8_str_new_cstr("bdi"), argv[0]);
486
- }
487
-
488
- static VALUE berns_bdo_element(int argc, VALUE* argv, VALUE self) {
489
- rb_check_arity(argc, 0, 1);
490
- return berns_internal_element(rb_utf8_str_new_cstr("bdo"), argv[0]);
491
- }
492
-
493
- static VALUE berns_blockquote_element(int argc, VALUE* argv, VALUE self) {
494
- rb_check_arity(argc, 0, 1);
495
- return berns_internal_element(rb_utf8_str_new_cstr("blockquote"), argv[0]);
496
- }
497
-
498
- static VALUE berns_body_element(int argc, VALUE* argv, VALUE self) {
499
- rb_check_arity(argc, 0, 1);
500
- return berns_internal_element(rb_utf8_str_new_cstr("body"), argv[0]);
501
- }
502
-
503
- static VALUE berns_button_element(int argc, VALUE* argv, VALUE self) {
504
- rb_check_arity(argc, 0, 1);
505
- return berns_internal_element(rb_utf8_str_new_cstr("button"), argv[0]);
506
- }
507
-
508
- static VALUE berns_canvas_element(int argc, VALUE* argv, VALUE self) {
509
- rb_check_arity(argc, 0, 1);
510
- return berns_internal_element(rb_utf8_str_new_cstr("canvas"), argv[0]);
511
- }
512
-
513
- static VALUE berns_caption_element(int argc, VALUE* argv, VALUE self) {
514
- rb_check_arity(argc, 0, 1);
515
- return berns_internal_element(rb_utf8_str_new_cstr("caption"), argv[0]);
516
- }
517
-
518
- static VALUE berns_cite_element(int argc, VALUE* argv, VALUE self) {
519
- rb_check_arity(argc, 0, 1);
520
- return berns_internal_element(rb_utf8_str_new_cstr("cite"), argv[0]);
521
- }
522
-
523
- static VALUE berns_code_element(int argc, VALUE* argv, VALUE self) {
524
- rb_check_arity(argc, 0, 1);
525
- return berns_internal_element(rb_utf8_str_new_cstr("code"), argv[0]);
526
- }
527
-
528
- static VALUE berns_colgroup_element(int argc, VALUE* argv, VALUE self) {
529
- rb_check_arity(argc, 0, 1);
530
- return berns_internal_element(rb_utf8_str_new_cstr("colgroup"), argv[0]);
531
- }
532
-
533
- static VALUE berns_datalist_element(int argc, VALUE* argv, VALUE self) {
534
- rb_check_arity(argc, 0, 1);
535
- return berns_internal_element(rb_utf8_str_new_cstr("datalist"), argv[0]);
536
- }
537
-
538
- static VALUE berns_dd_element(int argc, VALUE* argv, VALUE self) {
539
- rb_check_arity(argc, 0, 1);
540
- return berns_internal_element(rb_utf8_str_new_cstr("dd"), argv[0]);
541
- }
542
-
543
- static VALUE berns_del_element(int argc, VALUE* argv, VALUE self) {
544
- rb_check_arity(argc, 0, 1);
545
- return berns_internal_element(rb_utf8_str_new_cstr("del"), argv[0]);
546
- }
547
-
548
- static VALUE berns_details_element(int argc, VALUE* argv, VALUE self) {
549
- rb_check_arity(argc, 0, 1);
550
- return berns_internal_element(rb_utf8_str_new_cstr("details"), argv[0]);
551
- }
552
-
553
- static VALUE berns_dfn_element(int argc, VALUE* argv, VALUE self) {
554
- rb_check_arity(argc, 0, 1);
555
- return berns_internal_element(rb_utf8_str_new_cstr("dfn"), argv[0]);
556
- }
557
-
558
- static VALUE berns_dialog_element(int argc, VALUE* argv, VALUE self) {
559
- rb_check_arity(argc, 0, 1);
560
- return berns_internal_element(rb_utf8_str_new_cstr("dialog"), argv[0]);
561
- }
562
-
563
- static VALUE berns_div_element(int argc, VALUE* argv, VALUE self) {
564
- rb_check_arity(argc, 0, 1);
565
- return berns_internal_element(rb_utf8_str_new_cstr("div"), argv[0]);
566
- }
567
-
568
- static VALUE berns_dl_element(int argc, VALUE* argv, VALUE self) {
569
- rb_check_arity(argc, 0, 1);
570
- return berns_internal_element(rb_utf8_str_new_cstr("dl"), argv[0]);
571
- }
572
-
573
- static VALUE berns_dt_element(int argc, VALUE* argv, VALUE self) {
574
- rb_check_arity(argc, 0, 1);
575
- return berns_internal_element(rb_utf8_str_new_cstr("dt"), argv[0]);
576
- }
577
-
578
- static VALUE berns_em_element(int argc, VALUE* argv, VALUE self) {
579
- rb_check_arity(argc, 0, 1);
580
- return berns_internal_element(rb_utf8_str_new_cstr("em"), argv[0]);
581
- }
582
-
583
- static VALUE berns_fieldset_element(int argc, VALUE* argv, VALUE self) {
584
- rb_check_arity(argc, 0, 1);
585
- return berns_internal_element(rb_utf8_str_new_cstr("fieldset"), argv[0]);
586
- }
587
-
588
- static VALUE berns_figcaption_element(int argc, VALUE* argv, VALUE self) {
589
- rb_check_arity(argc, 0, 1);
590
- return berns_internal_element(rb_utf8_str_new_cstr("figcaption"), argv[0]);
591
- }
592
-
593
- static VALUE berns_figure_element(int argc, VALUE* argv, VALUE self) {
594
- rb_check_arity(argc, 0, 1);
595
- return berns_internal_element(rb_utf8_str_new_cstr("figure"), argv[0]);
596
- }
597
-
598
- static VALUE berns_footer_element(int argc, VALUE* argv, VALUE self) {
599
- rb_check_arity(argc, 0, 1);
600
- return berns_internal_element(rb_utf8_str_new_cstr("footer"), argv[0]);
601
- }
602
-
603
- static VALUE berns_form_element(int argc, VALUE* argv, VALUE self) {
604
- rb_check_arity(argc, 0, 1);
605
- return berns_internal_element(rb_utf8_str_new_cstr("form"), argv[0]);
606
- }
607
-
608
- static VALUE berns_h1_element(int argc, VALUE* argv, VALUE self) {
609
- rb_check_arity(argc, 0, 1);
610
- return berns_internal_element(rb_utf8_str_new_cstr("h1"), argv[0]);
611
- }
612
-
613
- static VALUE berns_h2_element(int argc, VALUE* argv, VALUE self) {
614
- rb_check_arity(argc, 0, 1);
615
- return berns_internal_element(rb_utf8_str_new_cstr("h2"), argv[0]);
616
- }
617
-
618
- static VALUE berns_h3_element(int argc, VALUE* argv, VALUE self) {
619
- rb_check_arity(argc, 0, 1);
620
- return berns_internal_element(rb_utf8_str_new_cstr("h3"), argv[0]);
621
- }
622
-
623
- static VALUE berns_h4_element(int argc, VALUE* argv, VALUE self) {
624
- rb_check_arity(argc, 0, 1);
625
- return berns_internal_element(rb_utf8_str_new_cstr("h4"), argv[0]);
626
- }
627
-
628
- static VALUE berns_h5_element(int argc, VALUE* argv, VALUE self) {
629
- rb_check_arity(argc, 0, 1);
630
- return berns_internal_element(rb_utf8_str_new_cstr("h5"), argv[0]);
631
- }
632
-
633
- static VALUE berns_h6_element(int argc, VALUE* argv, VALUE self) {
634
- rb_check_arity(argc, 0, 1);
635
- return berns_internal_element(rb_utf8_str_new_cstr("h6"), argv[0]);
636
- }
637
-
638
- static VALUE berns_head_element(int argc, VALUE* argv, VALUE self) {
639
- rb_check_arity(argc, 0, 1);
640
- return berns_internal_element(rb_utf8_str_new_cstr("head"), argv[0]);
641
- }
642
-
643
- static VALUE berns_header_element(int argc, VALUE* argv, VALUE self) {
644
- rb_check_arity(argc, 0, 1);
645
- return berns_internal_element(rb_utf8_str_new_cstr("header"), argv[0]);
646
- }
647
-
648
- static VALUE berns_html_element(int argc, VALUE* argv, VALUE self) {
649
- rb_check_arity(argc, 0, 1);
650
- return berns_internal_element(rb_utf8_str_new_cstr("html"), argv[0]);
651
- }
652
-
653
- static VALUE berns_i_element(int argc, VALUE* argv, VALUE self) {
654
- rb_check_arity(argc, 0, 1);
655
- return berns_internal_element(rb_utf8_str_new_cstr("i"), argv[0]);
656
- }
657
-
658
- static VALUE berns_iframe_element(int argc, VALUE* argv, VALUE self) {
659
- rb_check_arity(argc, 0, 1);
660
- return berns_internal_element(rb_utf8_str_new_cstr("iframe"), argv[0]);
661
- }
662
-
663
- static VALUE berns_ins_element(int argc, VALUE* argv, VALUE self) {
664
- rb_check_arity(argc, 0, 1);
665
- return berns_internal_element(rb_utf8_str_new_cstr("ins"), argv[0]);
666
- }
667
-
668
- static VALUE berns_kbd_element(int argc, VALUE* argv, VALUE self) {
669
- rb_check_arity(argc, 0, 1);
670
- return berns_internal_element(rb_utf8_str_new_cstr("kbd"), argv[0]);
671
- }
672
-
673
- static VALUE berns_label_element(int argc, VALUE* argv, VALUE self) {
674
- rb_check_arity(argc, 0, 1);
675
- return berns_internal_element(rb_utf8_str_new_cstr("label"), argv[0]);
676
- }
677
-
678
- static VALUE berns_legend_element(int argc, VALUE* argv, VALUE self) {
679
- rb_check_arity(argc, 0, 1);
680
- return berns_internal_element(rb_utf8_str_new_cstr("legend"), argv[0]);
681
- }
682
-
683
- static VALUE berns_li_element(int argc, VALUE* argv, VALUE self) {
684
- rb_check_arity(argc, 0, 1);
685
- return berns_internal_element(rb_utf8_str_new_cstr("li"), argv[0]);
686
- }
687
-
688
- static VALUE berns_main_element(int argc, VALUE* argv, VALUE self) {
689
- rb_check_arity(argc, 0, 1);
690
- return berns_internal_element(rb_utf8_str_new_cstr("main"), argv[0]);
691
- }
692
-
693
- static VALUE berns_map_element(int argc, VALUE* argv, VALUE self) {
694
- rb_check_arity(argc, 0, 1);
695
- return berns_internal_element(rb_utf8_str_new_cstr("map"), argv[0]);
696
- }
697
-
698
- static VALUE berns_mark_element(int argc, VALUE* argv, VALUE self) {
699
- rb_check_arity(argc, 0, 1);
700
- return berns_internal_element(rb_utf8_str_new_cstr("mark"), argv[0]);
701
- }
702
-
703
- static VALUE berns_menu_element(int argc, VALUE* argv, VALUE self) {
704
- rb_check_arity(argc, 0, 1);
705
- return berns_internal_element(rb_utf8_str_new_cstr("menu"), argv[0]);
706
- }
707
-
708
- static VALUE berns_meter_element(int argc, VALUE* argv, VALUE self) {
709
- rb_check_arity(argc, 0, 1);
710
- return berns_internal_element(rb_utf8_str_new_cstr("meter"), argv[0]);
711
- }
712
-
713
- static VALUE berns_nav_element(int argc, VALUE* argv, VALUE self) {
714
- rb_check_arity(argc, 0, 1);
715
- return berns_internal_element(rb_utf8_str_new_cstr("nav"), argv[0]);
716
- }
717
-
718
- static VALUE berns_noscript_element(int argc, VALUE* argv, VALUE self) {
719
- rb_check_arity(argc, 0, 1);
720
- return berns_internal_element(rb_utf8_str_new_cstr("noscript"), argv[0]);
721
- }
722
-
723
- static VALUE berns_object_element(int argc, VALUE* argv, VALUE self) {
724
- rb_check_arity(argc, 0, 1);
725
- return berns_internal_element(rb_utf8_str_new_cstr("object"), argv[0]);
726
- }
727
-
728
- static VALUE berns_ol_element(int argc, VALUE* argv, VALUE self) {
729
- rb_check_arity(argc, 0, 1);
730
- return berns_internal_element(rb_utf8_str_new_cstr("ol"), argv[0]);
731
- }
732
-
733
- static VALUE berns_optgroup_element(int argc, VALUE* argv, VALUE self) {
734
- rb_check_arity(argc, 0, 1);
735
- return berns_internal_element(rb_utf8_str_new_cstr("optgroup"), argv[0]);
736
- }
737
-
738
- static VALUE berns_option_element(int argc, VALUE* argv, VALUE self) {
739
- rb_check_arity(argc, 0, 1);
740
- return berns_internal_element(rb_utf8_str_new_cstr("option"), argv[0]);
741
- }
742
-
743
- static VALUE berns_output_element(int argc, VALUE* argv, VALUE self) {
744
- rb_check_arity(argc, 0, 1);
745
- return berns_internal_element(rb_utf8_str_new_cstr("output"), argv[0]);
746
- }
747
-
748
- static VALUE berns_p_element(int argc, VALUE* argv, VALUE self) {
749
- rb_check_arity(argc, 0, 1);
750
- return berns_internal_element(rb_utf8_str_new_cstr("p"), argv[0]);
751
- }
752
-
753
- static VALUE berns_picture_element(int argc, VALUE* argv, VALUE self) {
754
- rb_check_arity(argc, 0, 1);
755
- return berns_internal_element(rb_utf8_str_new_cstr("picture"), argv[0]);
756
- }
757
-
758
- static VALUE berns_pre_element(int argc, VALUE* argv, VALUE self) {
759
- rb_check_arity(argc, 0, 1);
760
- return berns_internal_element(rb_utf8_str_new_cstr("pre"), argv[0]);
761
- }
762
-
763
- static VALUE berns_progress_element(int argc, VALUE* argv, VALUE self) {
764
- rb_check_arity(argc, 0, 1);
765
- return berns_internal_element(rb_utf8_str_new_cstr("progress"), argv[0]);
766
- }
767
-
768
- static VALUE berns_q_element(int argc, VALUE* argv, VALUE self) {
769
- rb_check_arity(argc, 0, 1);
770
- return berns_internal_element(rb_utf8_str_new_cstr("q"), argv[0]);
771
- }
772
-
773
- static VALUE berns_rp_element(int argc, VALUE* argv, VALUE self) {
774
- rb_check_arity(argc, 0, 1);
775
- return berns_internal_element(rb_utf8_str_new_cstr("rp"), argv[0]);
776
- }
777
-
778
- static VALUE berns_rt_element(int argc, VALUE* argv, VALUE self) {
779
- rb_check_arity(argc, 0, 1);
780
- return berns_internal_element(rb_utf8_str_new_cstr("rt"), argv[0]);
781
- }
782
-
783
- static VALUE berns_ruby_element(int argc, VALUE* argv, VALUE self) {
784
- rb_check_arity(argc, 0, 1);
785
- return berns_internal_element(rb_utf8_str_new_cstr("ruby"), argv[0]);
786
- }
787
-
788
- static VALUE berns_s_element(int argc, VALUE* argv, VALUE self) {
789
- rb_check_arity(argc, 0, 1);
790
- return berns_internal_element(rb_utf8_str_new_cstr("s"), argv[0]);
791
- }
792
-
793
- static VALUE berns_samp_element(int argc, VALUE* argv, VALUE self) {
794
- rb_check_arity(argc, 0, 1);
795
- return berns_internal_element(rb_utf8_str_new_cstr("samp"), argv[0]);
796
- }
451
+ if (TYPE(tag) == T_SYMBOL) {
452
+ tag = rb_sym2str(tag);
453
+ }
797
454
 
798
- static VALUE berns_script_element(int argc, VALUE* argv, VALUE self) {
799
- rb_check_arity(argc, 0, 1);
800
- return berns_internal_element(rb_utf8_str_new_cstr("script"), argv[0]);
801
- }
455
+ StringValue(tag);
802
456
 
803
- static VALUE berns_section_element(int argc, VALUE* argv, VALUE self) {
804
- rb_check_arity(argc, 0, 1);
805
- return berns_internal_element(rb_utf8_str_new_cstr("section"), argv[0]);
806
- }
457
+ char *string = void_element(RSTRING_PTR(tag), RSTRING_LEN(tag), &attributes);
458
+ VALUE rstring = rb_utf8_str_new_cstr(string);
807
459
 
808
- static VALUE berns_select_element(int argc, VALUE* argv, VALUE self) {
809
- rb_check_arity(argc, 0, 1);
810
- return berns_internal_element(rb_utf8_str_new_cstr("select"), argv[0]);
811
- }
460
+ free(string);
812
461
 
813
- static VALUE berns_small_element(int argc, VALUE* argv, VALUE self) {
814
- rb_check_arity(argc, 0, 1);
815
- return berns_internal_element(rb_utf8_str_new_cstr("small"), argv[0]);
462
+ return rstring;
816
463
  }
817
464
 
818
- static VALUE berns_span_element(int argc, VALUE* argv, VALUE self) {
819
- rb_check_arity(argc, 0, 1);
820
- return berns_internal_element(rb_utf8_str_new_cstr("span"), argv[0]);
821
- }
465
+ static char * element(char *tag, size_t tlen, char *content, size_t conlen, VALUE *attributes) {
466
+ char *empty = "";
467
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
468
+ size_t alen = strlen(attrs);
822
469
 
823
- static VALUE berns_strong_element(int argc, VALUE* argv, VALUE self) {
824
- rb_check_arity(argc, 0, 1);
825
- return berns_internal_element(rb_utf8_str_new_cstr("strong"), argv[0]);
826
- }
470
+ size_t total = tag_olen + tlen + tag_clen + tag_olen + sllen + tlen + tag_clen + 1;
827
471
 
828
- static VALUE berns_style_element(int argc, VALUE* argv, VALUE self) {
829
- rb_check_arity(argc, 0, 1);
830
- return berns_internal_element(rb_utf8_str_new_cstr("style"), argv[0]);
831
- }
472
+ /* If we have some attributes, add a space and the attributes' length. */
473
+ if (alen > 0) {
474
+ total += splen + alen;
475
+ }
832
476
 
833
- static VALUE berns_sub_element(int argc, VALUE* argv, VALUE self) {
834
- rb_check_arity(argc, 0, 1);
835
- return berns_internal_element(rb_utf8_str_new_cstr("sub"), argv[0]);
836
- }
477
+ /* If we have some content, add the content length to our total. */
478
+ if (conlen > 0) {
479
+ total += conlen;
480
+ }
837
481
 
838
- static VALUE berns_summary_element(int argc, VALUE* argv, VALUE self) {
839
- rb_check_arity(argc, 0, 1);
840
- return berns_internal_element(rb_utf8_str_new_cstr("summary"), argv[0]);
841
- }
482
+ char *dest = malloc(total);
483
+ char *ptr = NULL;
484
+ char *end = dest + total;
842
485
 
843
- static VALUE berns_table_element(int argc, VALUE* argv, VALUE self) {
844
- rb_check_arity(argc, 0, 1);
845
- return berns_internal_element(rb_utf8_str_new_cstr("table"), argv[0]);
846
- }
486
+ ptr = stecpy(dest, tag_open, end);
487
+ ptr = stecpy(ptr, tag, end);
847
488
 
848
- static VALUE berns_tbody_element(int argc, VALUE* argv, VALUE self) {
849
- rb_check_arity(argc, 0, 1);
850
- return berns_internal_element(rb_utf8_str_new_cstr("tbody"), argv[0]);
851
- }
489
+ if (alen > 0) {
490
+ ptr = stecpy(ptr, space, end);
491
+ ptr = stecpy(ptr, attrs, end);
492
+ }
852
493
 
853
- static VALUE berns_td_element(int argc, VALUE* argv, VALUE self) {
854
- rb_check_arity(argc, 0, 1);
855
- return berns_internal_element(rb_utf8_str_new_cstr("td"), argv[0]);
856
- }
494
+ ptr = stecpy(ptr, tag_close, end);
857
495
 
858
- static VALUE berns_template_element(int argc, VALUE* argv, VALUE self) {
859
- rb_check_arity(argc, 0, 1);
860
- return berns_internal_element(rb_utf8_str_new_cstr("template"), argv[0]);
861
- }
496
+ if (conlen > 0) {
497
+ ptr = stecpy(ptr, content, end);
498
+ }
862
499
 
863
- static VALUE berns_textarea_element(int argc, VALUE* argv, VALUE self) {
864
- rb_check_arity(argc, 0, 1);
865
- return berns_internal_element(rb_utf8_str_new_cstr("textarea"), argv[0]);
866
- }
500
+ ptr = stecpy(ptr, tag_open, end);
501
+ ptr = stecpy(ptr, slash, end);
502
+ ptr = stecpy(ptr, tag, end);
503
+ ptr = stecpy(ptr, tag_close, end);
867
504
 
868
- static VALUE berns_tfoot_element(int argc, VALUE* argv, VALUE self) {
869
- rb_check_arity(argc, 0, 1);
870
- return berns_internal_element(rb_utf8_str_new_cstr("tfoot"), argv[0]);
871
- }
505
+ free(attrs);
872
506
 
873
- static VALUE berns_th_element(int argc, VALUE* argv, VALUE self) {
874
- rb_check_arity(argc, 0, 1);
875
- return berns_internal_element(rb_utf8_str_new_cstr("th"), argv[0]);
507
+ return dest;
876
508
  }
877
509
 
878
- static VALUE berns_thead_element(int argc, VALUE* argv, VALUE self) {
879
- rb_check_arity(argc, 0, 1);
880
- return berns_internal_element(rb_utf8_str_new_cstr("thead"), argv[0]);
881
- }
510
+ /*
511
+ * The external API for Berns.element.
512
+ *
513
+ * The first argument should be a string or symbol, otherwise an error is raised.
514
+ * The second argument must be a hash if present.
515
+ * An optional block can be given which will used as the contents of the element.
516
+ *
517
+ */
518
+ static VALUE external_element(int argc, VALUE *arguments, RB_UNUSED_VAR(VALUE self)) {
519
+ rb_check_arity(argc, 1, 2);
882
520
 
883
- static VALUE berns_time_element(int argc, VALUE* argv, VALUE self) {
884
- rb_check_arity(argc, 0, 1);
885
- return berns_internal_element(rb_utf8_str_new_cstr("time"), argv[0]);
886
- }
521
+ VALUE tag = arguments[0];
522
+ VALUE attributes = arguments[1];
887
523
 
888
- static VALUE berns_title_element(int argc, VALUE* argv, VALUE self) {
889
- rb_check_arity(argc, 0, 1);
890
- return berns_internal_element(rb_utf8_str_new_cstr("title"), argv[0]);
891
- }
524
+ if (TYPE(tag) == T_SYMBOL) {
525
+ tag = rb_sym2str(tag);
526
+ }
892
527
 
893
- static VALUE berns_tr_element(int argc, VALUE* argv, VALUE self) {
894
- rb_check_arity(argc, 0, 1);
895
- return berns_internal_element(rb_utf8_str_new_cstr("tr"), argv[0]);
896
- }
528
+ StringValue(tag);
897
529
 
898
- static VALUE berns_u_element(int argc, VALUE* argv, VALUE self) {
899
- rb_check_arity(argc, 0, 1);
900
- return berns_internal_element(rb_utf8_str_new_cstr("u"), argv[0]);
901
- }
530
+ CONTENT_FROM_BLOCK;
902
531
 
903
- static VALUE berns_ul_element(int argc, VALUE* argv, VALUE self) {
904
- rb_check_arity(argc, 0, 1);
905
- return berns_internal_element(rb_utf8_str_new_cstr("ul"), argv[0]);
906
- }
532
+ char *string = element(RSTRING_PTR(tag), RSTRING_LEN(tag), RSTRING_PTR(content), RSTRING_LEN(content), &attributes);
533
+ VALUE rstring = rb_utf8_str_new_cstr(string);
534
+ free(string);
907
535
 
908
- static VALUE berns_var_element(int argc, VALUE* argv, VALUE self) {
909
- rb_check_arity(argc, 0, 1);
910
- return berns_internal_element(rb_utf8_str_new_cstr("var"), argv[0]);
536
+ return rstring;
911
537
  }
912
538
 
913
- static VALUE berns_video_element(int argc, VALUE* argv, VALUE self) {
914
- rb_check_arity(argc, 0, 1);
915
- return berns_internal_element(rb_utf8_str_new_cstr("video"), argv[0]);
916
- }
539
+ VOID_ELEMENT(area);
540
+ VOID_ELEMENT(base);
541
+ VOID_ELEMENT(br);
542
+ VOID_ELEMENT(col);
543
+ VOID_ELEMENT(embed);
544
+ VOID_ELEMENT(hr);
545
+ VOID_ELEMENT(img);
546
+ VOID_ELEMENT(input);
547
+ VOID_ELEMENT(link);
548
+ VOID_ELEMENT(menuitem);
549
+ VOID_ELEMENT(meta);
550
+ VOID_ELEMENT(param);
551
+ VOID_ELEMENT(source);
552
+ VOID_ELEMENT(track);
553
+ VOID_ELEMENT(wbr);
554
+
555
+ STANDARD_ELEMENT(a);
556
+ STANDARD_ELEMENT(abbr);
557
+ STANDARD_ELEMENT(address);
558
+ STANDARD_ELEMENT(article);
559
+ STANDARD_ELEMENT(aside);
560
+ STANDARD_ELEMENT(audio);
561
+ STANDARD_ELEMENT(b);
562
+ STANDARD_ELEMENT(bdi);
563
+ STANDARD_ELEMENT(bdo);
564
+ STANDARD_ELEMENT(blockquote);
565
+ STANDARD_ELEMENT(body);
566
+ STANDARD_ELEMENT(button);
567
+ STANDARD_ELEMENT(canvas);
568
+ STANDARD_ELEMENT(caption);
569
+ STANDARD_ELEMENT(cite);
570
+ STANDARD_ELEMENT(code);
571
+ STANDARD_ELEMENT(colgroup);
572
+ STANDARD_ELEMENT(datalist);
573
+ STANDARD_ELEMENT(dd);
574
+ STANDARD_ELEMENT(del);
575
+ STANDARD_ELEMENT(details);
576
+ STANDARD_ELEMENT(dfn);
577
+ STANDARD_ELEMENT(dialog);
578
+ STANDARD_ELEMENT(div);
579
+ STANDARD_ELEMENT(dl);
580
+ STANDARD_ELEMENT(dt);
581
+ STANDARD_ELEMENT(em);
582
+ STANDARD_ELEMENT(fieldset);
583
+ STANDARD_ELEMENT(figcaption);
584
+ STANDARD_ELEMENT(figure);
585
+ STANDARD_ELEMENT(footer);
586
+ STANDARD_ELEMENT(form);
587
+ STANDARD_ELEMENT(h1);
588
+ STANDARD_ELEMENT(h2);
589
+ STANDARD_ELEMENT(h3);
590
+ STANDARD_ELEMENT(h4);
591
+ STANDARD_ELEMENT(h5);
592
+ STANDARD_ELEMENT(h6);
593
+ STANDARD_ELEMENT(head);
594
+ STANDARD_ELEMENT(header);
595
+ STANDARD_ELEMENT(html);
596
+ STANDARD_ELEMENT(i);
597
+ STANDARD_ELEMENT(iframe);
598
+ STANDARD_ELEMENT(ins);
599
+ STANDARD_ELEMENT(kbd);
600
+ STANDARD_ELEMENT(label);
601
+ STANDARD_ELEMENT(legend);
602
+ STANDARD_ELEMENT(li);
603
+ STANDARD_ELEMENT(main);
604
+ STANDARD_ELEMENT(map);
605
+ STANDARD_ELEMENT(mark);
606
+ STANDARD_ELEMENT(menu);
607
+ STANDARD_ELEMENT(meter);
608
+ STANDARD_ELEMENT(nav);
609
+ STANDARD_ELEMENT(noscript);
610
+ STANDARD_ELEMENT(object);
611
+ STANDARD_ELEMENT(ol);
612
+ STANDARD_ELEMENT(optgroup);
613
+ STANDARD_ELEMENT(option);
614
+ STANDARD_ELEMENT(output);
615
+ STANDARD_ELEMENT(p);
616
+ STANDARD_ELEMENT(picture);
617
+ STANDARD_ELEMENT(pre);
618
+ STANDARD_ELEMENT(progress);
619
+ STANDARD_ELEMENT(q);
620
+ STANDARD_ELEMENT(rp);
621
+ STANDARD_ELEMENT(rt);
622
+ STANDARD_ELEMENT(ruby);
623
+ STANDARD_ELEMENT(s);
624
+ STANDARD_ELEMENT(samp);
625
+ STANDARD_ELEMENT(script);
626
+ STANDARD_ELEMENT(section);
627
+ STANDARD_ELEMENT(select);
628
+ STANDARD_ELEMENT(small);
629
+ STANDARD_ELEMENT(span);
630
+ STANDARD_ELEMENT(strong);
631
+ STANDARD_ELEMENT(style);
632
+ STANDARD_ELEMENT(sub);
633
+ STANDARD_ELEMENT(summary);
634
+ STANDARD_ELEMENT(table);
635
+ STANDARD_ELEMENT(tbody);
636
+ STANDARD_ELEMENT(td);
637
+ STANDARD_ELEMENT(template);
638
+ STANDARD_ELEMENT(textarea);
639
+ STANDARD_ELEMENT(tfoot);
640
+ STANDARD_ELEMENT(th);
641
+ STANDARD_ELEMENT(thead);
642
+ STANDARD_ELEMENT(time);
643
+ STANDARD_ELEMENT(title);
644
+ STANDARD_ELEMENT(tr);
645
+ STANDARD_ELEMENT(u);
646
+ STANDARD_ELEMENT(ul);
647
+ STANDARD_ELEMENT(var);
648
+ STANDARD_ELEMENT(video);
917
649
 
918
650
  void Init_berns() {
919
651
  VALUE Berns = rb_define_module("Berns");
920
652
 
921
- rb_define_singleton_method(Berns, "element", berns_element, -1);
922
- rb_define_singleton_method(Berns, "escape_html", berns_escape_html, 1);
923
- rb_define_singleton_method(Berns, "to_attribute", berns_to_attribute, 2);
924
- rb_define_singleton_method(Berns, "to_attributes", berns_to_attributes, 1);
925
- rb_define_singleton_method(Berns, "void", berns_void_element, -1);
653
+ rb_define_singleton_method(Berns, "element", external_element, -1);
654
+ rb_define_singleton_method(Berns, "escape_html", external_escape_html, 1);
655
+ rb_define_singleton_method(Berns, "to_attribute", external_to_attribute, 2);
656
+ rb_define_singleton_method(Berns, "to_attributes", external_to_attributes, 1);
657
+ rb_define_singleton_method(Berns, "void", external_void_element, -1);
926
658
 
927
659
  /*
928
660
  * List of void elements - http://xahlee.info/js/html5_non-closing_tag.html
@@ -930,21 +662,21 @@ void Init_berns() {
930
662
  * area base br col embed hr img input link menuitem meta param source track wbr
931
663
  *
932
664
  */
933
- rb_define_singleton_method(Berns, "area", berns_area_element, -1);
934
- rb_define_singleton_method(Berns, "base", berns_base_element, -1);
935
- rb_define_singleton_method(Berns, "br", berns_br_element, -1);
936
- rb_define_singleton_method(Berns, "col", berns_col_element, -1);
937
- rb_define_singleton_method(Berns, "embed", berns_embed_element, -1);
938
- rb_define_singleton_method(Berns, "hr", berns_hr_element, -1);
939
- rb_define_singleton_method(Berns, "img", berns_img_element, -1);
940
- rb_define_singleton_method(Berns, "input", berns_input_element, -1);
941
- rb_define_singleton_method(Berns, "link", berns_link_element, -1);
942
- rb_define_singleton_method(Berns, "menuitem", berns_menuitem_element, -1);
943
- rb_define_singleton_method(Berns, "meta", berns_meta_element, -1);
944
- rb_define_singleton_method(Berns, "param", berns_param_element, -1);
945
- rb_define_singleton_method(Berns, "source", berns_source_element, -1);
946
- rb_define_singleton_method(Berns, "track", berns_track_element, -1);
947
- rb_define_singleton_method(Berns, "wbr", berns_wbr_element, -1);
665
+ rb_define_singleton_method(Berns, "area", external_area_element, -1);
666
+ rb_define_singleton_method(Berns, "base", external_base_element, -1);
667
+ rb_define_singleton_method(Berns, "br", external_br_element, -1);
668
+ rb_define_singleton_method(Berns, "col", external_col_element, -1);
669
+ rb_define_singleton_method(Berns, "embed", external_embed_element, -1);
670
+ rb_define_singleton_method(Berns, "hr", external_hr_element, -1);
671
+ rb_define_singleton_method(Berns, "img", external_img_element, -1);
672
+ rb_define_singleton_method(Berns, "input", external_input_element, -1);
673
+ rb_define_singleton_method(Berns, "link", external_link_element, -1);
674
+ rb_define_singleton_method(Berns, "menuitem", external_menuitem_element, -1);
675
+ rb_define_singleton_method(Berns, "meta", external_meta_element, -1);
676
+ rb_define_singleton_method(Berns, "param", external_param_element, -1);
677
+ rb_define_singleton_method(Berns, "source", external_source_element, -1);
678
+ rb_define_singleton_method(Berns, "track", external_track_element, -1);
679
+ rb_define_singleton_method(Berns, "wbr", external_wbr_element, -1);
948
680
 
949
681
  /*
950
682
  * List of standard HTML5 elements - https://www.w3schools.com/TAgs/default.asp
@@ -959,98 +691,98 @@ void Init_berns() {
959
691
  * video
960
692
  *
961
693
  */
962
- rb_define_singleton_method(Berns, "a", berns_a_element, -1);
963
- rb_define_singleton_method(Berns, "abbr", berns_abbr_element, -1);
964
- rb_define_singleton_method(Berns, "address", berns_address_element, -1);
965
- rb_define_singleton_method(Berns, "article", berns_article_element, -1);
966
- rb_define_singleton_method(Berns, "aside", berns_aside_element, -1);
967
- rb_define_singleton_method(Berns, "audio", berns_audio_element, -1);
968
- rb_define_singleton_method(Berns, "b", berns_b_element, -1);
969
- rb_define_singleton_method(Berns, "bdi", berns_bdi_element, -1);
970
- rb_define_singleton_method(Berns, "bdo", berns_bdo_element, -1);
971
- rb_define_singleton_method(Berns, "blockquote", berns_blockquote_element, -1);
972
- rb_define_singleton_method(Berns, "body", berns_body_element, -1);
973
- rb_define_singleton_method(Berns, "button", berns_button_element, -1);
974
- rb_define_singleton_method(Berns, "canvas", berns_canvas_element, -1);
975
- rb_define_singleton_method(Berns, "caption", berns_caption_element, -1);
976
- rb_define_singleton_method(Berns, "cite", berns_cite_element, -1);
977
- rb_define_singleton_method(Berns, "code", berns_code_element, -1);
978
- rb_define_singleton_method(Berns, "colgroup", berns_colgroup_element, -1);
979
- rb_define_singleton_method(Berns, "datalist", berns_datalist_element, -1);
980
- rb_define_singleton_method(Berns, "dd", berns_dd_element, -1);
981
- rb_define_singleton_method(Berns, "del", berns_del_element, -1);
982
- rb_define_singleton_method(Berns, "details", berns_details_element, -1);
983
- rb_define_singleton_method(Berns, "dfn", berns_dfn_element, -1);
984
- rb_define_singleton_method(Berns, "dialog", berns_dialog_element, -1);
985
- rb_define_singleton_method(Berns, "div", berns_div_element, -1);
986
- rb_define_singleton_method(Berns, "dl", berns_dl_element, -1);
987
- rb_define_singleton_method(Berns, "dt", berns_dt_element, -1);
988
- rb_define_singleton_method(Berns, "em", berns_em_element, -1);
989
- rb_define_singleton_method(Berns, "fieldset", berns_fieldset_element, -1);
990
- rb_define_singleton_method(Berns, "figcaption", berns_figcaption_element, -1);
991
- rb_define_singleton_method(Berns, "figure", berns_figure_element, -1);
992
- rb_define_singleton_method(Berns, "footer", berns_footer_element, -1);
993
- rb_define_singleton_method(Berns, "form", berns_form_element, -1);
994
- rb_define_singleton_method(Berns, "h1", berns_h1_element, -1);
995
- rb_define_singleton_method(Berns, "h2", berns_h2_element, -1);
996
- rb_define_singleton_method(Berns, "h3", berns_h3_element, -1);
997
- rb_define_singleton_method(Berns, "h4", berns_h4_element, -1);
998
- rb_define_singleton_method(Berns, "h5", berns_h5_element, -1);
999
- rb_define_singleton_method(Berns, "h6", berns_h6_element, -1);
1000
- rb_define_singleton_method(Berns, "head", berns_head_element, -1);
1001
- rb_define_singleton_method(Berns, "header", berns_header_element, -1);
1002
- rb_define_singleton_method(Berns, "html", berns_html_element, -1);
1003
- rb_define_singleton_method(Berns, "i", berns_i_element, -1);
1004
- rb_define_singleton_method(Berns, "iframe", berns_iframe_element, -1);
1005
- rb_define_singleton_method(Berns, "ins", berns_ins_element, -1);
1006
- rb_define_singleton_method(Berns, "kbd", berns_kbd_element, -1);
1007
- rb_define_singleton_method(Berns, "label", berns_label_element, -1);
1008
- rb_define_singleton_method(Berns, "legend", berns_legend_element, -1);
1009
- rb_define_singleton_method(Berns, "li", berns_li_element, -1);
1010
- rb_define_singleton_method(Berns, "main", berns_main_element, -1);
1011
- rb_define_singleton_method(Berns, "map", berns_map_element, -1);
1012
- rb_define_singleton_method(Berns, "mark", berns_mark_element, -1);
1013
- rb_define_singleton_method(Berns, "menu", berns_menu_element, -1);
1014
- rb_define_singleton_method(Berns, "meter", berns_meter_element, -1);
1015
- rb_define_singleton_method(Berns, "nav", berns_nav_element, -1);
1016
- rb_define_singleton_method(Berns, "noscript", berns_noscript_element, -1);
1017
- rb_define_singleton_method(Berns, "object", berns_object_element, -1);
1018
- rb_define_singleton_method(Berns, "ol", berns_ol_element, -1);
1019
- rb_define_singleton_method(Berns, "optgroup", berns_optgroup_element, -1);
1020
- rb_define_singleton_method(Berns, "option", berns_option_element, -1);
1021
- rb_define_singleton_method(Berns, "output", berns_output_element, -1);
1022
- rb_define_singleton_method(Berns, "p", berns_p_element, -1);
1023
- rb_define_singleton_method(Berns, "picture", berns_picture_element, -1);
1024
- rb_define_singleton_method(Berns, "pre", berns_pre_element, -1);
1025
- rb_define_singleton_method(Berns, "progress", berns_progress_element, -1);
1026
- rb_define_singleton_method(Berns, "q", berns_q_element, -1);
1027
- rb_define_singleton_method(Berns, "rp", berns_rp_element, -1);
1028
- rb_define_singleton_method(Berns, "rt", berns_rt_element, -1);
1029
- rb_define_singleton_method(Berns, "ruby", berns_ruby_element, -1);
1030
- rb_define_singleton_method(Berns, "s", berns_s_element, -1);
1031
- rb_define_singleton_method(Berns, "samp", berns_samp_element, -1);
1032
- rb_define_singleton_method(Berns, "script", berns_script_element, -1);
1033
- rb_define_singleton_method(Berns, "section", berns_section_element, -1);
1034
- rb_define_singleton_method(Berns, "select", berns_select_element, -1);
1035
- rb_define_singleton_method(Berns, "small", berns_small_element, -1);
1036
- rb_define_singleton_method(Berns, "span", berns_span_element, -1);
1037
- rb_define_singleton_method(Berns, "strong", berns_strong_element, -1);
1038
- rb_define_singleton_method(Berns, "style", berns_style_element, -1);
1039
- rb_define_singleton_method(Berns, "sub", berns_sub_element, -1);
1040
- rb_define_singleton_method(Berns, "summary", berns_summary_element, -1);
1041
- rb_define_singleton_method(Berns, "table", berns_table_element, -1);
1042
- rb_define_singleton_method(Berns, "tbody", berns_tbody_element, -1);
1043
- rb_define_singleton_method(Berns, "td", berns_td_element, -1);
1044
- rb_define_singleton_method(Berns, "template", berns_template_element, -1);
1045
- rb_define_singleton_method(Berns, "textarea", berns_textarea_element, -1);
1046
- rb_define_singleton_method(Berns, "tfoot", berns_tfoot_element, -1);
1047
- rb_define_singleton_method(Berns, "th", berns_th_element, -1);
1048
- rb_define_singleton_method(Berns, "thead", berns_thead_element, -1);
1049
- rb_define_singleton_method(Berns, "time", berns_time_element, -1);
1050
- rb_define_singleton_method(Berns, "title", berns_title_element, -1);
1051
- rb_define_singleton_method(Berns, "tr", berns_tr_element, -1);
1052
- rb_define_singleton_method(Berns, "u", berns_u_element, -1);
1053
- rb_define_singleton_method(Berns, "ul", berns_ul_element, -1);
1054
- rb_define_singleton_method(Berns, "var", berns_var_element, -1);
1055
- rb_define_singleton_method(Berns, "video", berns_video_element, -1);
694
+ rb_define_singleton_method(Berns, "a", external_a_element, -1);
695
+ rb_define_singleton_method(Berns, "abbr", external_abbr_element, -1);
696
+ rb_define_singleton_method(Berns, "address", external_address_element, -1);
697
+ rb_define_singleton_method(Berns, "article", external_article_element, -1);
698
+ rb_define_singleton_method(Berns, "aside", external_aside_element, -1);
699
+ rb_define_singleton_method(Berns, "audio", external_audio_element, -1);
700
+ rb_define_singleton_method(Berns, "b", external_b_element, -1);
701
+ rb_define_singleton_method(Berns, "bdi", external_bdi_element, -1);
702
+ rb_define_singleton_method(Berns, "bdo", external_bdo_element, -1);
703
+ rb_define_singleton_method(Berns, "blockquote", external_blockquote_element, -1);
704
+ rb_define_singleton_method(Berns, "body", external_body_element, -1);
705
+ rb_define_singleton_method(Berns, "button", external_button_element, -1);
706
+ rb_define_singleton_method(Berns, "canvas", external_canvas_element, -1);
707
+ rb_define_singleton_method(Berns, "caption", external_caption_element, -1);
708
+ rb_define_singleton_method(Berns, "cite", external_cite_element, -1);
709
+ rb_define_singleton_method(Berns, "code", external_code_element, -1);
710
+ rb_define_singleton_method(Berns, "colgroup", external_colgroup_element, -1);
711
+ rb_define_singleton_method(Berns, "datalist", external_datalist_element, -1);
712
+ rb_define_singleton_method(Berns, "dd", external_dd_element, -1);
713
+ rb_define_singleton_method(Berns, "del", external_del_element, -1);
714
+ rb_define_singleton_method(Berns, "details", external_details_element, -1);
715
+ rb_define_singleton_method(Berns, "dfn", external_dfn_element, -1);
716
+ rb_define_singleton_method(Berns, "dialog", external_dialog_element, -1);
717
+ rb_define_singleton_method(Berns, "div", external_div_element, -1);
718
+ rb_define_singleton_method(Berns, "dl", external_dl_element, -1);
719
+ rb_define_singleton_method(Berns, "dt", external_dt_element, -1);
720
+ rb_define_singleton_method(Berns, "em", external_em_element, -1);
721
+ rb_define_singleton_method(Berns, "fieldset", external_fieldset_element, -1);
722
+ rb_define_singleton_method(Berns, "figcaption", external_figcaption_element, -1);
723
+ rb_define_singleton_method(Berns, "figure", external_figure_element, -1);
724
+ rb_define_singleton_method(Berns, "footer", external_footer_element, -1);
725
+ rb_define_singleton_method(Berns, "form", external_form_element, -1);
726
+ rb_define_singleton_method(Berns, "h1", external_h1_element, -1);
727
+ rb_define_singleton_method(Berns, "h2", external_h2_element, -1);
728
+ rb_define_singleton_method(Berns, "h3", external_h3_element, -1);
729
+ rb_define_singleton_method(Berns, "h4", external_h4_element, -1);
730
+ rb_define_singleton_method(Berns, "h5", external_h5_element, -1);
731
+ rb_define_singleton_method(Berns, "h6", external_h6_element, -1);
732
+ rb_define_singleton_method(Berns, "head", external_head_element, -1);
733
+ rb_define_singleton_method(Berns, "header", external_header_element, -1);
734
+ rb_define_singleton_method(Berns, "html", external_html_element, -1);
735
+ rb_define_singleton_method(Berns, "i", external_i_element, -1);
736
+ rb_define_singleton_method(Berns, "iframe", external_iframe_element, -1);
737
+ rb_define_singleton_method(Berns, "ins", external_ins_element, -1);
738
+ rb_define_singleton_method(Berns, "kbd", external_kbd_element, -1);
739
+ rb_define_singleton_method(Berns, "label", external_label_element, -1);
740
+ rb_define_singleton_method(Berns, "legend", external_legend_element, -1);
741
+ rb_define_singleton_method(Berns, "li", external_li_element, -1);
742
+ rb_define_singleton_method(Berns, "main", external_main_element, -1);
743
+ rb_define_singleton_method(Berns, "map", external_map_element, -1);
744
+ rb_define_singleton_method(Berns, "mark", external_mark_element, -1);
745
+ rb_define_singleton_method(Berns, "menu", external_menu_element, -1);
746
+ rb_define_singleton_method(Berns, "meter", external_meter_element, -1);
747
+ rb_define_singleton_method(Berns, "nav", external_nav_element, -1);
748
+ rb_define_singleton_method(Berns, "noscript", external_noscript_element, -1);
749
+ rb_define_singleton_method(Berns, "object", external_object_element, -1);
750
+ rb_define_singleton_method(Berns, "ol", external_ol_element, -1);
751
+ rb_define_singleton_method(Berns, "optgroup", external_optgroup_element, -1);
752
+ rb_define_singleton_method(Berns, "option", external_option_element, -1);
753
+ rb_define_singleton_method(Berns, "output", external_output_element, -1);
754
+ rb_define_singleton_method(Berns, "p", external_p_element, -1);
755
+ rb_define_singleton_method(Berns, "picture", external_picture_element, -1);
756
+ rb_define_singleton_method(Berns, "pre", external_pre_element, -1);
757
+ rb_define_singleton_method(Berns, "progress", external_progress_element, -1);
758
+ rb_define_singleton_method(Berns, "q", external_q_element, -1);
759
+ rb_define_singleton_method(Berns, "rp", external_rp_element, -1);
760
+ rb_define_singleton_method(Berns, "rt", external_rt_element, -1);
761
+ rb_define_singleton_method(Berns, "ruby", external_ruby_element, -1);
762
+ rb_define_singleton_method(Berns, "s", external_s_element, -1);
763
+ rb_define_singleton_method(Berns, "samp", external_samp_element, -1);
764
+ rb_define_singleton_method(Berns, "script", external_script_element, -1);
765
+ rb_define_singleton_method(Berns, "section", external_section_element, -1);
766
+ rb_define_singleton_method(Berns, "select", external_select_element, -1);
767
+ rb_define_singleton_method(Berns, "small", external_small_element, -1);
768
+ rb_define_singleton_method(Berns, "span", external_span_element, -1);
769
+ rb_define_singleton_method(Berns, "strong", external_strong_element, -1);
770
+ rb_define_singleton_method(Berns, "style", external_style_element, -1);
771
+ rb_define_singleton_method(Berns, "sub", external_sub_element, -1);
772
+ rb_define_singleton_method(Berns, "summary", external_summary_element, -1);
773
+ rb_define_singleton_method(Berns, "table", external_table_element, -1);
774
+ rb_define_singleton_method(Berns, "tbody", external_tbody_element, -1);
775
+ rb_define_singleton_method(Berns, "td", external_td_element, -1);
776
+ rb_define_singleton_method(Berns, "template", external_template_element, -1);
777
+ rb_define_singleton_method(Berns, "textarea", external_textarea_element, -1);
778
+ rb_define_singleton_method(Berns, "tfoot", external_tfoot_element, -1);
779
+ rb_define_singleton_method(Berns, "th", external_th_element, -1);
780
+ rb_define_singleton_method(Berns, "thead", external_thead_element, -1);
781
+ rb_define_singleton_method(Berns, "time", external_time_element, -1);
782
+ rb_define_singleton_method(Berns, "title", external_title_element, -1);
783
+ rb_define_singleton_method(Berns, "tr", external_tr_element, -1);
784
+ rb_define_singleton_method(Berns, "u", external_u_element, -1);
785
+ rb_define_singleton_method(Berns, "ul", external_ul_element, -1);
786
+ rb_define_singleton_method(Berns, "var", external_var_element, -1);
787
+ rb_define_singleton_method(Berns, "video", external_video_element, -1);
1056
788
  }