phlex 0.3.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of phlex might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.editorconfig +8 -0
- data/.rubocop.yml +21 -5
- data/Gemfile +26 -12
- data/Procfile.dev +3 -0
- data/README.md +1 -1
- data/Rakefile +3 -5
- data/SECURITY.md +1 -1
- data/bench.rb +7 -0
- data/config/sus.rb +15 -0
- data/docs/assets/application.css +6 -0
- data/docs/build.rb +17 -10
- data/docs/components/callout.rb +1 -1
- data/docs/components/code_block.rb +2 -2
- data/docs/components/code_span.rb +9 -0
- data/docs/components/example.rb +5 -5
- data/docs/components/heading.rb +2 -2
- data/docs/components/layout.rb +62 -17
- data/docs/components/markdown.rb +14 -15
- data/docs/components/nav/item.rb +33 -0
- data/docs/components/nav.rb +6 -0
- data/docs/components/tabs/tab.rb +4 -2
- data/docs/components/tabs.rb +1 -1
- data/docs/components/title.rb +2 -2
- data/docs/page_builder.rb +3 -0
- data/docs/pages/application_page.rb +1 -1
- data/docs/pages/helpers.rb +97 -0
- data/docs/pages/index.rb +6 -17
- data/docs/pages/library/collections.rb +83 -0
- data/docs/pages/rails/getting_started.rb +53 -0
- data/docs/pages/rails/helpers.rb +55 -0
- data/docs/pages/rails/layouts.rb +61 -0
- data/docs/pages/rails/migrating.rb +37 -0
- data/docs/pages/rails/rendering_views.rb +35 -0
- data/docs/pages/templates.rb +53 -151
- data/docs/pages/testing/capybara.rb +48 -0
- data/docs/pages/testing/getting_started.rb +44 -0
- data/docs/pages/testing/nokogiri.rb +83 -0
- data/docs/pages/testing/rails.rb +17 -0
- data/docs/pages/translations.rb +81 -0
- data/docs/pages/views.rb +87 -78
- data/fixtures/compiler_test_helpers.rb +19 -0
- data/fixtures/content.rb +60 -0
- data/fixtures/dummy/app/components/comment_component.html.erb +14 -0
- data/fixtures/dummy/app/components/comment_component.rb +8 -0
- data/fixtures/dummy/app/components/reaction_component.html.erb +3 -0
- data/fixtures/dummy/app/components/reaction_component.rb +7 -0
- data/fixtures/dummy/app/controllers/comments_controller.rb +4 -0
- data/fixtures/dummy/app/views/application_view.rb +8 -0
- data/fixtures/dummy/app/views/articles/form.rb +3 -1
- data/fixtures/dummy/app/views/card.rb +4 -2
- data/fixtures/dummy/app/views/comments/comment.rb +25 -0
- data/fixtures/dummy/app/views/comments/index.html.erb +3 -0
- data/fixtures/dummy/app/views/comments/reaction.rb +17 -0
- data/fixtures/dummy/app/views/comments/show.html.erb +3 -0
- data/fixtures/dummy/app/views/heading.rb +1 -1
- data/fixtures/layout.rb +5 -5
- data/fixtures/page.rb +18 -24
- data/fixtures/{test_helper.rb → rails_helper.rb} +3 -7
- data/fixtures/standard_element.rb +87 -0
- data/fixtures/view_helper.rb +1 -1
- data/fixtures/void_element.rb +31 -0
- data/lib/generators/phlex/collection/USAGE +8 -0
- data/lib/generators/phlex/collection/collection_generator.rb +13 -0
- data/lib/generators/phlex/collection/templates/collection.rb.erb +16 -0
- data/lib/generators/phlex/controller/USAGE +10 -0
- data/lib/generators/phlex/controller/controller_generator.rb +54 -0
- data/lib/generators/phlex/controller/templates/controller.rb.erb +10 -0
- data/lib/generators/phlex/controller/templates/view.rb.erb +14 -0
- data/lib/generators/phlex/layout/USAGE +8 -0
- data/lib/generators/phlex/layout/layout_generator.rb +13 -0
- data/lib/generators/phlex/layout/templates/layout.rb.erb +31 -0
- data/lib/generators/phlex/page/USAGE +8 -0
- data/lib/generators/phlex/page/page_generator.rb +13 -0
- data/lib/generators/phlex/page/templates/page.rb.erb +13 -0
- data/lib/generators/phlex/table/USAGE +8 -0
- data/lib/generators/phlex/table/table_generator.rb +14 -0
- data/lib/generators/phlex/table/templates/table.rb.erb +11 -0
- data/lib/generators/phlex/view/templates/view.rb.erb +7 -1
- data/lib/generators/phlex/view/view_generator.rb +9 -1
- data/lib/install/phlex.rb +10 -1
- data/lib/phlex/block.rb +2 -4
- data/lib/phlex/buffered.rb +6 -8
- data/lib/phlex/callable.rb +9 -0
- data/lib/phlex/collection.rb +33 -0
- data/lib/phlex/compiler/elements.rb +49 -0
- data/lib/phlex/compiler/generators/content.rb +103 -0
- data/lib/phlex/compiler/generators/element.rb +61 -0
- data/lib/phlex/compiler/nodes/base.rb +19 -0
- data/lib/phlex/compiler/nodes/call.rb +9 -0
- data/lib/phlex/compiler/nodes/command.rb +13 -0
- data/lib/phlex/compiler/nodes/fcall.rb +18 -0
- data/lib/phlex/compiler/nodes/method_add_block.rb +33 -0
- data/lib/phlex/compiler/nodes/vcall.rb +9 -0
- data/lib/phlex/compiler/optimizer.rb +66 -0
- data/lib/phlex/compiler/visitors/base.rb +15 -0
- data/lib/phlex/compiler/visitors/file.rb +23 -11
- data/lib/phlex/compiler/visitors/stable_scope.rb +28 -0
- data/lib/phlex/compiler/visitors/statements.rb +36 -0
- data/lib/phlex/compiler/visitors/view.rb +19 -0
- data/lib/phlex/compiler/visitors/view_method.rb +59 -0
- data/lib/phlex/compiler.rb +23 -3
- data/lib/phlex/elements.rb +57 -0
- data/lib/phlex/engine.rb +0 -3
- data/lib/phlex/helpers.rb +59 -0
- data/lib/phlex/html/callbacks.rb +11 -0
- data/lib/phlex/html.rb +209 -54
- data/lib/phlex/markdown.rb +76 -0
- data/lib/phlex/rails/form.rb +67 -0
- data/lib/phlex/rails/helpers.rb +118 -0
- data/lib/phlex/rails/layout.rb +15 -0
- data/lib/phlex/rails.rb +10 -0
- data/lib/phlex/renderable.rb +9 -3
- data/lib/phlex/table.rb +104 -0
- data/lib/phlex/testing/capybara.rb +25 -0
- data/lib/phlex/testing/nokogiri.rb +24 -0
- data/lib/phlex/testing/rails.rb +19 -0
- data/lib/phlex/testing/view_helper.rb +15 -0
- data/lib/phlex/translation.rb +23 -0
- data/lib/phlex/turbo/frame.rb +21 -0
- data/lib/phlex/turbo/stream.rb +18 -0
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +22 -24
- metadata +112 -15
- data/.rspec +0 -1
- data/fixtures/compilation/vcall.rb +0 -38
- data/lib/phlex/compiler/generators/standard_element.rb +0 -30
- data/lib/phlex/compiler/generators/void_element.rb +0 -29
- data/lib/phlex/compiler/optimizers/base_optimizer.rb +0 -34
- data/lib/phlex/compiler/optimizers/vcall.rb +0 -29
- data/lib/phlex/compiler/visitors/base_visitor.rb +0 -19
- data/lib/phlex/compiler/visitors/component.rb +0 -28
- data/lib/phlex/compiler/visitors/component_method.rb +0 -28
- data/lib/phlex/rails/tag_helpers.rb +0 -29
- data/lib/phlex/view.rb +0 -223
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest"
|
4
|
+
|
5
|
+
module Pages
|
6
|
+
module Testing
|
7
|
+
class Capybara < ApplicationPage
|
8
|
+
def template
|
9
|
+
render Layout.new(title: "Testing with Capybara") do
|
10
|
+
render Markdown.new(<<~MD)
|
11
|
+
# Testing with Capybara
|
12
|
+
|
13
|
+
Require `phlex/testing/capybara` and include `Phlex::Testing::Capybara::ViewHelper` to use [Capybara](http://teamcapybara.github.io/capybara/) matchers.
|
14
|
+
|
15
|
+
The `render` method will return a `Capybara::Node::Simple` and set the `page` attribute to the result.
|
16
|
+
MD
|
17
|
+
|
18
|
+
render Example.new do |e|
|
19
|
+
e.tab "test.rb", <<~RUBY
|
20
|
+
require "phlex/testing/capybara"
|
21
|
+
|
22
|
+
class TestExample < Minitest::Test
|
23
|
+
include Phlex::Testing::Capybara::ViewHelper
|
24
|
+
|
25
|
+
def test_example
|
26
|
+
render Example.new("Joel")
|
27
|
+
assert_select "h1", text: "Hello Joel"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
RUBY
|
31
|
+
|
32
|
+
e.tab "hello.rb", <<~RUBY
|
33
|
+
class Hello < Phlex::HTML
|
34
|
+
def initialize(name)
|
35
|
+
@name = name
|
36
|
+
end
|
37
|
+
|
38
|
+
def template
|
39
|
+
h1 { "Hello \#{@name}" }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
RUBY
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pages
|
4
|
+
module Testing
|
5
|
+
class GettingStarted < ApplicationPage
|
6
|
+
def template
|
7
|
+
render Layout.new(title: "Getting Started Testing Phlex Views") do
|
8
|
+
render Markdown.new(<<~MD)
|
9
|
+
# Getting Started
|
10
|
+
|
11
|
+
The `Phlex::Testing::ViewHelper` module defines `render` allowing you to render Phlex views directly in your tests and make assertions against the output.
|
12
|
+
MD
|
13
|
+
|
14
|
+
render Example.new do |e|
|
15
|
+
e.tab "test/test_hello.rb", <<~RUBY
|
16
|
+
require "phlex/testing/view_helper"
|
17
|
+
|
18
|
+
class TestHello < Minitest::Test
|
19
|
+
include Phlex::Testing::ViewHelper
|
20
|
+
|
21
|
+
def test_hello_output_includes_name
|
22
|
+
output = render Hello.new("Joel")
|
23
|
+
assert_equal "<h1>Hello Joel</h1>", output
|
24
|
+
end
|
25
|
+
end
|
26
|
+
RUBY
|
27
|
+
|
28
|
+
e.tab "hello.rb", <<~RUBY
|
29
|
+
class Hello < Phlex::HTML
|
30
|
+
def initialize(name)
|
31
|
+
@name = name
|
32
|
+
end
|
33
|
+
|
34
|
+
def template
|
35
|
+
h1 { "Hello \#{@name}" }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
RUBY
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pages
|
4
|
+
module Testing
|
5
|
+
class Nokogiri < ApplicationPage
|
6
|
+
def template
|
7
|
+
render Layout.new(title: "Testing with Nokogiri") do
|
8
|
+
render Markdown.new(<<~MD)
|
9
|
+
# Testing with Nokogiri
|
10
|
+
|
11
|
+
Phlex includes test helpers for working with rendered views as [Nokogiri](https://nokogiri.org) documents and fragments.
|
12
|
+
|
13
|
+
Nokogiri is not a dependency of Phlex, so you’ll need to install that separately to use this helper.
|
14
|
+
|
15
|
+
## Documents
|
16
|
+
|
17
|
+
If your view represents a whole HTML document, you can require `phlex/testing/nokogiri` and include the `Phlex::Testing::Nokogiri::DocumentHelper` module to render your view as `Nokogiri::Document` using the `render` method.
|
18
|
+
MD
|
19
|
+
|
20
|
+
render Example.new do |e|
|
21
|
+
e.tab "test.rb", <<~RUBY
|
22
|
+
require "phlex/testing/nokogiri"
|
23
|
+
|
24
|
+
class TestExample < Minitest::Test
|
25
|
+
include Phlex::Testing::Nokogiri::DocumentHelper
|
26
|
+
|
27
|
+
def test_example
|
28
|
+
output = render Example.new
|
29
|
+
assert_equal "Hello Joel", output.css("h1").text
|
30
|
+
end
|
31
|
+
end
|
32
|
+
RUBY
|
33
|
+
|
34
|
+
e.tab "hello.rb", <<~RUBY
|
35
|
+
class Hello < Phlex::HTML
|
36
|
+
def initialize(name)
|
37
|
+
@name = name
|
38
|
+
end
|
39
|
+
|
40
|
+
def template
|
41
|
+
h1 { "Hello \#{@name}" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
end
|
46
|
+
|
47
|
+
render Markdown.new(<<~MD)
|
48
|
+
## Fragments
|
49
|
+
|
50
|
+
If your view represents a fragment (partial), you can require `phlex/testing/nokogiri` and include the `Phlex::Testing::Nokogiri::FragmentHelper` module to render your view as `Nokogiri::Fragment` with the `render` method.
|
51
|
+
MD
|
52
|
+
|
53
|
+
render Example.new do |e|
|
54
|
+
e.tab "test.rb", <<~RUBY
|
55
|
+
require "phlex/testing/nokogiri"
|
56
|
+
|
57
|
+
class TestExample < Minitest::Test
|
58
|
+
include Phlex::Testing::Nokogiri::FragmentHelper
|
59
|
+
|
60
|
+
def test_example
|
61
|
+
output = render Example.new("Joel")
|
62
|
+
assert_equal "Hello Joel", output.css("h1").text
|
63
|
+
end
|
64
|
+
end
|
65
|
+
RUBY
|
66
|
+
|
67
|
+
e.tab "hello.rb", <<~RUBY
|
68
|
+
class Hello < Phlex::HTML
|
69
|
+
def initialize(name)
|
70
|
+
@name = name
|
71
|
+
end
|
72
|
+
|
73
|
+
def template
|
74
|
+
h1 { "Hello \#{@name}" }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
RUBY
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pages
|
4
|
+
module Testing
|
5
|
+
class Rails < ApplicationPage
|
6
|
+
def template
|
7
|
+
render Layout.new(title: "Testing Phlex Views in Rails") do
|
8
|
+
render Markdown.new(<<~MD)
|
9
|
+
# Testing Phlex views in Rails
|
10
|
+
|
11
|
+
When you include `Phlex::Testing::Rails::ViewHelper`, views rendered in the test will have a view context, so they can use Rails helpers.
|
12
|
+
MD
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pages
|
4
|
+
class Translations < ApplicationPage
|
5
|
+
def initialize
|
6
|
+
I18n.backend.store_translations(
|
7
|
+
"pt-BR", {
|
8
|
+
hello: "Olá",
|
9
|
+
views: { feedback: { welcome_message: { hello: "Olá" } } }
|
10
|
+
}
|
11
|
+
)
|
12
|
+
I18n.locale = "pt-BR"
|
13
|
+
end
|
14
|
+
|
15
|
+
def template
|
16
|
+
render Layout.new(title: "Translations") do
|
17
|
+
render Markdown.new(<<~MD)
|
18
|
+
# Translations
|
19
|
+
|
20
|
+
Phlex has built-in support for translations with the **[I18n Gem](https://github.com/ruby-i18n/i18n)**.
|
21
|
+
|
22
|
+
Just include `Phlex::Translation` in your view and use the `translate` method to access a translation.
|
23
|
+
MD
|
24
|
+
|
25
|
+
render Example.new do |e|
|
26
|
+
e.tab "welcome_message.rb", <<~RUBY
|
27
|
+
class WelcomeMessage < Phlex::HTML
|
28
|
+
include Phlex::Translation
|
29
|
+
|
30
|
+
def template
|
31
|
+
h1 { translate("hello") }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
RUBY
|
35
|
+
|
36
|
+
e.tab "pt-PR.yml", <<~YAML, syntax: :yaml
|
37
|
+
pt-BR:
|
38
|
+
hello: "Olá"
|
39
|
+
YAML
|
40
|
+
|
41
|
+
e.execute "WelcomeMessage.new.call"
|
42
|
+
end
|
43
|
+
|
44
|
+
render Markdown.new(<<~MD)
|
45
|
+
## Implicit scoopes
|
46
|
+
|
47
|
+
Start your translate key with a `.` to use the name of the view as an implicit scope.
|
48
|
+
MD
|
49
|
+
|
50
|
+
render Example.new do |e|
|
51
|
+
e.tab "welcome_message.rb", <<~RUBY
|
52
|
+
module Views
|
53
|
+
module Feedback
|
54
|
+
class WelcomeMessage < Phlex::HTML
|
55
|
+
include Phlex::Translation
|
56
|
+
|
57
|
+
def template
|
58
|
+
h1 { translate(".hello") }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
RUBY
|
64
|
+
|
65
|
+
e.tab "pt-BR.yml", <<~YAML, syntax: :yaml
|
66
|
+
pt-BR:
|
67
|
+
views:
|
68
|
+
feedback:
|
69
|
+
welcome_message:
|
70
|
+
hello: Olá
|
71
|
+
YAML
|
72
|
+
|
73
|
+
e.execute <<~RUBY
|
74
|
+
Views::Feedback::WelcomeMessage.translation_path = 'views.feedback.welcome_message'
|
75
|
+
Views::Feedback::WelcomeMessage.new.call
|
76
|
+
RUBY
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/docs/pages/views.rb
CHANGED
@@ -3,69 +3,77 @@
|
|
3
3
|
module Pages
|
4
4
|
class Views < ApplicationPage
|
5
5
|
def template
|
6
|
-
render Layout.new(title: "
|
6
|
+
render Layout.new(title: "Phlex Views") do
|
7
7
|
render Markdown.new(<<~MD)
|
8
8
|
# Views
|
9
9
|
|
10
|
-
|
10
|
+
Phlex Views are Ruby objects that represent your app's user interface — from pages and layouts and nav-bars, to headings and buttons and links.
|
11
11
|
|
12
|
-
|
12
|
+
You can create a view class by subclassing `Phlex::HTML` and defining a `template` instance method.
|
13
13
|
MD
|
14
14
|
|
15
15
|
render Example.new do |e|
|
16
|
-
e.tab "
|
17
|
-
class
|
18
|
-
def template
|
19
|
-
|
20
|
-
h1 "Amazing content!"
|
21
|
-
yield_content(&)
|
22
|
-
}
|
16
|
+
e.tab "hello.rb", <<~RUBY
|
17
|
+
class Hello < Phlex::HTML
|
18
|
+
def template
|
19
|
+
h1 { "👋 Hello World!" }
|
23
20
|
end
|
24
21
|
end
|
25
22
|
RUBY
|
26
23
|
|
27
|
-
e.execute "
|
24
|
+
e.execute "Hello.new.call"
|
28
25
|
end
|
29
26
|
|
30
27
|
render Markdown.new(<<~MD)
|
31
|
-
|
28
|
+
The `template` method determines what your view will output when its rendered. The above example will output an `<h1>` tag with the content `👋 Hello world!`. Click on the "Output" tab above to see for yourself.
|
29
|
+
|
30
|
+
## Accepting arguments
|
32
31
|
|
33
|
-
|
32
|
+
You can define an initializer for your views just like any other Ruby class. Let's make our `Hello` view take a `name` as a keyword argument, save it in an instance variable and render that variable in the template.
|
33
|
+
|
34
|
+
We'll render this view with the arguments `name: "Joel"` and see what it produces.
|
34
35
|
MD
|
35
36
|
|
36
37
|
render Example.new do |e|
|
37
|
-
e.tab "
|
38
|
-
class
|
39
|
-
def
|
40
|
-
|
38
|
+
e.tab "hello.rb", <<~RUBY
|
39
|
+
class Hello < Phlex::HTML
|
40
|
+
def initialize(name:)
|
41
|
+
@name = name
|
42
|
+
end
|
43
|
+
|
44
|
+
def template
|
45
|
+
h1 { "👋 Hello \#{@name}!" }
|
41
46
|
end
|
42
47
|
end
|
43
48
|
RUBY
|
44
49
|
|
45
|
-
e.execute "
|
50
|
+
e.execute "Hello.new(name: 'Joel').call"
|
46
51
|
end
|
47
52
|
|
48
53
|
render Markdown.new(<<~MD)
|
49
|
-
##
|
54
|
+
## Rendering views
|
50
55
|
|
51
|
-
|
56
|
+
Views can render other views in their templates using the `render` method. Let's try rendering a couple of instances of this `Hello` view from a new `Example` view and look at the output of the `Example` view.
|
52
57
|
MD
|
53
58
|
|
54
59
|
render Example.new do |e|
|
55
60
|
e.tab "example.rb", <<~RUBY
|
56
|
-
class Example < Phlex::
|
61
|
+
class Example < Phlex::HTML
|
57
62
|
def template
|
58
|
-
render
|
59
|
-
|
60
|
-
end
|
63
|
+
render Hello.new(name: "Joel")
|
64
|
+
render Hello.new(name: "Alexandre")
|
61
65
|
end
|
62
66
|
end
|
63
67
|
RUBY
|
64
68
|
|
65
|
-
e.tab "
|
66
|
-
class
|
67
|
-
def
|
68
|
-
|
69
|
+
e.tab "hello.rb", <<~RUBY
|
70
|
+
class Hello < Phlex::HTML
|
71
|
+
def initialize(name:)
|
72
|
+
@name = name
|
73
|
+
end
|
74
|
+
|
75
|
+
def template
|
76
|
+
h1 { "👋 Hello \#{@name}!" }
|
69
77
|
end
|
70
78
|
end
|
71
79
|
RUBY
|
@@ -74,22 +82,28 @@ module Pages
|
|
74
82
|
end
|
75
83
|
|
76
84
|
render Markdown.new(<<~MD)
|
77
|
-
|
85
|
+
## Passing content blocks
|
86
|
+
|
87
|
+
Views can also yield content blocks, which can be passed in when rendering. Let's make a `Card` component that yields content in an `<article>` element with a `drop-shadow` class on it.
|
78
88
|
MD
|
79
89
|
|
80
90
|
render Example.new do |e|
|
81
|
-
e.tab "
|
82
|
-
class
|
83
|
-
def template
|
84
|
-
|
91
|
+
e.tab "card.rb", <<~RUBY
|
92
|
+
class Card < Phlex::HTML
|
93
|
+
def template(&content)
|
94
|
+
article(class: "drop-shadow") do
|
95
|
+
yield_content(&content)
|
96
|
+
end
|
85
97
|
end
|
86
98
|
end
|
87
99
|
RUBY
|
88
100
|
|
89
|
-
e.tab "
|
90
|
-
class
|
91
|
-
def template
|
92
|
-
|
101
|
+
e.tab "example.rb", <<~RUBY
|
102
|
+
class Example < Phlex::HTML
|
103
|
+
def template
|
104
|
+
render Card.new do
|
105
|
+
h1 { "👋 Hello!" }
|
106
|
+
end
|
93
107
|
end
|
94
108
|
end
|
95
109
|
RUBY
|
@@ -98,28 +112,38 @@ module Pages
|
|
98
112
|
end
|
99
113
|
|
100
114
|
render Markdown.new(<<~MD)
|
101
|
-
|
115
|
+
The template in the `Card` view accepts a block argument `&content` and uses the `yield_content` method to yield it in an `<article>` element.
|
102
116
|
|
103
|
-
|
104
|
-
MD
|
117
|
+
The `Example` view renders a `Card` and passes it a block with an `<h1>` element.
|
105
118
|
|
106
|
-
|
107
|
-
e.tab "hello.rb", <<~RUBY
|
108
|
-
class Hello < Phlex::View
|
109
|
-
def initialize(name:)
|
110
|
-
@name = name
|
111
|
-
end
|
119
|
+
Looking at the output of the `Example` view, we can see the `<h1>` element was rendered inside the `<article>` element from the `Card` view.
|
112
120
|
|
113
|
-
|
114
|
-
|
115
|
-
|
121
|
+
## Delegating content blocks
|
122
|
+
|
123
|
+
Since the block of content was the only thing we need in the `<article>` element, we could have just passed the content block to the element instead.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
class Card < Phlex::HTML
|
127
|
+
def template(&content)
|
128
|
+
article(class: "drop-shadow", &content)
|
116
129
|
end
|
117
|
-
|
130
|
+
end
|
131
|
+
```
|
132
|
+
MD
|
133
|
+
|
134
|
+
render Markdown.new(<<~MD)
|
135
|
+
## Registering custom elements
|
118
136
|
|
137
|
+
You can register custom elements with the `register_element` macro. The custom element will only be available in the view where it is registered and subclasses of that view.
|
138
|
+
MD
|
139
|
+
|
140
|
+
render Example.new do |e|
|
119
141
|
e.tab "example.rb", <<~RUBY
|
120
|
-
class Example < Phlex::
|
142
|
+
class Example < Phlex::HTML
|
143
|
+
register_element :trix_editor
|
144
|
+
|
121
145
|
def template
|
122
|
-
|
146
|
+
trix_editor input: "content", autofocus: true
|
123
147
|
end
|
124
148
|
end
|
125
149
|
RUBY
|
@@ -128,41 +152,26 @@ module Pages
|
|
128
152
|
end
|
129
153
|
|
130
154
|
render Markdown.new(<<~MD)
|
131
|
-
|
155
|
+
## Callbacks
|
132
156
|
|
133
|
-
|
134
|
-
|
135
|
-
Views are just Ruby classes, so you can perform calculations on view attributes by defining your own methods.
|
157
|
+
Prepend the `Phlex::HTML::Callbacks` module, and if you define `#before_rendering_template` and/or `#after_rendering_template` method in your view, they will be called immediately before and after your template is rendered.
|
136
158
|
MD
|
137
159
|
|
138
160
|
render Example.new do |e|
|
139
|
-
e.tab "
|
140
|
-
class
|
141
|
-
|
142
|
-
@status = status
|
143
|
-
end
|
161
|
+
e.tab "example.rb", <<~RUBY
|
162
|
+
class Example < Phlex::HTML
|
163
|
+
prepend Phlex::HTML::Callbacks
|
144
164
|
|
145
|
-
def
|
146
|
-
|
165
|
+
def before_rendering_template
|
166
|
+
h1 { "Hello" }
|
147
167
|
end
|
148
168
|
|
149
|
-
|
150
|
-
|
151
|
-
def status_emoji
|
152
|
-
case @status
|
153
|
-
when :success
|
154
|
-
"✅"
|
155
|
-
when :failure
|
156
|
-
"❌"
|
157
|
-
end
|
169
|
+
def template
|
170
|
+
h2 { "World" }
|
158
171
|
end
|
159
|
-
end
|
160
|
-
RUBY
|
161
172
|
|
162
|
-
|
163
|
-
|
164
|
-
def template
|
165
|
-
render Status.new(status: :success)
|
173
|
+
def after_rendering_template
|
174
|
+
h3 { "Bye" }
|
166
175
|
end
|
167
176
|
end
|
168
177
|
RUBY
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CompilerTestHelpers
|
4
|
+
# @return Array
|
5
|
+
def compile(view)
|
6
|
+
@compiler = Phlex::Compiler.new(view)
|
7
|
+
output = []
|
8
|
+
|
9
|
+
mock(@compiler) do |m|
|
10
|
+
m.before(:redefine) { output << _1 }
|
11
|
+
end
|
12
|
+
|
13
|
+
@compiler.call
|
14
|
+
|
15
|
+
output.map! do |method|
|
16
|
+
Phlex::Compiler::Formatter.format("", SyntaxTree.parse(method))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/fixtures/content.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fixtures
|
4
|
+
module Content
|
5
|
+
class BareString < Phlex::HTML
|
6
|
+
def template
|
7
|
+
h1 { "Hello" }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Symbol < Phlex::HTML
|
12
|
+
def template
|
13
|
+
h1 { :hello }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Float < Phlex::HTML
|
18
|
+
def template
|
19
|
+
h1 { 1.2 }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Integer < Phlex::HTML
|
24
|
+
def template
|
25
|
+
h1 { 1 }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Variable < Phlex::HTML
|
30
|
+
def template
|
31
|
+
greeting = "Hello"
|
32
|
+
h1 { greeting }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class InstanceVariable < Phlex::HTML
|
37
|
+
def template
|
38
|
+
h1 { @hello }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class NestedTags < Phlex::HTML
|
43
|
+
def template
|
44
|
+
article {
|
45
|
+
h1 { "Inside" }
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class NonMutatingNestedContent < Phlex::HTML
|
51
|
+
def template
|
52
|
+
div { say_hello }
|
53
|
+
end
|
54
|
+
|
55
|
+
def say_hello
|
56
|
+
"Hello"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div>
|
2
|
+
<span>
|
3
|
+
<%= @name %>
|
4
|
+
</span>
|
5
|
+
<span>
|
6
|
+
<%= @body %>
|
7
|
+
</span>
|
8
|
+
|
9
|
+
<%= content %>
|
10
|
+
|
11
|
+
<%= render Views::Comments::Reaction.new(emoji: 'hamburger') do |reaction| %>
|
12
|
+
<p>Emoji reaction for a comment from <%= @name %> with body <%= @body %></p>
|
13
|
+
<% end %>
|
14
|
+
</div>
|