require 'spec_helper' RSpec.describe 'Attributes rendering', type: :render do it 'parses attributes' do expect(render_string('%span{class: "x"} hello')).to eq(%Q{hello\n}) end it 'parses attributes' do expect(render_string('%span{class: "x", "old" => 2} hello')).to eq(%Q{hello\n}) end it 'is not element with id attribute' do expect(render_string('#{1 + 2}')).to eq("3\n") end it 'renders attributes with symbol literal' do expect(render_string("%span{foo: 'baz'}")).to eq("\n") expect(render_string("%span{:foo => 'baz'}")).to eq("\n") expect(render_string("%span{:'foo-bar' => 'baz'}")).to eq("\n") end if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0') it 'renders attributes with 2.2-style symbol literals' do expect(render_string(%Q|%span{"foo": 'bar'}|)).to eq("\n") expect(render_string(%Q|- x = 'bar'\n%span{"foo": x}|)).to eq("\n") expect(render_string(%Q|%span{'foo': 'bar'}|)).to eq("\n") expect(render_string(%Q|- x = 'bar'\n%span{'foo': x}|)).to eq("\n") end end it 'renders dynamic attributes' do expect(render_string(%q|%span#main{class: "na#{'ni'}ka"} hello|)).to eq(%Q{hello\n}) end it 'renders array class' do expect(render_string('%span.c2{class: "c1"}')).to eq("\n") expect(render_string('%span.c2{class: ["c1", "c3"]}')).to eq("\n") end it "renders boolean attributes" do expect(render_string('%input{checked: true}')).to eq("\n") expect(render_string('%input{checked: false}')).to eq("\n") expect(render_string('%input{checked: nil}')).to eq("\n") expect(render_string('%input{checked: "a" == "a"}')).to eq("\n") expect(render_string('%input{checked: "a" != "a"}')).to eq("\n") expect(render_string("- x = nil\n%input{checked: x}")).to eq("\n") expect(render_string("- h = {checked: true}\n%input{h}")).to eq("\n") expect(render_string("- h = {checked: false}\n%input{h}")).to eq("\n") expect(render_string("- h = {checked: nil}\n%input{h}")).to eq("\n") end it 'merges classes' do expect(render_string(<hello\n") - h1 = {class: 'c1', id: ['id1', 'id3']} - h2 = {class: [{}, 'c2'], id: 'id2'} %span#main.content{h1, h2} hello HAML end it 'strigify non-string classes' do expect(render_string('%span.foo{class: :bar} hello')).to eq("hello\n") expect(render_string('%span.foo{class: 1} hello')).to eq("hello\n") end it 'remove duplicated classes' do expect(render_string('%span.foo{class: :foo}')).to eq("\n") expect(render_string('%span.foo{class: "foo bar"}')).to eq("\n") expect(render_string('%span.foo{class: %w[foo bar]}')).to eq("\n") end it 'strigify non-string ids' do expect(render_string('%span#foo{id: :bar} hello')).to eq("hello\n") end it 'escapes' do expect(render_string(%q|%span{class: "x\"y'z"} hello|)).to eq(%Q{hello\n}) end it "doesn't parse extra brace" do expect(render_string('%span{foo: 1}{bar: 2}')).to eq("{bar: 2}\n") end it 'renders only name if value is true' do expect(render_string(%q|%span{foo: true, bar: 1} hello|)).to eq(%Q{hello\n}) end it 'raises error when unparsable Ruby code is given' do expect { render_string('%span{x ==== 2}') }.to raise_error(Faml::Compiler::UnparsableRubyCode) end context 'with xhtml format' do it 'renders name="name" if value is true' do expect(render_string(%q|%span{foo: true, bar: 1} hello|, format: :xhtml)).to eq(%Q{hello\n}) expect(render_string(%Q|- foo = true\n%span{foo: foo, bar: 1} hello|, format: :xhtml)).to eq(%Q{hello\n}) expect(render_string(%Q|- h = {foo: true, bar: 1}\n%span{h} hello|, format: :xhtml)).to eq(%Q{hello\n}) end end it 'renders nested attributes' do expect(render_string(%q|%span{foo: {bar: 1+2}} hello|)).to eq(%Q|hello\n|) end it 'renders code attributes' do expect(render_string(<hello\n|) - attrs = { foo: 1, bar: { hoge: :fuga }, baz: true } %span{attrs} hello HAML end it 'renders dstr attributes' do expect(render_string(<hello\n|) - data = { foo: 1 } %span{data: "x\#{data}y"} hello HAML end it 'renders nested dstr attributes' do expect(render_string(<<'HAML')).to eq(%Q|hello\n|) - data = { foo: 1 } %span{foo: {bar: "x#{1}y"}} hello HAML end it 'optimize send case' do expect(render_string('%span{foo: {bar: 1+2}} hello')).to eq("hello\n") end it 'merges static id' do expect(render_string('#foo{id: "bar"} baz')).to eq("
baz
\n") end it 'merges static class' do expect(render_string('.foo{class: "bar"} baz')).to eq("
baz
\n") expect(render_string(<<'HAML')).to eq("
baz
\n") - bar = 'bar' .foo{class: "#{bar}"} baz HAML end it 'converts underscore to hyphen in data attributes' do expect(render_string("%span{data: {foo_bar: 'baz'}}")).to eq("\n") expect(render_string("- h = {foo_bar: 'baz'}\n%span{data: h}")).to eq("\n") end context 'with unmatched brace' do it 'raises error' do expect { render_string('%span{foo hello') }.to raise_error(Faml::SyntaxError) end it 'tries to parse next lines' do expect(render_string(<hello\n") %span{foo: 1, bar: 2} hello HAML end it "doesn't try to parse next lines without trailing comma" do expect { render_string(< :fuga, k1: { k2: 'v3' }}} hello|)).to eq(%Q{hello\n}) end it 'renders nested dynamic attributes' do expect(render_string(%q|%span{data: {foo: "b#{'a'}r"}} hello|)).to eq(%Q{hello\n}) end it 'renders nested attributes' do expect(render_string(%q|%span{data: {foo: 1, bar: 2+3}} hello|)).to eq(%Q{hello\n}) end it 'renders nested code attributes' do expect(render_string(<hello\n}) - data = { foo: 1, bar: 2 } %span{data: data} hello HAML end end it 'renders __LINE__ correctly' do expect(render_string(<\n") %span{b: __LINE__, a: __LINE__} HAML end describe 'with HTML-style attributes' do it 'parses simple values' do expect(render_string('%span(foo=1 bar=3) hello')).to eq("hello\n") end it 'parses variables' do expect(render_string(<hello\n") - foo = 'xxx' %span(foo=foo bar=3) hello HAML end it 'parses attributes with old syntax' do expect(render_string(<hello\n") - foo = 'foo' %span(foo=foo){bar: 3} hello HAML end it 'parses multiline attribute list' do expect(render_string(<\nhello\n\n") %span{data: {foo: 1, bar: 2}} %span hello HAML end it 'parses HTML-style multiline attribute list' do expect(render_string(<hello\n") %span(foo=1 bar=3) hello HAML end it "doesn't parse extra parens" do expect(render_string('%span(foo=1)(bar=3) hello')).to eq("(bar=3) hello\n") end it 'parses quoted value' do expect(render_string('%span(foo=1 bar="baz") hello')).to eq("hello\n") expect(render_string("%span(foo=1 bar='baz') hello")).to eq("hello\n") end it 'parses key-only attribute' do expect(render_string('%span(foo bar=1) hello')).to eq("hello\n") end it 'renders string interpolation' do expect(render_string(%q|%span(foo=1 bar="baz#{1 + 2}") hello|)).to eq("hello\n") expect(render_string(%q|%span(foo=1 bar='baz#{1 + 2}') hello|)).to eq("hello\n") end it 'parses escapes' do expect(render_string(%q|%span(foo=1 bar="ba\"z") hello|)).to eq("hello\n") expect(render_string(%q|%span(foo=1 bar='ba\'z') hello|)).to eq("hello\n") end it 'raises error when attributes list is unterminated' do expect { render_string('%span(foo=1 bar=2') }.to raise_error(Faml::SyntaxError) end it 'raises error when key is not alnum' do expect { render_string('%span(foo=1 3.14=3) hello') }.to raise_error(Faml::SyntaxError) end it 'raises error when value is missing' do expect { render_string('%span(foo=1 bar=) hello') }.to raise_error(Faml::SyntaxError) end it 'raises error when quote is unterminated' do expect { render_string('%span(foo=1 bar="baz) hello') }.to raise_error(Faml::SyntaxError) end it 'raises error when string interpolation is unterminated' do expect { render_string('%span(foo=1 bar="ba#{1") hello') }.to raise_error(Faml::SyntaxError) end it 'renders __LINE__ correctly' do expect(render_string(<\n") %span(b=__LINE__ a=__LINE__) HAML end end end