1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

Support aria attribute as another data attribute

Fix #57
This commit is contained in:
Takashi Kokubun 2018-10-16 19:55:31 +09:00
parent 3486a4ba8a
commit 572c704974
3 changed files with 98 additions and 16 deletions

View file

@ -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("-")));

View file

@ -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]

View file

@ -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)