berns 3.0.3 → 3.1.1

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: 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
  }