berns 3.0.6 → 3.1.0

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