hamlit 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +47 -0
  4. data/CHANGELOG.md +702 -0
  5. data/Gemfile +30 -0
  6. data/LICENSE.txt +44 -0
  7. data/README.md +150 -0
  8. data/REFERENCE.md +272 -0
  9. data/Rakefile +117 -0
  10. data/benchmark/boolean_attribute.haml +6 -0
  11. data/benchmark/class_attribute.haml +5 -0
  12. data/benchmark/common_attribute.haml +3 -0
  13. data/benchmark/data_attribute.haml +4 -0
  14. data/benchmark/dynamic_attributes/boolean_attribute.haml +4 -0
  15. data/benchmark/dynamic_attributes/class_attribute.haml +4 -0
  16. data/benchmark/dynamic_attributes/common_attribute.haml +2 -0
  17. data/benchmark/dynamic_attributes/data_attribute.haml +2 -0
  18. data/benchmark/dynamic_attributes/id_attribute.haml +2 -0
  19. data/benchmark/dynamic_boolean_attribute.haml +4 -0
  20. data/benchmark/dynamic_merger/benchmark.rb +25 -0
  21. data/benchmark/dynamic_merger/hello.haml +50 -0
  22. data/benchmark/dynamic_merger/hello.string +50 -0
  23. data/benchmark/etc/attribute_builder.haml +5 -0
  24. data/benchmark/etc/real_sample.haml +888 -0
  25. data/benchmark/etc/real_sample.rb +11 -0
  26. data/benchmark/etc/static_analyzer.haml +1 -0
  27. data/benchmark/etc/string_interpolation.haml +2 -0
  28. data/benchmark/etc/tags.haml +3 -0
  29. data/benchmark/etc/tags_loop.haml +2 -0
  30. data/benchmark/ext/build_data.rb +17 -0
  31. data/benchmark/ext/build_id.rb +13 -0
  32. data/benchmark/id_attribute.haml +3 -0
  33. data/benchmark/plain.haml +4 -0
  34. data/benchmark/script.haml +4 -0
  35. data/benchmark/slim/LICENSE +21 -0
  36. data/benchmark/slim/context.rb +11 -0
  37. data/benchmark/slim/run-benchmarks.rb +94 -0
  38. data/benchmark/slim/view.erb +23 -0
  39. data/benchmark/slim/view.haml +18 -0
  40. data/benchmark/slim/view.slim +17 -0
  41. data/benchmark/utils/benchmark_ips_extension.rb +43 -0
  42. data/bin/bench +77 -0
  43. data/bin/console +11 -0
  44. data/bin/ruby +3 -0
  45. data/bin/setup +7 -0
  46. data/bin/stackprof +27 -0
  47. data/bin/test +24 -0
  48. data/exe/hamlit +6 -0
  49. data/ext/hamlit/extconf.rb +10 -0
  50. data/ext/hamlit/hamlit.c +555 -0
  51. data/ext/hamlit/hescape.c +108 -0
  52. data/ext/hamlit/hescape.h +20 -0
  53. data/hamlit.gemspec +47 -0
  54. data/lib/hamlit.rb +11 -0
  55. data/lib/hamlit/attribute_builder.rb +175 -0
  56. data/lib/hamlit/attribute_compiler.rb +125 -0
  57. data/lib/hamlit/attribute_parser.rb +110 -0
  58. data/lib/hamlit/cli.rb +130 -0
  59. data/lib/hamlit/compiler.rb +97 -0
  60. data/lib/hamlit/compiler/children_compiler.rb +112 -0
  61. data/lib/hamlit/compiler/comment_compiler.rb +36 -0
  62. data/lib/hamlit/compiler/doctype_compiler.rb +46 -0
  63. data/lib/hamlit/compiler/script_compiler.rb +106 -0
  64. data/lib/hamlit/compiler/silent_script_compiler.rb +24 -0
  65. data/lib/hamlit/compiler/tag_compiler.rb +76 -0
  66. data/lib/hamlit/dynamic_merger.rb +67 -0
  67. data/lib/hamlit/engine.rb +38 -0
  68. data/lib/hamlit/error.rb +15 -0
  69. data/lib/hamlit/escapable.rb +13 -0
  70. data/lib/hamlit/filters.rb +75 -0
  71. data/lib/hamlit/filters/base.rb +12 -0
  72. data/lib/hamlit/filters/cdata.rb +20 -0
  73. data/lib/hamlit/filters/coffee.rb +17 -0
  74. data/lib/hamlit/filters/css.rb +33 -0
  75. data/lib/hamlit/filters/erb.rb +10 -0
  76. data/lib/hamlit/filters/escaped.rb +22 -0
  77. data/lib/hamlit/filters/javascript.rb +33 -0
  78. data/lib/hamlit/filters/less.rb +20 -0
  79. data/lib/hamlit/filters/markdown.rb +10 -0
  80. data/lib/hamlit/filters/plain.rb +29 -0
  81. data/lib/hamlit/filters/preserve.rb +22 -0
  82. data/lib/hamlit/filters/ruby.rb +10 -0
  83. data/lib/hamlit/filters/sass.rb +15 -0
  84. data/lib/hamlit/filters/scss.rb +15 -0
  85. data/lib/hamlit/filters/text_base.rb +25 -0
  86. data/lib/hamlit/filters/tilt_base.rb +49 -0
  87. data/lib/hamlit/force_escapable.rb +29 -0
  88. data/lib/hamlit/helpers.rb +15 -0
  89. data/lib/hamlit/html.rb +14 -0
  90. data/lib/hamlit/identity.rb +13 -0
  91. data/lib/hamlit/object_ref.rb +30 -0
  92. data/lib/hamlit/parser.rb +49 -0
  93. data/lib/hamlit/parser/MIT-LICENSE +20 -0
  94. data/lib/hamlit/parser/README.md +30 -0
  95. data/lib/hamlit/parser/haml_buffer.rb +348 -0
  96. data/lib/hamlit/parser/haml_compiler.rb +553 -0
  97. data/lib/hamlit/parser/haml_error.rb +61 -0
  98. data/lib/hamlit/parser/haml_helpers.rb +727 -0
  99. data/lib/hamlit/parser/haml_options.rb +286 -0
  100. data/lib/hamlit/parser/haml_parser.rb +800 -0
  101. data/lib/hamlit/parser/haml_util.rb +288 -0
  102. data/lib/hamlit/parser/haml_xss_mods.rb +109 -0
  103. data/lib/hamlit/rails_helpers.rb +51 -0
  104. data/lib/hamlit/rails_template.rb +59 -0
  105. data/lib/hamlit/railtie.rb +10 -0
  106. data/lib/hamlit/ruby_expression.rb +32 -0
  107. data/lib/hamlit/string_splitter.rb +19 -0
  108. data/lib/hamlit/template.rb +28 -0
  109. data/lib/hamlit/utils.rb +20 -0
  110. data/lib/hamlit/version.rb +4 -0
  111. metadata +392 -0
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+
3
+ VERSIONS=(
4
+ 2.1.10
5
+ 2.2.5
6
+ 2.3.1
7
+ )
8
+
9
+ set -e
10
+ trap 'echo "${VERSIONS[2]}" > .ruby-version' 0
11
+
12
+ function test_with() {
13
+ version=$1
14
+ rbenv local $version
15
+ if ! bundle check > /dev/null; then
16
+ bundle install
17
+ fi
18
+ ruby -v
19
+ bundle exec rake test
20
+ }
21
+
22
+ for version in ${VERSIONS[@]}; do
23
+ test_with $version
24
+ done
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+ require 'hamlit/cli'
5
+
6
+ Hamlit::CLI.start(ARGV)
@@ -0,0 +1,10 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << ' -Wall -Wextra'
4
+
5
+ $srcs = %w[
6
+ hamlit.c
7
+ hescape.c
8
+ ]
9
+
10
+ create_makefile('hamlit/hamlit')
@@ -0,0 +1,555 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #ifndef TRUFFLERUBY
4
+ #include "hescape.h"
5
+ #include "string.h"
6
+
7
+ VALUE mAttributeBuilder, mObjectRef;
8
+ static ID id_flatten, id_keys, id_parse, id_prepend, id_tr, id_uniq_bang;
9
+ static ID id_aria, id_data, id_equal, id_hyphen, id_space, id_underscore;
10
+ static ID id_boolean_attributes, id_xhtml;
11
+
12
+ static VALUE str_aria() { return rb_const_get(mAttributeBuilder, id_aria); }
13
+ static VALUE str_data() { return rb_const_get(mAttributeBuilder, id_data); }
14
+ static VALUE str_equal() { return rb_const_get(mAttributeBuilder, id_equal); }
15
+ static VALUE str_hyphen() { return rb_const_get(mAttributeBuilder, id_hyphen); }
16
+ static VALUE str_space() { return rb_const_get(mAttributeBuilder, id_space); }
17
+ static VALUE str_underscore() { return rb_const_get(mAttributeBuilder, id_underscore); }
18
+
19
+ static void
20
+ delete_falsey_values(VALUE values)
21
+ {
22
+ VALUE value;
23
+ long i;
24
+
25
+ for (i = RARRAY_LEN(values) - 1; 0 <= i; i--) {
26
+ value = rb_ary_entry(values, i);
27
+ if (!RTEST(value)) {
28
+ rb_ary_delete_at(values, i);
29
+ }
30
+ }
31
+ }
32
+
33
+ static int
34
+ str_eq(VALUE str, const char *cstr, long n)
35
+ {
36
+ return RSTRING_LEN(str) == n && memcmp(RSTRING_PTR(str), cstr, n) == 0;
37
+ }
38
+
39
+ static VALUE
40
+ to_s(VALUE value)
41
+ {
42
+ return rb_convert_type(value, T_STRING, "String", "to_s");
43
+ }
44
+
45
+ static VALUE
46
+ hyphenate(VALUE str)
47
+ {
48
+ long i;
49
+
50
+ if (OBJ_FROZEN(str)) str = rb_str_dup(str);
51
+
52
+ for (i = 0; i < RSTRING_LEN(str); i++) {
53
+ if (RSTRING_PTR(str)[i] == '_') {
54
+ rb_str_update(str, i, 1, str_hyphen());
55
+ }
56
+ }
57
+ return str;
58
+ }
59
+
60
+ static VALUE
61
+ escape_html(VALUE str)
62
+ {
63
+ char *buf;
64
+ unsigned int size;
65
+ Check_Type(str, T_STRING);
66
+
67
+ size = hesc_escape_html(&buf, RSTRING_PTR(str), RSTRING_LEN(str));
68
+ if (size > RSTRING_LEN(str)) {
69
+ str = rb_enc_str_new(buf, size, rb_utf8_encoding());
70
+ free((void *)buf);
71
+ }
72
+
73
+ return str;
74
+ }
75
+
76
+ static VALUE
77
+ escape_attribute(VALUE escape_attrs, VALUE str)
78
+ {
79
+ if (RTEST(escape_attrs)) {
80
+ return escape_html(str);
81
+ } else {
82
+ return str;
83
+ }
84
+ }
85
+
86
+ static VALUE
87
+ rb_escape_html(RB_UNUSED_VAR(VALUE self), VALUE value)
88
+ {
89
+ return escape_html(to_s(value));
90
+ }
91
+
92
+ static VALUE
93
+ hamlit_build_id(VALUE escape_attrs, VALUE values)
94
+ {
95
+ VALUE attr_value;
96
+
97
+ values = rb_funcall(values, id_flatten, 0);
98
+ delete_falsey_values(values);
99
+
100
+ attr_value = rb_ary_join(values, str_underscore());
101
+ return escape_attribute(escape_attrs, attr_value);
102
+ }
103
+
104
+ static VALUE
105
+ hamlit_build_single_class(VALUE escape_attrs, VALUE value)
106
+ {
107
+ switch (TYPE(value)) {
108
+ case T_STRING:
109
+ break;
110
+ case T_ARRAY:
111
+ value = rb_funcall(value, id_flatten, 0);
112
+ delete_falsey_values(value);
113
+ value = rb_ary_join(value, str_space());
114
+ break;
115
+ default:
116
+ if (RTEST(value)) {
117
+ value = to_s(value);
118
+ } else {
119
+ return rb_str_new_cstr("");
120
+ }
121
+ break;
122
+ }
123
+ return escape_attribute(escape_attrs, value);
124
+ }
125
+
126
+ static VALUE
127
+ hamlit_build_multi_class(VALUE escape_attrs, VALUE values)
128
+ {
129
+ long i, j;
130
+ VALUE value, buf;
131
+
132
+ buf = rb_ary_new2(RARRAY_LEN(values));
133
+
134
+ for (i = 0; i < RARRAY_LEN(values); i++) {
135
+ value = rb_ary_entry(values, i);
136
+ switch (TYPE(value)) {
137
+ case T_STRING:
138
+ rb_ary_concat(buf, rb_str_split(value, " "));
139
+ break;
140
+ case T_ARRAY:
141
+ value = rb_funcall(value, id_flatten, 0);
142
+ delete_falsey_values(value);
143
+ for (j = 0; j < RARRAY_LEN(value); j++) {
144
+ rb_ary_push(buf, to_s(rb_ary_entry(value, j)));
145
+ }
146
+ break;
147
+ default:
148
+ if (RTEST(value)) {
149
+ rb_ary_push(buf, to_s(value));
150
+ }
151
+ break;
152
+ }
153
+ }
154
+
155
+ rb_ary_sort_bang(buf);
156
+ rb_funcall(buf, id_uniq_bang, 0);
157
+
158
+ return escape_attribute(escape_attrs, rb_ary_join(buf, str_space()));
159
+ }
160
+
161
+ static VALUE
162
+ hamlit_build_class(VALUE escape_attrs, VALUE array)
163
+ {
164
+ if (RARRAY_LEN(array) == 1) {
165
+ return hamlit_build_single_class(escape_attrs, rb_ary_entry(array, 0));
166
+ } else {
167
+ return hamlit_build_multi_class(escape_attrs, array);
168
+ }
169
+ }
170
+
171
+ struct merge_data_attrs_var {
172
+ VALUE merged;
173
+ VALUE key_str;
174
+ };
175
+
176
+ static int
177
+ merge_data_attrs_i(VALUE key, VALUE value, VALUE ptr)
178
+ {
179
+ struct merge_data_attrs_var *arg = (struct merge_data_attrs_var *)ptr;
180
+ VALUE merged = arg->merged;
181
+ VALUE key_str = arg->key_str;
182
+
183
+ if (NIL_P(key)) {
184
+ rb_hash_aset(merged, key_str, value);
185
+ } else {
186
+ key = rb_str_concat(rb_str_concat(rb_str_dup(key_str), rb_str_new_cstr("-")), to_s(key));
187
+ rb_hash_aset(merged, key, value);
188
+ }
189
+ return ST_CONTINUE;
190
+ }
191
+
192
+ static VALUE
193
+ merge_data_attrs(VALUE values, VALUE key_str)
194
+ {
195
+ long i;
196
+ VALUE value, merged = rb_hash_new();
197
+
198
+ for (i = 0; i < RARRAY_LEN(values); i++) {
199
+ struct merge_data_attrs_var arg;
200
+ arg.merged = merged;
201
+ arg.key_str = key_str;
202
+
203
+ value = rb_ary_entry(values, i);
204
+ switch (TYPE(value)) {
205
+ case T_HASH:
206
+ rb_hash_foreach(value, merge_data_attrs_i, (VALUE)&arg);
207
+ break;
208
+ default:
209
+ rb_hash_aset(merged, key_str, value);
210
+ break;
211
+ }
212
+ }
213
+ return merged;
214
+ }
215
+
216
+ struct flatten_data_attrs_i2_arg {
217
+ VALUE flattened;
218
+ VALUE key;
219
+ };
220
+
221
+ static int
222
+ flatten_data_attrs_i2(VALUE k, VALUE v, VALUE ptr)
223
+ {
224
+ VALUE key;
225
+ struct flatten_data_attrs_i2_arg *arg = (struct flatten_data_attrs_i2_arg *)ptr;
226
+
227
+ if (!RTEST(v)) return ST_CONTINUE;
228
+
229
+ if (k == Qnil) {
230
+ rb_hash_aset(arg->flattened, arg->key, v);
231
+ } else {
232
+ key = rb_str_dup(arg->key);
233
+ rb_str_cat(key, "-", 1);
234
+ rb_str_concat(key, to_s(k));
235
+
236
+ rb_hash_aset(arg->flattened, key, v);
237
+ }
238
+ return ST_CONTINUE;
239
+ }
240
+
241
+ static VALUE flatten_data_attrs(VALUE attrs);
242
+
243
+ static int
244
+ flatten_data_attrs_i(VALUE key, VALUE value, VALUE flattened)
245
+ {
246
+ struct flatten_data_attrs_i2_arg arg;
247
+ key = hyphenate(to_s(key));
248
+
249
+ switch (TYPE(value)) {
250
+ case T_HASH:
251
+ value = flatten_data_attrs(value);
252
+ arg.key = key;
253
+ arg.flattened = flattened;
254
+ rb_hash_foreach(value, flatten_data_attrs_i2, (VALUE)(&arg));
255
+ break;
256
+ default:
257
+ if (RTEST(value)) rb_hash_aset(flattened, key, value);
258
+ break;
259
+ }
260
+ return ST_CONTINUE;
261
+ }
262
+
263
+ static VALUE
264
+ flatten_data_attrs(VALUE attrs)
265
+ {
266
+ VALUE flattened = rb_hash_new();
267
+ rb_hash_foreach(attrs, flatten_data_attrs_i, flattened);
268
+
269
+ return flattened;
270
+ }
271
+
272
+ static VALUE
273
+ hamlit_build_data(VALUE escape_attrs, VALUE quote, VALUE values, VALUE key_str)
274
+ {
275
+ long i;
276
+ VALUE attrs, buf, keys, key, value;
277
+
278
+ attrs = merge_data_attrs(values, key_str);
279
+ attrs = flatten_data_attrs(attrs);
280
+ keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
281
+ buf = rb_str_new("", 0);
282
+
283
+ for (i = 0; i < RARRAY_LEN(keys); i++) {
284
+ key = rb_ary_entry(keys, i);
285
+ value = rb_hash_aref(attrs, key);
286
+
287
+ switch (value) {
288
+ case Qtrue:
289
+ rb_str_concat(buf, str_space());
290
+ rb_str_concat(buf, key);
291
+ break;
292
+ case Qnil:
293
+ break; // noop
294
+ case Qfalse:
295
+ break; // noop
296
+ default:
297
+ rb_str_concat(buf, str_space());
298
+ rb_str_concat(buf, key);
299
+ rb_str_concat(buf, str_equal());
300
+ rb_str_concat(buf, quote);
301
+ rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value)));
302
+ rb_str_concat(buf, quote);
303
+ break;
304
+ }
305
+ }
306
+
307
+ return buf;
308
+ }
309
+
310
+ static VALUE
311
+ parse_object_ref(VALUE object_ref)
312
+ {
313
+ return rb_funcall(mObjectRef, id_parse, 1, object_ref);
314
+ }
315
+
316
+ static int
317
+ merge_all_attrs_i(VALUE key, VALUE value, VALUE merged)
318
+ {
319
+ VALUE array;
320
+
321
+ key = to_s(key);
322
+ if (str_eq(key, "id", 2) || str_eq(key, "class", 5) || str_eq(key, "data", 4) || str_eq(key, "aria", 4)) {
323
+ array = rb_hash_aref(merged, key);
324
+ if (NIL_P(array)) {
325
+ array = rb_ary_new2(1);
326
+ rb_hash_aset(merged, key, array);
327
+ }
328
+ rb_ary_push(array, value);
329
+ } else {
330
+ rb_hash_aset(merged, key, value);
331
+ }
332
+ return ST_CONTINUE;
333
+ }
334
+
335
+ static VALUE
336
+ merge_all_attrs(VALUE hashes)
337
+ {
338
+ long i;
339
+ VALUE hash, merged = rb_hash_new();
340
+
341
+ for (i = 0; i < RARRAY_LEN(hashes); i++) {
342
+ hash = rb_ary_entry(hashes, i);
343
+ if (!RB_TYPE_P(hash, T_HASH)) {
344
+ rb_raise(rb_eArgError, "Non-hash object is given to attributes!");
345
+ }
346
+ rb_hash_foreach(hash, merge_all_attrs_i, merged);
347
+ }
348
+ return merged;
349
+ }
350
+
351
+ int
352
+ is_boolean_attribute(VALUE key)
353
+ {
354
+ VALUE boolean_attributes;
355
+ if (str_eq(rb_str_substr(key, 0, 5), "data-", 5)) return 1;
356
+ if (str_eq(rb_str_substr(key, 0, 5), "aria-", 5)) return 1;
357
+
358
+ boolean_attributes = rb_const_get(mAttributeBuilder, id_boolean_attributes);
359
+ return RTEST(rb_ary_includes(boolean_attributes, key));
360
+ }
361
+
362
+ void
363
+ hamlit_build_for_id(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
364
+ {
365
+ rb_str_cat(buf, " id=", 4);
366
+ rb_str_concat(buf, quote);
367
+ rb_str_concat(buf, hamlit_build_id(escape_attrs, values));
368
+ rb_str_concat(buf, quote);
369
+ }
370
+
371
+ void
372
+ hamlit_build_for_class(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
373
+ {
374
+ rb_str_cat(buf, " class=", 7);
375
+ rb_str_concat(buf, quote);
376
+ rb_str_concat(buf, hamlit_build_class(escape_attrs, values));
377
+ rb_str_concat(buf, quote);
378
+ }
379
+
380
+ void
381
+ hamlit_build_for_data(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
382
+ {
383
+ rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_data()));
384
+ }
385
+
386
+ void
387
+ hamlit_build_for_aria(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
388
+ {
389
+ rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_aria()));
390
+ }
391
+
392
+ void
393
+ hamlit_build_for_others(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE key, VALUE value)
394
+ {
395
+ rb_str_cat(buf, " ", 1);
396
+ rb_str_concat(buf, key);
397
+ rb_str_cat(buf, "=", 1);
398
+ rb_str_concat(buf, quote);
399
+ rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value)));
400
+ rb_str_concat(buf, quote);
401
+ }
402
+
403
+ void
404
+ hamlit_build_for_boolean(VALUE escape_attrs, VALUE quote, VALUE format, VALUE buf, VALUE key, VALUE value)
405
+ {
406
+ switch (value) {
407
+ case Qtrue:
408
+ rb_str_cat(buf, " ", 1);
409
+ rb_str_concat(buf, key);
410
+ if ((TYPE(format) == T_SYMBOL || TYPE(format) == T_STRING) && rb_to_id(format) == id_xhtml) {
411
+ rb_str_cat(buf, "=", 1);
412
+ rb_str_concat(buf, quote);
413
+ rb_str_concat(buf, key);
414
+ rb_str_concat(buf, quote);
415
+ }
416
+ break;
417
+ case Qfalse:
418
+ break; // noop
419
+ case Qnil:
420
+ break; // noop
421
+ default:
422
+ hamlit_build_for_others(escape_attrs, quote, buf, key, value);
423
+ break;
424
+ }
425
+ }
426
+
427
+ static VALUE
428
+ hamlit_build(VALUE escape_attrs, VALUE quote, VALUE format, VALUE object_ref, VALUE hashes)
429
+ {
430
+ long i;
431
+ VALUE attrs, buf, key, keys, value;
432
+
433
+ if (!NIL_P(object_ref)) rb_ary_push(hashes, parse_object_ref(object_ref));
434
+ attrs = merge_all_attrs(hashes);
435
+ buf = rb_str_new("", 0);
436
+ keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
437
+
438
+ for (i = 0; i < RARRAY_LEN(keys); i++) {
439
+ key = rb_ary_entry(keys, i);
440
+ value = rb_hash_aref(attrs, key);
441
+ if (str_eq(key, "id", 2)) {
442
+ hamlit_build_for_id(escape_attrs, quote, buf, value);
443
+ } else if (str_eq(key, "class", 5)) {
444
+ hamlit_build_for_class(escape_attrs, quote, buf, value);
445
+ } else if (str_eq(key, "data", 4)) {
446
+ hamlit_build_for_data(escape_attrs, quote, buf, value);
447
+ } else if (str_eq(key, "aria", 4)) {
448
+ hamlit_build_for_aria(escape_attrs, quote, buf, value);
449
+ } else if (is_boolean_attribute(key)) {
450
+ hamlit_build_for_boolean(escape_attrs, quote, format, buf, key, value);
451
+ } else {
452
+ hamlit_build_for_others(escape_attrs, quote, buf, key, value);
453
+ }
454
+ }
455
+
456
+ return buf;
457
+ }
458
+
459
+ static VALUE
460
+ rb_hamlit_build_id(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
461
+ {
462
+ VALUE array;
463
+
464
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
465
+ rb_scan_args(argc - 1, argv + 1, "*", &array);
466
+
467
+ return hamlit_build_id(argv[0], array);
468
+ }
469
+
470
+ static VALUE
471
+ rb_hamlit_build_class(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
472
+ {
473
+ VALUE array;
474
+
475
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
476
+ rb_scan_args(argc - 1, argv + 1, "*", &array);
477
+
478
+ return hamlit_build_class(argv[0], array);
479
+ }
480
+
481
+ static VALUE
482
+ rb_hamlit_build_aria(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
483
+ {
484
+ VALUE array;
485
+
486
+ rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
487
+ rb_scan_args(argc - 2, argv + 2, "*", &array);
488
+
489
+ return hamlit_build_data(argv[0], argv[1], array, str_aria());
490
+ }
491
+
492
+ static VALUE
493
+ rb_hamlit_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
494
+ {
495
+ VALUE array;
496
+
497
+ rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
498
+ rb_scan_args(argc - 2, argv + 2, "*", &array);
499
+
500
+ return hamlit_build_data(argv[0], argv[1], array, str_data());
501
+ }
502
+
503
+ static VALUE
504
+ rb_hamlit_build(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
505
+ {
506
+ VALUE array;
507
+
508
+ rb_check_arity(argc, 4, UNLIMITED_ARGUMENTS);
509
+ rb_scan_args(argc - 4, argv + 4, "*", &array);
510
+
511
+ return hamlit_build(argv[0], argv[1], argv[2], argv[3], array);
512
+ }
513
+
514
+ void
515
+ Init_hamlit(void)
516
+ {
517
+ VALUE mHamlit, mUtils;
518
+
519
+ mHamlit = rb_define_module("Hamlit");
520
+ mObjectRef = rb_define_module_under(mHamlit, "ObjectRef");
521
+ mUtils = rb_define_module_under(mHamlit, "Utils");
522
+ mAttributeBuilder = rb_define_module_under(mHamlit, "AttributeBuilder");
523
+
524
+ rb_define_singleton_method(mUtils, "escape_html", rb_escape_html, 1);
525
+ rb_define_singleton_method(mAttributeBuilder, "build", rb_hamlit_build, -1);
526
+ rb_define_singleton_method(mAttributeBuilder, "build_id", rb_hamlit_build_id, -1);
527
+ rb_define_singleton_method(mAttributeBuilder, "build_class", rb_hamlit_build_class, -1);
528
+ rb_define_singleton_method(mAttributeBuilder, "build_aria", rb_hamlit_build_aria, -1);
529
+ rb_define_singleton_method(mAttributeBuilder, "build_data", rb_hamlit_build_data, -1);
530
+
531
+ id_flatten = rb_intern("flatten");
532
+ id_keys = rb_intern("keys");
533
+ id_parse = rb_intern("parse");
534
+ id_prepend = rb_intern("prepend");
535
+ id_tr = rb_intern("tr");
536
+ id_uniq_bang = rb_intern("uniq!");
537
+
538
+ id_aria = rb_intern("ARIA");
539
+ id_data = rb_intern("DATA");
540
+ id_equal = rb_intern("EQUAL");
541
+ id_hyphen = rb_intern("HYPHEN");
542
+ id_space = rb_intern("SPACE");
543
+ id_underscore = rb_intern("UNDERSCORE");
544
+
545
+ id_boolean_attributes = rb_intern("BOOLEAN_ATTRIBUTES");
546
+ id_xhtml = rb_intern("xhtml");
547
+
548
+ rb_const_set(mAttributeBuilder, id_aria, rb_obj_freeze(rb_str_new_cstr("aria")));
549
+ rb_const_set(mAttributeBuilder, id_data, rb_obj_freeze(rb_str_new_cstr("data")));
550
+ rb_const_set(mAttributeBuilder, id_equal, rb_obj_freeze(rb_str_new_cstr("=")));
551
+ rb_const_set(mAttributeBuilder, id_hyphen, rb_obj_freeze(rb_str_new_cstr("-")));
552
+ rb_const_set(mAttributeBuilder, id_space, rb_obj_freeze(rb_str_new_cstr(" ")));
553
+ rb_const_set(mAttributeBuilder, id_underscore, rb_obj_freeze(rb_str_new_cstr("_")));
554
+ }
555
+ #endif