rux 1.1.2 → 1.3.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.
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'attributes', type: :parser do
4
+ it 'handles single-quoted rux attributes' do
5
+ expect(compile("<Hello foo='bar' />")).to eq(
6
+ 'render(Hello.new(foo: "bar"))'
7
+ )
8
+
9
+ expect(compile("<Hello foo='bar'></Hello>")).to eq(
10
+ 'render(Hello.new(foo: "bar"))'
11
+ )
12
+ end
13
+
14
+ it 'handles double-quoted rux attributes' do
15
+ expect(compile('<Hello foo="bar" />')).to eq(
16
+ 'render(Hello.new(foo: "bar"))'
17
+ )
18
+
19
+ expect(compile('<Hello foo="bar"></Hello>')).to eq(
20
+ 'render(Hello.new(foo: "bar"))'
21
+ )
22
+ end
23
+
24
+ it 'handles unquoted rux attributes' do
25
+ expect(compile('<Hello foo=bar />')).to eq(
26
+ 'render(Hello.new(foo: "bar"))'
27
+ )
28
+
29
+ expect(compile('<Hello foo=bar></Hello>')).to eq(
30
+ 'render(Hello.new(foo: "bar"))'
31
+ )
32
+ end
33
+
34
+ it 'handles non-uniform spacing between attributes' do
35
+ expect(compile('<Hello foo="bar" baz= "boo" bix ="bit" />')).to eq(
36
+ 'render(Hello.new(foo: "bar", baz: "boo", bix: "bit"))'
37
+ )
38
+ end
39
+
40
+ it 'handles boolean attributes' do
41
+ expect(compile('<Hello disabled />')).to eq(
42
+ 'render(Hello.new(disabled: "true"))'
43
+ )
44
+
45
+ expect(compile('<Hello disabled/>')).to eq(
46
+ 'render(Hello.new(disabled: "true"))'
47
+ )
48
+
49
+ expect(compile('<Hello disabled></Hello>')).to eq(
50
+ 'render(Hello.new(disabled: "true"))'
51
+ )
52
+ end
53
+
54
+ it 'converts dashes to underscores in attribute keys' do
55
+ expect(compile('<Hello foo-bar="baz" />')).to eq(
56
+ 'render(Hello.new(foo_bar: "baz"))'
57
+ )
58
+ end
59
+
60
+ it 'handles simple ruby statements in attributes' do
61
+ expect(compile('<Hello foo={true} />')).to eq(
62
+ 'render(Hello.new(foo: true))'
63
+ )
64
+ end
65
+
66
+ it 'handles ruby hashes in attributes' do
67
+ expect(compile('<Hello foo={{ foo: "bar", baz: "boo" }} />')).to eq(
68
+ 'render(Hello.new(foo: { foo: "bar", baz: "boo" }))'
69
+ )
70
+ end
71
+
72
+ it 'handles ruby code with curly braces in attributes' do
73
+ expect(compile('<Hello foo={[1, 2, 3].map { |n| n * 2 }} />')).to eq(<<~RUBY.strip)
74
+ render(Hello.new(foo: [1, 2, 3].map { |n|
75
+ n * 2
76
+ }))
77
+ RUBY
78
+ end
79
+
80
+ it 'slugifies ruby arguments' do
81
+ code = <<~RUX
82
+ <Hello data-foo="bar" />
83
+ RUX
84
+ expect(compile(code)).to eq(<<~RUBY.strip)
85
+ render(Hello.new(data_foo: "bar"))
86
+ RUBY
87
+ end
88
+
89
+ it 'does not slugify HTML attributes' do
90
+ code = <<~RUX
91
+ <div data-foo="bar" />
92
+ RUX
93
+ expect(compile(code)).to eq(<<~RUBY.strip)
94
+ Rux.tag("div", { :"data-foo" => "bar" })
95
+ RUBY
96
+ end
97
+
98
+ it 'yields the component instance to the block using the as: argument for the variable name' do
99
+ code = <<~RUX
100
+ <Hello as={hello}>
101
+ {hello.foo}
102
+ </Hello>
103
+ RUX
104
+ expect(compile(code)).to eq(<<~RUBY.strip)
105
+ render(Hello.new) { |hello|
106
+ Rux.create_buffer.tap { |_rux_buf_|
107
+ _rux_buf_.append(hello.foo)
108
+ }.to_s
109
+ }
110
+ RUBY
111
+ end
112
+
113
+ it 'allows attributes to start with @' do
114
+ code = <<~RUX
115
+ <div @click="alert('foo')" />
116
+ RUX
117
+ expect(compile(code)).to eq(<<~RUBY.strip)
118
+ Rux.tag("div", { :@click => "alert('foo')" })
119
+ RUBY
120
+ end
121
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'fragments', type: :parser do
4
+ it 'allows fragments' do
5
+ code = <<~RUX
6
+ <>
7
+ <div>Foo 1</div>
8
+ <div>Foo 2</div>
9
+ </>
10
+ RUX
11
+ expect(compile(code)).to eq(<<~RUBY.strip)
12
+ Rux.create_buffer.tap { |_rux_buf_|
13
+ _rux_buf_.append(Rux.tag("div") {
14
+ Rux.create_buffer.tap { |_rux_buf_|
15
+ _rux_buf_.safe_append("Foo 1")
16
+ }.to_s
17
+ })
18
+ _rux_buf_.append(Rux.tag("div") {
19
+ Rux.create_buffer.tap { |_rux_buf_|
20
+ _rux_buf_.safe_append("Foo 2")
21
+ }.to_s
22
+ })
23
+ }.to_s
24
+ RUBY
25
+ end
26
+
27
+ it 'allows fragments nested inside ruby code' do
28
+ code = <<~RUX
29
+ <table>
30
+ {rows.map do |row|
31
+ <>{row}</>
32
+ end}
33
+ </table>
34
+ RUX
35
+ expect(compile(code)).to eq(<<~RUBY.strip)
36
+ Rux.tag("table") {
37
+ Rux.create_buffer.tap { |_rux_buf_|
38
+ _rux_buf_.append(rows.map { |row|
39
+ Rux.create_buffer.tap { |_rux_buf_|
40
+ _rux_buf_.append(row)
41
+ }.to_s
42
+ })
43
+ }.to_s
44
+ }
45
+ RUBY
46
+ end
47
+
48
+ it 'allows fragments nested inside other tags' do
49
+ code = <<~RUX
50
+ <div>
51
+ <>{"foo"}</>
52
+ </div>
53
+ RUX
54
+ expect(compile(code)).to eq(<<~RUBY.strip)
55
+ Rux.tag("div") {
56
+ Rux.create_buffer.tap { |_rux_buf_|
57
+ _rux_buf_.append(Rux.create_buffer.tap { |_rux_buf_|
58
+ _rux_buf_.append("foo")
59
+ }.to_s)
60
+ }.to_s
61
+ }
62
+ RUBY
63
+ end
64
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'html safety', type: :parser do
4
+ it 'escapes HTML entities in strings' do
5
+ expect(compile('<Hello>"foo"</Hello>')).to eq(<<~RUBY.strip)
6
+ render(Hello.new) { |rux_block_arg0|
7
+ Rux.create_buffer.tap { |_rux_buf_|
8
+ _rux_buf_.safe_append("&quot;foo&quot;")
9
+ }.to_s
10
+ }
11
+ RUBY
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'slots', type: :parser do
4
+ it 'correctly transforms slot components into slot methods' do
5
+ code = <<~RUX
6
+ <TableComponent>
7
+ <WithRow>
8
+ <WithColumn>Foo 1</WithColumn>
9
+ </WithRow>
10
+ <WithRow>
11
+ <WithColumn>Foo 2</WithColumn>
12
+ </WithRow>
13
+ </TableComponent>
14
+ RUX
15
+ expect(compile(code)).to eq(<<~RUBY.strip)
16
+ render(TableComponent.new) { |rux_block_arg0|
17
+ Rux.create_buffer.tap { |_rux_buf_|
18
+ _rux_buf_.append((rux_block_arg0.with_row { |rux_block_arg1|
19
+ Rux.create_buffer.tap { |_rux_buf_|
20
+ _rux_buf_.append((rux_block_arg1.with_column { |rux_block_arg2|
21
+ Rux.create_buffer.tap { |_rux_buf_|
22
+ _rux_buf_.safe_append("Foo 1")
23
+ }.to_s
24
+ }; nil))
25
+ }.to_s
26
+ }; nil))
27
+ _rux_buf_.append((rux_block_arg0.with_row { |rux_block_arg1|
28
+ Rux.create_buffer.tap { |_rux_buf_|
29
+ _rux_buf_.append((rux_block_arg1.with_column { |rux_block_arg2|
30
+ Rux.create_buffer.tap { |_rux_buf_|
31
+ _rux_buf_.safe_append("Foo 2")
32
+ }.to_s
33
+ }; nil))
34
+ }.to_s
35
+ }; nil))
36
+ }.to_s
37
+ }
38
+ RUBY
39
+ end
40
+ end
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'tags', type: :parser do
4
+ it 'handles a single self-closing tag' do
5
+ expect(compile("<Hello/>")).to eq("render(Hello.new)")
6
+ end
7
+
8
+ it 'handles a self-closing tag with spaces preceding the closing punctuation' do
9
+ expect(compile("<Hello />")).to eq("render(Hello.new)")
10
+ end
11
+
12
+ it 'handles a single opening and closing tag' do
13
+ expect(compile("<Hello></Hello>")).to eq('render(Hello.new)')
14
+ end
15
+
16
+ it 'handles a single tag with a text body' do
17
+ expect(compile("<Hello>foo</Hello>")).to eq(<<~RUBY.strip)
18
+ render(Hello.new) { |rux_block_arg0|
19
+ Rux.create_buffer.tap { |_rux_buf_|
20
+ _rux_buf_.safe_append("foo")
21
+ }.to_s
22
+ }
23
+ RUBY
24
+ end
25
+
26
+ it 'handles simple ruby statements in tag bodies' do
27
+ expect(compile('<Hello>{"foo"}</Hello>')).to eq(<<~RUBY.strip)
28
+ render(Hello.new) { |rux_block_arg0|
29
+ Rux.create_buffer.tap { |_rux_buf_|
30
+ _rux_buf_.append("foo")
31
+ }.to_s
32
+ }
33
+ RUBY
34
+ end
35
+
36
+ it 'handles tag bodies containing ruby code with curly braces' do
37
+ expect(compile('<Hello>{[1, 2, 3].map { |n| n * 2 }.join(", ")}</Hello>')).to eq(<<~RUBY.strip)
38
+ render(Hello.new) { |rux_block_arg0|
39
+ Rux.create_buffer.tap { |_rux_buf_|
40
+ _rux_buf_.append([1, 2, 3].map { |n|
41
+ n * 2
42
+ }.join(", "))
43
+ }.to_s
44
+ }
45
+ RUBY
46
+ end
47
+
48
+ it 'handles tag bodies with intermixed text and ruby code' do
49
+ expect(compile('<Hello>abc {foo} def {bar} baz</Hello>')).to eq(<<~RUBY.strip)
50
+ render(Hello.new) { |rux_block_arg0|
51
+ Rux.create_buffer.tap { |_rux_buf_|
52
+ _rux_buf_.safe_append("abc ")
53
+ _rux_buf_.append(foo)
54
+ _rux_buf_.safe_append(" def ")
55
+ _rux_buf_.append(bar)
56
+ _rux_buf_.safe_append(" baz")
57
+ }.to_s
58
+ }
59
+ RUBY
60
+ end
61
+
62
+ it 'handles rux tags inside ruby code' do
63
+ rux_code = <<~RUX
64
+ <Outer>
65
+ {5.times.map do
66
+ <Inner>What a {@thing}</Inner>
67
+ end}
68
+ </Outer>
69
+ RUX
70
+
71
+ expect(compile(rux_code)).to eq(<<~RUBY.strip)
72
+ render(Outer.new) { |rux_block_arg0|
73
+ Rux.create_buffer.tap { |_rux_buf_|
74
+ _rux_buf_.append(5.times.map {
75
+ render(Inner.new) { |rux_block_arg1|
76
+ Rux.create_buffer.tap { |_rux_buf_|
77
+ _rux_buf_.safe_append("What a ")
78
+ _rux_buf_.append(@thing)
79
+ }.to_s
80
+ }
81
+ })
82
+ }.to_s
83
+ }
84
+ RUBY
85
+ end
86
+
87
+ it 'handles HTML tags inside ruby code' do
88
+ rux_code = <<~RUX
89
+ <div>
90
+ {5.times.map do
91
+ <p>What a {@thing}</p>
92
+ end}
93
+ </div>
94
+ RUX
95
+
96
+ expect(compile(rux_code)).to eq(<<~RUBY.strip)
97
+ Rux.tag("div") {
98
+ Rux.create_buffer.tap { |_rux_buf_|
99
+ _rux_buf_.append(5.times.map {
100
+ Rux.tag("p") {
101
+ Rux.create_buffer.tap { |_rux_buf_|
102
+ _rux_buf_.safe_append("What a ")
103
+ _rux_buf_.append(@thing)
104
+ }.to_s
105
+ }
106
+ })
107
+ }.to_s
108
+ }
109
+ RUBY
110
+ end
111
+
112
+ it 'handles regular HTML tags' do
113
+ expect(compile('<div>foo</div>')).to eq(<<~RUBY.strip)
114
+ Rux.tag("div") {
115
+ Rux.create_buffer.tap { |_rux_buf_|
116
+ _rux_buf_.safe_append("foo")
117
+ }.to_s
118
+ }
119
+ RUBY
120
+ end
121
+
122
+ it 'handles regular HTML tags inside ruby code' do
123
+ rux_code = <<~RUX
124
+ <Outer>
125
+ {5.times.map do
126
+ <div>So {@cool}</div>
127
+ end}
128
+ </Outer>
129
+ RUX
130
+
131
+ expect(compile(rux_code)).to eq(<<~RUBY.strip)
132
+ render(Outer.new) { |rux_block_arg0|
133
+ Rux.create_buffer.tap { |_rux_buf_|
134
+ _rux_buf_.append(5.times.map {
135
+ Rux.tag("div") {
136
+ Rux.create_buffer.tap { |_rux_buf_|
137
+ _rux_buf_.safe_append("So ")
138
+ _rux_buf_.append(@cool)
139
+ }.to_s
140
+ }
141
+ })
142
+ }.to_s
143
+ }
144
+ RUBY
145
+ end
146
+
147
+ it 'demonstrates that tags support keyword splats' do
148
+ code = <<~RUX
149
+ <div {**args}>foo</div>
150
+ RUX
151
+
152
+ expect(compile(code)).to eq(<<~RUBY.strip)
153
+ Rux.tag("div", { **args }) {
154
+ Rux.create_buffer.tap { |_rux_buf_|
155
+ _rux_buf_.safe_append("foo")
156
+ }.to_s
157
+ }
158
+ RUBY
159
+ end
160
+
161
+ it 'demonstrates that tags support keyword arguments mixed with splats' do
162
+ code = <<~RUX
163
+ <div foo="bar" {**args} baz={"boo"}>foo</div>
164
+ RUX
165
+
166
+ expect(compile(code)).to eq(<<~RUBY.strip)
167
+ Rux.tag("div", { foo: "bar", **args, baz: "boo" }) {
168
+ Rux.create_buffer.tap { |_rux_buf_|
169
+ _rux_buf_.safe_append("foo")
170
+ }.to_s
171
+ }
172
+ RUBY
173
+ end
174
+ end