mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
parent
3486a4ba8a
commit
572c704974
3 changed files with 98 additions and 16 deletions
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
VALUE mAttributeBuilder, mObjectRef;
|
VALUE mAttributeBuilder, mObjectRef;
|
||||||
static ID id_flatten, id_keys, id_parse, id_prepend, id_tr, id_uniq_bang;
|
static ID id_flatten, id_keys, id_parse, id_prepend, id_tr, id_uniq_bang;
|
||||||
static ID id_data, id_equal, id_hyphen, id_space, id_underscore;
|
static ID id_aria, id_data, id_equal, id_hyphen, id_space, id_underscore;
|
||||||
static ID id_boolean_attributes, id_xhtml;
|
static ID id_boolean_attributes, id_xhtml;
|
||||||
|
|
||||||
|
static VALUE str_aria() { return rb_const_get(mAttributeBuilder, id_aria); }
|
||||||
static VALUE str_data() { return rb_const_get(mAttributeBuilder, id_data); }
|
static VALUE str_data() { return rb_const_get(mAttributeBuilder, id_data); }
|
||||||
static VALUE str_equal() { return rb_const_get(mAttributeBuilder, id_equal); }
|
static VALUE str_equal() { return rb_const_get(mAttributeBuilder, id_equal); }
|
||||||
static VALUE str_hyphen() { return rb_const_get(mAttributeBuilder, id_hyphen); }
|
static VALUE str_hyphen() { return rb_const_get(mAttributeBuilder, id_hyphen); }
|
||||||
|
@ -166,32 +167,45 @@ hamlit_build_class(VALUE escape_attrs, VALUE array)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct merge_data_attrs_var {
|
||||||
|
VALUE merged;
|
||||||
|
VALUE key_str;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
merge_data_attrs_i(VALUE key, VALUE value, VALUE merged)
|
merge_data_attrs_i(VALUE key, VALUE value, VALUE ptr)
|
||||||
{
|
{
|
||||||
|
struct merge_data_attrs_var *arg = (struct merge_data_attrs_var *)ptr;
|
||||||
|
VALUE merged = arg->merged;
|
||||||
|
VALUE key_str = arg->key_str;
|
||||||
|
|
||||||
if (NIL_P(key)) {
|
if (NIL_P(key)) {
|
||||||
rb_hash_aset(merged, str_data(), value);
|
rb_hash_aset(merged, key_str, value);
|
||||||
} else {
|
} else {
|
||||||
key = rb_str_concat(rb_str_new_cstr("data-"), to_s(key));
|
key = rb_str_concat(rb_str_concat(rb_str_dup(key_str), rb_str_new_cstr("-")), to_s(key));
|
||||||
rb_hash_aset(merged, key, value);
|
rb_hash_aset(merged, key, value);
|
||||||
}
|
}
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
merge_data_attrs(VALUE values)
|
merge_data_attrs(VALUE values, VALUE key_str)
|
||||||
{
|
{
|
||||||
long i;
|
long i;
|
||||||
VALUE value, merged = rb_hash_new();
|
VALUE value, merged = rb_hash_new();
|
||||||
|
|
||||||
for (i = 0; i < RARRAY_LEN(values); i++) {
|
for (i = 0; i < RARRAY_LEN(values); i++) {
|
||||||
|
struct merge_data_attrs_var arg;
|
||||||
|
arg.merged = merged;
|
||||||
|
arg.key_str = key_str;
|
||||||
|
|
||||||
value = rb_ary_entry(values, i);
|
value = rb_ary_entry(values, i);
|
||||||
switch (TYPE(value)) {
|
switch (TYPE(value)) {
|
||||||
case T_HASH:
|
case T_HASH:
|
||||||
rb_hash_foreach(value, merge_data_attrs_i, merged);
|
rb_hash_foreach(value, merge_data_attrs_i, (VALUE)&arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rb_hash_aset(merged, str_data(), value);
|
rb_hash_aset(merged, key_str, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,12 +269,12 @@ flatten_data_attrs(VALUE attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
hamlit_build_data(VALUE escape_attrs, VALUE quote, VALUE values)
|
hamlit_build_data(VALUE escape_attrs, VALUE quote, VALUE values, VALUE key_str)
|
||||||
{
|
{
|
||||||
long i;
|
long i;
|
||||||
VALUE attrs, buf, keys, key, value;
|
VALUE attrs, buf, keys, key, value;
|
||||||
|
|
||||||
attrs = merge_data_attrs(values);
|
attrs = merge_data_attrs(values, key_str);
|
||||||
attrs = flatten_data_attrs(attrs);
|
attrs = flatten_data_attrs(attrs);
|
||||||
keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
|
keys = rb_ary_sort_bang(rb_funcall(attrs, id_keys, 0));
|
||||||
buf = rb_str_new("", 0);
|
buf = rb_str_new("", 0);
|
||||||
|
@ -304,7 +318,7 @@ merge_all_attrs_i(VALUE key, VALUE value, VALUE merged)
|
||||||
VALUE array;
|
VALUE array;
|
||||||
|
|
||||||
key = to_s(key);
|
key = to_s(key);
|
||||||
if (str_eq(key, "id", 2) || str_eq(key, "class", 5) || str_eq(key, "data", 4)) {
|
if (str_eq(key, "id", 2) || str_eq(key, "class", 5) || str_eq(key, "data", 4) || str_eq(key, "aria", 4)) {
|
||||||
array = rb_hash_aref(merged, key);
|
array = rb_hash_aref(merged, key);
|
||||||
if (NIL_P(array)) {
|
if (NIL_P(array)) {
|
||||||
array = rb_ary_new2(1);
|
array = rb_ary_new2(1);
|
||||||
|
@ -338,6 +352,7 @@ is_boolean_attribute(VALUE key)
|
||||||
{
|
{
|
||||||
VALUE boolean_attributes;
|
VALUE boolean_attributes;
|
||||||
if (str_eq(rb_str_substr(key, 0, 5), "data-", 5)) return 1;
|
if (str_eq(rb_str_substr(key, 0, 5), "data-", 5)) return 1;
|
||||||
|
if (str_eq(rb_str_substr(key, 0, 5), "aria-", 5)) return 1;
|
||||||
|
|
||||||
boolean_attributes = rb_const_get(mAttributeBuilder, id_boolean_attributes);
|
boolean_attributes = rb_const_get(mAttributeBuilder, id_boolean_attributes);
|
||||||
return RTEST(rb_ary_includes(boolean_attributes, key));
|
return RTEST(rb_ary_includes(boolean_attributes, key));
|
||||||
|
@ -364,7 +379,13 @@ hamlit_build_for_class(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
|
||||||
void
|
void
|
||||||
hamlit_build_for_data(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
|
hamlit_build_for_data(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
|
||||||
{
|
{
|
||||||
rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values));
|
rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hamlit_build_for_aria(VALUE escape_attrs, VALUE quote, VALUE buf, VALUE values)
|
||||||
|
{
|
||||||
|
rb_str_concat(buf, hamlit_build_data(escape_attrs, quote, values, str_aria()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -422,6 +443,8 @@ hamlit_build(VALUE escape_attrs, VALUE quote, VALUE format, VALUE object_ref, VA
|
||||||
hamlit_build_for_class(escape_attrs, quote, buf, value);
|
hamlit_build_for_class(escape_attrs, quote, buf, value);
|
||||||
} else if (str_eq(key, "data", 4)) {
|
} else if (str_eq(key, "data", 4)) {
|
||||||
hamlit_build_for_data(escape_attrs, quote, buf, value);
|
hamlit_build_for_data(escape_attrs, quote, buf, value);
|
||||||
|
} else if (str_eq(key, "aria", 4)) {
|
||||||
|
hamlit_build_for_aria(escape_attrs, quote, buf, value);
|
||||||
} else if (is_boolean_attribute(key)) {
|
} else if (is_boolean_attribute(key)) {
|
||||||
hamlit_build_for_boolean(escape_attrs, quote, format, buf, key, value);
|
hamlit_build_for_boolean(escape_attrs, quote, format, buf, key, value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -454,6 +477,17 @@ rb_hamlit_build_class(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
|
||||||
return hamlit_build_class(argv[0], array);
|
return hamlit_build_class(argv[0], array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_hamlit_build_aria(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
|
||||||
|
{
|
||||||
|
VALUE array;
|
||||||
|
|
||||||
|
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
|
||||||
|
rb_scan_args(argc - 2, argv + 2, "*", &array);
|
||||||
|
|
||||||
|
return hamlit_build_data(argv[0], argv[1], array, str_aria());
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_hamlit_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
|
rb_hamlit_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
|
||||||
{
|
{
|
||||||
|
@ -462,7 +496,7 @@ rb_hamlit_build_data(int argc, VALUE *argv, RB_UNUSED_VAR(VALUE self))
|
||||||
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
|
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
|
||||||
rb_scan_args(argc - 2, argv + 2, "*", &array);
|
rb_scan_args(argc - 2, argv + 2, "*", &array);
|
||||||
|
|
||||||
return hamlit_build_data(argv[0], argv[1], array);
|
return hamlit_build_data(argv[0], argv[1], array, str_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -490,6 +524,7 @@ Init_hamlit(void)
|
||||||
rb_define_singleton_method(mAttributeBuilder, "build", rb_hamlit_build, -1);
|
rb_define_singleton_method(mAttributeBuilder, "build", rb_hamlit_build, -1);
|
||||||
rb_define_singleton_method(mAttributeBuilder, "build_id", rb_hamlit_build_id, -1);
|
rb_define_singleton_method(mAttributeBuilder, "build_id", rb_hamlit_build_id, -1);
|
||||||
rb_define_singleton_method(mAttributeBuilder, "build_class", rb_hamlit_build_class, -1);
|
rb_define_singleton_method(mAttributeBuilder, "build_class", rb_hamlit_build_class, -1);
|
||||||
|
rb_define_singleton_method(mAttributeBuilder, "build_aria", rb_hamlit_build_aria, -1);
|
||||||
rb_define_singleton_method(mAttributeBuilder, "build_data", rb_hamlit_build_data, -1);
|
rb_define_singleton_method(mAttributeBuilder, "build_data", rb_hamlit_build_data, -1);
|
||||||
|
|
||||||
id_flatten = rb_intern("flatten");
|
id_flatten = rb_intern("flatten");
|
||||||
|
@ -499,6 +534,7 @@ Init_hamlit(void)
|
||||||
id_tr = rb_intern("tr");
|
id_tr = rb_intern("tr");
|
||||||
id_uniq_bang = rb_intern("uniq!");
|
id_uniq_bang = rb_intern("uniq!");
|
||||||
|
|
||||||
|
id_aria = rb_intern("ARIA");
|
||||||
id_data = rb_intern("DATA");
|
id_data = rb_intern("DATA");
|
||||||
id_equal = rb_intern("EQUAL");
|
id_equal = rb_intern("EQUAL");
|
||||||
id_hyphen = rb_intern("HYPHEN");
|
id_hyphen = rb_intern("HYPHEN");
|
||||||
|
@ -508,6 +544,7 @@ Init_hamlit(void)
|
||||||
id_boolean_attributes = rb_intern("BOOLEAN_ATTRIBUTES");
|
id_boolean_attributes = rb_intern("BOOLEAN_ATTRIBUTES");
|
||||||
id_xhtml = rb_intern("xhtml");
|
id_xhtml = rb_intern("xhtml");
|
||||||
|
|
||||||
|
rb_const_set(mAttributeBuilder, id_aria, rb_obj_freeze(rb_str_new_cstr("aria")));
|
||||||
rb_const_set(mAttributeBuilder, id_data, rb_obj_freeze(rb_str_new_cstr("data")));
|
rb_const_set(mAttributeBuilder, id_data, rb_obj_freeze(rb_str_new_cstr("data")));
|
||||||
rb_const_set(mAttributeBuilder, id_equal, rb_obj_freeze(rb_str_new_cstr("=")));
|
rb_const_set(mAttributeBuilder, id_equal, rb_obj_freeze(rb_str_new_cstr("=")));
|
||||||
rb_const_set(mAttributeBuilder, id_hyphen, rb_obj_freeze(rb_str_new_cstr("-")));
|
rb_const_set(mAttributeBuilder, id_hyphen, rb_obj_freeze(rb_str_new_cstr("-")));
|
||||||
|
|
|
@ -45,9 +45,9 @@ module Hamlit
|
||||||
compile_id!(temple, key, values)
|
compile_id!(temple, key, values)
|
||||||
when 'class'
|
when 'class'
|
||||||
compile_class!(temple, key, values)
|
compile_class!(temple, key, values)
|
||||||
when 'data'
|
when 'data', 'aria'
|
||||||
compile_data!(temple, key, values)
|
compile_data!(temple, key, values)
|
||||||
when *AttributeBuilder::BOOLEAN_ATTRIBUTES, /\Adata-/
|
when *AttributeBuilder::BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/
|
||||||
compile_boolean!(temple, key, values)
|
compile_boolean!(temple, key, values)
|
||||||
else
|
else
|
||||||
compile_common!(temple, key, values)
|
compile_common!(temple, key, values)
|
||||||
|
@ -76,7 +76,7 @@ module Hamlit
|
||||||
|
|
||||||
def compile_data!(temple, key, values)
|
def compile_data!(temple, key, values)
|
||||||
args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", values.map { |v| literal_for(v) }]
|
args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", values.map { |v| literal_for(v) }]
|
||||||
build_code = "::Hamlit::AttributeBuilder.build_data(#{args.join(', ')})"
|
build_code = "::Hamlit::AttributeBuilder.build_#{key}(#{args.join(', ')})"
|
||||||
|
|
||||||
if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) }
|
if values.all? { |type, exp| type == :static || Temple::StaticAnalyzer.static?(exp) }
|
||||||
temple << [:static, eval(build_code).to_s]
|
temple << [:static, eval(build_code).to_s]
|
||||||
|
|
|
@ -290,7 +290,7 @@ describe Hamlit::Engine do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'nested attributes' do
|
describe 'nested data attributes' do
|
||||||
it 'renders data attribute by hash' do
|
it 'renders data attribute by hash' do
|
||||||
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
<span class='foo' data-bar='baz'></span>
|
<span class='foo' data-bar='baz'></span>
|
||||||
|
@ -335,6 +335,51 @@ describe Hamlit::Engine do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'nested aria attributes' do
|
||||||
|
it 'renders aria attribute by hash' do
|
||||||
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
<span aria-bar='baz' class='foo'></span>
|
||||||
|
HTML
|
||||||
|
- hash = { bar: 'baz' }
|
||||||
|
%span.foo{ aria: hash }
|
||||||
|
HAML
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders true attributes' do
|
||||||
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
<span aria-disabled>bar</span>
|
||||||
|
HTML
|
||||||
|
%span{ aria: { disabled: true } } bar
|
||||||
|
HAML
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders nested hash whose value is variable' do
|
||||||
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
<span aria-disabled>bar</span>
|
||||||
|
HTML
|
||||||
|
- hash = { disabled: true }
|
||||||
|
%span{ aria: hash } bar
|
||||||
|
HAML
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'changes an underscore in a nested key to a hyphen' do
|
||||||
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
<div aria-raw-src='foo'></div>
|
||||||
|
HTML
|
||||||
|
%div{ aria: { raw_src: 'foo' } }
|
||||||
|
HAML
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'changes an underscore in a nested dynamic attribute' do
|
||||||
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
<div aria-raw-src='foo'></div>
|
||||||
|
HTML
|
||||||
|
- hash = { raw_src: 'foo' }
|
||||||
|
%div{ aria: hash }
|
||||||
|
HAML
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'element class with attribute class' do
|
describe 'element class with attribute class' do
|
||||||
it 'does not generate double classes' do
|
it 'does not generate double classes' do
|
||||||
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
assert_render(<<-HTML.unindent, <<-HAML.unindent)
|
||||||
|
|
Loading…
Reference in a new issue