haml 5.2.2 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.github/FUNDING.yml +1 -0
 - data/.github/workflows/test.yml +13 -9
 - data/.gitignore +16 -16
 - data/CHANGELOG.md +14 -3
 - data/Gemfile +18 -11
 - data/MIT-LICENSE +1 -1
 - data/README.md +13 -19
 - data/Rakefile +94 -93
 - data/bin/bench +66 -0
 - data/bin/console +11 -0
 - data/bin/ruby +3 -0
 - data/bin/setup +7 -0
 - data/bin/stackprof +27 -0
 - data/bin/test +24 -0
 - data/exe/haml +6 -0
 - data/ext/haml/extconf.rb +10 -0
 - data/ext/haml/haml.c +537 -0
 - data/ext/haml/hescape.c +108 -0
 - data/ext/haml/hescape.h +20 -0
 - data/haml.gemspec +39 -37
 - data/lib/haml/ambles.rb +20 -0
 - data/lib/haml/attribute_builder.rb +135 -179
 - data/lib/haml/attribute_compiler.rb +85 -194
 - data/lib/haml/attribute_parser.rb +86 -126
 - data/lib/haml/cli.rb +154 -0
 - data/lib/haml/compiler/children_compiler.rb +126 -0
 - data/lib/haml/compiler/comment_compiler.rb +39 -0
 - data/lib/haml/compiler/doctype_compiler.rb +46 -0
 - data/lib/haml/compiler/script_compiler.rb +116 -0
 - data/lib/haml/compiler/silent_script_compiler.rb +24 -0
 - data/lib/haml/compiler/tag_compiler.rb +76 -0
 - data/lib/haml/compiler.rb +63 -296
 - data/lib/haml/dynamic_merger.rb +67 -0
 - data/lib/haml/engine.rb +42 -227
 - data/lib/haml/error.rb +5 -4
 - data/lib/haml/escapable.rb +6 -70
 - data/lib/haml/filters/base.rb +12 -0
 - data/lib/haml/filters/cdata.rb +20 -0
 - data/lib/haml/filters/coffee.rb +17 -0
 - data/lib/haml/filters/css.rb +33 -0
 - data/lib/haml/filters/erb.rb +10 -0
 - data/lib/haml/filters/escaped.rb +22 -0
 - data/lib/haml/filters/javascript.rb +33 -0
 - data/lib/haml/filters/less.rb +20 -0
 - data/lib/haml/filters/markdown.rb +11 -0
 - data/lib/haml/filters/plain.rb +29 -0
 - data/lib/haml/filters/preserve.rb +22 -0
 - data/lib/haml/filters/ruby.rb +10 -0
 - data/lib/haml/filters/sass.rb +15 -0
 - data/lib/haml/filters/scss.rb +15 -0
 - data/lib/haml/filters/text_base.rb +25 -0
 - data/lib/haml/filters/tilt_base.rb +49 -0
 - data/lib/haml/filters.rb +54 -378
 - data/lib/haml/force_escapable.rb +29 -0
 - data/lib/haml/helpers.rb +3 -697
 - data/lib/haml/html.rb +22 -0
 - data/lib/haml/identity.rb +13 -0
 - data/lib/haml/object_ref.rb +30 -0
 - data/lib/haml/parser.rb +157 -22
 - data/lib/haml/rails_helpers.rb +51 -0
 - data/lib/haml/rails_template.rb +55 -0
 - data/lib/haml/railtie.rb +7 -45
 - data/lib/haml/ruby_expression.rb +32 -0
 - data/lib/haml/string_splitter.rb +20 -0
 - data/lib/haml/template.rb +15 -34
 - data/lib/haml/temple_line_counter.rb +2 -1
 - data/lib/haml/util.rb +17 -15
 - data/lib/haml/version.rb +1 -2
 - data/lib/haml.rb +8 -20
 - metadata +205 -52
 - data/.gitmodules +0 -3
 - data/.yardopts +0 -22
 - data/TODO +0 -24
 - data/benchmark.rb +0 -70
 - data/bin/haml +0 -9
 - data/lib/haml/.gitattributes +0 -1
 - data/lib/haml/buffer.rb +0 -182
 - data/lib/haml/exec.rb +0 -347
 - data/lib/haml/generator.rb +0 -42
 - data/lib/haml/helpers/action_view_extensions.rb +0 -60
 - data/lib/haml/helpers/action_view_mods.rb +0 -132
 - data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
 - data/lib/haml/helpers/safe_erubi_template.rb +0 -20
 - data/lib/haml/helpers/safe_erubis_template.rb +0 -33
 - data/lib/haml/helpers/xss_mods.rb +0 -114
 - data/lib/haml/options.rb +0 -273
 - data/lib/haml/plugin.rb +0 -54
 - data/lib/haml/sass_rails_filter.rb +0 -47
 - data/lib/haml/template/options.rb +0 -27
 - data/lib/haml/temple_engine.rb +0 -124
 - data/yard/default/.gitignore +0 -1
 - data/yard/default/fulldoc/html/css/common.sass +0 -15
 - data/yard/default/layout/html/footer.erb +0 -12
 
    
        data/ext/haml/haml.c
    ADDED
    
    | 
         @@ -0,0 +1,537 @@ 
     | 
|
| 
      
 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_xhtml;
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            static VALUE str_aria, str_data, str_equal, str_hyphen, str_space, str_underscore;
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            static void
         
     | 
| 
      
 14 
     | 
    
         
            +
            delete_falsey_values(VALUE values)
         
     | 
| 
      
 15 
     | 
    
         
            +
            {
         
     | 
| 
      
 16 
     | 
    
         
            +
              VALUE value;
         
     | 
| 
      
 17 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              for (i = RARRAY_LEN(values) - 1; 0 <= i; i--) {
         
     | 
| 
      
 20 
     | 
    
         
            +
                value = rb_ary_entry(values, i);
         
     | 
| 
      
 21 
     | 
    
         
            +
                if (!RTEST(value)) {
         
     | 
| 
      
 22 
     | 
    
         
            +
                  rb_ary_delete_at(values, i);
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
              }
         
     | 
| 
      
 25 
     | 
    
         
            +
            }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            static int
         
     | 
| 
      
 28 
     | 
    
         
            +
            str_eq(VALUE str, const char *cstr, long n)
         
     | 
| 
      
 29 
     | 
    
         
            +
            {
         
     | 
| 
      
 30 
     | 
    
         
            +
              return RSTRING_LEN(str) == n && memcmp(RSTRING_PTR(str), cstr, n) == 0;
         
     | 
| 
      
 31 
     | 
    
         
            +
            }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 34 
     | 
    
         
            +
            to_s(VALUE value)
         
     | 
| 
      
 35 
     | 
    
         
            +
            {
         
     | 
| 
      
 36 
     | 
    
         
            +
              return rb_convert_type(value, T_STRING, "String", "to_s");
         
     | 
| 
      
 37 
     | 
    
         
            +
            }
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 40 
     | 
    
         
            +
            hyphenate(VALUE str)
         
     | 
| 
      
 41 
     | 
    
         
            +
            {
         
     | 
| 
      
 42 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              if (OBJ_FROZEN(str)) str = rb_str_dup(str);
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              for (i = 0; i < RSTRING_LEN(str); i++) {
         
     | 
| 
      
 47 
     | 
    
         
            +
                if (RSTRING_PTR(str)[i] == '_') {
         
     | 
| 
      
 48 
     | 
    
         
            +
                  rb_str_update(str, i, 1, str_hyphen);
         
     | 
| 
      
 49 
     | 
    
         
            +
                }
         
     | 
| 
      
 50 
     | 
    
         
            +
              }
         
     | 
| 
      
 51 
     | 
    
         
            +
              return str;
         
     | 
| 
      
 52 
     | 
    
         
            +
            }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 55 
     | 
    
         
            +
            escape_html(VALUE str)
         
     | 
| 
      
 56 
     | 
    
         
            +
            {
         
     | 
| 
      
 57 
     | 
    
         
            +
              char *buf;
         
     | 
| 
      
 58 
     | 
    
         
            +
              unsigned int size;
         
     | 
| 
      
 59 
     | 
    
         
            +
              Check_Type(str, T_STRING);
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              size = hesc_escape_html(&buf, RSTRING_PTR(str), RSTRING_LEN(str));
         
     | 
| 
      
 62 
     | 
    
         
            +
              if (size > RSTRING_LEN(str)) {
         
     | 
| 
      
 63 
     | 
    
         
            +
                str = rb_enc_str_new(buf, size, rb_utf8_encoding());
         
     | 
| 
      
 64 
     | 
    
         
            +
                free((void *)buf);
         
     | 
| 
      
 65 
     | 
    
         
            +
              }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              return str;
         
     | 
| 
      
 68 
     | 
    
         
            +
            }
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 71 
     | 
    
         
            +
            escape_attribute(VALUE escape_attrs, VALUE str)
         
     | 
| 
      
 72 
     | 
    
         
            +
            {
         
     | 
| 
      
 73 
     | 
    
         
            +
              if (RTEST(escape_attrs)) {
         
     | 
| 
      
 74 
     | 
    
         
            +
                return escape_html(str);
         
     | 
| 
      
 75 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 76 
     | 
    
         
            +
                return str;
         
     | 
| 
      
 77 
     | 
    
         
            +
              }
         
     | 
| 
      
 78 
     | 
    
         
            +
            }
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 81 
     | 
    
         
            +
            rb_escape_html(RB_UNUSED_VAR(VALUE self), VALUE value)
         
     | 
| 
      
 82 
     | 
    
         
            +
            {
         
     | 
| 
      
 83 
     | 
    
         
            +
              return escape_html(to_s(value));
         
     | 
| 
      
 84 
     | 
    
         
            +
            }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 87 
     | 
    
         
            +
            haml_build_id(VALUE escape_attrs, VALUE values)
         
     | 
| 
      
 88 
     | 
    
         
            +
            {
         
     | 
| 
      
 89 
     | 
    
         
            +
              VALUE attr_value;
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              values = rb_funcall(values, id_flatten, 0);
         
     | 
| 
      
 92 
     | 
    
         
            +
              delete_falsey_values(values);
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
              attr_value = rb_ary_join(values, str_underscore);
         
     | 
| 
      
 95 
     | 
    
         
            +
              return escape_attribute(escape_attrs, attr_value);
         
     | 
| 
      
 96 
     | 
    
         
            +
            }
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 99 
     | 
    
         
            +
            haml_build_single_class(VALUE escape_attrs, VALUE value)
         
     | 
| 
      
 100 
     | 
    
         
            +
            {
         
     | 
| 
      
 101 
     | 
    
         
            +
              switch (TYPE(value)) {
         
     | 
| 
      
 102 
     | 
    
         
            +
                case T_STRING:
         
     | 
| 
      
 103 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 104 
     | 
    
         
            +
                case T_ARRAY:
         
     | 
| 
      
 105 
     | 
    
         
            +
                  value = rb_funcall(value, id_flatten, 0);
         
     | 
| 
      
 106 
     | 
    
         
            +
                  delete_falsey_values(value);
         
     | 
| 
      
 107 
     | 
    
         
            +
                  value = rb_ary_join(value, str_space);
         
     | 
| 
      
 108 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 109 
     | 
    
         
            +
                default:
         
     | 
| 
      
 110 
     | 
    
         
            +
                  if (RTEST(value)) {
         
     | 
| 
      
 111 
     | 
    
         
            +
                    value = to_s(value);
         
     | 
| 
      
 112 
     | 
    
         
            +
                  } else {
         
     | 
| 
      
 113 
     | 
    
         
            +
                    return rb_str_new_cstr("");
         
     | 
| 
      
 114 
     | 
    
         
            +
                  }
         
     | 
| 
      
 115 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 116 
     | 
    
         
            +
              }
         
     | 
| 
      
 117 
     | 
    
         
            +
              return escape_attribute(escape_attrs, value);
         
     | 
| 
      
 118 
     | 
    
         
            +
            }
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 121 
     | 
    
         
            +
            haml_build_multi_class(VALUE escape_attrs, VALUE values)
         
     | 
| 
      
 122 
     | 
    
         
            +
            {
         
     | 
| 
      
 123 
     | 
    
         
            +
              long i, j;
         
     | 
| 
      
 124 
     | 
    
         
            +
              VALUE value, buf;
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              buf = rb_ary_new2(RARRAY_LEN(values));
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              for (i = 0; i < RARRAY_LEN(values); i++) {
         
     | 
| 
      
 129 
     | 
    
         
            +
                value = rb_ary_entry(values, i);
         
     | 
| 
      
 130 
     | 
    
         
            +
                switch (TYPE(value)) {
         
     | 
| 
      
 131 
     | 
    
         
            +
                  case T_STRING:
         
     | 
| 
      
 132 
     | 
    
         
            +
                    rb_ary_concat(buf, rb_str_split(value, " "));
         
     | 
| 
      
 133 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 134 
     | 
    
         
            +
                  case T_ARRAY:
         
     | 
| 
      
 135 
     | 
    
         
            +
                    value = rb_funcall(value, id_flatten, 0);
         
     | 
| 
      
 136 
     | 
    
         
            +
                    delete_falsey_values(value);
         
     | 
| 
      
 137 
     | 
    
         
            +
                    for (j = 0; j < RARRAY_LEN(value); j++) {
         
     | 
| 
      
 138 
     | 
    
         
            +
                      rb_ary_push(buf, to_s(rb_ary_entry(value, j)));
         
     | 
| 
      
 139 
     | 
    
         
            +
                    }
         
     | 
| 
      
 140 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 141 
     | 
    
         
            +
                  default:
         
     | 
| 
      
 142 
     | 
    
         
            +
                    if (RTEST(value)) {
         
     | 
| 
      
 143 
     | 
    
         
            +
                      rb_ary_push(buf, to_s(value));
         
     | 
| 
      
 144 
     | 
    
         
            +
                    }
         
     | 
| 
      
 145 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 146 
     | 
    
         
            +
                }
         
     | 
| 
      
 147 
     | 
    
         
            +
              }
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              rb_funcall(buf, id_uniq_bang, 0);
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
              return escape_attribute(escape_attrs, rb_ary_join(buf, str_space));
         
     | 
| 
      
 152 
     | 
    
         
            +
            }
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 155 
     | 
    
         
            +
            haml_build_class(VALUE escape_attrs, VALUE array)
         
     | 
| 
      
 156 
     | 
    
         
            +
            {
         
     | 
| 
      
 157 
     | 
    
         
            +
              if (RARRAY_LEN(array) == 1) {
         
     | 
| 
      
 158 
     | 
    
         
            +
                return haml_build_single_class(escape_attrs, rb_ary_entry(array, 0));
         
     | 
| 
      
 159 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 160 
     | 
    
         
            +
                return haml_build_multi_class(escape_attrs, array);
         
     | 
| 
      
 161 
     | 
    
         
            +
              }
         
     | 
| 
      
 162 
     | 
    
         
            +
            }
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
            struct merge_data_attrs_var {
         
     | 
| 
      
 165 
     | 
    
         
            +
              VALUE merged;
         
     | 
| 
      
 166 
     | 
    
         
            +
              VALUE key_str;
         
     | 
| 
      
 167 
     | 
    
         
            +
            };
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
            static int
         
     | 
| 
      
 170 
     | 
    
         
            +
            merge_data_attrs_i(VALUE key, VALUE value, VALUE ptr)
         
     | 
| 
      
 171 
     | 
    
         
            +
            {
         
     | 
| 
      
 172 
     | 
    
         
            +
              struct merge_data_attrs_var *arg = (struct merge_data_attrs_var *)ptr;
         
     | 
| 
      
 173 
     | 
    
         
            +
              VALUE merged = arg->merged;
         
     | 
| 
      
 174 
     | 
    
         
            +
              VALUE key_str = arg->key_str;
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
              if (NIL_P(key)) {
         
     | 
| 
      
 177 
     | 
    
         
            +
                rb_hash_aset(merged, key_str, value);
         
     | 
| 
      
 178 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 179 
     | 
    
         
            +
                key = rb_str_concat(rb_str_concat(rb_str_dup(key_str), rb_str_new_cstr("-")), to_s(key));
         
     | 
| 
      
 180 
     | 
    
         
            +
                rb_hash_aset(merged, key, value);
         
     | 
| 
      
 181 
     | 
    
         
            +
              }
         
     | 
| 
      
 182 
     | 
    
         
            +
              return ST_CONTINUE;
         
     | 
| 
      
 183 
     | 
    
         
            +
            }
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 186 
     | 
    
         
            +
            merge_data_attrs(VALUE values, VALUE key_str)
         
     | 
| 
      
 187 
     | 
    
         
            +
            {
         
     | 
| 
      
 188 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 189 
     | 
    
         
            +
              VALUE value, merged = rb_hash_new();
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              for (i = 0; i < RARRAY_LEN(values); i++) {
         
     | 
| 
      
 192 
     | 
    
         
            +
                struct merge_data_attrs_var arg;
         
     | 
| 
      
 193 
     | 
    
         
            +
                arg.merged = merged;
         
     | 
| 
      
 194 
     | 
    
         
            +
                arg.key_str = key_str;
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                value = rb_ary_entry(values, i);
         
     | 
| 
      
 197 
     | 
    
         
            +
                switch (TYPE(value)) {
         
     | 
| 
      
 198 
     | 
    
         
            +
                  case T_HASH:
         
     | 
| 
      
 199 
     | 
    
         
            +
                    rb_hash_foreach(value, merge_data_attrs_i, (VALUE)&arg);
         
     | 
| 
      
 200 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 201 
     | 
    
         
            +
                  default:
         
     | 
| 
      
 202 
     | 
    
         
            +
                    rb_hash_aset(merged, key_str, value);
         
     | 
| 
      
 203 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 204 
     | 
    
         
            +
                }
         
     | 
| 
      
 205 
     | 
    
         
            +
              }
         
     | 
| 
      
 206 
     | 
    
         
            +
              return merged;
         
     | 
| 
      
 207 
     | 
    
         
            +
            }
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
            struct flatten_data_attrs_i2_arg {
         
     | 
| 
      
 210 
     | 
    
         
            +
              VALUE flattened;
         
     | 
| 
      
 211 
     | 
    
         
            +
              VALUE key;
         
     | 
| 
      
 212 
     | 
    
         
            +
            };
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
            static int
         
     | 
| 
      
 215 
     | 
    
         
            +
            flatten_data_attrs_i2(VALUE k, VALUE v, VALUE ptr)
         
     | 
| 
      
 216 
     | 
    
         
            +
            {
         
     | 
| 
      
 217 
     | 
    
         
            +
              VALUE key;
         
     | 
| 
      
 218 
     | 
    
         
            +
              struct flatten_data_attrs_i2_arg *arg = (struct flatten_data_attrs_i2_arg *)ptr;
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
              if (!RTEST(v)) return ST_CONTINUE;
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
              if (k == Qnil) {
         
     | 
| 
      
 223 
     | 
    
         
            +
                rb_hash_aset(arg->flattened, arg->key, v);
         
     | 
| 
      
 224 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 225 
     | 
    
         
            +
                key = rb_str_dup(arg->key);
         
     | 
| 
      
 226 
     | 
    
         
            +
                rb_str_cat(key, "-", 1);
         
     | 
| 
      
 227 
     | 
    
         
            +
                rb_str_concat(key, to_s(k));
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                rb_hash_aset(arg->flattened, key, v);
         
     | 
| 
      
 230 
     | 
    
         
            +
              }
         
     | 
| 
      
 231 
     | 
    
         
            +
              return ST_CONTINUE;
         
     | 
| 
      
 232 
     | 
    
         
            +
            }
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
            static VALUE flatten_data_attrs(VALUE attrs);
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
            static int
         
     | 
| 
      
 237 
     | 
    
         
            +
            flatten_data_attrs_i(VALUE key, VALUE value, VALUE flattened)
         
     | 
| 
      
 238 
     | 
    
         
            +
            {
         
     | 
| 
      
 239 
     | 
    
         
            +
              struct flatten_data_attrs_i2_arg arg;
         
     | 
| 
      
 240 
     | 
    
         
            +
              key = hyphenate(to_s(key));
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
              switch (TYPE(value)) {
         
     | 
| 
      
 243 
     | 
    
         
            +
                case T_HASH:
         
     | 
| 
      
 244 
     | 
    
         
            +
                  value = flatten_data_attrs(value);
         
     | 
| 
      
 245 
     | 
    
         
            +
                  arg.key       = key;
         
     | 
| 
      
 246 
     | 
    
         
            +
                  arg.flattened = flattened;
         
     | 
| 
      
 247 
     | 
    
         
            +
                  rb_hash_foreach(value, flatten_data_attrs_i2, (VALUE)(&arg));
         
     | 
| 
      
 248 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 249 
     | 
    
         
            +
                default:
         
     | 
| 
      
 250 
     | 
    
         
            +
                  if (RTEST(value)) rb_hash_aset(flattened, key, value);
         
     | 
| 
      
 251 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 252 
     | 
    
         
            +
              }
         
     | 
| 
      
 253 
     | 
    
         
            +
              return ST_CONTINUE;
         
     | 
| 
      
 254 
     | 
    
         
            +
            }
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 257 
     | 
    
         
            +
            flatten_data_attrs(VALUE attrs)
         
     | 
| 
      
 258 
     | 
    
         
            +
            {
         
     | 
| 
      
 259 
     | 
    
         
            +
              VALUE flattened = rb_hash_new();
         
     | 
| 
      
 260 
     | 
    
         
            +
              rb_hash_foreach(attrs, flatten_data_attrs_i, flattened);
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
              return flattened;
         
     | 
| 
      
 263 
     | 
    
         
            +
            }
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 266 
     | 
    
         
            +
            haml_build_data(VALUE escape_attrs, VALUE quote, VALUE values, VALUE key_str)
         
     | 
| 
      
 267 
     | 
    
         
            +
            {
         
     | 
| 
      
 268 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 269 
     | 
    
         
            +
              VALUE attrs, buf, keys, key, value;
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
              attrs = merge_data_attrs(values, key_str);
         
     | 
| 
      
 272 
     | 
    
         
            +
              attrs = flatten_data_attrs(attrs);
         
     | 
| 
      
 273 
     | 
    
         
            +
              keys  = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
         
     | 
| 
      
 274 
     | 
    
         
            +
              buf   = rb_str_new("", 0);
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
              for (i = 0; i < RARRAY_LEN(keys); i++) {
         
     | 
| 
      
 277 
     | 
    
         
            +
                key   = rb_ary_entry(keys, i);
         
     | 
| 
      
 278 
     | 
    
         
            +
                value = rb_hash_aref(attrs, key);
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
                switch (value) {
         
     | 
| 
      
 281 
     | 
    
         
            +
                  case Qtrue:
         
     | 
| 
      
 282 
     | 
    
         
            +
                    rb_str_concat(buf, str_space);
         
     | 
| 
      
 283 
     | 
    
         
            +
                    rb_str_concat(buf, key);
         
     | 
| 
      
 284 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 285 
     | 
    
         
            +
                  case Qnil:
         
     | 
| 
      
 286 
     | 
    
         
            +
                    break; // noop
         
     | 
| 
      
 287 
     | 
    
         
            +
                  case Qfalse:
         
     | 
| 
      
 288 
     | 
    
         
            +
                    break; // noop
         
     | 
| 
      
 289 
     | 
    
         
            +
                  default:
         
     | 
| 
      
 290 
     | 
    
         
            +
                    rb_str_concat(buf, str_space);
         
     | 
| 
      
 291 
     | 
    
         
            +
                    rb_str_concat(buf, key);
         
     | 
| 
      
 292 
     | 
    
         
            +
                    rb_str_concat(buf, str_equal);
         
     | 
| 
      
 293 
     | 
    
         
            +
                    rb_str_concat(buf, quote);
         
     | 
| 
      
 294 
     | 
    
         
            +
                    rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value)));
         
     | 
| 
      
 295 
     | 
    
         
            +
                    rb_str_concat(buf, quote);
         
     | 
| 
      
 296 
     | 
    
         
            +
                    break;
         
     | 
| 
      
 297 
     | 
    
         
            +
                }
         
     | 
| 
      
 298 
     | 
    
         
            +
              }
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
              return buf;
         
     | 
| 
      
 301 
     | 
    
         
            +
            }
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 304 
     | 
    
         
            +
            parse_object_ref(VALUE object_ref)
         
     | 
| 
      
 305 
     | 
    
         
            +
            {
         
     | 
| 
      
 306 
     | 
    
         
            +
              return rb_funcall(mObjectRef, id_parse, 1, object_ref);
         
     | 
| 
      
 307 
     | 
    
         
            +
            }
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
      
 309 
     | 
    
         
            +
            static int
         
     | 
| 
      
 310 
     | 
    
         
            +
            merge_all_attrs_i(VALUE key, VALUE value, VALUE merged)
         
     | 
| 
      
 311 
     | 
    
         
            +
            {
         
     | 
| 
      
 312 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
              key = to_s(key);
         
     | 
| 
      
 315 
     | 
    
         
            +
              if (str_eq(key, "id", 2) || str_eq(key, "class", 5) || str_eq(key, "data", 4) || str_eq(key, "aria", 4)) {
         
     | 
| 
      
 316 
     | 
    
         
            +
                array = rb_hash_aref(merged, key);
         
     | 
| 
      
 317 
     | 
    
         
            +
                if (NIL_P(array)) {
         
     | 
| 
      
 318 
     | 
    
         
            +
                  array = rb_ary_new2(1);
         
     | 
| 
      
 319 
     | 
    
         
            +
                  rb_hash_aset(merged, key, array);
         
     | 
| 
      
 320 
     | 
    
         
            +
                }
         
     | 
| 
      
 321 
     | 
    
         
            +
                rb_ary_push(array, value);
         
     | 
| 
      
 322 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 323 
     | 
    
         
            +
                rb_hash_aset(merged, key, value);
         
     | 
| 
      
 324 
     | 
    
         
            +
              }
         
     | 
| 
      
 325 
     | 
    
         
            +
              return ST_CONTINUE;
         
     | 
| 
      
 326 
     | 
    
         
            +
            }
         
     | 
| 
      
 327 
     | 
    
         
            +
             
     | 
| 
      
 328 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 329 
     | 
    
         
            +
            merge_all_attrs(VALUE hashes)
         
     | 
| 
      
 330 
     | 
    
         
            +
            {
         
     | 
| 
      
 331 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 332 
     | 
    
         
            +
              VALUE hash, merged = rb_hash_new();
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
              for (i = 0; i < RARRAY_LEN(hashes); i++) {
         
     | 
| 
      
 335 
     | 
    
         
            +
                hash = rb_ary_entry(hashes, i);
         
     | 
| 
      
 336 
     | 
    
         
            +
                if (!RB_TYPE_P(hash, T_HASH)) {
         
     | 
| 
      
 337 
     | 
    
         
            +
                  rb_raise(rb_eArgError, "Non-hash object is given to attributes!");
         
     | 
| 
      
 338 
     | 
    
         
            +
                }
         
     | 
| 
      
 339 
     | 
    
         
            +
                rb_hash_foreach(hash, merge_all_attrs_i, merged);
         
     | 
| 
      
 340 
     | 
    
         
            +
              }
         
     | 
| 
      
 341 
     | 
    
         
            +
              return merged;
         
     | 
| 
      
 342 
     | 
    
         
            +
            }
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
            int
         
     | 
| 
      
 345 
     | 
    
         
            +
            is_boolean_attribute(VALUE key, VALUE boolean_attributes)
         
     | 
| 
      
 346 
     | 
    
         
            +
            {
         
     | 
| 
      
 347 
     | 
    
         
            +
              if (str_eq(rb_str_substr(key, 0, 5), "data-", 5)) return 1;
         
     | 
| 
      
 348 
     | 
    
         
            +
              if (str_eq(rb_str_substr(key, 0, 5), "aria-", 5)) return 1;
         
     | 
| 
      
 349 
     | 
    
         
            +
              return RTEST(rb_ary_includes(boolean_attributes, key));
         
     | 
| 
      
 350 
     | 
    
         
            +
            }
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
      
 352 
     | 
    
         
            +
            void
         
     | 
| 
      
 353 
     | 
    
         
            +
            haml_build_for_id(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
         
     | 
| 
      
 354 
     | 
    
         
            +
            {
         
     | 
| 
      
 355 
     | 
    
         
            +
              rb_str_cat(buf, " id=", 4);
         
     | 
| 
      
 356 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 357 
     | 
    
         
            +
              rb_str_concat(buf, haml_build_id(escape_attrs, values));
         
     | 
| 
      
 358 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 359 
     | 
    
         
            +
            }
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
            void
         
     | 
| 
      
 362 
     | 
    
         
            +
            haml_build_for_class(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
         
     | 
| 
      
 363 
     | 
    
         
            +
            {
         
     | 
| 
      
 364 
     | 
    
         
            +
              rb_str_cat(buf, " class=", 7);
         
     | 
| 
      
 365 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 366 
     | 
    
         
            +
              rb_str_concat(buf, haml_build_class(escape_attrs, values));
         
     | 
| 
      
 367 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 368 
     | 
    
         
            +
            }
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
            void
         
     | 
| 
      
 371 
     | 
    
         
            +
            haml_build_for_data(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
         
     | 
| 
      
 372 
     | 
    
         
            +
            {
         
     | 
| 
      
 373 
     | 
    
         
            +
              rb_str_concat(buf, haml_build_data(escape_attrs, quote, values, str_data));
         
     | 
| 
      
 374 
     | 
    
         
            +
            }
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
            void
         
     | 
| 
      
 377 
     | 
    
         
            +
            haml_build_for_aria(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
         
     | 
| 
      
 378 
     | 
    
         
            +
            {
         
     | 
| 
      
 379 
     | 
    
         
            +
              rb_str_concat(buf, haml_build_data(escape_attrs, quote, values, str_aria));
         
     | 
| 
      
 380 
     | 
    
         
            +
            }
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
            void
         
     | 
| 
      
 383 
     | 
    
         
            +
            haml_build_for_others(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE key, VALUE value)
         
     | 
| 
      
 384 
     | 
    
         
            +
            {
         
     | 
| 
      
 385 
     | 
    
         
            +
              rb_str_cat(buf, " ", 1);
         
     | 
| 
      
 386 
     | 
    
         
            +
              rb_str_concat(buf, key);
         
     | 
| 
      
 387 
     | 
    
         
            +
              rb_str_cat(buf, "=", 1);
         
     | 
| 
      
 388 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 389 
     | 
    
         
            +
              rb_str_concat(buf, escape_attribute(escape_attrs, to_s(value)));
         
     | 
| 
      
 390 
     | 
    
         
            +
              rb_str_concat(buf, quote);
         
     | 
| 
      
 391 
     | 
    
         
            +
            }
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
            void
         
     | 
| 
      
 394 
     | 
    
         
            +
            haml_build_for_boolean(VALUE escape_attrs, VALUE quote, VALUE format, VALUE buf, VALUE key, VALUE value)
         
     | 
| 
      
 395 
     | 
    
         
            +
            {
         
     | 
| 
      
 396 
     | 
    
         
            +
              switch (value) {
         
     | 
| 
      
 397 
     | 
    
         
            +
                case Qtrue:
         
     | 
| 
      
 398 
     | 
    
         
            +
                  rb_str_cat(buf, " ", 1);
         
     | 
| 
      
 399 
     | 
    
         
            +
                  rb_str_concat(buf, key);
         
     | 
| 
      
 400 
     | 
    
         
            +
                  if ((TYPE(format) == T_SYMBOL || TYPE(format) == T_STRING) && rb_to_id(format) == id_xhtml) {
         
     | 
| 
      
 401 
     | 
    
         
            +
                    rb_str_cat(buf, "=", 1);
         
     | 
| 
      
 402 
     | 
    
         
            +
                    rb_str_concat(buf, quote);
         
     | 
| 
      
 403 
     | 
    
         
            +
                    rb_str_concat(buf, key);
         
     | 
| 
      
 404 
     | 
    
         
            +
                    rb_str_concat(buf, quote);
         
     | 
| 
      
 405 
     | 
    
         
            +
                  }
         
     | 
| 
      
 406 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 407 
     | 
    
         
            +
                case Qfalse:
         
     | 
| 
      
 408 
     | 
    
         
            +
                  break; // noop
         
     | 
| 
      
 409 
     | 
    
         
            +
                case Qnil:
         
     | 
| 
      
 410 
     | 
    
         
            +
                  break; // noop
         
     | 
| 
      
 411 
     | 
    
         
            +
                default:
         
     | 
| 
      
 412 
     | 
    
         
            +
                  haml_build_for_others(escape_attrs, quote, buf, key, value);
         
     | 
| 
      
 413 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 414 
     | 
    
         
            +
              }
         
     | 
| 
      
 415 
     | 
    
         
            +
            }
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 418 
     | 
    
         
            +
            haml_build(VALUE escape_attrs, VALUE quote, VALUE format, VALUE boolean_attributes, VALUE object_ref, VALUE hashes)
         
     | 
| 
      
 419 
     | 
    
         
            +
            {
         
     | 
| 
      
 420 
     | 
    
         
            +
              long i;
         
     | 
| 
      
 421 
     | 
    
         
            +
              VALUE attrs, buf, key, keys, value;
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
              if (!NIL_P(object_ref)) rb_ary_push(hashes, parse_object_ref(object_ref));
         
     | 
| 
      
 424 
     | 
    
         
            +
              attrs = merge_all_attrs(hashes);
         
     | 
| 
      
 425 
     | 
    
         
            +
              buf   = rb_str_new("", 0);
         
     | 
| 
      
 426 
     | 
    
         
            +
              keys  = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
         
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
      
 428 
     | 
    
         
            +
              for (i = 0; i < RARRAY_LEN(keys); i++) {
         
     | 
| 
      
 429 
     | 
    
         
            +
                key   = rb_ary_entry(keys, i);
         
     | 
| 
      
 430 
     | 
    
         
            +
                value = rb_hash_aref(attrs, key);
         
     | 
| 
      
 431 
     | 
    
         
            +
                if (str_eq(key, "id", 2)) {
         
     | 
| 
      
 432 
     | 
    
         
            +
                  haml_build_for_id(escape_attrs, quote, buf, value);
         
     | 
| 
      
 433 
     | 
    
         
            +
                } else if (str_eq(key, "class", 5)) {
         
     | 
| 
      
 434 
     | 
    
         
            +
                  haml_build_for_class(escape_attrs, quote, buf, value);
         
     | 
| 
      
 435 
     | 
    
         
            +
                } else if (str_eq(key, "data", 4)) {
         
     | 
| 
      
 436 
     | 
    
         
            +
                  haml_build_for_data(escape_attrs, quote, buf, value);
         
     | 
| 
      
 437 
     | 
    
         
            +
                } else if (str_eq(key, "aria", 4)) {
         
     | 
| 
      
 438 
     | 
    
         
            +
                  haml_build_for_aria(escape_attrs, quote, buf, value);
         
     | 
| 
      
 439 
     | 
    
         
            +
                } else if (is_boolean_attribute(key, boolean_attributes)) {
         
     | 
| 
      
 440 
     | 
    
         
            +
                  haml_build_for_boolean(escape_attrs, quote, format, buf, key, value);
         
     | 
| 
      
 441 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 442 
     | 
    
         
            +
                  haml_build_for_others(escape_attrs, quote, buf, key, value);
         
     | 
| 
      
 443 
     | 
    
         
            +
                }
         
     | 
| 
      
 444 
     | 
    
         
            +
              }
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
              return buf;
         
     | 
| 
      
 447 
     | 
    
         
            +
            }
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 450 
     | 
    
         
            +
            rb_haml_build_id(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
         
     | 
| 
      
 451 
     | 
    
         
            +
            {
         
     | 
| 
      
 452 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 453 
     | 
    
         
            +
             
     | 
| 
      
 454 
     | 
    
         
            +
              rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 455 
     | 
    
         
            +
              rb_scan_args(argc - 1, argv + 1, "*", &array);
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
      
 457 
     | 
    
         
            +
              return haml_build_id(argv[0], array);
         
     | 
| 
      
 458 
     | 
    
         
            +
            }
         
     | 
| 
      
 459 
     | 
    
         
            +
             
     | 
| 
      
 460 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 461 
     | 
    
         
            +
            rb_haml_build_class(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
         
     | 
| 
      
 462 
     | 
    
         
            +
            {
         
     | 
| 
      
 463 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 464 
     | 
    
         
            +
             
     | 
| 
      
 465 
     | 
    
         
            +
              rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 466 
     | 
    
         
            +
              rb_scan_args(argc - 1, argv + 1, "*", &array);
         
     | 
| 
      
 467 
     | 
    
         
            +
             
     | 
| 
      
 468 
     | 
    
         
            +
              return haml_build_class(argv[0], array);
         
     | 
| 
      
 469 
     | 
    
         
            +
            }
         
     | 
| 
      
 470 
     | 
    
         
            +
             
     | 
| 
      
 471 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 472 
     | 
    
         
            +
            rb_haml_build_aria(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
         
     | 
| 
      
 473 
     | 
    
         
            +
            {
         
     | 
| 
      
 474 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 475 
     | 
    
         
            +
             
     | 
| 
      
 476 
     | 
    
         
            +
              rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 477 
     | 
    
         
            +
              rb_scan_args(argc - 2, argv + 2, "*", &array);
         
     | 
| 
      
 478 
     | 
    
         
            +
             
     | 
| 
      
 479 
     | 
    
         
            +
              return haml_build_data(argv[0], argv[1], array, str_aria);
         
     | 
| 
      
 480 
     | 
    
         
            +
            }
         
     | 
| 
      
 481 
     | 
    
         
            +
             
     | 
| 
      
 482 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 483 
     | 
    
         
            +
            rb_haml_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
         
     | 
| 
      
 484 
     | 
    
         
            +
            {
         
     | 
| 
      
 485 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 486 
     | 
    
         
            +
             
     | 
| 
      
 487 
     | 
    
         
            +
              rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 488 
     | 
    
         
            +
              rb_scan_args(argc - 2, argv + 2, "*", &array);
         
     | 
| 
      
 489 
     | 
    
         
            +
             
     | 
| 
      
 490 
     | 
    
         
            +
              return haml_build_data(argv[0], argv[1], array, str_data);
         
     | 
| 
      
 491 
     | 
    
         
            +
            }
         
     | 
| 
      
 492 
     | 
    
         
            +
             
     | 
| 
      
 493 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 494 
     | 
    
         
            +
            rb_haml_build(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
         
     | 
| 
      
 495 
     | 
    
         
            +
            {
         
     | 
| 
      
 496 
     | 
    
         
            +
              VALUE array;
         
     | 
| 
      
 497 
     | 
    
         
            +
             
     | 
| 
      
 498 
     | 
    
         
            +
              rb_check_arity(argc, 5, UNLIMITED_ARGUMENTS);
         
     | 
| 
      
 499 
     | 
    
         
            +
              rb_scan_args(argc - 5, argv + 5, "*", &array);
         
     | 
| 
      
 500 
     | 
    
         
            +
             
     | 
| 
      
 501 
     | 
    
         
            +
              return haml_build(argv[0], argv[1], argv[2], argv[3], argv[4], array);
         
     | 
| 
      
 502 
     | 
    
         
            +
            }
         
     | 
| 
      
 503 
     | 
    
         
            +
             
     | 
| 
      
 504 
     | 
    
         
            +
            void
         
     | 
| 
      
 505 
     | 
    
         
            +
            Init_haml(void)
         
     | 
| 
      
 506 
     | 
    
         
            +
            {
         
     | 
| 
      
 507 
     | 
    
         
            +
              VALUE mHaml, mUtil;
         
     | 
| 
      
 508 
     | 
    
         
            +
             
     | 
| 
      
 509 
     | 
    
         
            +
              mHaml             = rb_define_module("Haml");
         
     | 
| 
      
 510 
     | 
    
         
            +
              mObjectRef        = rb_define_module_under(mHaml, "ObjectRef");
         
     | 
| 
      
 511 
     | 
    
         
            +
              mUtil             = rb_define_module_under(mHaml, "Util");
         
     | 
| 
      
 512 
     | 
    
         
            +
              mAttributeBuilder = rb_define_module_under(mHaml, "AttributeBuilder");
         
     | 
| 
      
 513 
     | 
    
         
            +
             
     | 
| 
      
 514 
     | 
    
         
            +
              rb_define_singleton_method(mUtil, "escape_html", rb_escape_html, 1);
         
     | 
| 
      
 515 
     | 
    
         
            +
              rb_define_singleton_method(mAttributeBuilder, "build", rb_haml_build, -1);
         
     | 
| 
      
 516 
     | 
    
         
            +
              rb_define_singleton_method(mAttributeBuilder, "build_id", rb_haml_build_id, -1);
         
     | 
| 
      
 517 
     | 
    
         
            +
              rb_define_singleton_method(mAttributeBuilder, "build_class", rb_haml_build_class, -1);
         
     | 
| 
      
 518 
     | 
    
         
            +
              rb_define_singleton_method(mAttributeBuilder, "build_aria", rb_haml_build_aria, -1);
         
     | 
| 
      
 519 
     | 
    
         
            +
              rb_define_singleton_method(mAttributeBuilder, "build_data", rb_haml_build_data, -1);
         
     | 
| 
      
 520 
     | 
    
         
            +
             
     | 
| 
      
 521 
     | 
    
         
            +
              id_flatten   = rb_intern("flatten");
         
     | 
| 
      
 522 
     | 
    
         
            +
              id_keys      = rb_intern("keys");
         
     | 
| 
      
 523 
     | 
    
         
            +
              id_parse     = rb_intern("parse");
         
     | 
| 
      
 524 
     | 
    
         
            +
              id_prepend   = rb_intern("prepend");
         
     | 
| 
      
 525 
     | 
    
         
            +
              id_tr        = rb_intern("tr");
         
     | 
| 
      
 526 
     | 
    
         
            +
              id_uniq_bang = rb_intern("uniq!");
         
     | 
| 
      
 527 
     | 
    
         
            +
              id_xhtml     = rb_intern("xhtml");
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
      
 529 
     | 
    
         
            +
              // Consider using rb_interned_str() once we stop supporting Ruby 2.7.
         
     | 
| 
      
 530 
     | 
    
         
            +
              rb_gc_register_mark_object(str_aria       = rb_obj_freeze(rb_str_new_cstr("aria")));
         
     | 
| 
      
 531 
     | 
    
         
            +
              rb_gc_register_mark_object(str_data       = rb_obj_freeze(rb_str_new_cstr("data")));
         
     | 
| 
      
 532 
     | 
    
         
            +
              rb_gc_register_mark_object(str_equal      = rb_obj_freeze(rb_str_new_cstr("=")));
         
     | 
| 
      
 533 
     | 
    
         
            +
              rb_gc_register_mark_object(str_hyphen     = rb_obj_freeze(rb_str_new_cstr("-")));
         
     | 
| 
      
 534 
     | 
    
         
            +
              rb_gc_register_mark_object(str_space      = rb_obj_freeze(rb_str_new_cstr(" ")));
         
     | 
| 
      
 535 
     | 
    
         
            +
              rb_gc_register_mark_object(str_underscore = rb_obj_freeze(rb_str_new_cstr("_")));
         
     | 
| 
      
 536 
     | 
    
         
            +
            }
         
     | 
| 
      
 537 
     | 
    
         
            +
            #endif
         
     | 
    
        data/ext/haml/hescape.c
    ADDED
    
    | 
         @@ -0,0 +1,108 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include <stdio.h>
         
     | 
| 
      
 2 
     | 
    
         
            +
            #include <string.h>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <stdlib.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #include "hescape.h"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            static const char *ESCAPED_STRING[] = {
         
     | 
| 
      
 7 
     | 
    
         
            +
              "",
         
     | 
| 
      
 8 
     | 
    
         
            +
              """,
         
     | 
| 
      
 9 
     | 
    
         
            +
              "&",
         
     | 
| 
      
 10 
     | 
    
         
            +
              "'",
         
     | 
| 
      
 11 
     | 
    
         
            +
              "<",
         
     | 
| 
      
 12 
     | 
    
         
            +
              ">",
         
     | 
| 
      
 13 
     | 
    
         
            +
            };
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            // This is strlen(ESCAPED_STRING[x]) optimized specially.
         
     | 
| 
      
 16 
     | 
    
         
            +
            // Mapping: 1 => 6, 2 => 5, 3 => 5, 4 => 4, 5 => 4
         
     | 
| 
      
 17 
     | 
    
         
            +
            #define ESC_LEN(x) ((13 - x) / 2)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            /*
         
     | 
| 
      
 20 
     | 
    
         
            +
             * Given ASCII-compatible character, return index of ESCAPED_STRING.
         
     | 
| 
      
 21 
     | 
    
         
            +
             *
         
     | 
| 
      
 22 
     | 
    
         
            +
             * " (34) => 1 (")
         
     | 
| 
      
 23 
     | 
    
         
            +
             * & (38) => 2 (&)
         
     | 
| 
      
 24 
     | 
    
         
            +
             * ' (39) => 3 (')
         
     | 
| 
      
 25 
     | 
    
         
            +
             * < (60) => 4 (<)
         
     | 
| 
      
 26 
     | 
    
         
            +
             * > (62) => 5 (>)
         
     | 
| 
      
 27 
     | 
    
         
            +
             */
         
     | 
| 
      
 28 
     | 
    
         
            +
            static const char HTML_ESCAPE_TABLE[] = {
         
     | 
| 
      
 29 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 30 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 31 
     | 
    
         
            +
              0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 32 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, 0,
         
     | 
| 
      
 33 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 34 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 35 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 36 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 37 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 38 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 39 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 40 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 41 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 42 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 43 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 44 
     | 
    
         
            +
              0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         
     | 
| 
      
 45 
     | 
    
         
            +
            };
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            static char*
         
     | 
| 
      
 48 
     | 
    
         
            +
            ensure_allocated(char *buf, size_t size, size_t *asize)
         
     | 
| 
      
 49 
     | 
    
         
            +
            {
         
     | 
| 
      
 50 
     | 
    
         
            +
              size_t new_size;
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              if (size < *asize)
         
     | 
| 
      
 53 
     | 
    
         
            +
                return buf;
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              if (*asize == 0) {
         
     | 
| 
      
 56 
     | 
    
         
            +
                new_size = size;
         
     | 
| 
      
 57 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 58 
     | 
    
         
            +
                new_size = *asize;
         
     | 
| 
      
 59 
     | 
    
         
            +
              }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              // Increase buffer size by 1.5x if realloced multiple times.
         
     | 
| 
      
 62 
     | 
    
         
            +
              while (new_size < size)
         
     | 
| 
      
 63 
     | 
    
         
            +
                new_size = (new_size << 1) - (new_size >> 1);
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              // Round allocation up to multiple of 8.
         
     | 
| 
      
 66 
     | 
    
         
            +
              new_size = (new_size + 7) & ~7;
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              *asize = new_size;
         
     | 
| 
      
 69 
     | 
    
         
            +
              return realloc(buf, new_size);
         
     | 
| 
      
 70 
     | 
    
         
            +
            }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            size_t
         
     | 
| 
      
 73 
     | 
    
         
            +
            hesc_escape_html(char **dest, const char *buf, size_t size)
         
     | 
| 
      
 74 
     | 
    
         
            +
            {
         
     | 
| 
      
 75 
     | 
    
         
            +
              size_t asize = 0, esc_i = 0, esize = 0, i = 0, rbuf_end = 0;
         
     | 
| 
      
 76 
     | 
    
         
            +
              const char *esc;
         
     | 
| 
      
 77 
     | 
    
         
            +
              char *rbuf = NULL;
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              while (i < size) {
         
     | 
| 
      
 80 
     | 
    
         
            +
                // Loop here to skip non-escaped characters fast.
         
     | 
| 
      
 81 
     | 
    
         
            +
                while (i < size && (esc_i = HTML_ESCAPE_TABLE[(unsigned char)buf[i]]) == 0)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  i++;
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                if (i < size && esc_i) {
         
     | 
| 
      
 85 
     | 
    
         
            +
                  esc = ESCAPED_STRING[esc_i];
         
     | 
| 
      
 86 
     | 
    
         
            +
                  rbuf = ensure_allocated(rbuf, sizeof(char) * (size + esize + ESC_LEN(esc_i) + 1), &asize);
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  // Copy pending characters and escaped string.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  memmove(rbuf + rbuf_end, buf + (rbuf_end - esize), i - (rbuf_end - esize));
         
     | 
| 
      
 90 
     | 
    
         
            +
                  memmove(rbuf + i + esize, esc, ESC_LEN(esc_i));
         
     | 
| 
      
 91 
     | 
    
         
            +
                  rbuf_end = i + esize + ESC_LEN(esc_i);
         
     | 
| 
      
 92 
     | 
    
         
            +
                  esize += ESC_LEN(esc_i) - 1;
         
     | 
| 
      
 93 
     | 
    
         
            +
                }
         
     | 
| 
      
 94 
     | 
    
         
            +
                i++;
         
     | 
| 
      
 95 
     | 
    
         
            +
              }
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              if (rbuf_end == 0) {
         
     | 
| 
      
 98 
     | 
    
         
            +
                // Return given buf and size if there are no escaped characters.
         
     | 
| 
      
 99 
     | 
    
         
            +
                *dest = (char *)buf;
         
     | 
| 
      
 100 
     | 
    
         
            +
                return size;
         
     | 
| 
      
 101 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 102 
     | 
    
         
            +
                // Copy pending characters including NULL character.
         
     | 
| 
      
 103 
     | 
    
         
            +
                memmove(rbuf + rbuf_end, buf + (rbuf_end - esize), (size + 1) - (rbuf_end - esize));
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                *dest = rbuf;
         
     | 
| 
      
 106 
     | 
    
         
            +
                return size + esize;
         
     | 
| 
      
 107 
     | 
    
         
            +
              }
         
     | 
| 
      
 108 
     | 
    
         
            +
            }
         
     | 
    
        data/ext/haml/hescape.h
    ADDED
    
    | 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #ifndef HESCAPE_H
         
     | 
| 
      
 2 
     | 
    
         
            +
            #define HESCAPE_H
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            #include <sys/types.h>
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            /*
         
     | 
| 
      
 7 
     | 
    
         
            +
             * Replace characters according to the following rules.
         
     | 
| 
      
 8 
     | 
    
         
            +
             * Note that this function can handle only ASCII-compatible string.
         
     | 
| 
      
 9 
     | 
    
         
            +
             *
         
     | 
| 
      
 10 
     | 
    
         
            +
             * " => "
         
     | 
| 
      
 11 
     | 
    
         
            +
             * & => &
         
     | 
| 
      
 12 
     | 
    
         
            +
             * ' => '
         
     | 
| 
      
 13 
     | 
    
         
            +
             * < => <
         
     | 
| 
      
 14 
     | 
    
         
            +
             * > => >
         
     | 
| 
      
 15 
     | 
    
         
            +
             *
         
     | 
| 
      
 16 
     | 
    
         
            +
             * @return size of dest. If it's larger than len, dest is required to be freed.
         
     | 
| 
      
 17 
     | 
    
         
            +
             */
         
     | 
| 
      
 18 
     | 
    
         
            +
            extern size_t hesc_escape_html(char **dest, const char *src, size_t size);
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            #endif
         
     |