berns 3.0.6 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0513b5d30f4b3b8cc581baa1d46a2bd64469d76224638cdcdb45fe3faab1e66
4
- data.tar.gz: 857d58645cdad849eea710bc68bd3e5ab3695e9e0ba763b54392fa96956836dc
3
+ metadata.gz: bce7bd3384f01f587a75bd722cca156b4357e0953bd90a5a2c8f97a630deb8db
4
+ data.tar.gz: 2c830eb788274a6d96e3e0a7db0e75826dea451eabecb3444878901d6e1adb08
5
5
  SHA512:
6
- metadata.gz: aa90410871bd7491fc665c55cb3527dfa7441c43962c2a50fab5f68fb0e87f9c5b2960e619aa97273d0f91164c9d7c6d63dda6ebd93534227e3b3f5a034fcf34
7
- data.tar.gz: d8ed28163f684577aec0f8b1fe8010e9135e8c03ecabba2797a8e60640d55143763b9db0adf0f0258fd660faf7f6d975dc70f9c97dfa39691fc90a9b7e4945ed
6
+ metadata.gz: d20138c2bc54ab035eb9d79f1e0ae18065ba422157fa453258acd5d974f08062afee105b50d2d3564b3e4882b4331ec6f93e4da3a3091a1440ad8a74c10f1686
7
+ data.tar.gz: 598843f7a87302d0a59ba53d8e52caf0f864a2e146b473c2d95b50f1da5b11536603f4d9f51f990de385bbaa08fb6e273381672eb823ddda2b0bb614532aef33
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,567 @@ 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 strdup("");
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 strdup("");
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;
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 + 1];
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_FALSE:
243
+ combined = strdup("");
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_NIL:
247
+ /* Fall through. */
248
+ case T_TRUE:
249
+ combined = string_value_to_attribute(subattr, subattr_len, "", 0);
250
+ break;
193
251
 
194
- if (length == 0) {
195
- return rb_utf8_str_new_cstr("");
196
- }
252
+ case T_STRING:
253
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
254
+ break;
197
255
 
198
- char *string = NULL;
199
- size_t size = 0; /* IN BYTES */
256
+ case T_SYMBOL:
257
+ subvalue = rb_sym2str(subvalue);
258
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
259
+ break;
200
260
 
201
- const char *space = " ";
202
- const size_t splen = strlen(space);
261
+ case T_HASH:
262
+ combined = hash_value_to_attribute(subattr, subattr_len, subvalue);
263
+ break;
203
264
 
204
- size_t alen;
265
+ default:
266
+ subvalue = rb_funcall(subvalue, rb_intern("to_s"), 0);
267
+ combined = string_value_to_attribute(subattr, subattr_len, RSTRING_PTR(subvalue), RSTRING_LEN(subvalue));
268
+ break;
269
+ }
205
270
 
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);
271
+ size_t combined_len = strlen(combined);
272
+ size_t size_to_append = combined_len + 1;
210
273
 
211
274
  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
- }
275
+ size_to_append += splen;
276
+ }
217
277
 
218
- string = tmp;
278
+ if ((size_to_append + occupied) > allocated) {
279
+ /* To avoid an abundance of reallocations, this is a multiple of 256. */
280
+ double multiple = (double) (size_to_append + occupied) / 256;
281
+ size_t new_size_to_allocate = (unsigned int) ceil(multiple) * 256;
219
282
 
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);
283
+ char *tmp = realloc(destination, new_size_to_allocate);
225
284
 
226
285
  if (tmp == NULL) {
227
- rb_raise(rb_eNoMemError, "Berns.to_attributes could not allocate sufficient memory.");
286
+ free(destination);
287
+ rb_raise(rb_eNoMemError, "Berns could not allocate sufficient memory.");
228
288
  }
229
289
 
230
- string = tmp;
290
+ allocated = new_size_to_allocate;
291
+ destination = tmp;
292
+ position = destination + occupied;
293
+ end = destination + allocated;
294
+ }
231
295
 
232
- stecpy(string + size, RSTRING_PTR(attribute), string + size + alen + 1);
233
- size = size + alen;
296
+ if (i > 0) {
297
+ position = stecpy(position, space, end);
298
+ occupied += splen;
234
299
  }
235
- }
236
300
 
237
- rstring = rb_utf8_str_new_cstr(string);
238
- free(string);
301
+ position = stecpy(position, combined, end);
302
+ occupied += combined_len;
239
303
 
240
- return rstring;
241
- }
304
+ free(combined);
305
+ }
242
306
 
243
- static VALUE berns_internal_void(VALUE tag, VALUE attributes) {
244
- const VALUE berns = rb_const_get(rb_cObject, rb_intern("Berns"));
307
+ return destination;
308
+ }
245
309
 
246
- switch(TYPE(tag)) {
247
- case T_STRING:
248
- break;
310
+ /*
311
+ * Convert an attribute name and value into a string.
312
+ */
313
+ static char * to_attribute(VALUE attr, VALUE value) {
314
+ switch(TYPE(attr)) {
249
315
  case T_SYMBOL:
250
- tag = rb_sym_to_s(tag);
316
+ attr = rb_sym2str(attr);
251
317
  break;
252
318
  default:
253
- rb_raise(rb_eTypeError, "Berns.void elements must be a String or Symbol.");
254
319
  break;
255
320
  }
256
321
 
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"));
322
+ StringValue(attr);
300
323
 
301
- VALUE content;
324
+ char *val = NULL;
325
+ VALUE str;
302
326
 
303
- switch(TYPE(tag)) {
327
+ switch(TYPE(value)) {
328
+ case T_NIL:
329
+ case T_TRUE:
330
+ val = empty_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr));
331
+ break;
332
+ case T_FALSE:
333
+ val = strdup("");
334
+ break;
335
+ case T_HASH:
336
+ val = hash_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), value);
337
+ break;
304
338
  case T_STRING:
339
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(value), RSTRING_LEN(value));
305
340
  break;
306
341
  case T_SYMBOL:
307
- tag = rb_sym_to_s(tag);
342
+ str = rb_sym2str(value);
343
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(str), RSTRING_LEN(str));
308
344
  break;
309
345
  default:
310
- rb_raise(rb_eTypeError, "Berns.element elements must be a String or Symbol.");
346
+ str = rb_funcall(value, rb_intern("to_s"), 0);
347
+ val = string_value_to_attribute(RSTRING_PTR(attr), RSTRING_LEN(attr), RSTRING_PTR(str), RSTRING_LEN(str));
311
348
  break;
312
349
  }
313
350
 
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);
351
+ return val;
367
352
  }
368
353
 
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
- }
354
+ /*
355
+ * The external API for Berns.to_attribute.
356
+ *
357
+ * attr should be either a symbol or string, otherwise an error is raised.
358
+ * value can be anything to responds to #to_s
359
+ *
360
+ */
361
+ static VALUE external_to_attribute(RB_UNUSED_VAR(VALUE self), VALUE attr, VALUE value) {
362
+ switch(TYPE(attr)) {
363
+ case T_SYMBOL:
364
+ attr = rb_sym2str(attr);
365
+ break;
366
+ default:
367
+ break;
368
+ }
373
369
 
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
- }
370
+ StringValue(attr);
378
371
 
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
- }
372
+ char *val = to_attribute(attr, value);
373
+ VALUE rstring = rb_utf8_str_new_cstr(val);
374
+ free(val);
383
375
 
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]);
376
+ return rstring;
387
377
  }
388
378
 
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
- }
379
+ /*
380
+ * The external API for Berns.to_attributes.
381
+ *
382
+ * attributes should be a hash, otherwise an error is raised.
383
+ *
384
+ */
385
+ static VALUE external_to_attributes(RB_UNUSED_VAR(VALUE self), VALUE attributes) {
386
+ Check_Type(attributes, T_HASH);
393
387
 
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
- }
388
+ if (rb_hash_size(attributes) == 1) {
389
+ return rb_utf8_str_new_cstr("");
390
+ }
398
391
 
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
- }
392
+ char *empty = "";
393
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
403
394
 
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
- }
395
+ VALUE rstring = rb_utf8_str_new_cstr(attrs);
396
+ free(attrs);
408
397
 
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]);
398
+ return rstring;
412
399
  }
413
400
 
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
- }
401
+ static char * void_element(char *tag, size_t tlen, VALUE attributes) {
402
+ /* T_IMEMO is what we get if an optional argument was not passed. */
403
+ if (TYPE(attributes) == T_IMEMO) {
404
+ size_t total = tag_olen + tlen + tag_clen + 1;
405
+ char *string = malloc(total);
406
+ char *ptr;
407
+ char *end = string + total;
418
408
 
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
- }
409
+ ptr = stecpy(string, tag_open, end);
410
+ ptr = stecpy(ptr, tag, end);
411
+ ptr = stecpy(ptr, tag_close, end);
423
412
 
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
- }
413
+ return string;
414
+ } else {
415
+ char *empty = "";
416
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
428
417
 
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
- }
418
+ size_t total = tag_olen + tlen + splen + strlen(attrs) + tag_clen + 1;
419
+ char *string = malloc(total);
420
+ char *ptr;
421
+ char *end = string + total;
433
422
 
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
- }
423
+ ptr = stecpy(string, tag_open, end);
424
+ ptr = stecpy(ptr, tag, end);
425
+ ptr = stecpy(ptr, space, end);
426
+ ptr = stecpy(ptr, attrs, end);
427
+ ptr = stecpy(ptr, tag_close, end);
438
428
 
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
- }
429
+ free(attrs);
443
430
 
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]);
431
+ return string;
432
+ }
447
433
  }
448
434
 
449
- static VALUE berns_element(int argc, VALUE* argv, VALUE self) {
435
+ /*
436
+ * The external API for Berns.void.
437
+ *
438
+ * The first argument should be a string or symbol, otherwise an error is raised.
439
+ * The second argument must be a hash if present.
440
+ *
441
+ */
442
+ static VALUE external_void_element(int argc, VALUE *arguments, RB_UNUSED_VAR(VALUE self)) {
450
443
  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
-
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
444
 
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
- }
445
+ VALUE tag = arguments[0];
446
+ VALUE attributes = arguments[1];
678
447
 
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
- }
448
+ if (TYPE(tag) == T_SYMBOL) {
449
+ tag = rb_sym2str(tag);
450
+ }
803
451
 
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
- }
452
+ StringValue(tag);
808
453
 
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
- }
454
+ char *string = void_element(RSTRING_PTR(tag), RSTRING_LEN(tag), attributes);
455
+ VALUE rstring = rb_utf8_str_new_cstr(string);
813
456
 
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
- }
457
+ free(string);
818
458
 
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]);
459
+ return rstring;
822
460
  }
823
461
 
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
- }
462
+ static char * element(char *tag, size_t tlen, char *content, size_t conlen, VALUE attributes) {
463
+ char *empty = "";
464
+ char *attrs = hash_value_to_attribute(empty, 0, attributes);
465
+ size_t alen = strlen(attrs);
828
466
 
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
- }
467
+ size_t total = tag_olen + tlen + tag_clen + tag_olen + sllen + tlen + tag_clen + 1;
833
468
 
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
- }
469
+ /* If we have some attributes, add a space and the attributes' length. */
470
+ if (alen > 0) {
471
+ total += splen + alen;
472
+ }
838
473
 
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
- }
474
+ /* If we have some content, add the content length to our total. */
475
+ if (conlen > 0) {
476
+ total += conlen;
477
+ }
843
478
 
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
- }
479
+ char *dest = malloc(total);
480
+ char *ptr = NULL;
481
+ char *end = dest + total;
848
482
 
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
- }
483
+ ptr = stecpy(dest, tag_open, end);
484
+ ptr = stecpy(ptr, tag, end);
853
485
 
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
- }
486
+ if (alen > 0) {
487
+ ptr = stecpy(ptr, space, end);
488
+ ptr = stecpy(ptr, attrs, end);
489
+ }
858
490
 
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
- }
491
+ ptr = stecpy(ptr, tag_close, end);
863
492
 
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
- }
493
+ if (conlen > 0) {
494
+ ptr = stecpy(ptr, content, end);
495
+ }
868
496
 
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
- }
497
+ ptr = stecpy(ptr, tag_open, end);
498
+ ptr = stecpy(ptr, slash, end);
499
+ ptr = stecpy(ptr, tag, end);
500
+ ptr = stecpy(ptr, tag_close, end);
873
501
 
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
- }
502
+ free(attrs);
878
503
 
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]);
504
+ return dest;
882
505
  }
883
506
 
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
- }
507
+ /*
508
+ * The external API for Berns.element.
509
+ *
510
+ * The first argument should be a string or symbol, otherwise an error is raised.
511
+ * The second argument must be a hash if present.
512
+ * An optional block can be given which will used as the contents of the element.
513
+ *
514
+ */
515
+ static VALUE external_element(int argc, VALUE *arguments, RB_UNUSED_VAR(VALUE self)) {
516
+ rb_check_arity(argc, 1, 2);
888
517
 
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
- }
518
+ VALUE tag = arguments[0];
519
+ VALUE attributes = arguments[1];
893
520
 
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
- }
521
+ if (TYPE(tag) == T_SYMBOL) {
522
+ tag = rb_sym2str(tag);
523
+ }
898
524
 
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
- }
525
+ StringValue(tag);
903
526
 
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
- }
527
+ CONTENT_FROM_BLOCK;
908
528
 
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
- }
529
+ char *string = element(RSTRING_PTR(tag), RSTRING_LEN(tag), RSTRING_PTR(content), RSTRING_LEN(content), attributes);
530
+ VALUE rstring = rb_utf8_str_new_cstr(string);
531
+ free(string);
913
532
 
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]);
533
+ return rstring;
917
534
  }
918
535
 
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
- }
536
+ VOID_ELEMENT(area);
537
+ VOID_ELEMENT(base);
538
+ VOID_ELEMENT(br);
539
+ VOID_ELEMENT(col);
540
+ VOID_ELEMENT(embed);
541
+ VOID_ELEMENT(hr);
542
+ VOID_ELEMENT(img);
543
+ VOID_ELEMENT(input);
544
+ VOID_ELEMENT(link);
545
+ VOID_ELEMENT(menuitem);
546
+ VOID_ELEMENT(meta);
547
+ VOID_ELEMENT(param);
548
+ VOID_ELEMENT(source);
549
+ VOID_ELEMENT(track);
550
+ VOID_ELEMENT(wbr);
551
+
552
+ STANDARD_ELEMENT(a);
553
+ STANDARD_ELEMENT(abbr);
554
+ STANDARD_ELEMENT(address);
555
+ STANDARD_ELEMENT(article);
556
+ STANDARD_ELEMENT(aside);
557
+ STANDARD_ELEMENT(audio);
558
+ STANDARD_ELEMENT(b);
559
+ STANDARD_ELEMENT(bdi);
560
+ STANDARD_ELEMENT(bdo);
561
+ STANDARD_ELEMENT(blockquote);
562
+ STANDARD_ELEMENT(body);
563
+ STANDARD_ELEMENT(button);
564
+ STANDARD_ELEMENT(canvas);
565
+ STANDARD_ELEMENT(caption);
566
+ STANDARD_ELEMENT(cite);
567
+ STANDARD_ELEMENT(code);
568
+ STANDARD_ELEMENT(colgroup);
569
+ STANDARD_ELEMENT(datalist);
570
+ STANDARD_ELEMENT(dd);
571
+ STANDARD_ELEMENT(del);
572
+ STANDARD_ELEMENT(details);
573
+ STANDARD_ELEMENT(dfn);
574
+ STANDARD_ELEMENT(dialog);
575
+ STANDARD_ELEMENT(div);
576
+ STANDARD_ELEMENT(dl);
577
+ STANDARD_ELEMENT(dt);
578
+ STANDARD_ELEMENT(em);
579
+ STANDARD_ELEMENT(fieldset);
580
+ STANDARD_ELEMENT(figcaption);
581
+ STANDARD_ELEMENT(figure);
582
+ STANDARD_ELEMENT(footer);
583
+ STANDARD_ELEMENT(form);
584
+ STANDARD_ELEMENT(h1);
585
+ STANDARD_ELEMENT(h2);
586
+ STANDARD_ELEMENT(h3);
587
+ STANDARD_ELEMENT(h4);
588
+ STANDARD_ELEMENT(h5);
589
+ STANDARD_ELEMENT(h6);
590
+ STANDARD_ELEMENT(head);
591
+ STANDARD_ELEMENT(header);
592
+ STANDARD_ELEMENT(html);
593
+ STANDARD_ELEMENT(i);
594
+ STANDARD_ELEMENT(iframe);
595
+ STANDARD_ELEMENT(ins);
596
+ STANDARD_ELEMENT(kbd);
597
+ STANDARD_ELEMENT(label);
598
+ STANDARD_ELEMENT(legend);
599
+ STANDARD_ELEMENT(li);
600
+ STANDARD_ELEMENT(main);
601
+ STANDARD_ELEMENT(map);
602
+ STANDARD_ELEMENT(mark);
603
+ STANDARD_ELEMENT(menu);
604
+ STANDARD_ELEMENT(meter);
605
+ STANDARD_ELEMENT(nav);
606
+ STANDARD_ELEMENT(noscript);
607
+ STANDARD_ELEMENT(object);
608
+ STANDARD_ELEMENT(ol);
609
+ STANDARD_ELEMENT(optgroup);
610
+ STANDARD_ELEMENT(option);
611
+ STANDARD_ELEMENT(output);
612
+ STANDARD_ELEMENT(p);
613
+ STANDARD_ELEMENT(picture);
614
+ STANDARD_ELEMENT(pre);
615
+ STANDARD_ELEMENT(progress);
616
+ STANDARD_ELEMENT(q);
617
+ STANDARD_ELEMENT(rp);
618
+ STANDARD_ELEMENT(rt);
619
+ STANDARD_ELEMENT(ruby);
620
+ STANDARD_ELEMENT(s);
621
+ STANDARD_ELEMENT(samp);
622
+ STANDARD_ELEMENT(script);
623
+ STANDARD_ELEMENT(section);
624
+ STANDARD_ELEMENT(select);
625
+ STANDARD_ELEMENT(small);
626
+ STANDARD_ELEMENT(span);
627
+ STANDARD_ELEMENT(strong);
628
+ STANDARD_ELEMENT(style);
629
+ STANDARD_ELEMENT(sub);
630
+ STANDARD_ELEMENT(summary);
631
+ STANDARD_ELEMENT(table);
632
+ STANDARD_ELEMENT(tbody);
633
+ STANDARD_ELEMENT(td);
634
+ STANDARD_ELEMENT(template);
635
+ STANDARD_ELEMENT(textarea);
636
+ STANDARD_ELEMENT(tfoot);
637
+ STANDARD_ELEMENT(th);
638
+ STANDARD_ELEMENT(thead);
639
+ STANDARD_ELEMENT(time);
640
+ STANDARD_ELEMENT(title);
641
+ STANDARD_ELEMENT(tr);
642
+ STANDARD_ELEMENT(u);
643
+ STANDARD_ELEMENT(ul);
644
+ STANDARD_ELEMENT(var);
645
+ STANDARD_ELEMENT(video);
923
646
 
924
647
  void Init_berns() {
925
648
  VALUE Berns = rb_define_module("Berns");
926
649
 
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);
650
+ rb_define_singleton_method(Berns, "element", external_element, -1);
651
+ rb_define_singleton_method(Berns, "escape_html", external_escape_html, 1);
652
+ rb_define_singleton_method(Berns, "to_attribute", external_to_attribute, 2);
653
+ rb_define_singleton_method(Berns, "to_attributes", external_to_attributes, 1);
654
+ rb_define_singleton_method(Berns, "void", external_void_element, -1);
932
655
 
933
656
  /*
934
657
  * List of void elements - http://xahlee.info/js/html5_non-closing_tag.html
@@ -936,21 +659,21 @@ void Init_berns() {
936
659
  * area base br col embed hr img input link menuitem meta param source track wbr
937
660
  *
938
661
  */
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);
662
+ rb_define_singleton_method(Berns, "area", external_area_element, -1);
663
+ rb_define_singleton_method(Berns, "base", external_base_element, -1);
664
+ rb_define_singleton_method(Berns, "br", external_br_element, -1);
665
+ rb_define_singleton_method(Berns, "col", external_col_element, -1);
666
+ rb_define_singleton_method(Berns, "embed", external_embed_element, -1);
667
+ rb_define_singleton_method(Berns, "hr", external_hr_element, -1);
668
+ rb_define_singleton_method(Berns, "img", external_img_element, -1);
669
+ rb_define_singleton_method(Berns, "input", external_input_element, -1);
670
+ rb_define_singleton_method(Berns, "link", external_link_element, -1);
671
+ rb_define_singleton_method(Berns, "menuitem", external_menuitem_element, -1);
672
+ rb_define_singleton_method(Berns, "meta", external_meta_element, -1);
673
+ rb_define_singleton_method(Berns, "param", external_param_element, -1);
674
+ rb_define_singleton_method(Berns, "source", external_source_element, -1);
675
+ rb_define_singleton_method(Berns, "track", external_track_element, -1);
676
+ rb_define_singleton_method(Berns, "wbr", external_wbr_element, -1);
954
677
 
955
678
  /*
956
679
  * List of standard HTML5 elements - https://www.w3schools.com/TAgs/default.asp
@@ -965,98 +688,98 @@ void Init_berns() {
965
688
  * video
966
689
  *
967
690
  */
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);
691
+ rb_define_singleton_method(Berns, "a", external_a_element, -1);
692
+ rb_define_singleton_method(Berns, "abbr", external_abbr_element, -1);
693
+ rb_define_singleton_method(Berns, "address", external_address_element, -1);
694
+ rb_define_singleton_method(Berns, "article", external_article_element, -1);
695
+ rb_define_singleton_method(Berns, "aside", external_aside_element, -1);
696
+ rb_define_singleton_method(Berns, "audio", external_audio_element, -1);
697
+ rb_define_singleton_method(Berns, "b", external_b_element, -1);
698
+ rb_define_singleton_method(Berns, "bdi", external_bdi_element, -1);
699
+ rb_define_singleton_method(Berns, "bdo", external_bdo_element, -1);
700
+ rb_define_singleton_method(Berns, "blockquote", external_blockquote_element, -1);
701
+ rb_define_singleton_method(Berns, "body", external_body_element, -1);
702
+ rb_define_singleton_method(Berns, "button", external_button_element, -1);
703
+ rb_define_singleton_method(Berns, "canvas", external_canvas_element, -1);
704
+ rb_define_singleton_method(Berns, "caption", external_caption_element, -1);
705
+ rb_define_singleton_method(Berns, "cite", external_cite_element, -1);
706
+ rb_define_singleton_method(Berns, "code", external_code_element, -1);
707
+ rb_define_singleton_method(Berns, "colgroup", external_colgroup_element, -1);
708
+ rb_define_singleton_method(Berns, "datalist", external_datalist_element, -1);
709
+ rb_define_singleton_method(Berns, "dd", external_dd_element, -1);
710
+ rb_define_singleton_method(Berns, "del", external_del_element, -1);
711
+ rb_define_singleton_method(Berns, "details", external_details_element, -1);
712
+ rb_define_singleton_method(Berns, "dfn", external_dfn_element, -1);
713
+ rb_define_singleton_method(Berns, "dialog", external_dialog_element, -1);
714
+ rb_define_singleton_method(Berns, "div", external_div_element, -1);
715
+ rb_define_singleton_method(Berns, "dl", external_dl_element, -1);
716
+ rb_define_singleton_method(Berns, "dt", external_dt_element, -1);
717
+ rb_define_singleton_method(Berns, "em", external_em_element, -1);
718
+ rb_define_singleton_method(Berns, "fieldset", external_fieldset_element, -1);
719
+ rb_define_singleton_method(Berns, "figcaption", external_figcaption_element, -1);
720
+ rb_define_singleton_method(Berns, "figure", external_figure_element, -1);
721
+ rb_define_singleton_method(Berns, "footer", external_footer_element, -1);
722
+ rb_define_singleton_method(Berns, "form", external_form_element, -1);
723
+ rb_define_singleton_method(Berns, "h1", external_h1_element, -1);
724
+ rb_define_singleton_method(Berns, "h2", external_h2_element, -1);
725
+ rb_define_singleton_method(Berns, "h3", external_h3_element, -1);
726
+ rb_define_singleton_method(Berns, "h4", external_h4_element, -1);
727
+ rb_define_singleton_method(Berns, "h5", external_h5_element, -1);
728
+ rb_define_singleton_method(Berns, "h6", external_h6_element, -1);
729
+ rb_define_singleton_method(Berns, "head", external_head_element, -1);
730
+ rb_define_singleton_method(Berns, "header", external_header_element, -1);
731
+ rb_define_singleton_method(Berns, "html", external_html_element, -1);
732
+ rb_define_singleton_method(Berns, "i", external_i_element, -1);
733
+ rb_define_singleton_method(Berns, "iframe", external_iframe_element, -1);
734
+ rb_define_singleton_method(Berns, "ins", external_ins_element, -1);
735
+ rb_define_singleton_method(Berns, "kbd", external_kbd_element, -1);
736
+ rb_define_singleton_method(Berns, "label", external_label_element, -1);
737
+ rb_define_singleton_method(Berns, "legend", external_legend_element, -1);
738
+ rb_define_singleton_method(Berns, "li", external_li_element, -1);
739
+ rb_define_singleton_method(Berns, "main", external_main_element, -1);
740
+ rb_define_singleton_method(Berns, "map", external_map_element, -1);
741
+ rb_define_singleton_method(Berns, "mark", external_mark_element, -1);
742
+ rb_define_singleton_method(Berns, "menu", external_menu_element, -1);
743
+ rb_define_singleton_method(Berns, "meter", external_meter_element, -1);
744
+ rb_define_singleton_method(Berns, "nav", external_nav_element, -1);
745
+ rb_define_singleton_method(Berns, "noscript", external_noscript_element, -1);
746
+ rb_define_singleton_method(Berns, "object", external_object_element, -1);
747
+ rb_define_singleton_method(Berns, "ol", external_ol_element, -1);
748
+ rb_define_singleton_method(Berns, "optgroup", external_optgroup_element, -1);
749
+ rb_define_singleton_method(Berns, "option", external_option_element, -1);
750
+ rb_define_singleton_method(Berns, "output", external_output_element, -1);
751
+ rb_define_singleton_method(Berns, "p", external_p_element, -1);
752
+ rb_define_singleton_method(Berns, "picture", external_picture_element, -1);
753
+ rb_define_singleton_method(Berns, "pre", external_pre_element, -1);
754
+ rb_define_singleton_method(Berns, "progress", external_progress_element, -1);
755
+ rb_define_singleton_method(Berns, "q", external_q_element, -1);
756
+ rb_define_singleton_method(Berns, "rp", external_rp_element, -1);
757
+ rb_define_singleton_method(Berns, "rt", external_rt_element, -1);
758
+ rb_define_singleton_method(Berns, "ruby", external_ruby_element, -1);
759
+ rb_define_singleton_method(Berns, "s", external_s_element, -1);
760
+ rb_define_singleton_method(Berns, "samp", external_samp_element, -1);
761
+ rb_define_singleton_method(Berns, "script", external_script_element, -1);
762
+ rb_define_singleton_method(Berns, "section", external_section_element, -1);
763
+ rb_define_singleton_method(Berns, "select", external_select_element, -1);
764
+ rb_define_singleton_method(Berns, "small", external_small_element, -1);
765
+ rb_define_singleton_method(Berns, "span", external_span_element, -1);
766
+ rb_define_singleton_method(Berns, "strong", external_strong_element, -1);
767
+ rb_define_singleton_method(Berns, "style", external_style_element, -1);
768
+ rb_define_singleton_method(Berns, "sub", external_sub_element, -1);
769
+ rb_define_singleton_method(Berns, "summary", external_summary_element, -1);
770
+ rb_define_singleton_method(Berns, "table", external_table_element, -1);
771
+ rb_define_singleton_method(Berns, "tbody", external_tbody_element, -1);
772
+ rb_define_singleton_method(Berns, "td", external_td_element, -1);
773
+ rb_define_singleton_method(Berns, "template", external_template_element, -1);
774
+ rb_define_singleton_method(Berns, "textarea", external_textarea_element, -1);
775
+ rb_define_singleton_method(Berns, "tfoot", external_tfoot_element, -1);
776
+ rb_define_singleton_method(Berns, "th", external_th_element, -1);
777
+ rb_define_singleton_method(Berns, "thead", external_thead_element, -1);
778
+ rb_define_singleton_method(Berns, "time", external_time_element, -1);
779
+ rb_define_singleton_method(Berns, "title", external_title_element, -1);
780
+ rb_define_singleton_method(Berns, "tr", external_tr_element, -1);
781
+ rb_define_singleton_method(Berns, "u", external_u_element, -1);
782
+ rb_define_singleton_method(Berns, "ul", external_ul_element, -1);
783
+ rb_define_singleton_method(Berns, "var", external_var_element, -1);
784
+ rb_define_singleton_method(Berns, "video", external_video_element, -1);
1062
785
  }