- <%%= form.submit "Sign in", class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
+ <%%= form.submit "Sign in", class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
diff --git a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
index 39c2da1f..8748210d 100644
--- a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
+++ b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
@@ -1,5 +1,6 @@
require "rails/generators/erb/scaffold/scaffold_generator"
require "rails/generators/resource_helpers"
+require File.expand_path("../../test_unit/scaffold/scaffold_generator.rb", __dir__)
module Tailwindcss
module Generators
diff --git a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
index 9e392609..1821201c 100644
--- a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
@@ -12,32 +12,32 @@
<%% end %>
<% attributes.each do |attribute| -%>
-
+
">
<% if attribute.password_digest? -%>
<%%= form.label :password %>
- <%%= form.password_field :password, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %>
+ <%%= form.password_field :password, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %>
<%%= form.label :password_confirmation %>
- <%%= form.password_field :password_confirmation, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password_confirmation].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password_confirmation].any?}] %>
+ <%%= form.password_field :password_confirmation, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password_confirmation].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password_confirmation].any?}] %>
<% elsif attribute.attachments? -%>
<%%= form.label :<%= attribute.column_name %> %>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %>
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
<% else -%>
<%%= form.label :<%= attribute.column_name %> %>
<% if attribute.field_type == :textarea || attribute.field_type == :text_area -%>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
<% elsif attribute.field_type == :checkbox || attribute.field_type == :check_box -%>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border outline-hidden mt-2 h-5 w-5", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border order-first h-5 w-5", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
<% else -%>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %>
<% end -%>
<% end -%>
<% end -%>
- <%%= form.submit class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
+ <%%= form.submit class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
<%% end %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt
index 74edd3de..08d92d3a 100644
--- a/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt
@@ -5,6 +5,6 @@
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
- <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
- <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt
index 3d337f95..12a0db16 100644
--- a/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt
@@ -10,13 +10,17 @@
<%%= link_to "New <%= human_name.downcase %>", new_<%= singular_route_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium" %>
+
<%% if @<%= plural_table_name %>.any? %>
<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
- <%%= render <%= singular_table_name %> %>
-
- <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
-
+
+ <%%= render <%= singular_table_name %> %>
+
+ <%%= link_to "Show", <%= model_resource_name(singular_table_name) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Edit", <%= edit_helper(singular_table_name, type: :path) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= button_to "Destroy", <%= model_resource_name %>, method: :delete, class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %>
+
+
<%% end %>
<%% else %>
No <%= human_name.downcase.pluralize %> found.
diff --git a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
index 0a10d967..32ad9b83 100644
--- a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
@@ -5,5 +5,5 @@
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
- <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt
index 88dc3eda..433b7a33 100644
--- a/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt
@@ -1,16 +1,18 @@
-
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
-
+
<%= attribute.human_name %>:
<% if attribute.attachment? -%>
- <%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %> if <%= singular_name %>.<%= attribute.column_name %>.attached? %>
+ <%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %>, class: "text-gray-700 underline hover:no-underline" if <%= singular_name %>.<%= attribute.column_name %>.attached? %>
<% elsif attribute.attachments? -%>
<%% <%= singular_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
-
<%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %>
+
<%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %>, class: "text-gray-700 underline hover:no-underline" %>
<%% end %>
+<% elsif attribute.type == :boolean -%>
+ <%%= <%= singular_name %>.<%= attribute.column_name %>? ? "Yes" : "No" %>
<% else -%>
<%%= <%= singular_name %>.<%= attribute.column_name %> %>
<% end -%>
-
+
<% end -%>
diff --git a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
index 3a49e9a0..2b6687d2 100644
--- a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
@@ -9,9 +9,7 @@
<%%= render @<%= singular_table_name %> %>
- <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "mt-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
- <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
-
- <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, class: "mt-2 rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium" %>
-
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, form_class: "sm:inline-block mt-2 sm:mt-0 sm:ml-2", class: "w-full rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %>
diff --git a/lib/generators/test_unit/scaffold/scaffold_generator.rb b/lib/generators/test_unit/scaffold/scaffold_generator.rb
new file mode 100644
index 00000000..511ca7d1
--- /dev/null
+++ b/lib/generators/test_unit/scaffold/scaffold_generator.rb
@@ -0,0 +1,20 @@
+require "rails/generators/test_unit/scaffold/scaffold_generator"
+
+module TestUnit # :nodoc:
+ module Generators # :nodoc:
+ class ScaffoldGenerator < Base # :nodoc:
+ def fix_system_test
+ system_test_file = File.join("test/system", class_path, "#{file_name.pluralize}_test.rb")
+ if turbo_defined? && options[:system_tests] && File.exist?(system_test_file)
+ gsub_file(system_test_file, /(click_on.*Destroy this.*)$/, "accept_confirm { \\1 }")
+ end
+ end
+
+ private
+
+ def turbo_defined?
+ defined?(Turbo)
+ end
+ end
+ end
+end
diff --git a/lib/install/upgrade_tailwindcss.rb b/lib/install/upgrade_tailwindcss.rb
index 6266583a..d6ecadab 100644
--- a/lib/install/upgrade_tailwindcss.rb
+++ b/lib/install/upgrade_tailwindcss.rb
@@ -45,8 +45,14 @@
end
if system("npx --version")
+ # We're pinning to v4.1.4 because v4.1.5 of the upgrade tool introduces a dependency version check
+ # on tailwind and I haven't been able to figure out how to get that to work reliably and I am
+ # extremely frustrated with the whole thing. See #544
+ #
+ # At some point we will probably need to unpin this at which point I am sincerely hoping that
+ # someone else will do it.
say "Running the upstream Tailwind CSS upgrader"
- command = Shellwords.join(["npx", "@tailwindcss/upgrade@next", "--force", "--config", TAILWIND_CONFIG_PATH.to_s])
+ command = Shellwords.join(["npx", "@tailwindcss/upgrade@4.1.4", "--force", "--config", TAILWIND_CONFIG_PATH.to_s])
success = run(command, abort_on_failure: false)
unless success
say "The upgrade tool failed!", :red
diff --git a/lib/puma/plugin/tailwindcss.rb b/lib/puma/plugin/tailwindcss.rb
index 4624d7e8..29b5b621 100644
--- a/lib/puma/plugin/tailwindcss.rb
+++ b/lib/puma/plugin/tailwindcss.rb
@@ -13,14 +13,18 @@ def start(launcher)
# If we use system(*command) instead, IRB and Debug can't read from $stdin
# correctly bacause some keystrokes will be taken by watch_command.
begin
- IO.popen(Tailwindcss::Commands.watch_command, 'r+') do |io|
+ IO.popen(['bin/rails', 'tailwindcss:watch'], 'r+') do |io|
IO.copy_stream(io, $stdout)
end
rescue Interrupt
end
end
- launcher.events.on_stopped { stop_tailwind }
+ if Gem::Version.new(Puma::Const::PUMA_VERSION) >= Gem::Version.new("7")
+ launcher.events.after_stopped { stop_tailwind }
+ else
+ launcher.events.on_stopped { stop_tailwind }
+ end
in_background do
monitor_tailwind
diff --git a/lib/tailwindcss-rails.rb b/lib/tailwindcss-rails.rb
index 2b86ff1c..bdfb592d 100644
--- a/lib/tailwindcss-rails.rb
+++ b/lib/tailwindcss-rails.rb
@@ -2,5 +2,6 @@ module Tailwindcss
end
require_relative "tailwindcss/version"
+require_relative "tailwindcss/engines"
require_relative "tailwindcss/engine"
require_relative "tailwindcss/commands"
diff --git a/lib/tailwindcss/commands.rb b/lib/tailwindcss/commands.rb
index fb90f4f6..9c910de8 100644
--- a/lib/tailwindcss/commands.rb
+++ b/lib/tailwindcss/commands.rb
@@ -4,6 +4,7 @@ module Tailwindcss
module Commands
class << self
def compile_command(debug: false, **kwargs)
+ debug = ENV["TAILWINDCSS_DEBUG"].present? if ENV.key?("TAILWINDCSS_DEBUG")
rails_root = defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd)
command = [
@@ -20,11 +21,16 @@ def compile_command(debug: false, **kwargs)
command
end
- def watch_command(always: false, poll: false, **kwargs)
+ def watch_command(always: false, **kwargs)
compile_command(**kwargs).tap do |command|
command << "-w"
command << "always" if always
- command << "-p" if poll
+ end
+ end
+
+ def command_env(verbose:)
+ {}.tap do |env|
+ env["DEBUG"] = "1" if verbose
end
end
diff --git a/lib/tailwindcss/engines.rb b/lib/tailwindcss/engines.rb
new file mode 100644
index 00000000..90bd6d59
--- /dev/null
+++ b/lib/tailwindcss/engines.rb
@@ -0,0 +1,23 @@
+module Tailwindcss
+ module Engines
+ class << self
+ def bundle
+ FileUtils.mkdir_p(Rails.root.join("app/assets/builds/tailwind"))
+ Rails::Engine.subclasses.select do |engine|
+ engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css").exist?
+ end.each do |engine|
+ file_path = Rails.root.join("app/assets/builds/tailwind/#{engine.engine_name}.css")
+ FileUtils.rm(file_path) if File.exist?(file_path)
+ template = <<~TEMPLATE
+ /* DO NOT MODIFY THIS FILE, it was auto-generated by tailwindcss-rails */
+
+ @import "#{engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css")}";
+ TEMPLATE
+ File.open(file_path, 'w') do |file|
+ file.puts template
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/tailwindcss/version.rb b/lib/tailwindcss/version.rb
index acb989e3..81738c04 100644
--- a/lib/tailwindcss/version.rb
+++ b/lib/tailwindcss/version.rb
@@ -1,3 +1,3 @@
module Tailwindcss
- VERSION = "4.0.0.rc5"
+ VERSION = "4.4.0"
end
diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake
index 3044ff05..539a8df9 100644
--- a/lib/tasks/build.rake
+++ b/lib/tasks/build.rake
@@ -1,23 +1,35 @@
namespace :tailwindcss do
desc "Build your Tailwind CSS"
- task build: :environment do |_, args|
+ task build: [:environment, :engines] do |_, args|
debug = args.extras.include?("debug")
+ verbose = args.extras.include?("verbose")
+
command = Tailwindcss::Commands.compile_command(debug: debug)
- puts command.inspect if args.extras.include?("verbose")
- system(*command, exception: true)
+ env = Tailwindcss::Commands.command_env(verbose: verbose)
+ puts "Running: #{Shellwords.join(command)}" if verbose
+
+ system(env, *command, exception: true)
end
desc "Watch and build your Tailwind CSS on file changes"
- task watch: :environment do |_, args|
+ task watch: [:environment, :engines] do |_, args|
debug = args.extras.include?("debug")
- poll = args.extras.include?("poll")
always = args.extras.include?("always")
- command = Tailwindcss::Commands.watch_command(always: always, debug: debug, poll: poll)
- puts command.inspect if args.extras.include?("verbose")
- system(*command)
+ verbose = args.extras.include?("verbose")
+
+ command = Tailwindcss::Commands.watch_command(always: always, debug: debug)
+ env = Tailwindcss::Commands.command_env(verbose: verbose)
+ puts "Running: #{Shellwords.join(command)}" if verbose
+
+ system(env, *command)
rescue Interrupt
puts "Received interrupt, exiting tailwindcss:watch" if args.extras.include?("verbose")
end
+
+ desc "Create Tailwind CSS entry point files for Rails Engines"
+ task engines: :environment do
+ Tailwindcss::Engines.bundle
+ end
end
Rake::Task["assets:precompile"].enhance(["tailwindcss:build"])
diff --git a/tailwindcss-rails.gemspec b/tailwindcss-rails.gemspec
index 0b31c4a8..45c19c28 100644
--- a/tailwindcss-rails.gemspec
+++ b/tailwindcss-rails.gemspec
@@ -20,4 +20,18 @@ Gem::Specification.new do |spec|
spec.add_dependency "railties", ">= 7.0.0"
spec.add_dependency "tailwindcss-ruby", "~> 4.0"
+
+ # TODO: remove this after a suitable period of time after the v4.0.0 release.
+ spec.post_install_message = <<~TEXT
+ == Upgrading to Tailwind CSS v4 ==
+
+ If you are upgrading to tailwindcss-rails 4.x, please read the upgrade guide at:
+
+ https://github.com/rails/tailwindcss-rails/blob/main/README.md#upgrading-your-application-from-tailwind-v3-to-v4
+
+ If you're not ready to upgrade yet, please pin to version 3 in your Gemfile:
+
+ gem "tailwindcss-rails", "~> 3.3.1"
+
+ TEXT
end
diff --git a/test/integration/user_install_test.sh b/test/integration/user_install_test.sh
index 09b03b2f..46b50560 100755
--- a/test/integration/user_install_test.sh
+++ b/test/integration/user_install_test.sh
@@ -6,38 +6,49 @@ set -o pipefail
set -eux
# set up dependencies
+gem install bcrypt # it's complicated, see Rails 7549ba77. can probably be removed once Rails 8.0 is EOL.
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
rm -f Gemfile.lock
-bundle remove actionmailer
bundle add rails --skip-install ${RAILSOPTS:-}
bundle install --prefer-local
+bundle exec rails -v
# do our work a directory with spaces in the name (#176, #184)
rm -rf "My Workspace"
mkdir "My Workspace"
pushd "My Workspace"
-# create a rails app
-bundle exec rails -v
+function prepare_deps {
+ # make sure to use the same version of rails (e.g., install from git source if necessary)
+ bundle remove rails --skip-install
+ rm -f Gemfile.lock
+ bundle add rails --skip-install ${RAILSOPTS:-}
+
+ # use the tailwindcss-rails under test
+ bundle add tailwindcss-rails --skip-install --path="../.."
+ bundle add tailwindcss-ruby --skip-install ${TAILWINDCSSOPTS:-}
+ bundle install --prefer-local
+ bundle show --paths | fgrep tailwind
+ bundle binstubs --all
+}
+
+function install_tailwindcss {
+ # install tailwindcss
+ bin/rails tailwindcss:install
+
+ # TEST: tailwind was installed correctly
+ grep -q "
> Rakefile
@@ -47,7 +58,7 @@ end
EOF
cat >> app/assets/tailwind/application.css < "Rails 8.0.0.beta" ]] ; then
grep -q PasswordsController app/controllers/passwords_controller.rb
fi
+# TEST: doesn't fail when not generating system tests
+bin/rails generate scaffold memo title:string body:text published:boolean --system-tests=false
+grep -q "Show" app/views/memos/index.html.erb
+
# TEST: presence of the generated file
-bin/rails generate scaffold post title:string body:text published:boolean
-grep -q "Show this post" app/views/posts/index.html.erb
+bin/rails generate scaffold post title:string body:text published:boolean --system-tests=true
+grep -q "Show" app/views/posts/index.html.erb
+
+# TEST: the "accept_confirm" system test change was applied cleanly
+grep -q "accept_confirm { click_on \"Destroy this post\"" test/system/posts_test.rb
# TEST: contents of the css file
bin/rails tailwindcss:build[verbose]
@@ -69,4 +87,17 @@ grep -q "py-2" app/assets/builds/tailwind.css
# TEST: contents include application.css directives
grep -q "#abc12399" app/assets/builds/tailwind.css
+# Application variation #2 ----------------------------------------
+popd
+bundle exec rails new test-install2 --skip-bundle --skip-system-test
+pushd test-install2
+
+prepare_deps
+install_tailwindcss
+
+# TEST: presence of the generated file
+# TEST: nothing blew up without system tests, https://github.com/rails/tailwindcss-rails/issues/559
+bin/rails generate scaffold post title:string body:text published:boolean
+grep -q "Show" app/views/posts/index.html.erb
+
echo "OK"
diff --git a/test/integration/user_upgrade_test.sh b/test/integration/user_upgrade_test.sh
index 25039a02..ae4c6852 100755
--- a/test/integration/user_upgrade_test.sh
+++ b/test/integration/user_upgrade_test.sh
@@ -6,8 +6,11 @@ set -o pipefail
set -eux
# set up dependencies
+gem install bcrypt # it's complicated, see Rails 7549ba77. can probably be removed once Rails 8.0 is EOL.
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
rm -f Gemfile.lock
-bundle remove actionmailer
bundle add rails --skip-install ${RAILSOPTS:-}
bundle install --prefer-local
@@ -23,6 +26,7 @@ pushd test-upgrade
# make sure to use the same version of rails (e.g., install from git source if necessary)
bundle remove rails --skip-install
+rm -f Gemfile.lock
bundle add rails --skip-install ${RAILSOPTS:-}
# set up app with tailwindcss-rails v3 and tailwindcss-ruby v3
diff --git a/test/lib/tailwindcss/commands_test.rb b/test/lib/tailwindcss/commands_test.rb
index 3c7e5302..62d1e684 100644
--- a/test/lib/tailwindcss/commands_test.rb
+++ b/test/lib/tailwindcss/commands_test.rb
@@ -33,6 +33,32 @@ def setup
end
end
+ test ".compile_command debug environment variable" do
+ begin
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ ENV["TAILWINDCSS_DEBUG"] = ""
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ ENV["TAILWINDCSS_DEBUG"] = "any non-blank value"
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+ end
+ ensure
+ ENV.delete('TAILWINDCSS_DEBUG')
+ end
+ end
+
test ".compile_command when Rails compression is on" do
Rails.stub(:root, File) do # Rails.root won't work in this test suite
Tailwindcss::Commands.stub(:rails_css_compressor?, true) do
@@ -85,14 +111,6 @@ def setup
refute_includes(actual, "-p")
refute_includes(actual, "--minify")
- actual = Tailwindcss::Commands.watch_command(poll: true)
- assert_kind_of(Array, actual)
- assert_equal(executable, actual.first)
- assert_includes(actual, "-w")
- refute_includes(actual, "always")
- assert_includes(actual, "-p")
- assert_includes(actual, "--minify")
-
actual = Tailwindcss::Commands.watch_command(always: true)
assert_kind_of(Array, actual)
assert_equal(executable, actual.first)
diff --git a/test/lib/tailwindcss/engines_test.rb b/test/lib/tailwindcss/engines_test.rb
new file mode 100644
index 00000000..f4c1b0d2
--- /dev/null
+++ b/test/lib/tailwindcss/engines_test.rb
@@ -0,0 +1,89 @@
+require "test_helper"
+require "minitest/mock"
+
+class Tailwindcss::EnginesTest < ActiveSupport::TestCase
+ def setup
+ super
+ @tmpdir_path = Pathname.new(TAILWINDCSS_TEST_APP_ROOT)
+ @builds_dir = @tmpdir_path.join("app/assets/builds/tailwind")
+ end
+
+ test "bundle creates the builds directory" do
+ Rails.stub(:root, @tmpdir_path) do
+ Tailwindcss::Engines.bundle
+ assert Dir.exist?(@builds_dir), "Expected directory #{@builds_dir} to be created"
+ end
+ end
+
+ test "bundle generates CSS files for engine's tailwind assets" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("mock_engine", @tmpdir_path)
+
+ Tailwindcss::Engines.bundle
+
+ css_file_path = @builds_dir.join("mock_engine.css")
+ assert File.exist?(css_file_path), "Expected file #{css_file_path} to be created"
+
+ content = File.read(css_file_path)
+ assert_match(/DO NOT MODIFY THIS FILE/, content)
+ assert_match(/@import ".*\/app\/assets\/tailwind\/mock_engine\/engine.css"/, content)
+ end
+ end
+
+ test "bundle removes existing files before generating new ones" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("mock_engine", @tmpdir_path)
+
+ FileUtils.mkdir_p(@builds_dir)
+ css_file_path = @builds_dir.join("mock_engine.css")
+ File.write(css_file_path, "OLD CONTENT")
+
+ Tailwindcss::Engines.bundle
+
+ content = File.read(css_file_path)
+ assert_no_match(/OLD CONTENT/, content)
+ assert_match(/DO NOT MODIFY THIS FILE/, content)
+ end
+ end
+
+ test "bundle only processes engines with tailwind assets" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("engine_with_assets", @tmpdir_path)
+
+ Class.new(Rails::Engine) do
+ define_singleton_method(:engine_name) { "engine_without_assets" }
+ define_singleton_method(:root) { Pathname.new(Dir.mktmpdir) }
+ end
+
+ Tailwindcss::Engines.bundle
+
+ assert File.exist?(@builds_dir.join("engine_with_assets.css")), "Expected CSS file for engine with assets"
+ refute File.exist?(@builds_dir.join("engine_without_assets.css")), "Expected no CSS file for engine without assets"
+ end
+ end
+
+ test "bundle handles multiple engines" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("engine1", @tmpdir_path)
+ setup_mock_engine("engine2", @tmpdir_path)
+
+ Tailwindcss::Engines.bundle
+
+ assert File.exist?(@builds_dir.join("engine1.css")), "Expected CSS file for engine1"
+ assert File.exist?(@builds_dir.join("engine2.css")), "Expected CSS file for engine2"
+ end
+ end
+
+ private
+
+ def setup_mock_engine(name, root_path)
+ tailwind_dir = root_path.join("app/assets/tailwind/#{name}")
+ FileUtils.mkdir_p(tailwind_dir)
+ File.write(tailwind_dir.join("engine.css"), "/* Test CSS */")
+
+ Class.new(Rails::Engine) do
+ define_singleton_method(:engine_name) { name }
+ define_singleton_method(:root) { root_path }
+ end
+ end
+end