phlex 0.5.3 → 1.0.0.rc1

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.

Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -20
  3. data/config/sus.rb +0 -5
  4. data/lib/phlex/buffered.rb +2 -0
  5. data/lib/phlex/collection.rb +2 -0
  6. data/lib/phlex/elements.rb +1 -5
  7. data/lib/phlex/experimental.rb +10 -0
  8. data/lib/phlex/helpers.rb +2 -0
  9. data/lib/phlex/html.rb +73 -86
  10. data/lib/phlex/table.rb +1 -0
  11. data/lib/phlex/turbo/frame.rb +2 -0
  12. data/lib/phlex/turbo/stream.rb +2 -0
  13. data/lib/phlex/version.rb +1 -1
  14. data/lib/phlex.rb +2 -19
  15. metadata +6 -166
  16. data/Procfile.dev +0 -3
  17. data/Rakefile +0 -8
  18. data/config.ru +0 -9
  19. data/docs/assets/application.css +0 -32
  20. data/docs/assets/logo.png +0 -0
  21. data/docs/build.rb +0 -30
  22. data/docs/components/callout.rb +0 -9
  23. data/docs/components/code_block.rb +0 -26
  24. data/docs/components/code_span.rb +0 -9
  25. data/docs/components/example.rb +0 -32
  26. data/docs/components/heading.rb +0 -9
  27. data/docs/components/layout.rb +0 -91
  28. data/docs/components/markdown.rb +0 -25
  29. data/docs/components/nav/item.rb +0 -33
  30. data/docs/components/nav.rb +0 -6
  31. data/docs/components/tabs/tab.rb +0 -28
  32. data/docs/components/tabs.rb +0 -30
  33. data/docs/components/title.rb +0 -9
  34. data/docs/page_builder.rb +0 -39
  35. data/docs/pages/application_page.rb +0 -7
  36. data/docs/pages/helpers.rb +0 -97
  37. data/docs/pages/index.rb +0 -27
  38. data/docs/pages/library/collections.rb +0 -83
  39. data/docs/pages/rails/getting_started.rb +0 -57
  40. data/docs/pages/rails/helpers.rb +0 -55
  41. data/docs/pages/rails/layouts.rb +0 -61
  42. data/docs/pages/rails/migrating.rb +0 -37
  43. data/docs/pages/rails/rendering_views.rb +0 -35
  44. data/docs/pages/rails_integration.rb +0 -58
  45. data/docs/pages/templates.rb +0 -144
  46. data/docs/pages/testing/capybara.rb +0 -48
  47. data/docs/pages/testing/getting_started.rb +0 -44
  48. data/docs/pages/testing/nokogiri.rb +0 -83
  49. data/docs/pages/testing/rails.rb +0 -17
  50. data/docs/pages/translations.rb +0 -81
  51. data/docs/pages/views.rb +0 -184
  52. data/fixtures/compiler_test_helpers.rb +0 -19
  53. data/fixtures/content.rb +0 -60
  54. data/fixtures/dummy/app/assets/config/manifest.js +0 -0
  55. data/fixtures/dummy/app/components/comment_component.html.erb +0 -14
  56. data/fixtures/dummy/app/components/comment_component.rb +0 -8
  57. data/fixtures/dummy/app/components/reaction_component.html.erb +0 -3
  58. data/fixtures/dummy/app/components/reaction_component.rb +0 -7
  59. data/fixtures/dummy/app/controllers/articles_controller.rb +0 -4
  60. data/fixtures/dummy/app/controllers/comments_controller.rb +0 -4
  61. data/fixtures/dummy/app/views/application_view.rb +0 -8
  62. data/fixtures/dummy/app/views/articles/form.rb +0 -15
  63. data/fixtures/dummy/app/views/articles/index.html.erb +0 -14
  64. data/fixtures/dummy/app/views/articles/new.html.erb +0 -1
  65. data/fixtures/dummy/app/views/card.rb +0 -15
  66. data/fixtures/dummy/app/views/comments/comment.rb +0 -25
  67. data/fixtures/dummy/app/views/comments/index.html.erb +0 -3
  68. data/fixtures/dummy/app/views/comments/reaction.rb +0 -17
  69. data/fixtures/dummy/app/views/comments/show.html.erb +0 -3
  70. data/fixtures/dummy/app/views/heading.rb +0 -9
  71. data/fixtures/dummy/config/database.yml +0 -3
  72. data/fixtures/dummy/config/routes.rb +0 -5
  73. data/fixtures/dummy/config/storage.yml +0 -3
  74. data/fixtures/dummy/db/schema.rb +0 -6
  75. data/fixtures/dummy/log/.gitignore +0 -1
  76. data/fixtures/dummy/public/favicon.ico +0 -0
  77. data/fixtures/rails_helper.rb +0 -11
  78. data/fixtures/standard_element.rb +0 -87
  79. data/fixtures/void_element.rb +0 -31
  80. data/lib/generators/phlex/collection/USAGE +0 -8
  81. data/lib/generators/phlex/collection/collection_generator.rb +0 -13
  82. data/lib/generators/phlex/collection/templates/collection.rb.erb +0 -16
  83. data/lib/generators/phlex/controller/USAGE +0 -10
  84. data/lib/generators/phlex/controller/controller_generator.rb +0 -54
  85. data/lib/generators/phlex/controller/templates/controller.rb.erb +0 -10
  86. data/lib/generators/phlex/controller/templates/view.rb.erb +0 -14
  87. data/lib/generators/phlex/layout/USAGE +0 -8
  88. data/lib/generators/phlex/layout/layout_generator.rb +0 -13
  89. data/lib/generators/phlex/layout/templates/layout.rb.erb +0 -31
  90. data/lib/generators/phlex/page/USAGE +0 -8
  91. data/lib/generators/phlex/page/page_generator.rb +0 -13
  92. data/lib/generators/phlex/page/templates/page.rb.erb +0 -13
  93. data/lib/generators/phlex/table/USAGE +0 -8
  94. data/lib/generators/phlex/table/table_generator.rb +0 -14
  95. data/lib/generators/phlex/table/templates/table.rb.erb +0 -11
  96. data/lib/generators/phlex/view/USAGE +0 -8
  97. data/lib/generators/phlex/view/templates/view.rb.erb +0 -14
  98. data/lib/generators/phlex/view/view_generator.rb +0 -21
  99. data/lib/install/phlex.rb +0 -39
  100. data/lib/phlex/block.rb +0 -16
  101. data/lib/phlex/compiler/elements.rb +0 -49
  102. data/lib/phlex/compiler/formatter.rb +0 -91
  103. data/lib/phlex/compiler/generators/content.rb +0 -103
  104. data/lib/phlex/compiler/generators/element.rb +0 -61
  105. data/lib/phlex/compiler/nodes/base.rb +0 -19
  106. data/lib/phlex/compiler/nodes/call.rb +0 -9
  107. data/lib/phlex/compiler/nodes/command.rb +0 -13
  108. data/lib/phlex/compiler/nodes/fcall.rb +0 -18
  109. data/lib/phlex/compiler/nodes/method_add_block.rb +0 -33
  110. data/lib/phlex/compiler/nodes/vcall.rb +0 -9
  111. data/lib/phlex/compiler/optimizer.rb +0 -66
  112. data/lib/phlex/compiler/visitors/base.rb +0 -15
  113. data/lib/phlex/compiler/visitors/file.rb +0 -29
  114. data/lib/phlex/compiler/visitors/stable_scope.rb +0 -28
  115. data/lib/phlex/compiler/visitors/statements.rb +0 -36
  116. data/lib/phlex/compiler/visitors/view.rb +0 -19
  117. data/lib/phlex/compiler/visitors/view_method.rb +0 -59
  118. data/lib/phlex/compiler.rb +0 -70
  119. data/lib/phlex/html/callbacks.rb +0 -11
  120. data/lib/phlex/markdown.rb +0 -76
  121. data/lib/phlex/rails/engine.rb +0 -10
  122. data/lib/phlex/rails/form.rb +0 -67
  123. data/lib/phlex/rails/helpers.rb +0 -118
  124. data/lib/phlex/rails/layout.rb +0 -15
  125. data/lib/phlex/rails.rb +0 -11
  126. data/lib/phlex/renderable.rb +0 -47
  127. data/lib/phlex/testing/capybara.rb +0 -25
  128. data/lib/phlex/testing/nokogiri.rb +0 -24
  129. data/lib/phlex/testing/rails.rb +0 -19
  130. data/lib/phlex/translation.rb +0 -23
  131. data/lib/tasks/phlex_tasks.rake +0 -11
  132. data/package-lock.json +0 -1195
  133. data/package.json +0 -5
  134. data/tailwind.config.js +0 -7
@@ -1,32 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- pre { tab-size: 2; }
6
-
7
- .tabs input[type="radio"]:checked + label {
8
- background: #f8f8f8;
9
- z-index: 1;
10
- margin-bottom: -1px;
11
- padding-bottom: 1px;
12
- }
13
-
14
- .tabs input[type="radio"]:focus + label {
15
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
16
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
17
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
18
- }
19
-
20
- .tabs input[type="radio"]:checked + label + .tab {
21
- display: block;
22
- }
23
-
24
- p {
25
- @apply my-5
26
- }
27
-
28
- .prose ol, .prose ul {
29
- list-style: revert;
30
- margin: 0 0 0 1rem;
31
- padding: 0 0 0 1rem;
32
- }
data/docs/assets/logo.png DELETED
Binary file
data/docs/build.rb DELETED
@@ -1,30 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- $stdout.sync = true
5
-
6
- require "phlex"
7
- require "phlex/markdown"
8
- require "bundler"
9
- require "fileutils"
10
- require "i18n"
11
-
12
- Bundler.require :docs
13
-
14
- loader = Zeitwerk::Loader.new
15
- loader.push_dir(__dir__)
16
- loader.ignore(__FILE__)
17
- loader.inflector.inflect("rspec" => "RSpec")
18
- loader.enable_reloading
19
- loader.setup
20
- loader.eager_load
21
-
22
- PageBuilder.build_all
23
-
24
- if ARGV.include? "--watch"
25
- Filewatcher.new("#{__dir__}/**/*rb").watch do |_changes|
26
- loader.reload
27
- loader.eager_load
28
- PageBuilder.build_all
29
- end
30
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Callout < Phlex::HTML
5
- def template(&block)
6
- div(class: "rounded bg-orange-50 text-sm p-5 border border-orange-100", &block)
7
- end
8
- end
9
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class CodeBlock < Phlex::HTML
5
- FORMATTER = Rouge::Formatters::HTML.new
6
-
7
- def initialize(code, syntax:)
8
- @code = code
9
- @syntax = syntax
10
- end
11
-
12
- def template
13
- pre(class: "highlight p-5 whitespace-pre-wrap bg-stone-50") {
14
- unsafe_raw FORMATTER.format(
15
- lexer.lex(@code)
16
- )
17
- }
18
- end
19
-
20
- private
21
-
22
- def lexer
23
- Rouge::Lexer.find(@syntax)
24
- end
25
- end
26
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class CodeSpan < Phlex::HTML
5
- def template(&block)
6
- code(class: "bg-stone-50 inline-block font-medium rounded border px-1 -mt-1", &block)
7
- end
8
- end
9
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Example < Phlex::HTML
5
- def initialize
6
- @sandbox = Module.new
7
- end
8
-
9
- def template(&block)
10
- render Tabs.new do |t|
11
- @t = t
12
- yield self
13
- end
14
- end
15
-
16
- def tab(name, code, syntax: :ruby)
17
- @t.tab(name) do
18
- render CodeBlock.new(code, syntax: syntax)
19
- end
20
-
21
- @sandbox.class_eval(code) if syntax == :ruby
22
- end
23
-
24
- def execute(code)
25
- output = @sandbox.class_eval(code)
26
-
27
- @t.tab("👀 Output") do
28
- render CodeBlock.new(HtmlBeautifier.beautify(output), syntax: :html)
29
- end
30
- end
31
- end
32
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Heading < Phlex::HTML
5
- def template(&block)
6
- h2(class: "text-2xl font-semibold mt-10 mb-5", &block)
7
- end
8
- end
9
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Layout < Phlex::HTML
5
- register_element :style
6
-
7
- def initialize(title:)
8
- @title = title
9
- end
10
-
11
- def template(&block)
12
- doctype
13
-
14
- html do
15
- head do
16
- meta charset: "utf-8"
17
- meta name: "viewport", content: "width=device-width, initial-scale=1"
18
- title { @title }
19
- link href: "/application.css", rel: "stylesheet"
20
- style { unsafe_raw Rouge::Theme.find("github").render(scope: ".highlight") }
21
- end
22
-
23
- body class: "text-stone-700" do
24
- div class: "flex flex-col" do
25
- header class: "border-b py-4 px-4 lg:px-10 flex justify-between items-center sticky top-0 left-0 bg-white z-50" do
26
- div class: "flex flex-row items-center gap-2" do
27
- label for: "nav-toggle", class: "cursor-pointer lg:hidden" do
28
- unsafe_raw '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-8 h-8"> <path fill-rule="evenodd" d="M3 6.75A.75.75 0 013.75 6h16.5a.75.75 0 010 1.5H3.75A.75.75 0 013 6.75zM3 12a.75.75 0 01.75-.75h16.5a.75.75 0 010 1.5H3.75A.75.75 0 013 12zm0 5.25a.75.75 0 01.75-.75h16.5a.75.75 0 010 1.5H3.75a.75.75 0 01-.75-.75z" clip-rule="evenodd" /> </svg>'
29
- end
30
-
31
- a(href: "/", class: "block") { img src: "/assets/logo.png", width: "100" }
32
- end
33
-
34
- nav(class: "text-stone-500 font-medium") do
35
- ul(class: "flex space-x-8") do
36
- li { a(href: "https://github.com/sponsors/joeldrapper") { "💖️ Sponsor" } }
37
- li { a(href: "https://github.com/joeldrapper/phlex") { "GitHub" } }
38
- end
39
- end
40
- end
41
-
42
- div do
43
- div class: "flex flex-row" do
44
- input type: "checkbox", id: "nav-toggle", class: "flex-0 peer hidden"
45
- label for: "nav-toggle", class: "top-0 bottom-0 left-0 right-0 bg-gray-900 opacity-0 transition-all peer-checked:fixed peer-checked:z-30 peer-checked:block peer-checked:opacity-50 lg:hidden lg:peer-checked:hidden"
46
- nav class: "fixed lg:relative w-3/4 border-r-2 border-gray-100 lg:border-0 lg:w-1/4 text-lg lg:text-base h-full z-40 px-10 py-5 -left-full transition-all peer-checked:left-0 lg:left-0 bg-white" do
47
- h2(class: "text-lg font-semibold pt-5") { "Guide" }
48
-
49
- ul do
50
- render Nav::Item.new("Introduction", to: Pages::Index, active_page: @_parent)
51
- render Nav::Item.new("Views", to: Pages::Views, active_page: @_parent)
52
- render Nav::Item.new("Templates", to: Pages::Templates, active_page: @_parent)
53
- render Nav::Item.new("Helpers", to: Pages::Helpers, active_page: @_parent)
54
- render Nav::Item.new("Translations", to: Pages::Translations, active_page: @_parent)
55
- end
56
-
57
- h2(class: "text-lg font-semibold pt-5") { "Testing" }
58
-
59
- ul do
60
- render Nav::Item.new("Getting Started", to: Pages::Testing::GettingStarted, active_page: @_parent)
61
- render Nav::Item.new("Nokogiri", to: Pages::Testing::Nokogiri, active_page: @_parent)
62
- render Nav::Item.new("Capybara", to: Pages::Testing::Capybara, active_page: @_parent)
63
- render Nav::Item.new("Rails", to: Pages::Testing::Rails, active_page: @_parent)
64
- end
65
-
66
- h2(class: "text-lg font-semibold pt-5") { "Rails" }
67
-
68
- ul do
69
- render Nav::Item.new("Getting started", to: Pages::Rails::GettingStarted, active_page: @_parent)
70
- render Nav::Item.new("Rendering views", to: Pages::Rails::RenderingViews, active_page: @_parent)
71
- render Nav::Item.new("Layouts", to: Pages::Rails::Layouts, active_page: @_parent)
72
- render Nav::Item.new("Helpers", to: Pages::Rails::Helpers, active_page: @_parent)
73
- render Nav::Item.new("Migrating to Phlex", to: Pages::Rails::Migrating, active_page: @_parent)
74
- end
75
- end
76
-
77
- main class: "w-full lg:w-3/4 px-6 lg:px-20 py-5 border-0 lg:border-l-2 border-gray-100" do
78
- div(class: "max-w-full lg:max-w-prose prose", &block)
79
- end
80
- end
81
-
82
- footer class: "border-t p-20 flex justify-center text-stone-500 text-lg font-medium" do
83
- a(href: "https://github.com/sponsors/joeldrapper") { "Sponsor this project 💖" }
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Markdown < Phlex::Markdown
5
- def code(&content)
6
- render CodeSpan.new, &content
7
- end
8
-
9
- def code_block(code, language:)
10
- render CodeBlock.new(code.gsub(/(?:^|\G) {4}/m, " "), syntax: language)
11
- end
12
-
13
- def h1(&content)
14
- render Title.new, &content
15
- end
16
-
17
- def h2(&content)
18
- render Heading.new, &content
19
- end
20
-
21
- def a(**attributes, &content)
22
- super(class: "font-bold text-red-600 underline underline-offset-4", **attributes, &content)
23
- end
24
- end
25
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Nav::Item < Phlex::HTML
5
- def initialize(text, to:, active_page:)
6
- @text = text
7
- @to = to
8
- @active_page = active_page
9
- end
10
-
11
- def template
12
- li do
13
- a(**link_classes, href: "/#{link}") { @text }
14
- end
15
- end
16
-
17
- def link_classes
18
- classes("pb-1 block font-medium text-stone-500", active?: "text-red-600 font-bold")
19
- end
20
-
21
- def link
22
- path == "index" ? "" : path
23
- end
24
-
25
- def path
26
- @to.name.split("::")[1..].map { _1.gsub(/(.)([A-Z])/, '\1-\2') }.map(&:downcase).join("/")
27
- end
28
-
29
- def active?
30
- @active_page.instance_of?(@to)
31
- end
32
- end
33
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Nav < Phlex::HTML
5
- end
6
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Tabs
5
- class Tab < Phlex::HTML
6
- def initialize(name:, checked:)
7
- @name = name
8
- @checked = checked
9
- end
10
-
11
- def template(&block)
12
- input class: "opacity-0 fixed peer", type: "radio", name: @_parent.unique_identifier, id: unique_identifier, checked: @checked
13
-
14
- label id: "#{unique_identifier}-label", for: unique_identifier, role: "tab", aria_controls: "#{unique_identifier}-panel", class: "order-1 py-2 px-5 bg-white text-sm border border-b-0 border-l-0 font-medium first-of-type:border-l first-of-type:rounded-tl last-of-type:rounded-tr before:absolute before:pointer-events-none before:w-full before:ring before:h-full before:left-0 before:top-0 before:hidden before:rounded peer-focus:before:block cursor-pointer" do
15
- @name
16
- end
17
-
18
- div id: "#{unique_identifier}-panel", role: "tabpanel", aria_labelledby: "#{unique_identifier}-label", class: "tab hidden order-2 w-full border rounded-b rounded-tr overflow-hidden" do
19
- @_parent.instance_exec(&block)
20
- end
21
- end
22
-
23
- def unique_identifier
24
- @unique_identifier ||= SecureRandom.hex
25
- end
26
- end
27
- end
28
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Tabs < Phlex::HTML
5
- def initialize
6
- @index = 1
7
- end
8
-
9
- def template(&block)
10
- div class: "tabs flex flex-wrap relative my-5", role: "tablist" do
11
- yield_content(&block)
12
- end
13
- end
14
-
15
- def tab(name, &block)
16
- render(Tab.new(name: name, checked: first?), &block)
17
- @index += 1
18
- end
19
-
20
- def unique_identifier
21
- @unique_identifier ||= SecureRandom.hex
22
- end
23
-
24
- private
25
-
26
- def first?
27
- @index == 1
28
- end
29
- end
30
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Components
4
- class Title < Phlex::HTML
5
- def template(&block)
6
- h1(class: "text-3xl font-semibold my-5", &block)
7
- end
8
- end
9
- end
data/docs/page_builder.rb DELETED
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class PageBuilder
4
- ROOT = Pages::ApplicationPage
5
-
6
- def self.build_all
7
- FileUtils.mkdir_p("#{__dir__}/dist")
8
- FileUtils.cp_r("#{__dir__}/assets", "#{__dir__}/dist")
9
- ROOT.subclasses.each { |page| new(page).call }
10
- end
11
-
12
- def initialize(page)
13
- @page = page
14
- end
15
-
16
- def call
17
- puts "Building #{@page.name}"
18
- FileUtils.mkdir_p(directory)
19
- File.write(file, @page.new.call)
20
- end
21
-
22
- private
23
-
24
- def file
25
- "#{directory}/index.html"
26
- end
27
-
28
- def directory
29
- if path == "index"
30
- "#{__dir__}/dist"
31
- else
32
- "#{__dir__}/dist/#{path}"
33
- end
34
- end
35
-
36
- def path
37
- @page.name.split("::")[1..].map { _1.gsub(/(.)([A-Z])/, '\1-\2') }.map(&:downcase).join("/")
38
- end
39
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pages
4
- class ApplicationPage < Phlex::HTML
5
- include ::Components
6
- end
7
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pages
4
- class Helpers < ApplicationPage
5
- def template
6
- render Layout.new(title: "Helpers") do
7
- render Markdown.new(<<~MD)
8
- # Helpers
9
-
10
- ## Conditional tokens and classes
11
-
12
- The `tokens` method helps you define conditional HTML attribute tokens (such as CSS classes). It accepts a splat of tokens that should always be output as well as optional keyword arguments for conditional tokens.
13
-
14
- The keyword arguments allow you to specify under which conditions certain tokens are applicable. The keys are the conditions and the values are the tokens. Conditions can be Procs which are evaluated, or Symbols that map to an instance method. The `:active?` Symbol, for example, maps to the `active?` instance method.
15
-
16
- Here we have a `Link` view that produces an `<a>` tag with the CSS class `nav-item`. If the link is _active_, we also apply the CSS class `nav-item-active`.
17
- MD
18
-
19
- render Example.new do |e|
20
- e.tab "link.rb", <<~RUBY
21
- class Link < Phlex::HTML
22
- def initialize(text, to:, active:)
23
- @text = text
24
- @to = to
25
- @active = active
26
- end
27
-
28
- def template
29
- a(href: @to, class: tokens("nav-item",
30
- active?: "nav-item-active")) { @text }
31
- end
32
-
33
- private
34
-
35
- def active? = @active
36
- end
37
- RUBY
38
-
39
- e.tab "example.rb", <<~RUBY
40
- class Example < Phlex::HTML
41
- def template
42
- nav do
43
- ul do
44
- li { render Link.new("Home", to: "/", active: true) }
45
- li { render Link.new("About", to: "/about", active: false) }
46
- end
47
- end
48
- end
49
- end
50
- RUBY
51
-
52
- e.execute "Example.new.call"
53
- end
54
-
55
- render Markdown.new(<<~MD)
56
- You can also use the `classes` helper method to create a token list of classes. Since this method returns a hash, e.g. `{ class: "your CSS classes here" }`, you can destructure it into a `class:` keyword argument using the `**` prefix operator.
57
- MD
58
-
59
- render Example.new do |e|
60
- e.tab "link.rb", <<~RUBY
61
- class Link < Phlex::HTML
62
- def initialize(text, to:, active:)
63
- @text = text
64
- @to = to
65
- @active = active
66
- end
67
-
68
- def template
69
- a(href: @to, **classes("nav-item",
70
- active?: "nav-item-active")) { @text }
71
- end
72
-
73
- private
74
-
75
- def active? = @active
76
- end
77
- RUBY
78
-
79
- e.tab "example.rb", <<~RUBY
80
- class Example < Phlex::HTML
81
- def template
82
- nav do
83
- ul do
84
- li { render Link.new("Home", to: "/", active: true) }
85
- li { render Link.new("About", to: "/about", active: false) }
86
- end
87
- end
88
- end
89
- end
90
- RUBY
91
-
92
- e.execute "Example.new.call"
93
- end
94
- end
95
- end
96
- end
97
- end
data/docs/pages/index.rb DELETED
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pages
4
- class Index < ApplicationPage
5
- def template
6
- render Layout.new(title: "Introduction to Phlex, a fast, object-oriented view framework for Ruby") do
7
- render Markdown.new(<<~MD)
8
- # Introduction
9
-
10
- Phlex is a framework for building fast, reusable, testable views in pure Ruby.
11
-
12
- ## Better developer experience 💃
13
-
14
- Phlex views are plain old Ruby objects. View classes are just Ruby classes, templates are just methods, and HTML tags are just method calls. If you know how to define a method that calls another method, you pretty much already know how to use Phlex.
15
-
16
- ## Better safety 🥽
17
-
18
- Phlex view templates render in an isolated execution context where only the instance variables and methods for the specific view are exposed.
19
-
20
- ## Better performance 🔥
21
-
22
- Rendering a Phlex view is ~4.35× faster than an ActionView partial and ~2× faster than ViewComponent component.
23
- MD
24
- end
25
- end
26
- end
27
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pages
4
- module Library
5
- class Collections < ApplicationPage
6
- def template
7
- render Layout.new(title: "Getting started with Rails") do
8
- render Markdown.new <<~MD
9
- # Collections
10
-
11
- Phlex comes with an abstract pattern for views that represent collections of resources — lists, grids, tables, etc. Collections have two parts: one part wraps the whole collection, the other part is repeated once for each item in that collection.
12
-
13
- When you include `Phlex::Collection` in a `Phlex::HTML`, the `template` and `initialize` methods are defined for you. You don't need to define these. Instead, you define a `collection_template` and `item_template`.
14
-
15
- ## Collection template
16
-
17
- The `collection_template` method should accept a content block which is used to yield the items. We can yield this block or pass it to another element, such as `<ul>`.
18
-
19
- ```ruby
20
- def collection_template(&)
21
- ul(&)
22
- end
23
- ```
24
-
25
- ## Item template
26
-
27
- From the `item_template` method, you can access a single item with the `@item` instance variable.
28
-
29
- ```ruby
30
- def item_template
31
- li { @item }
32
- end
33
- ```
34
-
35
- ## Rendering a collection
36
-
37
- Putting it all together, we can create a `List` view that renders each item in an `<li>`, all wrapped up in an outer `<ul>`.
38
-
39
- We can render the list by passing any Enumerable as the `collection` keyword argument. Here, we pass the array `["A", "B", "C"]`.
40
- MD
41
-
42
- render Example.new do |e|
43
- e.tab "list.rb", <<~RUBY
44
- class List < Phlex::HTML
45
- include Phlex::Collection
46
-
47
- def collection_template(&content)
48
- ul(&content)
49
- end
50
-
51
- def item_template
52
- li { @item }
53
- end
54
- end
55
- RUBY
56
-
57
- e.tab "example.rb", <<~RUBY
58
- class Example < Phlex::HTML
59
- def template
60
- render List.new(
61
- collection: ["A", "B", "C"]
62
- )
63
- end
64
- end
65
- RUBY
66
-
67
- e.execute "Example.new.call"
68
- end
69
-
70
- render Markdown.new <<~MD
71
- ## Rendering a single item
72
-
73
- Sometimes you need to render one item of a collection on its own. This is especially handy if you're using Hotwire to append an item to the end of an existing collection. You can render an individual item without the collection wrapper by passing an `item` keyword argument to the collection view.
74
-
75
- ```ruby
76
- render List.new(item: "A")
77
- ```
78
- MD
79
- end
80
- end
81
- end
82
- end
83
- end