fluxbit_view_components 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +7 -1
- data/app/components/fluxbit/form/component.rb +3 -2
- data/app/components/fluxbit/form/form_builder_component.rb +4 -6
- data/app/components/fluxbit/form/select_free_input_component.rb +1 -1
- data/app/components/fluxbit/form/upload_image_input_component.rb +3 -8
- data/app/helpers/fluxbit/classes_helper.rb +0 -12
- data/lib/fluxbit/templates/darkmode.js.template +7 -0
- data/lib/fluxbit/templates/tailwind.config.js.template +4 -0
- data/lib/fluxbit/view_components/version.rb +1 -3
- data/lib/install/install.rb +57 -47
- data/lib/tasks/fluxbit_view_components_tasks.rake +30 -10
- metadata +5 -8
- data/lib/fluxbit/view_components/codemods/v3_slot_setters.rb +0 -222
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbaf175424393a228d6fc82018fcd81b93dc388df861dd8afc1fb4ce0ab901b1
|
4
|
+
data.tar.gz: '0728a9d9f386fcb06bf8e21898e39c0cf58a9b2f44763acfb6fe591d251f2600'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 618572080999a095ed82ed77875fae33507d208c5c0abbca39bd410742502e651215f3f7c5cedab195baf0d2a486aaa5ce45fcc4910646ab7806f33454c6d98f
|
7
|
+
data.tar.gz: e1e05c2e0445d8c9f92bae5f3580e3f08f235c65b0bab273538ca45acd3f07df2e2e35429934178883682c89ace072816010c79ae2ac435b6b9892894356a420
|
data/README.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Fluxbit ViewComponents
|
2
2
|
|
3
|
+
     
|
4
|
+
|
5
|
+
|
6
|
+
|
3
7
|
Fluxbit ViewComponents is an implementation of the Fluxbit Design System using [ViewComponent](https://github.com/github/view_component).
|
4
8
|
|
5
9
|
<div style="text-align: center;">
|
@@ -8,7 +12,9 @@ Fluxbit ViewComponents is an implementation of the Fluxbit Design System using [
|
|
8
12
|
|
9
13
|
## Preview
|
10
14
|
|
11
|
-
|
15
|
+
We have a Lookbook app online to show the documentation and all the Components available in action!
|
16
|
+
|
17
|
+
Just [Click here!](https://fluxbit.artz.to)
|
12
18
|
|
13
19
|
## Usage
|
14
20
|
|
@@ -24,9 +24,10 @@ class Fluxbit::Form::Component < Fluxbit::Component
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def define_helper_popover(helper_popover, object, field)
|
27
|
-
return helper_popover if helper_popover != false && !helper_popover.nil?
|
27
|
+
return helper_popover if (helper_popover != false && !helper_popover.nil?) || object.nil?
|
28
28
|
|
29
|
-
|
29
|
+
object_name = object.class.name.underscore.to_sym
|
30
|
+
I18n.t(field, scope: [ :activerecord, :helper_popover, object_name ], default: nil)
|
30
31
|
end
|
31
32
|
|
32
33
|
def label_value(label, object, field, id)
|
@@ -79,6 +79,7 @@ class Fluxbit::Form::FormBuilderComponent < Fluxbit::Component
|
|
79
79
|
else
|
80
80
|
''
|
81
81
|
end}#{element_type(kwargs[:type])}Component".constantize
|
82
|
+
|
82
83
|
unless kwargs[:with_content]
|
83
84
|
return content_tag(:div, render(component_klass.new(**kwargs), &block), class: outer_div)
|
84
85
|
end
|
@@ -104,14 +105,11 @@ class Fluxbit::Form::FormBuilderComponent < Fluxbit::Component
|
|
104
105
|
def generate_elements
|
105
106
|
return elements if elements?
|
106
107
|
|
107
|
-
safe_join(
|
108
|
-
end
|
109
|
-
|
110
|
-
def generate_div
|
111
|
-
safe_join errors?, content_tag(:div, generate_elements, @props)
|
108
|
+
safe_join(@elements.map { |element| choose_element(element.merge({ form: @form }), nil) })
|
112
109
|
end
|
113
110
|
|
114
111
|
def call
|
115
|
-
|
112
|
+
elements_rendered = elements? ? elements : safe_join(@elements.map { |element| choose_element(element.merge({ form: @form }), nil) })
|
113
|
+
safe_join [ errors?, content_tag(:div, elements_rendered, @props) ]
|
116
114
|
end
|
117
115
|
end
|
@@ -25,17 +25,12 @@ class Fluxbit::Form::UploadImageInputComponent < Fluxbit::Form::Component
|
|
25
25
|
@props = props
|
26
26
|
# @height = height.in?(styles[:height].keys) ? height : :md
|
27
27
|
@label = label_value(label, @object, field, id)
|
28
|
-
@helper_text = define_helper_text(helper_text, @object, field)
|
28
|
+
@helper_text = helper_text.present? ? define_helper_text(helper_text, @object, field) : ''
|
29
29
|
@helper_popover = define_helper_popover(helper_popover, @object, field)
|
30
30
|
@helper_popover_placement = helper_popover_placement
|
31
|
-
# binding.pry
|
32
31
|
@image_path = image_path || (if @object&.send(@field)&.send("attached?")
|
33
|
-
@object&.send(@field)&.variant(
|
34
|
-
|
35
|
-
160, 160
|
36
|
-
]
|
37
|
-
)
|
38
|
-
end) || image_placeholder
|
32
|
+
@object&.send(@field)&.variant(resize_to_fit: [ 160, 160 ])
|
33
|
+
end) || image_placeholder || ""
|
39
34
|
@props["class"] = "absolute inset-0 h-full w-full cursor-pointer rounded-md border-gray-300 opacity-0"
|
40
35
|
end
|
41
36
|
|
@@ -5,17 +5,5 @@ module Fluxbit
|
|
5
5
|
def fx_body_class
|
6
6
|
"h-full bg-slate-100 dark:bg-slate-900 dark:text-white"
|
7
7
|
end
|
8
|
-
|
9
|
-
def fx_darkmode_js
|
10
|
-
<<-SCRIPT.squish
|
11
|
-
<script>
|
12
|
-
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
13
|
-
document.documentElement.classList.add('dark');
|
14
|
-
} else {
|
15
|
-
document.documentElement.classList.remove('dark')
|
16
|
-
}
|
17
|
-
</script>
|
18
|
-
SCRIPT
|
19
|
-
end
|
20
8
|
end
|
21
9
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<script>
|
2
|
+
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
3
|
+
document.documentElement.classList.add('dark');
|
4
|
+
} else {
|
5
|
+
document.documentElement.classList.remove('dark')
|
6
|
+
}
|
7
|
+
</script>
|
data/lib/install/install.rb
CHANGED
@@ -1,64 +1,74 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
gem_path = Gem.loaded_specs['fluxbit_view_components'].full_gem_path
|
4
|
+
template_path = File.join(gem_path, "lib/fluxbit/templates/tailwind.config.js.template")
|
5
|
+
darkmode_path = File.join(gem_path, "lib/fluxbit/templates/darkmode.js.template")
|
6
|
+
layout_path = Rails.root.join("app/views/layouts/application.html.erb")
|
7
|
+
importmap_binstub = Rails.root.join("bin/importmap")
|
8
|
+
importmap_config = Rails.root.join("config/importmap.rb")
|
9
|
+
stimulus_path = Rails.root.join("app/javascript/controllers/index.js")
|
10
|
+
package_json_path = Rails.root.join("package.json")
|
11
|
+
tailwind_config_path = Rails.root.join("tailwind.config.js")
|
12
|
+
stylesheets_path = Rails.root.join("app/assets/stylesheets/application.tailwind.css")
|
7
13
|
|
8
|
-
|
9
|
-
say "Add Fluxbit styles in application layout"
|
10
|
-
insert_into_file APPLICATION_LAYOUT_PATH.to_s, "\n <%= stylesheet_link_tag \"fluxbit_view_components\" %>", before: /\s*<\/head>/
|
14
|
+
say = ->(msg, color = :green) { puts color == :red ? "\e[31m#{msg}\e[0m" : "\e[32m#{msg}\e[0m" }
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
Bundler.with_unbundled_env do
|
17
|
+
say.call "- Adding TailwindCSS gems..."
|
18
|
+
system "bundle add tailwindcss-ruby"
|
19
|
+
system "bundle add tailwindcss-rails"
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
say.call "- Running tailwindcss:install..."
|
23
|
+
system "#{RbConfig.ruby} ./bin/rails tailwindcss:install"
|
24
|
+
|
25
|
+
say.call "- Installing Flowbite via npm..."
|
26
|
+
system "npm install flowbite --save"
|
27
|
+
|
28
|
+
say.call "- Copying tailwind.config.js from template..."
|
29
|
+
if File.exist?(template_path)
|
30
|
+
FileUtils.cp(template_path, tailwind_config_path)
|
31
|
+
say.call " tailwind.config.js copied successfully!"
|
23
32
|
else
|
24
|
-
say "
|
25
|
-
say " 1. Add <%= stylesheet_link_tag \"fluxbit_view_components\" %> within the <head> tag in your custom layout."
|
26
|
-
say " 2. Replace <html> with <html class=\"<%= fluxbit_html_classes %>\" style=\"<%= fluxbit_html_styles %>\"> in your custom layour."
|
27
|
-
say " 3. Replace <body> with <body style=\"<%= fluxbit_body_styles %>\"> in your custom layour."
|
33
|
+
say.call " tailwind.config.js.template not found at #{template_path}.", :red
|
28
34
|
end
|
29
35
|
|
30
|
-
if
|
31
|
-
|
36
|
+
if stylesheets_path.exist?
|
37
|
+
say.call "- Updating CSS with Flowbite imports..."
|
38
|
+
content = File.read(stylesheets_path)
|
39
|
+
content.prepend("@import \"flowbite/src/themes/default\";\n")
|
40
|
+
content << "\n@plugin \"flowbite/plugin\";\n@source \"../../../node_modules/flowbite\";\n@config \"../../../tailwind.config.js\";\n"
|
41
|
+
File.write(stylesheets_path, content)
|
42
|
+
else
|
43
|
+
say.call "⚠️ Couldn't find application.tailwind.css, skipping CSS modifications", :red
|
44
|
+
end
|
32
45
|
|
33
|
-
|
34
|
-
|
35
|
-
run "bin/importmap pin @rails/request.js --download"
|
36
|
-
end
|
46
|
+
if layout_path.exist?
|
47
|
+
say.call "- Updating layout to include Fluxbit styles..."
|
37
48
|
|
38
|
-
|
39
|
-
append_to_file IMPORTMAP_CONFIG_PATH do
|
40
|
-
%(pin "fluxbit-view-components", to: "fluxbit_view_components.js"\n)
|
41
|
-
end
|
42
|
-
else
|
43
|
-
package_json = File.read(Rails.root.join("package.json"))
|
49
|
+
layout_content = File.read(layout_path)
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
if layout_content.include?("<head>")
|
52
|
+
darkmode_content = File.read(darkmode_path)
|
53
|
+
gsub_file layout_path.to_s, "</head>", "#{darkmode_content}\n</head>"
|
54
|
+
say.call " Added darkmode js before </head> tag."
|
55
|
+
else
|
56
|
+
say.call "</head> tag is not found in application layout.", :red
|
57
|
+
say.call " Add darkmode js manually before the </head> tag."
|
48
58
|
end
|
49
59
|
|
50
|
-
say "Add fluxbit-view-components package"
|
51
|
-
run "yarn add fluxbit-view-components"
|
52
|
-
end
|
53
60
|
|
54
|
-
if
|
55
|
-
|
56
|
-
|
57
|
-
|
61
|
+
if layout_content.include?("<body")
|
62
|
+
# gsub_file layout_path.to_s, "<html", "<html class=\"<%= fluxbit_html_classes %>\""
|
63
|
+
gsub_file layout_path.to_s, "<body>", "<body class=\"<%= fx_body_class %>\">"
|
64
|
+
else
|
65
|
+
say.call "<body> tag is not found in application layout.", :red
|
66
|
+
say.call " Replace <html> and <body> manually as instructed."
|
58
67
|
end
|
59
68
|
else
|
60
|
-
say "Default
|
61
|
-
say " Add
|
62
|
-
say "
|
63
|
-
say " registerFluxbitControllers(Stimulus)"
|
69
|
+
say.call "❌ Default application.html.erb is missing!", :red
|
70
|
+
say.call " 1. Add stylesheet_link_tag inside <head>"
|
71
|
+
say.call " 2. Replace <html> and <body> manually."
|
64
72
|
end
|
73
|
+
|
74
|
+
say.call "✅ Fluxbit ViewComponents install completed!"
|
@@ -1,22 +1,42 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fluxbit/view_components/codemods/v3_slot_setters"
|
4
|
-
|
5
3
|
namespace :fluxbit_view_components do
|
6
4
|
desc "Setup Fluxbit::ViewComponents for the app"
|
7
5
|
task :install do
|
8
6
|
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install.rb", __dir__)}"
|
9
7
|
end
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
desc "Copy Fluxbit ViewComponents to the application (default value of destination is app/components/fluxbit)"
|
10
|
+
task :copy_components, [ :destination ] do |t, args|
|
11
|
+
require "fileutils"
|
12
|
+
|
13
|
+
gem_path = Gem.loaded_specs["fluxbit_view_components"].full_gem_path
|
14
|
+
components_source = File.join(gem_path, "app/components/fluxbit")
|
15
|
+
components_destination = args[:destination] || Rails.root.join("app/components/fluxbit")
|
16
|
+
|
17
|
+
if Dir.exist?(components_source)
|
18
|
+
FileUtils.mkdir_p(components_destination)
|
19
|
+
FileUtils.cp_r("#{components_source}/.", components_destination)
|
20
|
+
puts "✅ Components copied to #{components_destination}"
|
21
|
+
else
|
22
|
+
puts "❌ Components source directory not found at #{components_source}"
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
26
|
+
desc "Copy Fluxbit ViewComponents Previews to the application (default value of destination is test/components/previews/fluxbit)"
|
27
|
+
task :copy_previews, [ :destination ] do |t, args|
|
28
|
+
require "fileutils"
|
29
|
+
|
30
|
+
gem_path = Gem.loaded_specs["fluxbit_view_components"].full_gem_path
|
31
|
+
previews_source = File.join(gem_path, "previews/fluxbit")
|
32
|
+
previews_destination = args[:destination] || Rails.root.join("test/components/previews/fluxbit")
|
33
|
+
|
34
|
+
if Dir.exist?(previews_source)
|
35
|
+
FileUtils.mkdir_p(previews_destination)
|
36
|
+
FileUtils.cp_r("#{previews_source}/.", previews_destination)
|
37
|
+
puts "✅ Previews copied to #{previews_destination}"
|
38
|
+
else
|
39
|
+
puts "❌ Previews source directory not found at #{previews_source}"
|
40
|
+
end
|
21
41
|
end
|
22
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluxbit_view_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arthur Molina
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: anyicon
|
@@ -142,7 +141,6 @@ dependencies:
|
|
142
141
|
- - ">="
|
143
142
|
- !ruby/object:Gem::Version
|
144
143
|
version: '0'
|
145
|
-
description:
|
146
144
|
email:
|
147
145
|
- arthurmolina@gmail.com
|
148
146
|
executables: []
|
@@ -204,8 +202,9 @@ files:
|
|
204
202
|
- lib/fluxbit/config/tab_component.rb
|
205
203
|
- lib/fluxbit/config/text_component.rb
|
206
204
|
- lib/fluxbit/config/tooltip_component.rb
|
205
|
+
- lib/fluxbit/templates/darkmode.js.template
|
206
|
+
- lib/fluxbit/templates/tailwind.config.js.template
|
207
207
|
- lib/fluxbit/view_components.rb
|
208
|
-
- lib/fluxbit/view_components/codemods/v3_slot_setters.rb
|
209
208
|
- lib/fluxbit/view_components/engine.rb
|
210
209
|
- lib/fluxbit/view_components/version.rb
|
211
210
|
- lib/fluxbit_view_components.rb
|
@@ -216,7 +215,6 @@ licenses:
|
|
216
215
|
- MIT
|
217
216
|
metadata:
|
218
217
|
allowed_push_host: https://rubygems.org
|
219
|
-
post_install_message:
|
220
218
|
rdoc_options: []
|
221
219
|
require_paths:
|
222
220
|
- lib
|
@@ -231,8 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
229
|
- !ruby/object:Gem::Version
|
232
230
|
version: '0'
|
233
231
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
235
|
-
signing_key:
|
232
|
+
rubygems_version: 3.6.7
|
236
233
|
specification_version: 4
|
237
234
|
summary: ViewComponents for Fluxbit Design System
|
238
235
|
test_files: []
|
@@ -1,222 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Fluxbit
|
4
|
-
module ViewComponents
|
5
|
-
# Usage:
|
6
|
-
#
|
7
|
-
# Run via rake task:
|
8
|
-
#
|
9
|
-
# bin/rails fluxbit_view_components:detect_legacy_slots
|
10
|
-
# bin/rails fluxbit_view_components:migrate_legacy_slots
|
11
|
-
# bin/rails fluxbit_view_components:migrate_legacy_slots app/views
|
12
|
-
#
|
13
|
-
# Or run via rails console if you need to pass custom paths:
|
14
|
-
#
|
15
|
-
# Fluxbit::ViewComponents::Codemods::V3SlotSetters.new(
|
16
|
-
# view_path: Rails.root.join("app/views"),
|
17
|
-
# ).call
|
18
|
-
module Codemods
|
19
|
-
class V3SlotSetters
|
20
|
-
TEMPLATE_LANGUAGES = %w[erb slim haml].join(",").freeze
|
21
|
-
RENDER_REGEX = /render[( ](?<component>\w+(?:::\w+)*)\.new[) ]+(do|\{) \|(?<arg>\w+)\b/ # standard:disable Lint/MixedRegexpCaptureTypes
|
22
|
-
|
23
|
-
Suggestion = Struct.new(:file, :line, :message)
|
24
|
-
|
25
|
-
def initialize(view_component_path: [], view_path: [], migrate: false)
|
26
|
-
Rails.application.eager_load!
|
27
|
-
|
28
|
-
@view_component_path = view_component_path
|
29
|
-
@view_path = view_path
|
30
|
-
@migrate = migrate
|
31
|
-
end
|
32
|
-
|
33
|
-
def call
|
34
|
-
puts "Using ViewComponent path: #{view_component_paths.join(", ")}"
|
35
|
-
puts "Using Views path: #{view_paths.join(", ")}"
|
36
|
-
puts "#{view_components.size} ViewComponents found"
|
37
|
-
puts "#{slottable_components.size} ViewComponents using Slots found"
|
38
|
-
puts "#{view_component_files.size} ViewComponent templates found"
|
39
|
-
puts "#{view_files.size} view files found"
|
40
|
-
process_all_files
|
41
|
-
end
|
42
|
-
|
43
|
-
def process_all_files
|
44
|
-
all_files.each do |file|
|
45
|
-
process_file(file)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def process_file(file)
|
50
|
-
@suggestions = []
|
51
|
-
@suggestions += scan_exact_matches(file)
|
52
|
-
@suggestions += scan_uncertain_matches(file)
|
53
|
-
|
54
|
-
return unless @suggestions.any?
|
55
|
-
|
56
|
-
puts
|
57
|
-
puts "File: #{file}"
|
58
|
-
@suggestions.each do |s|
|
59
|
-
puts "=> line #{s.line}: #{s.message}"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def scan_exact_matches(file)
|
66
|
-
[].tap do |suggestions|
|
67
|
-
rendered_components = []
|
68
|
-
content = File.read(file)
|
69
|
-
|
70
|
-
if (render_match = content.match(RENDER_REGEX))
|
71
|
-
component = render_match[:component]
|
72
|
-
arg = render_match[:arg]
|
73
|
-
|
74
|
-
if registered_slots.key?(component.constantize)
|
75
|
-
used_slots_names = registered_slots[component.constantize]
|
76
|
-
rendered_components << { component: component, arg: arg, slots: used_slots_names }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
File.open(file, "r+") do |f|
|
81
|
-
lines = []
|
82
|
-
f.each_line do |line|
|
83
|
-
rendered_components.each do |rendered_component|
|
84
|
-
arg = rendered_component[:arg]
|
85
|
-
slots = rendered_component[:slots]
|
86
|
-
|
87
|
-
if (matches = line.scan(/#{arg}\.#{Regexp.union(slots)}/))
|
88
|
-
matches.each do |match|
|
89
|
-
new_value = match.gsub("#{arg}.", "#{arg}.with_")
|
90
|
-
message = if @migrate
|
91
|
-
"replaced `#{match}` with `#{new_value}`"
|
92
|
-
else
|
93
|
-
"probably replace `#{match}` with `#{new_value}`"
|
94
|
-
end
|
95
|
-
suggestions << Suggestion.new(file, f.lineno, message)
|
96
|
-
if @migrate
|
97
|
-
line.gsub!("#{arg}.", "#{arg}.with_")
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
lines << line
|
103
|
-
end
|
104
|
-
|
105
|
-
if @migrate
|
106
|
-
f.rewind
|
107
|
-
f.write(lines.join)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def scan_uncertain_matches(file)
|
114
|
-
[].tap do |suggestions|
|
115
|
-
File.open(file, "r+") do |f|
|
116
|
-
lines = []
|
117
|
-
f.each_line do |line|
|
118
|
-
if (matches = line.scan(/(?<!\s)\.(?<slot>#{Regexp.union(all_registered_slot_names)})\b/))
|
119
|
-
matches.flatten.each do |match|
|
120
|
-
next if @suggestions.find { |s| s.file == file && s.line == f.lineno }
|
121
|
-
|
122
|
-
message = if @migrate
|
123
|
-
"replaced `#{match}` with `with_#{match}`"
|
124
|
-
else
|
125
|
-
"maybe replace `#{match}` with `with_#{match}`"
|
126
|
-
end
|
127
|
-
suggestions << Suggestion.new(file, f.lineno, message)
|
128
|
-
if @migrate
|
129
|
-
line.gsub!(/(?<!\s)\.(#{match})\b/, ".with_\\1")
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
lines << line
|
134
|
-
end
|
135
|
-
|
136
|
-
if @migrate
|
137
|
-
f.rewind
|
138
|
-
f.write(lines.join)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def view_components
|
145
|
-
ViewComponent::Base.descendants
|
146
|
-
end
|
147
|
-
|
148
|
-
def slottable_components
|
149
|
-
view_components.select do |comp|
|
150
|
-
comp.registered_slots.any?
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def registered_slots
|
155
|
-
@registered_slots ||= {}.tap do |slots|
|
156
|
-
puts
|
157
|
-
puts "Detected slots:"
|
158
|
-
slottable_components.each do |comp|
|
159
|
-
puts "- `#{comp}` has slots: #{comp.registered_slots.keys.join(", ")}"
|
160
|
-
slots[comp] = comp.registered_slots.map do |slot_name, slot|
|
161
|
-
normalized_slot_name(slot_name, slot)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def all_registered_slot_names
|
168
|
-
@all_registered_slot_names ||= registered_slots.values.flatten.uniq
|
169
|
-
end
|
170
|
-
|
171
|
-
def view_component_files
|
172
|
-
Dir.glob(Pathname.new(File.join(view_component_path_glob, "**", "*.{rb,#{TEMPLATE_LANGUAGES}}")))
|
173
|
-
end
|
174
|
-
|
175
|
-
def view_files
|
176
|
-
Dir.glob(Pathname.new(File.join(view_path_glob, "**", "*.{#{TEMPLATE_LANGUAGES}}")))
|
177
|
-
end
|
178
|
-
|
179
|
-
def all_files
|
180
|
-
view_component_files + view_files
|
181
|
-
end
|
182
|
-
|
183
|
-
def view_component_paths
|
184
|
-
@view_component_paths ||= [
|
185
|
-
Rails.application.config.view_component.view_component_path,
|
186
|
-
@view_component_path
|
187
|
-
].flatten.compact.uniq
|
188
|
-
end
|
189
|
-
|
190
|
-
def view_component_path_glob
|
191
|
-
return view_component_paths.first if view_component_paths.size == 1
|
192
|
-
|
193
|
-
"{#{view_component_paths.join(",")}}"
|
194
|
-
end
|
195
|
-
|
196
|
-
def rails_view_paths
|
197
|
-
ActionController::Base.view_paths.select do |path|
|
198
|
-
path.to_s.include?(Rails.root.to_s)
|
199
|
-
end.map(&:to_s)
|
200
|
-
end
|
201
|
-
|
202
|
-
def view_paths
|
203
|
-
@view_paths ||= [
|
204
|
-
rails_view_paths,
|
205
|
-
Rails.application.config.view_component.preview_paths,
|
206
|
-
@view_path
|
207
|
-
].flatten.compact.uniq
|
208
|
-
end
|
209
|
-
|
210
|
-
def view_path_glob
|
211
|
-
return view_paths.first if view_paths.size == 1
|
212
|
-
|
213
|
-
"{#{view_paths.join(",")}}"
|
214
|
-
end
|
215
|
-
|
216
|
-
def normalized_slot_name(slot_name, slot)
|
217
|
-
slot[:collection] ? ActiveSupport::Inflector.singularize(slot_name) : slot_name.to_s
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|