rails_devtools 0.1.1
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 +7 -0
- data/README.md +92 -0
- data/Rakefile +8 -0
- data/app/assets/config/devtools_manifest.js +1 -0
- data/app/assets/stylesheets/devtools/application.css +15 -0
- data/app/controllers/rails_devtools/application_controller.rb +4 -0
- data/app/controllers/rails_devtools/base_controller.rb +7 -0
- data/app/controllers/rails_devtools/database_tables_controller.rb +16 -0
- data/app/controllers/rails_devtools/frontend/modules_controller.rb +18 -0
- data/app/controllers/rails_devtools/gems_controller.rb +16 -0
- data/app/controllers/rails_devtools/host_app_images_controller.rb +35 -0
- data/app/controllers/rails_devtools/image_assets_controller.rb +43 -0
- data/app/controllers/rails_devtools/routes/route_path_inputs_controller.rb +23 -0
- data/app/controllers/rails_devtools/routes_controller.rb +21 -0
- data/app/forms/rails_devtools/database_table_search_form.rb +51 -0
- data/app/forms/rails_devtools/gem_search_form.rb +86 -0
- data/app/forms/rails_devtools/image_search_form.rb +30 -0
- data/app/forms/rails_devtools/route_search_form.rb +17 -0
- data/app/helpers/rails_devtools/application_helper.rb +4 -0
- data/app/javascript/application.js +4 -0
- data/app/javascript/controllers/application.js +10 -0
- data/app/javascript/controllers/checkbox_controller.js +9 -0
- data/app/javascript/controllers/index.js +11 -0
- data/app/javascript/controllers/search_reset_controller.js +7 -0
- data/app/javascript/controllers/turbo_form_controller.js +9 -0
- data/app/jobs/rails_devtools/application_job.rb +4 -0
- data/app/mailers/rails_devtools/application_mailer.rb +6 -0
- data/app/models/rails_devtools/application_record.rb +5 -0
- data/app/models/rails_devtools/image_assets/image_info.rb +85 -0
- data/app/models/rails_devtools/routes/collection.rb +83 -0
- data/app/models/rails_devtools/routes/controller_info.rb +30 -0
- data/app/models/rails_devtools/routes/engine_info.rb +33 -0
- data/app/models/rails_devtools/routes/route_info.rb +120 -0
- data/app/views/rails_devtools/application_layout.rb +90 -0
- data/app/views/rails_devtools/application_view.rb +6 -0
- data/app/views/rails_devtools/components/application_component.rb +24 -0
- data/app/views/rails_devtools/components/flash_message.rb +29 -0
- data/app/views/rails_devtools/components/lucide/base.rb +18 -0
- data/app/views/rails_devtools/components/lucide/close.rb +25 -0
- data/app/views/rails_devtools/components/lucide/database.rb +26 -0
- data/app/views/rails_devtools/components/lucide/external_link.rb +26 -0
- data/app/views/rails_devtools/components/lucide/images.rb +27 -0
- data/app/views/rails_devtools/components/lucide/menu.rb +26 -0
- data/app/views/rails_devtools/components/lucide/package.rb +30 -0
- data/app/views/rails_devtools/components/lucide/pocket_knife.rb +28 -0
- data/app/views/rails_devtools/components/lucide/sign_post.rb +29 -0
- data/app/views/rails_devtools/components/lucide/trash.rb +26 -0
- data/app/views/rails_devtools/components/lucide/triangle_alert.rb +29 -0
- data/app/views/rails_devtools/components/page_content.rb +27 -0
- data/app/views/rails_devtools/components/ui/drawer.rb +49 -0
- data/app/views/rails_devtools/components/ui/menu.rb +81 -0
- data/app/views/rails_devtools/components/ui/search_form.rb +65 -0
- data/app/views/rails_devtools/components.rb +5 -0
- data/app/views/rails_devtools/database_tables/index.rb +32 -0
- data/app/views/rails_devtools/database_tables/table_card.rb +61 -0
- data/app/views/rails_devtools/gems/gem_card.rb +74 -0
- data/app/views/rails_devtools/gems/index.rb +32 -0
- data/app/views/rails_devtools/image_assets/image_card.rb +37 -0
- data/app/views/rails_devtools/image_assets/image_details.rb +82 -0
- data/app/views/rails_devtools/image_assets/index.rb +39 -0
- data/app/views/rails_devtools/routes/index.rb +37 -0
- data/app/views/rails_devtools/routes/route_card.rb +70 -0
- data/app/views/rails_devtools/routes/route_details/controller_card.rb +87 -0
- data/app/views/rails_devtools/routes/route_details/route_path_input.rb +46 -0
- data/app/views/rails_devtools/routes/route_details.rb +171 -0
- data/config/routes.rb +24 -0
- data/lib/rails_devtools/asset_config.rb +52 -0
- data/lib/rails_devtools/asset_providers/jsbundling_rails_config.rb +21 -0
- data/lib/rails_devtools/asset_providers/propshaft_config.rb +19 -0
- data/lib/rails_devtools/asset_providers/shakapacker_config.rb +26 -0
- data/lib/rails_devtools/asset_providers/sprocket_config.rb +19 -0
- data/lib/rails_devtools/asset_providers/vite_rails_config.rb +19 -0
- data/lib/rails_devtools/engine.rb +22 -0
- data/lib/rails_devtools/importmap.rb +16 -0
- data/lib/rails_devtools/importmaps/base.rb +82 -0
- data/lib/rails_devtools/version.rb +3 -0
- data/lib/rails_devtools.rb +20 -0
- data/lib/tasks/rails_devtools_tasks.rake +4 -0
- data/vendor/javascript/@stimulus-components--clipboard.js +4 -0
- data/vendor/javascript/@stimulus-components--notification.js +4 -0
- data/vendor/javascript/@stimulus-components--reveal.js +4 -0
- data/vendor/javascript/stimulus-autoloader.js +54 -0
- data/vendor/javascript/stimulus-importmap-autoloader.js +27 -0
- data/vendor/javascript/stimulus-loading.js +93 -0
- data/vendor/javascript/stimulus-use.js +4 -0
- data/vendor/javascript/stimulus.min.js +5 -0
- data/vendor/javascript/turbo.min.js +36 -0
- metadata +241 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d185839dcc19c72b18c2f20b4be8846054d829f8b6d0b517b512fc8c17ea5c99
|
4
|
+
data.tar.gz: b9af4f7560bb0ad748e35db0aaf3566f49bd4d020cc3bdf99564da79251d1156
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9f5311dd1591a436c7d0e81b6545a1131a014affb8e9b94cdecea219d42d33974e25d54dabb4243f21ac93d4c64000410f0ed0447de82498d5c68f7c30b984a2
|
7
|
+
data.tar.gz: 70286d2e5bb2ab8ca7670deb7335a941b3ec549ca70e00f801a490d5d900e821ba06d8ae6f53551b75406fa71932c546e02b1426746d1a0f6b0ca5d9bb3837ed
|
data/README.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Rails Devtools
|
2
|
+
|
3
|
+
Rails Devtools is a set of "quality of life" tools for your rails project, distributed as a rails engine.
|
4
|
+
This is inspired by the likes of Nuxt Devtools, Laravel Telescope...
|
5
|
+
|
6
|
+
This gem is meant to be only used in development, and cannot work at all in production.
|
7
|
+
|
8
|
+
> [!IMPORTANT]
|
9
|
+
> The gem is an alpha version. Is has been tested on several Rails projects from Rails 7.1 to Rails 8.0. It should work on many projects but it could also break easily if your project has some tricky stuff I didn't think about.
|
10
|
+
> If you encounter a bug, please create an issue, I'll do my best to fix it.
|
11
|
+
|
12
|
+
<br />
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
- Add the gem to your Gemfile
|
17
|
+
```ruby
|
18
|
+
gem 'rails-devtools, group: :development'
|
19
|
+
````
|
20
|
+
|
21
|
+
- Mount the engine in your routes
|
22
|
+
```ruby
|
23
|
+
mount RailsDevtools::Engine => "/devtools"
|
24
|
+
```
|
25
|
+
|
26
|
+
- Update the bundle
|
27
|
+
```sh
|
28
|
+
bundle install
|
29
|
+
```
|
30
|
+
- Go to `http://localhost:3000/devtools`
|
31
|
+
|
32
|
+
<br /><br />
|
33
|
+
|
34
|
+
## Screenshots
|
35
|
+
<details>
|
36
|
+
<summary> Expand to see more screnshots
|
37
|
+
<br /><br />
|
38
|
+
<img width="1187" alt="devtools_database_tables" src="https://github.com/user-attachments/assets/a5289293-c8c1-475c-abb2-b3c3f322c281" />
|
39
|
+
</summary>
|
40
|
+
<img width="1191" alt="devtools_gems" src="https://github.com/user-attachments/assets/204293e5-3eaf-400d-99e9-74e493571997" />
|
41
|
+
<img width="1194" alt="devtools_image_assets" src="https://github.com/user-attachments/assets/f6b41437-9ea4-4d0e-b1d5-3aff9c156730" />
|
42
|
+
<img width="1188" alt="devtools_routes" src="https://github.com/user-attachments/assets/9bcd8435-cc7e-48a3-8a71-83b2ee99afd7" />
|
43
|
+
<img width="459" alt="devtools_routes_responsive" src="https://github.com/user-attachments/assets/e3e3ff2d-a54e-4e45-9618-1653d4291d0c" />
|
44
|
+
<img width="474" alt="devtools_routes_details_responsive" src="https://github.com/user-attachments/assets/a245e2d0-23d1-4a19-b871-a738a68cd83a" />
|
45
|
+
</details>
|
46
|
+
<br /><br />
|
47
|
+
|
48
|
+
## Features
|
49
|
+
|
50
|
+
Rails Devtools are fully responsive. I think of them as a companion to my editing efforts and I want to be able to put them next to my IDE.
|
51
|
+
|
52
|
+
#### Database tables
|
53
|
+
- List all your database tables along with their columns and indexes.
|
54
|
+
- Search for tables or columns
|
55
|
+
|
56
|
+
#### Routes
|
57
|
+
- List all your application routes
|
58
|
+
- Display details about it, along with helpful actions and snippets
|
59
|
+
- Warn if a route is not linked to a controller / action (details provide more information)
|
60
|
+
- Search for routes by name
|
61
|
+
|
62
|
+
#### Image assets
|
63
|
+
Since there are quite a few asset pipelines in the rails ecosystem, Rails Devtools detects which one is used and adapts its behavior to it. It supports Propshaft, Sprockets, Shakapacker, JS-Bundling-Rails and Vite-Rails.
|
64
|
+
|
65
|
+
- list image assets in your codebase
|
66
|
+
- Display information about them, along with helpful actions and snippets
|
67
|
+
- Search for images by name
|
68
|
+
|
69
|
+
#### Gems
|
70
|
+
- list gems in your bundle
|
71
|
+
- display their summary
|
72
|
+
- display links to their code source, website...
|
73
|
+
- display outdated gems along with information about the last version
|
74
|
+
- search for gems by name
|
75
|
+
<br /><br />
|
76
|
+
> [!NOTE]
|
77
|
+
> Most of those features are starting points. There are many ways to get a better grasp of a rails codebase. I have some in mind but if you happen to have ideas, feel free to share them in the discussions!
|
78
|
+
|
79
|
+
<br /><br />
|
80
|
+
## Philosophy
|
81
|
+
|
82
|
+
As developers, we spend much of our time looking at walls of text. Our codebase does not provide any information architecture, besides classes or methods. There is no high level view of the project, and most of the tooling is either a bunch of commands to run or a script found on stackoverflow.
|
83
|
+
|
84
|
+
Rails, as a framework, knows many things about our project. This might seem obvious but it knows how to match a route and a controller, what path you need to write to use an image, or what scopes are defined on a model.
|
85
|
+
|
86
|
+
When you run `rails s`, all those informations are available. But they are hidden behind the mysteries of ActiveRecord, Rails.application and so on.
|
87
|
+
|
88
|
+
This is why I believe that it makes a lot of sense to provide tools that surface these informations when needed, in a friendly way.
|
89
|
+
|
90
|
+
<br /><br />
|
91
|
+
## License
|
92
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/devtools .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class DatabaseTablesController < BaseController
|
5
|
+
def index
|
6
|
+
form = DatabaseTableSearchForm.new(search: form_params[:search])
|
7
|
+
render DatabaseTables::Index.new(tables: form.results, form: form)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def form_params
|
13
|
+
params[:database_table_search_form] || { search: "" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RailsDevtools
|
2
|
+
module Frontend
|
3
|
+
class ModulesController < ApplicationController
|
4
|
+
protect_from_forgery except: :show
|
5
|
+
|
6
|
+
def show
|
7
|
+
file = RailsDevtools.importmap.find(params[:path]).file_path
|
8
|
+
return head :not_found unless file
|
9
|
+
|
10
|
+
send_file(
|
11
|
+
file,
|
12
|
+
type: "application/javascript",
|
13
|
+
disposition: "inline"
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class GemsController < BaseController
|
5
|
+
def index
|
6
|
+
form = GemSearchForm.new(search: form_params[:search])
|
7
|
+
render Gems::Index.new(gems: form.results, form: form)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def form_params
|
13
|
+
params[:gem_search_form] || { search: "" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class HostAppImagesController < BaseController
|
5
|
+
def show
|
6
|
+
return head :not_found unless image?
|
7
|
+
|
8
|
+
image_path = find_source_image
|
9
|
+
return head :not_found unless image_path
|
10
|
+
|
11
|
+
mime_type = Mime::Type.lookup_by_extension(params[:format])
|
12
|
+
|
13
|
+
send_file image_path, type: mime_type, disposition: "inline"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def image?
|
19
|
+
ImageAssets::ImageInfo::IMAGE_EXTENSIONS.include?(".#{params[:format]}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_source_image
|
23
|
+
filename = CGI.unescape(File.basename(params[:path]))
|
24
|
+
found = nil
|
25
|
+
|
26
|
+
RailsDevtools.asset_config.paths.each do |base_path|
|
27
|
+
paths = Dir.glob("#{base_path}/**/*#{filename}*")
|
28
|
+
found = paths.find { |file_path| File.file?(file_path) }
|
29
|
+
break if found
|
30
|
+
end
|
31
|
+
|
32
|
+
found
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class ImageAssetsController < BaseController
|
5
|
+
def show
|
6
|
+
image_info = ImageAssets::ImageInfo.new(params[:image_path])
|
7
|
+
render ImageAssets::ImageDetails.new(image_info: image_info)
|
8
|
+
end
|
9
|
+
|
10
|
+
def index
|
11
|
+
form = ImageSearchForm.new(search: form_params[:search])
|
12
|
+
render ImageAssets::Index.new(images_by_folder: form.results, form: form)
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
image_info = ImageAssets::ImageInfo.new(params[:image_path])
|
17
|
+
raise "This is a not an image" unless image_info.valid?
|
18
|
+
|
19
|
+
File.delete(image_info.full_path)
|
20
|
+
|
21
|
+
respond_to do |format|
|
22
|
+
format.html { redirect_to image_assets_path, notice: "Image was successfully destroyed." }
|
23
|
+
format.turbo_stream {
|
24
|
+
render turbo_stream: [
|
25
|
+
turbo_stream.remove(image_info.full_path),
|
26
|
+
turbo_stream.append(
|
27
|
+
"flash_messages",
|
28
|
+
Components::FlashMessage.new(
|
29
|
+
message: "Image was successfully destroyed."
|
30
|
+
)
|
31
|
+
)
|
32
|
+
]
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def form_params
|
40
|
+
params[:image_search_form] || { search: "" }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
module Routes
|
5
|
+
class RoutePathInputsController < ApplicationController
|
6
|
+
def update
|
7
|
+
route = Routes::Collection.find(params[:id])
|
8
|
+
|
9
|
+
input_params = { route: route }
|
10
|
+
|
11
|
+
if params[:engine_prefix].present? && params[:engine_prefix] == "1"
|
12
|
+
input_params.merge!(prefix: route.engine_info.helper_prefix)
|
13
|
+
end
|
14
|
+
|
15
|
+
if params[:url_suffix].present? && params[:url_suffix] == "1"
|
16
|
+
input_params.merge!(suffix: "url")
|
17
|
+
end
|
18
|
+
|
19
|
+
render Routes::RouteDetails::RoutePathInput.new(**input_params)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class RoutesController < BaseController
|
5
|
+
def index
|
6
|
+
form = RouteSearchForm.new(search: form_params[:search])
|
7
|
+
render Routes::Index.new(routes: form.results, form: form)
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
route = Routes::Collection.find(params[:id])
|
12
|
+
render Routes::RouteDetails.new(route: route)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def form_params
|
18
|
+
params[:route_search_form] || { search: "" }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class DatabaseTableSearchForm
|
5
|
+
include ActiveModel::Model
|
6
|
+
|
7
|
+
DatabaseTable = Data.define(:table_name, :columns, :indexes)
|
8
|
+
|
9
|
+
def initialize(search: "")
|
10
|
+
@search = search.downcase
|
11
|
+
end
|
12
|
+
|
13
|
+
def results
|
14
|
+
table_names = ActiveRecord::Base.connection.tables - ["schema_migrations", "ar_internal_metadata"]
|
15
|
+
|
16
|
+
tables = table_names.map do |table|
|
17
|
+
DatabaseTable.new(
|
18
|
+
table_name: table,
|
19
|
+
columns: ActiveRecord::Base.connection.columns(table),
|
20
|
+
indexes: indexes(table)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
return tables if @search.empty?
|
25
|
+
|
26
|
+
tables.select do |table|
|
27
|
+
table.table_name.include?(@search) ||
|
28
|
+
table.columns.any? { |column| column.name.include?(@search) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
ShortIndex = Data.define(:name, :columns, :unique)
|
35
|
+
|
36
|
+
def indexes(table)
|
37
|
+
indexes = ActiveRecord::Base.connection.indexes(table)
|
38
|
+
indexes.map do |index|
|
39
|
+
long_name = index.name
|
40
|
+
prefix = "index_#{table}_on_"
|
41
|
+
short_name = long_name.gsub(prefix, "").humanize
|
42
|
+
|
43
|
+
ShortIndex.new(
|
44
|
+
name: short_name,
|
45
|
+
columns: index.columns,
|
46
|
+
unique: index.unique
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class GemSearchForm
|
5
|
+
include ActiveModel::Model
|
6
|
+
|
7
|
+
GemInfo = Data.define(
|
8
|
+
:name,
|
9
|
+
:required_version,
|
10
|
+
:actual_version,
|
11
|
+
:homepage,
|
12
|
+
:summary,
|
13
|
+
:source_code,
|
14
|
+
:documentation,
|
15
|
+
:groups,
|
16
|
+
:date,
|
17
|
+
:latest_version,
|
18
|
+
:changelog
|
19
|
+
) do
|
20
|
+
def outdated?
|
21
|
+
return false if latest_version.nil?
|
22
|
+
|
23
|
+
actual_version < latest_version.version
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(search: "")
|
28
|
+
@search = search.downcase
|
29
|
+
end
|
30
|
+
|
31
|
+
def results
|
32
|
+
specs = ask_bundler_for_specs
|
33
|
+
gems_list = specs.map { |gem_spec| GemInfo.new(**gem_spec) }
|
34
|
+
|
35
|
+
return order(gems_list) if @search.empty?
|
36
|
+
|
37
|
+
order(
|
38
|
+
gems_list.select { |gem| gem.name.include?(@search) }
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
GROUP_PRIORITY = {
|
45
|
+
"default" => 0,
|
46
|
+
"production" => 1,
|
47
|
+
"development" => 2,
|
48
|
+
"development-test" => 3,
|
49
|
+
"test" => 4
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
def order(gems)
|
53
|
+
gems.sort_by do |item|
|
54
|
+
[GROUP_PRIORITY.fetch(item.groups.join("-"), 5), item.name]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
LatestSpec = Data.define(:version, :date)
|
59
|
+
|
60
|
+
def ask_bundler_for_specs
|
61
|
+
bundle = Bundler.load
|
62
|
+
|
63
|
+
dependencies = bundle.dependencies.map { |dep| [dep.name, dep.groups] }.to_h
|
64
|
+
specs = bundle.specs.select do |spec|
|
65
|
+
dependencies.keys.include?(spec.name)
|
66
|
+
end
|
67
|
+
|
68
|
+
specs.map do |spec|
|
69
|
+
latest_spec = Gem.latest_spec_for(spec.name)
|
70
|
+
{
|
71
|
+
name: spec.name,
|
72
|
+
latest_version: latest_spec ? LatestSpec.new(version: latest_spec.version, date: latest_spec.date) : nil,
|
73
|
+
date: spec.date,
|
74
|
+
required_version: spec.requirements.to_s,
|
75
|
+
actual_version: spec.version.to_s,
|
76
|
+
homepage: spec.homepage,
|
77
|
+
summary: spec.summary,
|
78
|
+
source_code: spec.metadata["source_code_uri"],
|
79
|
+
documentation: spec.metadata["documentation_uri"],
|
80
|
+
changelog: spec.metadata["changelog_uri"],
|
81
|
+
groups: dependencies[spec.name]
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class ImageSearchForm
|
5
|
+
include ActiveModel::Model
|
6
|
+
|
7
|
+
def initialize(search: "")
|
8
|
+
@search = search
|
9
|
+
end
|
10
|
+
|
11
|
+
def results
|
12
|
+
folders = RailsDevtools.asset_config.paths
|
13
|
+
|
14
|
+
images_by_folder = Hash.new { |hash, key| hash[key] = [] }
|
15
|
+
extensions = ImageAssets::ImageInfo::IMAGE_EXTENSIONS.map { |ext| ext.delete_prefix(".") }.join(",")
|
16
|
+
|
17
|
+
folders.each do |dir|
|
18
|
+
Dir.glob("#{dir}/**/*{#{@search.upcase}, #{@search.downcase}}*.{#{extensions}}").each do |path|
|
19
|
+
image_info = ImageAssets::ImageInfo.new(path)
|
20
|
+
next unless image_info.valid?
|
21
|
+
|
22
|
+
dir = File.dirname(path).gsub(Rails.root.to_s, "")
|
23
|
+
images_by_folder[dir] << image_info
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
images_by_folder
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsDevtools
|
4
|
+
class RouteSearchForm
|
5
|
+
include ActiveModel::Model
|
6
|
+
|
7
|
+
def initialize(search: "")
|
8
|
+
@search = search.downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
def results
|
12
|
+
Routes::Collection.all
|
13
|
+
.select { |route| route.name.downcase.include?(@search) }
|
14
|
+
.group_by { |route| route.engine_info.name }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { Application } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
const application = Application.start()
|
4
|
+
|
5
|
+
// Configure Stimulus development experience
|
6
|
+
application.debug = true
|
7
|
+
window.Stimulus = application
|
8
|
+
|
9
|
+
console.log("Hello from controllers/application.js")
|
10
|
+
export { application }
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { application } from "controllers/application";
|
2
|
+
import RevealController from '@stimulus-components/reveal'
|
3
|
+
import Clipboard from '@stimulus-components/clipboard'
|
4
|
+
import Notification from '@stimulus-components/notification'
|
5
|
+
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
|
6
|
+
|
7
|
+
application.register('reveal', RevealController)
|
8
|
+
application.register('clipboard', Clipboard)
|
9
|
+
application.register('notification', Notification)
|
10
|
+
|
11
|
+
eagerLoadControllersFrom("controllers", application)
|