better_vite_helper 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8aa9948651f9cdf4792fdc963c80b45192904b1515298aa2a51d5ccda21a7744
4
+ data.tar.gz: e217785641ddc537f9fba68f254baad56fbe607e8d26224c6b3931d21620a53c
5
+ SHA512:
6
+ metadata.gz: 77876f7bc002d468e2eb348990fd2898c6983950b708cfd075486d3b625ffe0e7db25ebc6e942a270a412309aa58497d0c19dc9bf7e0cc6c7a2b560693f1ccbd
7
+ data.tar.gz: a402d5bedc937a416aa28a9403044de878f2e94bcdf49de7f70bd274311b08737c4ef28ba018c20e5d25d0d092e20a5f318f6c117170e88c273a623b16ab442d
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright Umberto Peserico
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,68 @@
1
+ # BetterViteHelper
2
+
3
+ Rails Engine providing Vite view helpers with automatic dev server detection and manifest-based asset resolution.
4
+
5
+ ## Requirements
6
+
7
+ - Ruby >= 3.4.7
8
+ - Rails >= 8.0.0, < 8.2
9
+
10
+ ## Installation
11
+
12
+ Add to your Gemfile:
13
+
14
+ ```ruby
15
+ gem "better_vite_helper"
16
+ ```
17
+
18
+ Then run:
19
+
20
+ ```bash
21
+ bundle install
22
+ bin/rails generate better_vite_helper:install
23
+ ```
24
+
25
+ This copies `vite.config.js` and `postcss.config.js` to your application.
26
+
27
+ ## Usage
28
+
29
+ ### View Helpers
30
+
31
+ ```erb
32
+ <%# Include JavaScript entry %>
33
+ <%= vite_javascript_include_tag "application.js" %>
34
+
35
+ <%# Include stylesheet (production only, Vite handles HMR in dev) %>
36
+ <%= vite_stylesheet_link_tag "application.css" %>
37
+
38
+ <%# Get asset path directly %>
39
+ <%= vite_asset_path "application.js" %>
40
+
41
+ <%# Check if dev server is running %>
42
+ <% if vite_development? %>
43
+ <!-- dev mode -->
44
+ <% end %>
45
+ ```
46
+
47
+ ### Configuration
48
+
49
+ ```ruby
50
+ # config/initializers/better_vite_helper.rb
51
+ BetterViteHelper.configure do |config|
52
+ config.dev_server_url = "http://localhost:5173" # default, or ENV["VITE_DEV_SERVER_URL"]
53
+ config.manifest_path = Rails.root.join("public/assets/.vite/manifest.json") # default
54
+ config.asset_host = "https://cdn.example.com" # optional, falls back to Rails.application.config.asset_host
55
+ end
56
+ ```
57
+
58
+ ## Development
59
+
60
+ ```bash
61
+ bundle install
62
+ bundle exec rspec # Run tests
63
+ bin/rubocop -a # Lint and auto-fix
64
+ ```
65
+
66
+ ## License
67
+
68
+ 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,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "bundler/gem_tasks"
5
+
6
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
7
+ load "rails/tasks/engine.rake" if File.exist?(APP_RAKEFILE)
8
+
9
+ begin
10
+ require "rspec/core/rake_task"
11
+ RSpec::Core::RakeTask.new(:spec)
12
+ task default: :spec
13
+ rescue LoadError
14
+ # rspec not available
15
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterViteHelper
4
+ class Configuration
5
+ attr_accessor :asset_host
6
+ attr_writer :manifest_path, :dev_server_url
7
+
8
+ def initialize
9
+ @manifest_path = nil
10
+ @dev_server_url = nil
11
+ @asset_host = nil
12
+ end
13
+
14
+ def manifest_path
15
+ @manifest_path || default_manifest_path
16
+ end
17
+
18
+ def dev_server_url
19
+ @dev_server_url || ENV.fetch("VITE_DEV_SERVER_URL", "http://localhost:5173")
20
+ end
21
+
22
+ private
23
+
24
+ def default_manifest_path
25
+ Rails.root.join("public/assets/.vite/manifest.json")
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterViteHelper
4
+ class Railtie < ::Rails::Railtie
5
+ initializer "better_vite_helper.view_helpers" do
6
+ ActiveSupport.on_load(:action_view) do
7
+ include BetterViteHelper::ViewHelpers
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module BetterViteHelper
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module BetterViteHelper
8
+ module ViewHelpers
9
+ def vite_development?
10
+ Rails.env.development? && vite_dev_server_running?
11
+ end
12
+
13
+ def vite_dev_server_running?
14
+ return @vite_dev_server_running if defined?(@vite_dev_server_running)
15
+
16
+ @vite_dev_server_running = begin
17
+ uri = URI("#{BetterViteHelper.configuration.dev_server_url}/")
18
+ Net::HTTP.get_response(uri)
19
+ true
20
+ rescue StandardError
21
+ false
22
+ end
23
+ end
24
+
25
+ def vite_manifest
26
+ return {} if vite_development?
27
+
28
+ @vite_manifest ||= begin
29
+ manifest_path = BetterViteHelper.configuration.manifest_path
30
+ JSON.parse(File.read(manifest_path))
31
+ rescue Errno::ENOENT
32
+ Rails.logger.error "Vite manifest not found at #{manifest_path}"
33
+ raise "Vite manifest not found. Run 'yarn build' to generate assets."
34
+ rescue JSON::ParserError => e
35
+ Rails.logger.error "Invalid Vite manifest: #{e.message}"
36
+ raise "Invalid Vite manifest format"
37
+ end
38
+ end
39
+
40
+ def vite_asset_path(entry_name)
41
+ if vite_development?
42
+ dev_asset_path(entry_name)
43
+ else
44
+ production_asset_path(entry_name)
45
+ end
46
+ end
47
+
48
+ def vite_javascript_include_tag(entry_name, **options)
49
+ path = vite_asset_path(entry_name)
50
+ default_options = { type: "module", defer: true, crossorigin: "anonymous" }
51
+ javascript_include_tag(path, **default_options.merge(options))
52
+ end
53
+
54
+ def vite_stylesheet_link_tag(entry_name, **options)
55
+ return "" if vite_development?
56
+
57
+ manifest_key = resolve_manifest_key(entry_name)
58
+ asset = vite_manifest[manifest_key] or raise "Vite entry '#{entry_name}' not found in manifest"
59
+
60
+ if manifest_key.include?("stylesheets") || asset["file"].end_with?(".css")
61
+ css_path = build_asset_url(asset["file"])
62
+ stylesheet_link_tag(css_path, **{ media: "all" }.merge(options))
63
+ else
64
+ ""
65
+ end
66
+ end
67
+
68
+ def reset_vite_manifest_cache!
69
+ @vite_manifest = nil
70
+ end
71
+
72
+ def reset_vite_dev_server_cache!
73
+ remove_instance_variable(:@vite_dev_server_running) if defined?(@vite_dev_server_running)
74
+ end
75
+
76
+ private
77
+
78
+ def dev_asset_path(entry_name)
79
+ base_url = resolved_asset_host || BetterViteHelper.configuration.dev_server_url
80
+ case entry_name
81
+ when "application.js"
82
+ "#{base_url}/app/assets/javascripts/application.js"
83
+ when "application.css"
84
+ "#{base_url}/app/assets/stylesheets/application.css"
85
+ else
86
+ "#{base_url}/#{entry_name}"
87
+ end
88
+ end
89
+
90
+ def production_asset_path(entry_name)
91
+ manifest_key = resolve_manifest_key(entry_name)
92
+ asset = vite_manifest[manifest_key] or raise "Vite entry '#{entry_name}' not found in manifest"
93
+ build_asset_url(asset["file"])
94
+ end
95
+
96
+ def resolve_manifest_key(entry_name)
97
+ case entry_name
98
+ when "application.js"
99
+ "app/assets/javascripts/application.js"
100
+ when "application.css"
101
+ "app/assets/stylesheets/application.css"
102
+ else
103
+ entry_name
104
+ end
105
+ end
106
+
107
+ def build_asset_url(file)
108
+ if resolved_asset_host
109
+ "#{resolved_asset_host}/assets/#{file}"
110
+ else
111
+ "/assets/#{file}"
112
+ end
113
+ end
114
+
115
+ def resolved_asset_host
116
+ BetterViteHelper.configuration.asset_host || Rails.application.config.asset_host
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "better_vite_helper/version"
4
+ require "better_vite_helper/configuration"
5
+ require "better_vite_helper/view_helpers"
6
+ require "better_vite_helper/railtie"
7
+
8
+ module BetterViteHelper
9
+ class << self
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+
20
+ def reset_configuration!
21
+ @configuration = Configuration.new
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module BetterViteHelper
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Copies Vite and PostCSS configuration files to your application"
11
+
12
+ def copy_vite_config
13
+ copy_file "vite.config.js", "vite.config.js"
14
+ end
15
+
16
+ def copy_postcss_config
17
+ copy_file "postcss.config.js", "postcss.config.js"
18
+ end
19
+
20
+ def show_post_install_message
21
+ say ""
22
+ say "BetterViteHelper installed successfully!", :green
23
+ say ""
24
+ say "Next steps:"
25
+ say " 1. Run 'yarn add -D vite' to install Vite"
26
+ say " 2. Add your JavaScript entry point at app/assets/javascripts/application.js"
27
+ say " 3. Add your CSS entry point at app/assets/stylesheets/application.css"
28
+ say " 4. Run 'yarn vite' for development or 'yarn vite build' for production"
29
+ say ""
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ }
@@ -0,0 +1,49 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { defineConfig } from "vite";
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+
7
+ export default defineConfig({
8
+ publicDir: false, // avoid conflicts with outDir
9
+ emptyOutDir: true,
10
+ css: {
11
+ devSourcemap: true,
12
+ },
13
+
14
+ server: {
15
+ port: 5173,
16
+ host: "0.0.0.0",
17
+ cors: true,
18
+ hmr: {
19
+ port: 5173,
20
+ },
21
+ },
22
+
23
+ build: {
24
+ outDir: "public/assets",
25
+ manifest: true,
26
+ sourcemap: true,
27
+ emptyOutDir: true,
28
+
29
+ rollupOptions: {
30
+ input: {
31
+ application: resolve(
32
+ __dirname,
33
+ "app/assets/javascripts/application.js"
34
+ ),
35
+ styles: resolve(__dirname, "app/assets/stylesheets/application.css"),
36
+ },
37
+ output: {
38
+ entryFileNames: "application-[hash].js",
39
+ assetFileNames: (info) => {
40
+ if (info.name?.endsWith(".css")) {
41
+ return "application-[hash][extname]";
42
+ }
43
+ return "[name]-[hash][extname]";
44
+ },
45
+ },
46
+ external: [],
47
+ },
48
+ },
49
+ });
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :better_vite_helper do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_vite_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Umberto Peserico
8
+ - Alessio Bussolari
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 8.0.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '8.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 8.0.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '8.2'
33
+ description: Rails Engine providing Vite view helpers with automatic dev server detection
34
+ and manifest-based asset resolution for seamless Vite integration in Rails applications.
35
+ email:
36
+ - umberto.peserico@pandev.it
37
+ - alessio.bussolari@pandev.it
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - MIT-LICENSE
43
+ - README.md
44
+ - Rakefile
45
+ - lib/better_vite_helper.rb
46
+ - lib/better_vite_helper/configuration.rb
47
+ - lib/better_vite_helper/railtie.rb
48
+ - lib/better_vite_helper/version.rb
49
+ - lib/better_vite_helper/view_helpers.rb
50
+ - lib/generators/better_vite_helper/install/install_generator.rb
51
+ - lib/generators/better_vite_helper/install/templates/postcss.config.js
52
+ - lib/generators/better_vite_helper/install/templates/vite.config.js
53
+ - lib/tasks/better_vite_helper_tasks.rake
54
+ homepage: https://github.com/pandev-srl/better_vite_helper
55
+ licenses:
56
+ - MIT
57
+ metadata:
58
+ homepage_uri: https://github.com/pandev-srl/better_vite_helper
59
+ source_code_uri: https://github.com/pandev-srl/better_vite_helper
60
+ changelog_uri: https://github.com/pandev-srl/better_vite_helper/blob/main/CHANGELOG.md
61
+ rubygems_mfa_required: 'true'
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 3.2.0
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.7.2
77
+ specification_version: 4
78
+ summary: Rails Engine providing Vite view helpers with automatic dev server detection
79
+ test_files: []