vite_react 0.1.5
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/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +3 -0
- data/lib/generators/ui/component/component_generator.rb +31 -0
- data/lib/generators/ui/component/templates/component.tsx.erb +9 -0
- data/lib/generators/ui/register/register_generator.rb +33 -0
- data/lib/generators/vite_react/migration/migration.rb +63 -0
- data/lib/generators/vite_react/model_validation/model_validation_generator.rb +78 -0
- data/lib/generators/vite_react/scaffold/scaffold_generator.rb +75 -0
- data/lib/install/App.tsx +46 -0
- data/lib/install/application.css +69 -0
- data/lib/install/components.json +21 -0
- data/lib/install/eslint.config.js +0 -0
- data/lib/install/index.html.erb +31 -0
- data/lib/install/tailwind.config.js +74 -0
- data/lib/install/tsconfig.app.json +29 -0
- data/lib/install/tsconfig.json +13 -0
- data/lib/install/tsconfig.node.json +22 -0
- data/lib/install/utils.ts +7 -0
- data/lib/install/vite.config.js +17 -0
- data/lib/install/vite_react.rb +153 -0
- data/lib/tasks/install.rake +11 -0
- data/lib/vite_react/railtie.rb +28 -0
- data/lib/vite_react/version.rb +3 -0
- data/lib/vite_react.rb +5 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 81a7fb698949d219e73983161b10ec4afa5b68090ba34d331acdaf378812f019
|
4
|
+
data.tar.gz: '07931987bbe9296f2598b17818856a620509957da2016befe65614152a162027'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11819f83bc760d1438c867ddddc6039c9f85432f6d8e289facc1880094cbf108da5da7cb9a0b9c6c3338c6c8819521c8dc763c9a961345c803c3c156ad497f32
|
7
|
+
data.tar.gz: 83492e77f4b9a546d74b90317380939b74549e5ac25d25868d6d271e649b6b9a23cabe4510715bb420e9a1801ae92e40355fb45268a3e0a69731426c5ec6eb74
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright lsproule
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# ViteReact
|
2
|
+
|
3
|
+
Short description and motivation.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
How to use my plugin.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "vite_react"
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
```bash
|
17
|
+
bundle install
|
18
|
+
```
|
19
|
+
|
20
|
+
```bash
|
21
|
+
./bin/rails vite_react:install
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
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,31 @@
|
|
1
|
+
# lib/generators/ui/component/component_generator.rb
|
2
|
+
|
3
|
+
module Ui
|
4
|
+
class ComponentGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
6
|
+
desc "Generates a new React component (TSX) and registers it in turbo-mount.js"
|
7
|
+
|
8
|
+
def create_component_file
|
9
|
+
# Create a new TSX file in app/javascript/components
|
10
|
+
template "component.tsx.erb", "app/javascript/components/#{class_name}.tsx"
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_import_to_turbo_mount
|
14
|
+
# Inject an import statement into turbo-mount.js after the registerComponent import
|
15
|
+
inject_into_file(
|
16
|
+
"app/javascript/entrypoints/turbo-mount.js",
|
17
|
+
after: 'import { registerComponent } from "turbo-mount/react";'
|
18
|
+
) do
|
19
|
+
"\nimport { #{class_name} } from \"@/components/#{class_name}\";"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_component_in_turbo_mount
|
24
|
+
# Append a registerComponent call at the bottom of turbo-mount.js
|
25
|
+
append_to_file "app/javascript/entrypoints/turbo-mount.js", <<~JS
|
26
|
+
|
27
|
+
registerComponent(turboMount, "#{class_name}", #{class_name});
|
28
|
+
JS
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# lib/generators/ui/register/register_generator.rb
|
2
|
+
|
3
|
+
module Ui
|
4
|
+
class RegisterGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
6
|
+
desc "Takes an existing TSX component and auto-registers it in turbo-mount.js"
|
7
|
+
|
8
|
+
def ensure_component_exists
|
9
|
+
unless File.exist?("app/javascript/components/#{class_name}.tsx")
|
10
|
+
say "ERROR: app/javascript/components/#{class_name}.tsx not found!", :red
|
11
|
+
exit(1) # or raise an exception
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_import_to_turbo_mount
|
16
|
+
# Step 1: Inject an import line under the registerComponent import line
|
17
|
+
inject_into_file(
|
18
|
+
"app/javascript/entrypoints/turbo-mount.js",
|
19
|
+
after: 'import { registerComponent } from "turbo-mount/react";'
|
20
|
+
) do
|
21
|
+
"\nimport { #{class_name} } from \"@/components/#{class_name}\";"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def register_component_in_turbo_mount
|
26
|
+
# Step 2: Append the registerComponent call at the bottom of turbo-mount.js
|
27
|
+
append_to_file "app/javascript/entrypoints/turbo-mount.js", <<~JS
|
28
|
+
|
29
|
+
registerComponent(turboMount, "#{class_name}", #{class_name});
|
30
|
+
JS
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# lib/generators/rails/migration_ts/migration_ts_generator.rb
|
2
|
+
require "rails/generators/migration/migration_generator"
|
3
|
+
require "rails/generators/resource_helpers"
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
module ViteReact
|
8
|
+
module Generators
|
9
|
+
class MigrationGenerator < MigrationGenerator
|
10
|
+
source_root File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
argument :migration_name, type: :string
|
13
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
14
|
+
|
15
|
+
def update_types
|
16
|
+
puts "Updating TypeScript definitions based on #{migration_name}..."
|
17
|
+
|
18
|
+
types_file_path = Rails.root.join("app/javascript/types.d.ts")
|
19
|
+
# read the file, parse it, inject new columns if they don’t exist, etc.
|
20
|
+
# For references, do the same logic we did in the scaffold generator
|
21
|
+
|
22
|
+
interface_code = build_migration_interface_snippet
|
23
|
+
|
24
|
+
append_to_file types_file_path, interface_code
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def build_migration_interface_snippet
|
30
|
+
# This is obviously simplistic. You would incorporate something
|
31
|
+
# like the logic from your main TS generator, or even call
|
32
|
+
# a shared module that does the same parsing of attributes.
|
33
|
+
attributes_lines = attributes.flat_map do |attr|
|
34
|
+
if attr.type == "references"
|
35
|
+
[
|
36
|
+
"#{attr.name}_id: number;",
|
37
|
+
"#{attr.name}?: #{attr.name.camelize};"
|
38
|
+
]
|
39
|
+
else
|
40
|
+
[ "#{attr.name}?: #{rails_to_ts_type(attr.type)};" ]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
<<~TS
|
45
|
+
// AUTO-GENERATED by rails g migration #{migration_name}
|
46
|
+
// You may need to update validations or remove ? accordingly
|
47
|
+
// if presence validations exist.
|
48
|
+
// Changes introduced by: #{migration_name}
|
49
|
+
#{attributes_lines.join("
|
50
|
+
")}
|
51
|
+
TS
|
52
|
+
end
|
53
|
+
|
54
|
+
def rails_to_ts_type(rails_type)
|
55
|
+
case rails_type
|
56
|
+
when "integer", "float", "decimal" then "number"
|
57
|
+
when "boolean" then "boolean"
|
58
|
+
else "string"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# lib/generators/rails/tmodel_validation/model_validation_generator.rb
|
2
|
+
|
3
|
+
module ViteReact
|
4
|
+
module Generators
|
5
|
+
class ModelValidationGenerator < Rails::Generators::NamedBase
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
def update_types_for_validations
|
9
|
+
require File.join(Rails.root, "app/models/\#{file_path}.rb")
|
10
|
+
|
11
|
+
model_class = file_name.camelize.constantize
|
12
|
+
|
13
|
+
presence_attributes = model_class.validators
|
14
|
+
.select { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }
|
15
|
+
.flat_map(&:attributes)
|
16
|
+
.map(&:to_s)
|
17
|
+
|
18
|
+
required_belongs_tos = model_class.reflect_on_all_associations(:belongs_to)
|
19
|
+
.select { |assoc| assoc.options[:optional] == false || assoc.options[:required] == true }
|
20
|
+
.map(&:name)
|
21
|
+
.map(&:to_s)
|
22
|
+
|
23
|
+
presence_required = presence_attributes.to_set
|
24
|
+
required_belongs_tos.each do |assoc_name|
|
25
|
+
presence_required << assoc_name # e.g. user
|
26
|
+
presence_required << "\#{assoc_name}_id" # e.g. user_id
|
27
|
+
end
|
28
|
+
|
29
|
+
types_file_path = Rails.root.join("app/javascript/types.d.ts")
|
30
|
+
return unless File.exist?(types_file_path)
|
31
|
+
|
32
|
+
lines = File.read(types_file_path).split("\n")
|
33
|
+
|
34
|
+
|
35
|
+
in_target_interface = false
|
36
|
+
brace_depth = 0
|
37
|
+
|
38
|
+
|
39
|
+
start_of_interface_regex = /^\s*(?:export\s+)?interface\s+\#{Regexp.escape(model_class.name)}\s*(\{|extends|$)/
|
40
|
+
|
41
|
+
lines.map!.with_index do |line, idx|
|
42
|
+
if !in_target_interface && line =~ start_of_interface_regex
|
43
|
+
in_target_interface = true
|
44
|
+
brace_depth = line.count("{")
|
45
|
+
# {' '}
|
46
|
+
elsif in_target_interface
|
47
|
+
brace_depth += line.count("{")
|
48
|
+
brace_depth -= line.count("}")
|
49
|
+
# {' '}
|
50
|
+
if brace_depth <= 0
|
51
|
+
in_target_interface = false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if in_target_interface && brace_depth > 0
|
56
|
+
if line =~ /^(\s*)([a-zA-Z_0-9]+)(\??):/
|
57
|
+
leading_spaces = $1
|
58
|
+
attribute_name = $2
|
59
|
+
question_mark = $3 # could be "" or "?"
|
60
|
+
|
61
|
+
if presence_required.include?(attribute_name)
|
62
|
+
line = line.sub("\#{attribute_name}?:", "\#{attribute_name}:")
|
63
|
+
else
|
64
|
+
unless question_mark == "?"
|
65
|
+
line = line.sub("\#{attribute_name}:", "\#{attribute_name}?:")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
line
|
72
|
+
end
|
73
|
+
|
74
|
+
File.write(types_file_path, lines.join("\n"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "rails/generators/scaffold/scaffold_generator"
|
2
|
+
require "rails/generators/resource_helpers"
|
3
|
+
|
4
|
+
# lib/generators/rails/typescript/typescript_generator.rb
|
5
|
+
|
6
|
+
module ViteReact
|
7
|
+
module Generators
|
8
|
+
class ScaffoldGenerator < ScaffoldGenerator
|
9
|
+
include Rails::Generators::ResourceHelpers
|
10
|
+
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
12
|
+
|
13
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
14
|
+
|
15
|
+
|
16
|
+
def create_or_update_types
|
17
|
+
types_file_path = Rails.root.join("app/javascript/types.d.ts")
|
18
|
+
|
19
|
+
interface_code = generate_interface_code
|
20
|
+
|
21
|
+
if File.exist?(types_file_path)
|
22
|
+
append_to_file types_file_path, interface_code
|
23
|
+
else
|
24
|
+
create_file types_file_path, interface_code
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def generate_interface_code
|
33
|
+
attributes_lines = attributes.flat_map do |attr|
|
34
|
+
puts attr.inspect
|
35
|
+
if attr.type == :references
|
36
|
+
build_reference_lines(attr)
|
37
|
+
else
|
38
|
+
[ build_attribute_line(attr) ]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
<<~TS
|
43
|
+
// AUTO-GENERATED by rails g scaffold #{file_name}
|
44
|
+
interface #{class_name} {
|
45
|
+
#{attributes_lines.join("
|
46
|
+
")}
|
47
|
+
}
|
48
|
+
|
49
|
+
TS
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def build_attribute_line(attr)
|
54
|
+
"#{attr.name}?: #{rails_to_ts_type(attr.type)};"
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_reference_lines(attr)
|
58
|
+
referenced_interface_name = attr.name.camelize
|
59
|
+
[
|
60
|
+
"#{attr.name}_id: number;",
|
61
|
+
"#{attr.name}?: #{referenced_interface_name};"
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
def rails_to_ts_type(rails_type)
|
66
|
+
case rails_type
|
67
|
+
when "integer", "float", "decimal" then "number"
|
68
|
+
when "boolean" then "boolean"
|
69
|
+
else
|
70
|
+
"string"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/install/App.tsx
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
import { useState } from "react";
|
2
|
+
|
3
|
+
export function App() {
|
4
|
+
const [count, setCount] = useState(0);
|
5
|
+
|
6
|
+
return (
|
7
|
+
<div className="flex bg-[#242424] gap-12 text-white h-screen flex-col justify-center items-center mx-auto w-screen">
|
8
|
+
<div className="flex text-3xl">
|
9
|
+
<a href="https://guides.rubyonrails.org/index.html" target="_blank">
|
10
|
+
<img
|
11
|
+
src="/images/rails.svg"
|
12
|
+
className="logo rails"
|
13
|
+
alt="Rails logo"
|
14
|
+
/>
|
15
|
+
</a>
|
16
|
+
<a href="https://react.dev" target="_blank">
|
17
|
+
<img
|
18
|
+
src="/images/react.svg"
|
19
|
+
className="logo react"
|
20
|
+
alt="React logo"
|
21
|
+
/>
|
22
|
+
</a>
|
23
|
+
<a href="https://vite.dev" target="_blank">
|
24
|
+
<img src="/images/vite.svg" className="logo" alt="Vite logo" />
|
25
|
+
</a>
|
26
|
+
</div>
|
27
|
+
<h1 className="text-4xl font-bold">
|
28
|
+
<span className="text-[#CC0000]">Rails </span>#{' '}
|
29
|
+
+ <span className="text-[#61dafb]">React </span>
|
30
|
+
+ <span className="text-[#646cff]">Vite</span>#{' '}
|
31
|
+
</h1>
|
32
|
+
<div className="card flex flex-col items-center">
|
33
|
+
<button className="mb-4 font-semibold border border-transparent hover:border-[#646cff] cursor-pointer bg-[#1a1a1a] p-1 rounded-lg p-x-8" onClick={() => setCount((count) => count + 1)}>
|
34
|
+
count is {count}
|
35
|
+
</button>
|
36
|
+
<p>
|
37
|
+
Edit <code>app/javascript/components/App.tsx</code> and save to test
|
38
|
+
HMR
|
39
|
+
</p>
|
40
|
+
</div>
|
41
|
+
<p className="text-[#888]">
|
42
|
+
Click on the Rails, Vite and React logos to learn more
|
43
|
+
</p>
|
44
|
+
</div>
|
45
|
+
);
|
46
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
@tailwind base;
|
2
|
+
@tailwind components;
|
3
|
+
@tailwind utilities;
|
4
|
+
|
5
|
+
/* Example theming with CSS variables */
|
6
|
+
@layer base {
|
7
|
+
:root {
|
8
|
+
--background: 0 0% 100%;
|
9
|
+
--foreground: 0 0% 3.9%;
|
10
|
+
--card: 0 0% 100%;
|
11
|
+
--card-foreground: 0 0% 3.9%;
|
12
|
+
--popover: 0 0% 100%;
|
13
|
+
--popover-foreground: 0 0% 3.9%;
|
14
|
+
--primary: 0 0% 9%;
|
15
|
+
--primary-foreground: 0 0% 98%;
|
16
|
+
--secondary: 0 0% 96.1%;
|
17
|
+
--secondary-foreground: 0 0% 9%;
|
18
|
+
--muted: 0 0% 96.1%;
|
19
|
+
--muted-foreground: 0 0% 45.1%;
|
20
|
+
--accent: 0 0% 96.1%;
|
21
|
+
--accent-foreground: 0 0% 9%;
|
22
|
+
--destructive: 0 84.2% 60.2%;
|
23
|
+
--destructive-foreground: 0 0% 98%;
|
24
|
+
--border: 0 0% 89.8%;
|
25
|
+
--input: 0 0% 89.8%;
|
26
|
+
--ring: 0 0% 3.9%;
|
27
|
+
--chart-1: 12 76% 61%;
|
28
|
+
--chart-2: 173 58% 39%;
|
29
|
+
--chart-3: 197 37% 24%;
|
30
|
+
--chart-4: 43 74% 66%;
|
31
|
+
--chart-5: 27 87% 67%;
|
32
|
+
--radius: 0.5rem;
|
33
|
+
}
|
34
|
+
.dark {
|
35
|
+
--background: 0 0% 3.9%;
|
36
|
+
--foreground: 0 0% 98%;
|
37
|
+
--card: 0 0% 3.9%;
|
38
|
+
--card-foreground: 0 0% 98%;
|
39
|
+
--popover: 0 0% 3.9%;
|
40
|
+
--popover-foreground: 0 0% 98%;
|
41
|
+
--primary: 0 0% 98%;
|
42
|
+
--primary-foreground: 0 0% 9%;
|
43
|
+
--secondary: 0 0% 14.9%;
|
44
|
+
--secondary-foreground: 0 0% 98%;
|
45
|
+
--muted: 0 0% 14.9%;
|
46
|
+
--muted-foreground: 0 0% 63.9%;
|
47
|
+
--accent: 0 0% 14.9%;
|
48
|
+
--accent-foreground: 0 0% 98%;
|
49
|
+
--destructive: 0 62.8% 30.6%;
|
50
|
+
--destructive-foreground: 0 0% 98%;
|
51
|
+
--border: 0 0% 14.9%;
|
52
|
+
--input: 0 0% 14.9%;
|
53
|
+
--ring: 0 0% 83.1%;
|
54
|
+
--chart-1: 220 70% 50%;
|
55
|
+
--chart-2: 160 60% 45%;
|
56
|
+
--chart-3: 30 80% 55%;
|
57
|
+
--chart-4: 280 65% 60%;
|
58
|
+
--chart-5: 340 75% 55%;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
@layer base {
|
63
|
+
* {
|
64
|
+
@apply border-border;
|
65
|
+
}
|
66
|
+
body {
|
67
|
+
@apply bg-background text-foreground;
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
3
|
+
"style": "new-york",
|
4
|
+
"rsc": false,
|
5
|
+
"tsx": true,
|
6
|
+
"tailwind": {
|
7
|
+
"config": "tailwind.config.js",
|
8
|
+
"css": "app/javascript/entrypoints/application.css",
|
9
|
+
"baseColor": "neutral",
|
10
|
+
"cssVariables": true,
|
11
|
+
"prefix": ""
|
12
|
+
},
|
13
|
+
"aliases": {
|
14
|
+
"components": "@/components",
|
15
|
+
"utils": "@/lib/utils",
|
16
|
+
"ui": "@/components/ui",
|
17
|
+
"lib": "@/lib",
|
18
|
+
"hooks": "@/hooks"
|
19
|
+
},
|
20
|
+
"iconLibrary": "lucide"
|
21
|
+
}
|
File without changes
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<style>
|
2
|
+
.logo {
|
3
|
+
height: 6em;
|
4
|
+
padding: 1.5em;
|
5
|
+
will-change: filter;
|
6
|
+
transition: filter 300ms;
|
7
|
+
}
|
8
|
+
.logo:hover {
|
9
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
10
|
+
}
|
11
|
+
.logo.react:hover {
|
12
|
+
filter: drop-shadow(0 0 2em #61dafbaa);
|
13
|
+
}
|
14
|
+
.logo.rails:hover {
|
15
|
+
filter: drop-shadow(0 0 2em #CC0000);
|
16
|
+
}
|
17
|
+
|
18
|
+
@keyframes logo-spin {
|
19
|
+
from {
|
20
|
+
transform: rotate(0deg);
|
21
|
+
}
|
22
|
+
to {
|
23
|
+
transform: rotate(360deg);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
a .logo.react {
|
27
|
+
animation: logo-spin infinite 20s linear;
|
28
|
+
}
|
29
|
+
</style>
|
30
|
+
<%= turbo_mount('App') %>
|
31
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
const defaultTheme = require('tailwindcss/defaultTheme')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
darkMode: ['class'],
|
5
|
+
content: [
|
6
|
+
'./public/*.html',
|
7
|
+
'./app/helpers/**/*.rb',
|
8
|
+
'./app/javascript/**/*.{js,jsx,ts,tsx}',
|
9
|
+
'./app/views/**/*.{erb,haml,html,slim}'
|
10
|
+
],
|
11
|
+
theme: {
|
12
|
+
extend: {
|
13
|
+
fontFamily: {
|
14
|
+
sans: [
|
15
|
+
'Inter var',
|
16
|
+
...defaultTheme.fontFamily.sans
|
17
|
+
]
|
18
|
+
},
|
19
|
+
borderRadius: {
|
20
|
+
lg: 'var(--radius)',
|
21
|
+
md: 'calc(var(--radius) - 2px)',
|
22
|
+
sm: 'calc(var(--radius) - 4px)'
|
23
|
+
},
|
24
|
+
colors: {
|
25
|
+
background: 'hsl(var(--background))',
|
26
|
+
foreground: 'hsl(var(--foreground))',
|
27
|
+
card: {
|
28
|
+
DEFAULT: 'hsl(var(--card))',
|
29
|
+
foreground: 'hsl(var(--card-foreground))'
|
30
|
+
},
|
31
|
+
popover: {
|
32
|
+
DEFAULT: 'hsl(var(--popover))',
|
33
|
+
foreground: 'hsl(var(--popover-foreground))'
|
34
|
+
},
|
35
|
+
primary: {
|
36
|
+
DEFAULT: 'hsl(var(--primary))',
|
37
|
+
foreground: 'hsl(var(--primary-foreground))'
|
38
|
+
},
|
39
|
+
secondary: {
|
40
|
+
DEFAULT: 'hsl(var(--secondary))',
|
41
|
+
foreground: 'hsl(var(--secondary-foreground))'
|
42
|
+
},
|
43
|
+
muted: {
|
44
|
+
DEFAULT: 'hsl(var(--muted))',
|
45
|
+
foreground: 'hsl(var(--muted-foreground))'
|
46
|
+
},
|
47
|
+
accent: {
|
48
|
+
DEFAULT: 'hsl(var(--accent))',
|
49
|
+
foreground: 'hsl(var(--accent-foreground))'
|
50
|
+
},
|
51
|
+
destructive: {
|
52
|
+
DEFAULT: 'hsl(var(--destructive))',
|
53
|
+
foreground: 'hsl(var(--destructive-foreground))'
|
54
|
+
},
|
55
|
+
border: 'hsl(var(--border))',
|
56
|
+
input: 'hsl(var(--input))',
|
57
|
+
ring: 'hsl(var(--ring))',
|
58
|
+
chart: {
|
59
|
+
'1': 'hsl(var(--chart-1))',
|
60
|
+
'2': 'hsl(var(--chart-2))',
|
61
|
+
'3': 'hsl(var(--chart-3))',
|
62
|
+
'4': 'hsl(var(--chart-4))',
|
63
|
+
'5': 'hsl(var(--chart-5))'
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
},
|
68
|
+
plugins: [
|
69
|
+
require('@tailwindcss/forms'),
|
70
|
+
require('@tailwindcss/typography'),
|
71
|
+
require('@tailwindcss/container-queries'),
|
72
|
+
require('tailwindcss-animate')
|
73
|
+
]
|
74
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
4
|
+
"target": "ES2020",
|
5
|
+
"useDefineForClassFields": true,
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
7
|
+
"module": "ESNext",
|
8
|
+
"skipLibCheck": true,
|
9
|
+
|
10
|
+
"moduleResolution": "bundler",
|
11
|
+
"allowImportingTsExtensions": true,
|
12
|
+
"isolatedModules": true,
|
13
|
+
"moduleDetection": "force",
|
14
|
+
"noEmit": true,
|
15
|
+
"jsx": "react-jsx",
|
16
|
+
|
17
|
+
"strict": true,
|
18
|
+
"noUnusedLocals": true,
|
19
|
+
"noUnusedParameters": true,
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
21
|
+
"noUncheckedSideEffectImports": true,
|
22
|
+
|
23
|
+
"baseUrl": ".",
|
24
|
+
"paths": {
|
25
|
+
"@/*": ["./app/javascript/*"]
|
26
|
+
}
|
27
|
+
},
|
28
|
+
"include": ["app/javascript/**/*"]
|
29
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
4
|
+
"target": "ES2022",
|
5
|
+
"lib": ["ES2023"],
|
6
|
+
"module": "ESNext",
|
7
|
+
"skipLibCheck": true,
|
8
|
+
|
9
|
+
"moduleResolution": "bundler",
|
10
|
+
"allowImportingTsExtensions": true,
|
11
|
+
"isolatedModules": true,
|
12
|
+
"moduleDetection": "force",
|
13
|
+
"noEmit": true,
|
14
|
+
|
15
|
+
"strict": true,
|
16
|
+
"noUnusedLocals": true,
|
17
|
+
"noUnusedParameters": true,
|
18
|
+
"noFallthroughCasesInSwitch": true,
|
19
|
+
"noUncheckedSideEffectImports": true
|
20
|
+
},
|
21
|
+
"include": ["vite.config.ts"]
|
22
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import path from 'path'
|
2
|
+
import { defineConfig } from 'vite'
|
3
|
+
import RubyPlugin from 'vite-plugin-ruby'
|
4
|
+
import react from "@vitejs/plugin-react"
|
5
|
+
|
6
|
+
export default defineConfig({
|
7
|
+
plugins: [
|
8
|
+
react(),
|
9
|
+
RubyPlugin(),
|
10
|
+
],
|
11
|
+
resolve: {
|
12
|
+
alias: {
|
13
|
+
"@": path.resolve(__dirname, "./app/javascript"),
|
14
|
+
},
|
15
|
+
},
|
16
|
+
})
|
17
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
say "=== Vite-react setup starting... ===", :green
|
2
|
+
|
3
|
+
gem "vite_rails", "~> 3.0"
|
4
|
+
gem "turbo-mount", "~> 0.4.1"
|
5
|
+
gem "tailwindcss-rails", "~> 3.0"
|
6
|
+
|
7
|
+
|
8
|
+
rails_command "tailwindcss:install"
|
9
|
+
|
10
|
+
gsub_file "app/views/layouts/application.html.erb",
|
11
|
+
/<main class="container mx-auto mt-28 px-5 flex">/,
|
12
|
+
"<main class=\"\">"
|
13
|
+
|
14
|
+
# --------------------------------------------------------------------------
|
15
|
+
# 2.3: Vite + React + Tailwind + shadcn
|
16
|
+
# --------------------------------------------------------------------------
|
17
|
+
say "=== Installing Vite, React, Tailwind, shadcn, etc. ===", :green
|
18
|
+
|
19
|
+
# --- Vite ---
|
20
|
+
run "bundle exec vite install"
|
21
|
+
|
22
|
+
# --- Install NPM dependencies ---
|
23
|
+
run <<~CMD
|
24
|
+
npm install \
|
25
|
+
react react-dom \
|
26
|
+
turbo-mount stimulus-vite-helpers clsx tailwind-merge \
|
27
|
+
@hotwired/turbo-rails \
|
28
|
+
@rails/actioncable @rails/activestorage \
|
29
|
+
class-variance-authority clsx tailwind-merge lucide-react
|
30
|
+
CMD
|
31
|
+
|
32
|
+
run <<~CMD
|
33
|
+
npm install -D \
|
34
|
+
@vitejs/plugin-react eslint globals eslint-plugin-react-refresh typescript-eslint @eslint/js \
|
35
|
+
@types/react @types/react-dom vite-plugin-stimulus-hmr vite-plugin-full-reload \
|
36
|
+
tailwind autoprefixer tailwindcss-animate \
|
37
|
+
@tailwindcss/typography @tailwindcss/container-queries @tailwindcss/forms
|
38
|
+
CMD
|
39
|
+
|
40
|
+
# Initialize Tailwind configs
|
41
|
+
run "npx tailwindcss init -p"
|
42
|
+
|
43
|
+
# --------------------------------------------------------------------------
|
44
|
+
# 2.3.2: Overwrite vite.config.js with your React + Ruby config
|
45
|
+
# --------------------------------------------------------------------------
|
46
|
+
remove_file "vite.config.js"
|
47
|
+
copy_file "#{__dir__}/vite.config.js", "vite.config.js"
|
48
|
+
|
49
|
+
# --------------------------------------------------------------------------
|
50
|
+
# 2.3.3: Add TypeScript config files
|
51
|
+
# --------------------------------------------------------------------------
|
52
|
+
copy_file "#{__dir__}/tsconfig.json", "tsconfig.json"
|
53
|
+
copy_file "#{__dir__}/tsconfig.app.json", "tsconfig.app.json"
|
54
|
+
copy_file "#{__dir__}/tsconfig.node.json", "tsconfig.node.json"
|
55
|
+
|
56
|
+
# --------------------------------------------------------------------------
|
57
|
+
# 2.3.4: Remove default Rails assets / create Stimulus + Tailwind structure
|
58
|
+
# --------------------------------------------------------------------------
|
59
|
+
remove_file "app/javascript/application.js"
|
60
|
+
remove_file "app/javascript/controllers/index.js"
|
61
|
+
|
62
|
+
create_file "app/javascript/controllers/index.js", <<~JS
|
63
|
+
import { application } from "./application";
|
64
|
+
import { registerControllers } from "stimulus-vite-helpers";
|
65
|
+
|
66
|
+
const controllers = import.meta.glob("./**/*_controller.js", { eager: true });
|
67
|
+
registerControllers(application, controllers);
|
68
|
+
JS
|
69
|
+
|
70
|
+
|
71
|
+
copy_file "#{__dir__}/application.css", "app/javascript/entrypoints/application.css"
|
72
|
+
|
73
|
+
# 2.3.5: Create the main JS entrypoint for Vite
|
74
|
+
remove_file "app/javascript/entrypoints/application.js"
|
75
|
+
create_file "app/javascript/entrypoints/application.js", <<~JS
|
76
|
+
import "@hotwired/turbo-rails";
|
77
|
+
import "../controllers";
|
78
|
+
import "./turbo-mount";
|
79
|
+
import "./application.css";
|
80
|
+
|
81
|
+
console.log("Hello from application.js");
|
82
|
+
JS
|
83
|
+
|
84
|
+
# --------------------------------------------------------------------------
|
85
|
+
# 2.4: turbo-mount installation
|
86
|
+
# --------------------------------------------------------------------------
|
87
|
+
say "=== Installing turbo-mount ===", :green
|
88
|
+
generate "turbo_mount:install --framework=react"
|
89
|
+
|
90
|
+
# We’ll create a dedicated turbo-mount entry for React components
|
91
|
+
remove_file "app/javascript/turbo-mount.js"
|
92
|
+
create_file "app/javascript/entrypoints/turbo-mount.js", <<~JS
|
93
|
+
import { TurboMount } from "turbo-mount";
|
94
|
+
import { registerComponent } from "turbo-mount/react";
|
95
|
+
|
96
|
+
// Example React component
|
97
|
+
import { App } from "@/components/App";
|
98
|
+
|
99
|
+
const turboMount = new TurboMount();
|
100
|
+
registerComponent(turboMount, "App", App);
|
101
|
+
JS
|
102
|
+
|
103
|
+
# --------------------------------------------------------------------------
|
104
|
+
# 2.5: Example React component + Home controller
|
105
|
+
# --------------------------------------------------------------------------
|
106
|
+
|
107
|
+
copy_file "#{__dir__}/App.tsx", "app/javascript/components/App.tsx"
|
108
|
+
|
109
|
+
empty_directory "public/images"
|
110
|
+
run <<~CMD
|
111
|
+
curl -o public/images/rails.svg https://raw.githubusercontent.com/lsproule/react-rails-template/refs/heads/main/images/rails.svg
|
112
|
+
curl -o public/images/vite.svg https://raw.githubusercontent.com/lsproule/react-rails-template/refs/heads/main/images/vite.svg
|
113
|
+
curl -o public/images/react.svg https://raw.githubusercontent.com/lsproule/react-rails-template/refs/heads/main/images/react.svg
|
114
|
+
CMD
|
115
|
+
|
116
|
+
generate :controller, "route", "index", "--skip-routes", "--no-helper", "--no-assets"
|
117
|
+
route "root to: 'route#index'"
|
118
|
+
|
119
|
+
remove_file "app/views/route/index.html.erb", force: true
|
120
|
+
copy_file "#{__dir__}/index.html.erb", "app/views/route/index.html.erb"
|
121
|
+
|
122
|
+
# --------------------------------------------------------------------------
|
123
|
+
# 2.6: Insert needed tags in application.html.erb
|
124
|
+
# --------------------------------------------------------------------------
|
125
|
+
insert_into_file "app/views/layouts/application.html.erb",
|
126
|
+
after: "<%= csrf_meta_tags %>\n" do
|
127
|
+
<<~ERB
|
128
|
+
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
129
|
+
<%= javascript_importmap_tags %>
|
130
|
+
<%= vite_client_tag %>
|
131
|
+
<%= vite_javascript_tag 'application' %>
|
132
|
+
ERB
|
133
|
+
end
|
134
|
+
|
135
|
+
# --------------------------------------------------------------------------
|
136
|
+
# 2.7: shadcn initialization
|
137
|
+
# --------------------------------------------------------------------------
|
138
|
+
#run "npx shadcn@latest init"
|
139
|
+
copy_file "#{__dir__}/components.json", "components.json"
|
140
|
+
copy_file "#{__dir__}/utils.ts", "app/javascript/lib/utils.ts"
|
141
|
+
remove_file "tailwind.config.json"
|
142
|
+
copy_file "#{__dir__}/tailwind.config.js", "tailwind.config.js"
|
143
|
+
|
144
|
+
# --------------------------------------------------------------------------
|
145
|
+
# 2.8 setup eslint
|
146
|
+
copy_file "#{__dir__}/eslint.config.js", "eslint.config.js"
|
147
|
+
|
148
|
+
# --------------------------------------------------------------------------
|
149
|
+
# 2.9: Done!
|
150
|
+
# --------------------------------------------------------------------------
|
151
|
+
say "=== Setup Complete ===", :green
|
152
|
+
say "You can now run: bin/rails server", :yellow
|
153
|
+
say "Visit http://localhost:3000 to see the example turbo-mounted React component.", :yellow
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
# task :vite_react do
|
3
|
+
# # Task goes here
|
4
|
+
# end
|
5
|
+
#
|
6
|
+
namespace :vite_react do
|
7
|
+
desc "Install the vite react setup"
|
8
|
+
task :install do
|
9
|
+
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/vite_react.rb", __dir__)}"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "rails"
|
2
|
+
require "rails/railtie"
|
3
|
+
require "rails/generators"
|
4
|
+
require "rails/generators/rails/scaffold/scaffold_generator"
|
5
|
+
|
6
|
+
|
7
|
+
module ViteReact
|
8
|
+
module ScaffoldGenerator
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
included do
|
11
|
+
hook_for :scaffold, in: nil, default: true, type: :boolean
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
module ViteReact
|
19
|
+
class Railtie < ::Rails::Railtie
|
20
|
+
rake_tasks do
|
21
|
+
load "tasks/install.rake"
|
22
|
+
end
|
23
|
+
generators do |app|
|
24
|
+
Rails::Generators.configure! app.config.generators
|
25
|
+
Rails::Generators::ScaffoldGenerator.include ViteReact::ScaffoldGenerator
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/vite_react.rb
ADDED
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vite_react
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- lsproule
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-16 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: rails
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 8.0.1
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 8.0.1
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: devise
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: vite_rails
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: turbo-mount
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: tailwindcss-rails
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: tailwindcss-ruby
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :runtime
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
description: "Vite react adds a few generators and vite and react\nto your rails project.
|
97
|
+
It also gets it set up to be able \nto use shadcn. \n"
|
98
|
+
email:
|
99
|
+
- lucas.sproule.42@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- MIT-LICENSE
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/generators/ui/component/component_generator.rb
|
108
|
+
- lib/generators/ui/component/templates/component.tsx.erb
|
109
|
+
- lib/generators/ui/register/register_generator.rb
|
110
|
+
- lib/generators/vite_react/migration/migration.rb
|
111
|
+
- lib/generators/vite_react/model_validation/model_validation_generator.rb
|
112
|
+
- lib/generators/vite_react/scaffold/scaffold_generator.rb
|
113
|
+
- lib/install/App.tsx
|
114
|
+
- lib/install/application.css
|
115
|
+
- lib/install/components.json
|
116
|
+
- lib/install/eslint.config.js
|
117
|
+
- lib/install/index.html.erb
|
118
|
+
- lib/install/tailwind.config.js
|
119
|
+
- lib/install/tsconfig.app.json
|
120
|
+
- lib/install/tsconfig.json
|
121
|
+
- lib/install/tsconfig.node.json
|
122
|
+
- lib/install/utils.ts
|
123
|
+
- lib/install/vite.config.js
|
124
|
+
- lib/install/vite_react.rb
|
125
|
+
- lib/tasks/install.rake
|
126
|
+
- lib/vite_react.rb
|
127
|
+
- lib/vite_react/railtie.rb
|
128
|
+
- lib/vite_react/version.rb
|
129
|
+
homepage: https://docs.lucassproule.com
|
130
|
+
licenses:
|
131
|
+
- MIT
|
132
|
+
metadata:
|
133
|
+
homepage_uri: https://docs.lucassproule.com
|
134
|
+
source_code_uri: https://github.com/lsproule/vite_react
|
135
|
+
changelog_uri: https://github.com/lsproule/vite_react
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.6.2
|
151
|
+
specification_version: 4
|
152
|
+
summary: Vite react adds vite and react to your project
|
153
|
+
test_files: []
|