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