berns 3.0.4 → 3.1.2

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