tailwindcss-rails 3.3.2 → 4.0.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee1e391824b503c8e61b8a2febd7ccd47d31614bfefd933e272a70e6b02f7e9a
4
- data.tar.gz: 0b19a09424bdf6f2b8a74bc0cff3867373bd1a6c04c20ecb83ccdb1e2528d8eb
3
+ metadata.gz: 90c12e592470225fa2691b3d6a05f37a9e2ec42105914808503fb2ff8dcad26d
4
+ data.tar.gz: b8ed05daad38b1e5d444e642d2c6959a9bdeccf7b73dffb64cd6180298f9e9e0
5
5
  SHA512:
6
- metadata.gz: ce439d9897933e3c38d64a1bf6459d47cbe9ebf7daa0c79dac66dd1e7e62012eb0602dc0adb2bf239a37c9d2709e429a8912d1918768a777abb9bc5454354e36
7
- data.tar.gz: 14b70eee495bc67c4f465c041345d48acc5d985a3a06b2fead4bea4f90e5c521eb2aa854fa4f67b3df244aa4d63239bbd27ae1d9edab28a2790d322f3eb75023
6
+ metadata.gz: 503d686e869134450c4b7088881779bc63db162e2b75864c2ced185a4575a8d3425c8f7afb7929e892dbf1196e79cf163480e7e4d637a0a6467e03e26b9f256d
7
+ data.tar.gz: b44d09d37a35e990f020526880d4d227759b24f979c3443009d7dc5f2f0ffca03ad8a3ea686b6e969530f05e4e4bf96337812132ef58f5c7ff85657a94dfe85d
data/README.md CHANGED
@@ -9,6 +9,10 @@
9
9
  - [Installation](#installation)
10
10
  * [Choosing a specific version of `tailwindcss`](#choosing-a-specific-version-of-tailwindcss)
11
11
  * [Using a local installation of `tailwindcss`](#using-a-local-installation-of-tailwindcss)
12
+ - [Upgrading your application from Tailwind v3 to v4](#upgrading-your-application-from-tailwind-v3-to-v4)
13
+ * [You don't _have_ to upgrade](#you-dont-_have_-to-upgrade)
14
+ * [Upgrade steps](#upgrade-steps)
15
+ * [Troubleshooting](#troubleshooting)
12
16
  - [Developing with Tailwindcss](#developing-with-tailwindcss)
13
17
  * [Configuration and commands](#configuration-and-commands)
14
18
  * [Building for production](#building-for-production)
@@ -17,7 +21,7 @@
17
21
  * [Live rebuild](#live-rebuild)
18
22
  * [Using with PostCSS](#using-with-postcss)
19
23
  * [Custom inputs or outputs](#custom-inputs-or-outputs)
20
- - [Troubleshooting](#troubleshooting)
24
+ - [Troubleshooting](#troubleshooting-1)
21
25
  * [Lost keystrokes or hanging when using terminal-based debugging tools (e.g. IRB, Pry, `ruby/debug`...etc.) with the Puma plugin](#lost-keystrokes-or-hanging-when-using-terminal-based-debugging-tools-eg-irb-pry-rubydebugetc-with-the-puma-plugin)
22
26
  * [Running in a docker container exits prematurely](#running-in-a-docker-container-exits-prematurely)
23
27
  * [Conflict with sassc-rails](#conflict-with-sassc-rails)
@@ -55,21 +59,117 @@ gem "tailwindcss-ruby", "3.4.13"
55
59
  You can also use a local (npm-based) installation if you prefer, please go to https://github.com/flavorjones/tailwindcss-ruby for more information.
56
60
 
57
61
 
58
- ## Developing with Tailwindcss
62
+ ## Upgrading your application from Tailwind v3 to v4
59
63
 
60
- ### Configuration and commands
64
+ v4.x of this gem has been updated to work with Tailwind v4, including providing some help with upgrading your application.
65
+
66
+ A full explanation of a Tailwind v4 upgrade is out of scope for this README, so we strongly urge you to read the [official Tailwind v4 upgrade guide](https://tailwindcss.com/docs/upgrade-guide) before embarking on an upgrade to an existing large app.
67
+
68
+ This gem will help with some of the mechanics of the upgrade, however.
69
+
70
+ ### You don't _have_ to upgrade
71
+
72
+ Keep in mind that you don't _need_ to upgrade. You can stay on Tailwind v3 for the foreseeable future if you prefer not to migrate now, or if your migration runs into problems.
73
+
74
+ Just make sure you're pinning the version of **both** `tailwindcss-rails` and `tailwindcss-ruby`:
75
+
76
+ ``` ruby
77
+ # Gemfile
78
+ gem "tailwindcss-rails", "~> 3.3"
79
+ gem "tailwindcss-ruby", "~> 3.4"
80
+ ```
81
+
82
+
83
+ ### Upgrade steps
84
+
85
+ First, update to `tailwindcss-rails` v4.0.0 or higher. This will also ensure you're transitively depending on `tailwindcss-ruby` v4.
86
+
87
+ ``` html
88
+ # Gemfile
89
+ gem "tailwindcss-rails", "~> 4.0"
90
+ ```
91
+
92
+ Then, run the `tailwindcss:upgrade` task. Among other things, this will try to run the official Tailwind upgrade utility. It requires `npx` in order to run, but it's a one-time operation and is *highly recommended* for a successful upgrade.
93
+
94
+ Here's what the upgrade task does:
95
+
96
+ - Cleans up some things in the generated `config/tailwind.config.js`.
97
+ - Runs the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended).
98
+ - Removes references to the Inter font from the application layout.
99
+ - If present, moves `config/postcss.config.js` to the root directory.
100
+
101
+ Here's what that upgrade looks like on a vanilla Rails app:
102
+
103
+ ``` sh
104
+ $ bin/rails tailwindcss:upgrade
105
+ apply /path/to/tailwindcss-rails/lib/install/upgrade_tailwindcss.rb
106
+ Removing references to 'defaultTheme' from /home/user/myapp/config/tailwind.config.js
107
+ gsub config/tailwind.config.js
108
+ Running the upstream Tailwind CSS upgrader
109
+ run npx @tailwindcss/upgrade@next --force --config /home/user/myapp/config/tailwind.config.js from "."
110
+ ≈ tailwindcss v4.0.0
111
+
112
+ │ Searching for CSS files in the current directory and its subdirectories…
113
+
114
+ │ ↳ Linked `./config/tailwind.config.js` to `./app/assets/stylesheets/application.tailwind.css`
115
+
116
+ │ Migrating JavaScript configuration files…
61
117
 
62
- #### Configuration file: `config/tailwind.config.js`
118
+ The configuration file at `./config/tailwind.config.js` could not be automatically migrated to the new CSS
119
+ │ configuration format, so your CSS has been updated to load your existing configuration file.
63
120
 
64
- You can customize the Tailwind build through the `config/tailwind.config.js` file, just like you would if Tailwind was running in a traditional node installation. All the first-party plugins are supported.
121
+ Migrating templates…
122
+
123
+ │ ↳ Migrated templates for configuration file: `./config/tailwind.config.js`
124
+
125
+ │ Migrating stylesheets…
126
+
127
+ │ ↳ Migrated stylesheet: `./app/assets/stylesheets/application.tailwind.css`
128
+
129
+ │ ↳ No PostCSS config found, skipping migration.
130
+
131
+ │ Updating dependencies…
132
+
133
+ │ Could not detect a package manager. Please manually update `tailwindcss` to v4.
134
+
135
+ │ Verify the changes and commit them to your repository.
136
+
137
+ Strip Inter font CSS from application layout
138
+ gsub app/views/layouts/application.html.erb
139
+ Compile initial Tailwind build
140
+ run rails tailwindcss:build from "."
141
+ ≈ tailwindcss v4.0.0
142
+
143
+ Done in 52ms
144
+ run bundle install --quiet
145
+ ```
146
+
147
+ If this doesn't succeed, it's likely that you've customized your Tailwind configuration and you'll need to do some work to make sure your application upgrades. Please read the [official upgrade guide](https://tailwindcss.com/docs/upgrade-guide)!
148
+
149
+
150
+ ### Troubleshooting
151
+
152
+ You may want to check out [TailwindCSS v4 - upgrade experience report · rails/tailwindcss-rails · Discussion #450](https://github.com/rails/tailwindcss-rails/discussions/450) if you're having trouble upgrading.
153
+
154
+ We know there are some cases we haven't addressed with the upgrade task:
155
+
156
+ - If the user isn’t using PostCSS, some migrations (e.g., updating class names in the view files) may fail
157
+ - In setups without JavaScript tooling, the update process may fail to fully migrate `tailwind.config.js` because the tool assumes that the imported packages (e.g., tailwind plugins) are installed via a package manager, allowing them to be called.
158
+
159
+ We'll try to improve the upgrade process over time, but for now you may need to do some manual work to upgrade.
160
+
161
+
162
+ ## Developing with Tailwindcss
163
+
164
+ ### Configuration and commands
65
165
 
66
166
  #### Input file: `app/assets/stylesheets/application.tailwind.css`
67
167
 
68
- The installer will generate a Tailwind input file in `app/assets/stylesheets/application.tailwind.css`. This is where you import the plugins you want to use, and where you can setup your custom `@apply` rules.
168
+ The installer will generate a Tailwind input file in `app/assets/stylesheets/application.tailwind.css`. This is where you import the plugins you want to use and where you can setup your custom `@apply` rules.
69
169
 
70
170
  #### Output file: `app/assets/builds/tailwind.css`
71
171
 
72
- When you run `rails tailwindcss:build`, the input file will be used to generate the output in `app/assets/builds/tailwind.css`. That's the output CSS that you'll include in your app (the installer automatically configures this, alongside the Inter font as well).
172
+ When you run `rails tailwindcss:build`, the input file will be used to generate the output in `app/assets/builds/tailwind.css`. That's the output CSS that you'll include in your app.
73
173
 
74
174
  #### Commands
75
175
 
@@ -151,12 +251,12 @@ Running `bin/dev` invokes Foreman to start both the Tailwind watch process and t
151
251
 
152
252
  ### Using with PostCSS
153
253
 
154
- If you want to use PostCSS as a preprocessor, create a custom `config/postcss.config.js` and that file will be loaded by tailwind automatically.
254
+ If you want to use PostCSS as a preprocessor, create a custom `postcss.config.js` in your project root directory, and that file will be loaded by tailwind automatically.
155
255
 
156
256
  For example, to enable nesting:
157
257
 
158
258
  ```js
159
- // config/postcss.config.js
259
+ // postcss.config.js
160
260
  module.exports = {
161
261
  plugins: {
162
262
  'postcss-import': {},
@@ -7,11 +7,11 @@
7
7
 
8
8
  <%%= form_with url: password_path(params[:token]), method: :put, class: "contents" do |form| %>
9
9
  <div class="my-5">
10
- <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72, class: "block shadow rounded-md border border-gray-400 outline-none focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
10
+ <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
11
11
  </div>
12
12
 
13
13
  <div class="my-5">
14
- <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72, class: "block shadow rounded-md border border-gray-400 outline-none focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
14
+ <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
15
15
  </div>
16
16
 
17
17
  <div class="inline">
@@ -7,7 +7,7 @@
7
7
 
8
8
  <%%= form_with url: passwords_path, class: "contents" do |form| %>
9
9
  <div class="my-5">
10
- <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow rounded-md border border-gray-400 outline-none focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
10
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
11
11
  </div>
12
12
 
13
13
  <div class="inline">
@@ -11,11 +11,11 @@
11
11
 
12
12
  <%%= form_with url: session_url, class: "contents" do |form| %>
13
13
  <div class="my-5">
14
- <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow rounded-md border border-gray-400 focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
14
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow-sm rounded-md border border-gray-400 focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
15
15
  </div>
16
16
 
17
17
  <div class="my-5">
18
- <%%= form.password_field :password, required: true, autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72, class: "block shadow rounded-md border border-gray-400 focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
18
+ <%%= form.password_field :password, required: true, autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
19
19
  </div>
20
20
 
21
21
  <div class="col-span-6 sm:flex sm:items-center sm:gap-4">
@@ -15,23 +15,23 @@
15
15
  <div class="my-5">
16
16
  <% if attribute.password_digest? -%>
17
17
  <%%= form.label :password %>
18
- <%%= form.password_field :password, class: ["block shadow rounded-md border outline-none 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?}] %>
18
+ <%%= 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?}] %>
19
19
  </div>
20
20
 
21
21
  <div class="my-5">
22
22
  <%%= form.label :password_confirmation %>
23
- <%%= form.password_field :password_confirmation, class: ["block shadow rounded-md border outline-none 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?}] %>
23
+ <%%= 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?}] %>
24
24
  <% elsif attribute.attachments? -%>
25
25
  <%%= form.label :<%= attribute.column_name %> %>
26
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: ["block shadow rounded-md border outline-none 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?}] %>
26
+ <%%= 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?}] %>
27
27
  <% else -%>
28
28
  <%%= form.label :<%= attribute.column_name %> %>
29
29
  <% if attribute.field_type == :textarea || attribute.field_type == :text_area -%>
30
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: ["block shadow rounded-md border outline-none 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?}] %>
30
+ <%%= 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?}] %>
31
31
  <% elsif attribute.field_type == :checkbox || attribute.field_type == :check_box -%>
32
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow rounded-md border outline-none 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?}] %>
32
+ <%%= 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?}] %>
33
33
  <% else -%>
34
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow rounded-md border outline-none 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?}] %>
34
+ <%%= 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?}] %>
35
35
  <% end -%>
36
36
  <% end -%>
37
37
  </div>
@@ -1,13 +1 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- /*
6
-
7
- @layer components {
8
- .btn-primary {
9
- @apply py-2 px-4 bg-blue-200;
10
- }
11
- }
12
-
13
- */
1
+ @import "tailwindcss";
@@ -4,7 +4,7 @@ CENTERING_CONTAINER_INSERTION_POINT = /^\s*<%= yield %>/.freeze
4
4
  if APPLICATION_LAYOUT_PATH.exist?
5
5
  say "Add Tailwindcss include tags and container element in application layout"
6
6
  insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(4), before: /^\s*<%= stylesheet_link_tag/
7
- <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
7
+ <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
8
8
  ERB
9
9
 
10
10
  if File.open(APPLICATION_LAYOUT_PATH).read =~ /<body>\n\s*<%= yield %>\n\s*<\/body>/
@@ -13,7 +13,7 @@ if APPLICATION_LAYOUT_PATH.exist?
13
13
  end
14
14
  else
15
15
  say "Default application.html.erb is missing!", :red
16
- say %( Add <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> within the <head> tag in your custom layout.)
16
+ say %( Add <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> within the <head> tag in your custom layout.)
17
17
  end
18
18
 
19
19
  say "Build into app/assets/builds"
@@ -28,11 +28,6 @@ if Rails.root.join(".gitignore").exist?
28
28
  append_to_file(".gitignore", %(\n/app/assets/builds/*\n!/app/assets/builds/.keep\n))
29
29
  end
30
30
 
31
- unless Rails.root.join("config/tailwind.config.js").exist?
32
- say "Add default config/tailwindcss.config.js"
33
- copy_file "#{__dir__}/tailwind.config.js", "config/tailwind.config.js"
34
- end
35
-
36
31
  unless Rails.root.join("app/assets/stylesheets/application.tailwind.css").exist?
37
32
  say "Add default app/assets/stylesheets/application.tailwind.css"
38
33
  copy_file "#{__dir__}/application.tailwind.css", "app/assets/stylesheets/application.tailwind.css"
@@ -0,0 +1,48 @@
1
+ TAILWIND_CONFIG_PATH = Rails.root.join("config/tailwind.config.js")
2
+ APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
3
+ POSTCSS_CONFIG_PATH = Rails.root.join("config/postcss.config.js")
4
+
5
+ unless TAILWIND_CONFIG_PATH.exist?
6
+ say "Default tailwind.config.js is missing!", :red
7
+ abort
8
+ end
9
+
10
+ if File.read(TAILWIND_CONFIG_PATH).match?(/defaultTheme/)
11
+ say "Removing references to 'defaultTheme' from #{TAILWIND_CONFIG_PATH}"
12
+ gsub_file TAILWIND_CONFIG_PATH.to_s, /^(.*defaultTheme)/, "// \\1"
13
+ end
14
+
15
+ if POSTCSS_CONFIG_PATH.exist?
16
+ say "Moving PostCSS configuration to application root directory"
17
+ FileUtils.mv(POSTCSS_CONFIG_PATH, Rails.root, verbose: true) || abort
18
+ end
19
+
20
+ if system("npx --version")
21
+ say "Running the upstream Tailwind CSS upgrader"
22
+ command = Shellwords.join(["npx", "@tailwindcss/upgrade@next", "--force", "--config", TAILWIND_CONFIG_PATH.to_s])
23
+ success = run(command, abort_on_failure: false)
24
+ unless success
25
+ say "The upgrade tool failed!", :red
26
+ say %( You probably need to update your configuration. Please read the error messages,)
27
+ say %( and check the Tailwind CSS upgrade guide at https://tailwindcss.com/docs/upgrade-guide.)
28
+ abort
29
+ end
30
+ else
31
+ say "Could not run the Tailwind upgrade tool. Please see https://tailwindcss.com/docs/upgrade-guide for manual instructions.", :red
32
+ abort
33
+ end
34
+
35
+ if APPLICATION_LAYOUT_PATH.exist?
36
+ if File.read(APPLICATION_LAYOUT_PATH).match?(/"inter-font"/)
37
+ say "Strip Inter font CSS from application layout"
38
+ gsub_file APPLICATION_LAYOUT_PATH.to_s, %r{, "inter-font"}, ""
39
+ else
40
+ say "Inter font CSS not detected.", :green
41
+ end
42
+ else
43
+ say "Default application.html.erb is missing!", :red
44
+ say %( Please check your layouts and remove any "inter-font" stylesheet links.)
45
+ end
46
+
47
+ say "Compile initial Tailwind build"
48
+ run "rails tailwindcss:build"
@@ -13,7 +13,7 @@ Puma::Plugin.create do
13
13
  # If we use system(*command) instead, IRB and Debug can't read from $stdin
14
14
  # correctly bacause some keystrokes will be taken by watch_command.
15
15
  begin
16
- IO.popen(Tailwindcss::Commands::ENV, Tailwindcss::Commands.watch_command, 'r+') do |io|
16
+ IO.popen(Tailwindcss::Commands.watch_command, 'r+') do |io|
17
17
  IO.copy_stream(io, $stdout)
18
18
  end
19
19
  rescue Interrupt
@@ -2,8 +2,6 @@ require "tailwindcss/ruby"
2
2
 
3
3
  module Tailwindcss
4
4
  module Commands
5
- ENV = {'BROWSERSLIST_IGNORE_OLD_DATA' => '1'}
6
-
7
5
  class << self
8
6
  def compile_command(debug: false, **kwargs)
9
7
  rails_root = defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd)
@@ -12,7 +10,6 @@ module Tailwindcss
12
10
  Tailwindcss::Ruby.executable(**kwargs),
13
11
  "-i", rails_root.join("app/assets/stylesheets/application.tailwind.css").to_s,
14
12
  "-o", rails_root.join("app/assets/builds/tailwind.css").to_s,
15
- "-c", rails_root.join("config/tailwind.config.js").to_s,
16
13
  ]
17
14
 
18
15
  command << "--minify" unless (debug || rails_css_compressor?)
@@ -2,10 +2,6 @@ require "rails"
2
2
 
3
3
  module Tailwindcss
4
4
  class Engine < ::Rails::Engine
5
- initializer "tailwindcss.assets" do
6
- Rails.application.config.assets.precompile += %w( inter-font.css )
7
- end
8
-
9
5
  initializer "tailwindcss.disable_generator_stylesheets" do
10
6
  Rails.application.config.generators.stylesheets = false
11
7
  end
@@ -1,3 +1,3 @@
1
1
  module Tailwindcss
2
- VERSION = "3.3.2"
2
+ VERSION = "4.0.0.rc1"
3
3
  end
data/lib/tasks/build.rake CHANGED
@@ -4,7 +4,7 @@ namespace :tailwindcss do
4
4
  debug = args.extras.include?("debug")
5
5
  command = Tailwindcss::Commands.compile_command(debug: debug)
6
6
  puts command.inspect if args.extras.include?("verbose")
7
- system(Tailwindcss::Commands::ENV, *command, exception: true)
7
+ system(*command, exception: true)
8
8
  end
9
9
 
10
10
  desc "Watch and build your Tailwind CSS on file changes"
@@ -14,7 +14,7 @@ namespace :tailwindcss do
14
14
  always = args.extras.include?("always")
15
15
  command = Tailwindcss::Commands.watch_command(always: always, debug: debug, poll: poll)
16
16
  puts command.inspect if args.extras.include?("verbose")
17
- system(Tailwindcss::Commands::ENV, *command)
17
+ system(*command)
18
18
  rescue Interrupt
19
19
  puts "Received interrupt, exiting tailwindcss:watch" if args.extras.include?("verbose")
20
20
  end
@@ -1,6 +1,6 @@
1
1
  namespace :tailwindcss do
2
2
  desc "Install Tailwind CSS into the app"
3
3
  task :install do
4
- system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/tailwindcss.rb", __dir__)}"
4
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install_tailwindcss.rb", __dir__)}"
5
5
  end
6
6
  end
@@ -0,0 +1,6 @@
1
+ namespace :tailwindcss do
2
+ desc "Upgrade app from Tailwind CSS v3 to v4"
3
+ task :upgrade do
4
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/upgrade_tailwindcss.rb", __dir__)}"
5
+ end
6
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tailwindcss-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.2
4
+ version: 4.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-01-23 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '3.0'
32
+ version: '4.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '3.0'
39
+ version: '4.0'
40
40
  email: david@loudthinking.com
41
41
  executables: []
42
42
  extensions: []
@@ -61,7 +61,6 @@ files:
61
61
  - app/assets/fonts/Inter-roman.latin.var.woff2
62
62
  - app/assets/fonts/Inter-roman.symbols.var.woff2
63
63
  - app/assets/fonts/Inter-roman.vietnamese.var.woff2
64
- - app/assets/stylesheets/inter-font.css
65
64
  - lib/generators/tailwindcss/authentication/authentication_generator.rb
66
65
  - lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb
67
66
  - lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb
@@ -83,8 +82,8 @@ files:
83
82
  - lib/install/Procfile.dev
84
83
  - lib/install/application.tailwind.css
85
84
  - lib/install/dev
86
- - lib/install/tailwind.config.js
87
- - lib/install/tailwindcss.rb
85
+ - lib/install/install_tailwindcss.rb
86
+ - lib/install/upgrade_tailwindcss.rb
88
87
  - lib/puma/plugin/tailwindcss.rb
89
88
  - lib/tailwindcss-rails.rb
90
89
  - lib/tailwindcss/commands.rb
@@ -94,6 +93,7 @@ files:
94
93
  - lib/tasks/build.rake
95
94
  - lib/tasks/clobber.rake
96
95
  - lib/tasks/install.rake
96
+ - lib/tasks/upgrade.rake
97
97
  homepage: https://github.com/rails/tailwindcss-rails
98
98
  licenses:
99
99
  - MIT
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  - !ruby/object:Gem::Version
115
115
  version: 3.2.0
116
116
  requirements: []
117
- rubygems_version: 3.6.8
117
+ rubygems_version: 3.6.2
118
118
  specification_version: 4
119
119
  summary: Integrate Tailwind CSS with the asset pipeline in Rails.
120
120
  test_files: []
@@ -1,194 +0,0 @@
1
- /*
2
- *= link_directory ../fonts
3
- */
4
-
5
- @font-face {
6
- font-family: 'Inter var';
7
- font-style: italic;
8
- font-weight: 100 900;
9
- font-display: swap;
10
- src: url('Inter-italic.extra.var.woff2') format('woff2');
11
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
12
- font-named-instance: 'Italic';
13
- }
14
- /* alternates */
15
- @font-face {
16
- font-family: 'Inter var';
17
- font-style: italic;
18
- font-weight: 100 900;
19
- font-display: swap;
20
- src: url('Inter-italic.alternates.var.woff2') format('woff2');
21
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
22
- font-named-instance: 'Italic';
23
- }
24
- /* symbols */
25
- @font-face {
26
- font-family: 'Inter var';
27
- font-style: italic;
28
- font-weight: 100 900;
29
- font-display: swap;
30
- src: url('Inter-italic.symbols.var.woff2') format('woff2');
31
- unicode-range: U+20DD-20DF,U+2190-219A,U+21A9-21AB,U+21B0-21B2,U+21B3-21B6,U+21BA-21BC,U+21D0,U+21D2,U+21D4,U+21DE-21E0,U+21E4-21E6,U+21E7,U+21EA,U+2303,U+2305,U+2318,U+2325-2328,U+232B,U+2380,U+2387,U+238B,U+23CE-23D0,U+2460-2469,U+24B6-24D0,U+24EA,U+25A0-25A3,U+25B2-25B4,U+25B6-25B8,U+25BA-25BE,U+25C0-25C2,U+25C4-25C8,U+25CB,U+25CF,U+25EF,U+2600,U+2605-2607,U+263C,U+2661,U+2665,U+26A0,U+2713,U+2717,U+2756,U+2764,U+2780-2789,U+27F5-27FB,U+2B06,U+2B12-2B14,U+2B1C,U+E000,U+E12B-E164,U+1F130-1F14A,U+1F850,U+1F852;
32
- font-named-instance: 'Italic';
33
- }
34
-
35
- /* extra */
36
- @font-face {
37
- font-family: 'Inter var';
38
- font-style: italic;
39
- font-weight: 100 900;
40
- font-display: swap;
41
- src: url('Inter-italic.extra.var.woff2') format('woff2');
42
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
43
- font-named-instance: 'Italic';
44
- }
45
- /* alternates */
46
- @font-face {
47
- font-family: 'Inter var';
48
- font-style: italic;
49
- font-weight: 100 900;
50
- font-display: swap;
51
- src: url('Inter-italic.alternates.var.woff2') format('woff2');
52
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
53
- font-named-instance: 'Italic';
54
- }
55
- /* symbols */
56
- @font-face {
57
- font-family: 'Inter var';
58
- font-style: italic;
59
- font-weight: 100 900;
60
- font-display: swap;
61
- src: url('Inter-italic.symbols.var.woff2') format('woff2');
62
- unicode-range: U+20DD-20DF,U+2190-219A,U+21A9-21AB,U+21B0-21B2,U+21B3-21B6,U+21BA-21BC,U+21D0,U+21D2,U+21D4,U+21DE-21E0,U+21E4-21E6,U+21E7,U+21EA,U+2303,U+2305,U+2318,U+2325-2328,U+232B,U+2380,U+2387,U+238B,U+23CE-23D0,U+2460-2469,U+24B6-24D0,U+24EA,U+25A0-25A3,U+25B2-25B4,U+25B6-25B8,U+25BA-25BE,U+25C0-25C2,U+25C4-25C8,U+25CB,U+25CF,U+25EF,U+2600,U+2605-2607,U+263C,U+2661,U+2665,U+26A0,U+2713,U+2717,U+2756,U+2764,U+2780-2789,U+27F5-27FB,U+2B06,U+2B12-2B14,U+2B1C,U+E000,U+E12B-E164,U+1F130-1F14A,U+1F850,U+1F852;
63
- font-named-instance: 'Italic';
64
- }
65
- /* cyrillic */
66
- @font-face {
67
- font-family: 'Inter var';
68
- font-style: italic;
69
- font-weight: 100 900;
70
- font-display: swap;
71
- src: url('Inter-italic.cyrillic.var.woff2') format('woff2');
72
- unicode-range: U+0400-049E,U+04A0-0500,U+052F,U+20B4,U+2116,U+2DFF,U+A69F;
73
- font-named-instance: 'Italic';
74
- }
75
- /* greek */
76
- @font-face {
77
- font-family: 'Inter var';
78
- font-style: italic;
79
- font-weight: 100 900;
80
- font-display: swap;
81
- src: url('Inter-italic.greek.var.woff2') format('woff2');
82
- unicode-range: U+0370-0378,U+037A-0380,U+0384-038B,U+038C,U+038E-03A2,U+03A3-03E2,U+03F0-0400,U+1F00-1F16,U+1F18-1F1E,U+1F20-1F46,U+1F48-1F4E,U+1F50-1F58,U+1F59,U+1F5B,U+1F5D,U+1F5F-1F7E,U+1F80-1FB5,U+1FB6-1FC5,U+1FC6-1FD4,U+1FD6-1FDC,U+1FDD-1FF0,U+1FF2-1FF5,U+1FF6-1FFF;
83
- font-named-instance: 'Italic';
84
- }
85
- /* vietnamese */
86
- @font-face {
87
- font-family: 'Inter var';
88
- font-style: italic;
89
- font-weight: 100 900;
90
- font-display: swap;
91
- src: url('Inter-italic.vietnamese.var.woff2') format('woff2');
92
- unicode-range: U+0102-0104,U+0110-0112,U+0128-012A,U+0168-016A,U+01A0-01A2,U+01AF-01B1,U+1EA0-1EFA,U+20AB;
93
- font-named-instance: 'Italic';
94
- }
95
- /* latin-ext */
96
- @font-face {
97
- font-family: 'Inter var';
98
- font-style: italic;
99
- font-weight: 100 900;
100
- font-display: swap;
101
- src: url('Inter-italic.latin-ext.var.woff2') format('woff2');
102
- unicode-range: U+0100-0149,U+014A-01C4,U+01C5-0250,U+0259,U+1E00-1F00,U+2020,U+20A0-20AC,U+20AD-20C0,U+2113,U+2C7C,U+2C7F,U+A7FF;
103
- font-named-instance: 'Italic';
104
- }
105
- /* latin */
106
- @font-face {
107
- font-family: 'Inter var';
108
- font-style: italic;
109
- font-weight: 100 900;
110
- font-display: swap;
111
- src: url('Inter-italic.latin.var.woff2') format('woff2');
112
- unicode-range: U+0000-007F,U+00A0-0100,U+0131,U+0152-0154,U+02BB-02BD,U+02C6,U+02DA,U+02DC,U+2000-200C,U+2010-2028,U+202F-2060,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+FEFF;
113
- font-named-instance: 'Italic';
114
- }
115
- /* extra */
116
- @font-face {
117
- font-family: 'Inter var';
118
- font-style: normal;
119
- font-weight: 100 900;
120
- font-display: swap;
121
- src: url('Inter-roman.extra.var.woff2') format('woff2');
122
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
123
- font-named-instance: 'Regular';
124
- }
125
- /* alternates */
126
- @font-face {
127
- font-family: 'Inter var';
128
- font-style: normal;
129
- font-weight: 100 900;
130
- font-display: swap;
131
- src: url('Inter-roman.alternates.var.woff2') format('woff2');
132
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
133
- font-named-instance: 'Regular';
134
- }
135
- /* symbols */
136
- @font-face {
137
- font-family: 'Inter var';
138
- font-style: normal;
139
- font-weight: 100 900;
140
- font-display: swap;
141
- src: url('Inter-roman.symbols.var.woff2') format('woff2');
142
- unicode-range: U+20DD-20DF,U+2190-219A,U+21A9-21AB,U+21B0-21B2,U+21B3-21B6,U+21BA-21BC,U+21D0,U+21D2,U+21D4,U+21DE-21E0,U+21E4-21E6,U+21E7,U+21EA,U+2303,U+2305,U+2318,U+2325-2328,U+232B,U+2380,U+2387,U+238B,U+23CE-23D0,U+2460-2469,U+24B6-24D0,U+24EA,U+25A0-25A3,U+25B2-25B4,U+25B6-25B8,U+25BA-25BE,U+25C0-25C2,U+25C4-25C8,U+25CB,U+25CF,U+25EF,U+2600,U+2605-2607,U+263C,U+2661,U+2665,U+26A0,U+2713,U+2717,U+2756,U+2764,U+2780-2789,U+27F5-27FB,U+2B06,U+2B12-2B14,U+2B1C,U+E000,U+E12B-E164,U+1F130-1F14A,U+1F850,U+1F852;
143
- font-named-instance: 'Regular';
144
- }
145
- /* cyrillic */
146
- @font-face {
147
- font-family: 'Inter var';
148
- font-style: normal;
149
- font-weight: 100 900;
150
- font-display: swap;
151
- src: url('Inter-roman.cyrillic.var.woff2') format('woff2');
152
- unicode-range: U+0400-049E,U+04A0-0500,U+052F,U+20B4,U+2116,U+2DFF,U+A69F;
153
- font-named-instance: 'Regular';
154
- }
155
- /* greek */
156
- @font-face {
157
- font-family: 'Inter var';
158
- font-style: normal;
159
- font-weight: 100 900;
160
- font-display: swap;
161
- src: url('Inter-roman.greek.var.woff2') format('woff2');
162
- unicode-range: U+0370-0378,U+037A-0380,U+0384-038B,U+038C,U+038E-03A2,U+03A3-03E2,U+03F0-0400,U+1F00-1F16,U+1F18-1F1E,U+1F20-1F46,U+1F48-1F4E,U+1F50-1F58,U+1F59,U+1F5B,U+1F5D,U+1F5F-1F7E,U+1F80-1FB5,U+1FB6-1FC5,U+1FC6-1FD4,U+1FD6-1FDC,U+1FDD-1FF0,U+1FF2-1FF5,U+1FF6-1FFF;
163
- font-named-instance: 'Regular';
164
- }
165
- /* vietnamese */
166
- @font-face {
167
- font-family: 'Inter var';
168
- font-style: normal;
169
- font-weight: 100 900;
170
- font-display: swap;
171
- src: url('Inter-roman.vietnamese.var.woff2') format('woff2');
172
- unicode-range: U+0102-0104,U+0110-0112,U+0128-012A,U+0168-016A,U+01A0-01A2,U+01AF-01B1,U+1EA0-1EFA,U+20AB;
173
- font-named-instance: 'Regular';
174
- }
175
- /* latin-ext */
176
- @font-face {
177
- font-family: 'Inter var';
178
- font-style: normal;
179
- font-weight: 100 900;
180
- font-display: swap;
181
- src: url('Inter-roman.latin-ext.var.woff2') format('woff2');
182
- unicode-range: U+0100-0149,U+014A-01C4,U+01C5-0250,U+0259,U+1E00-1F00,U+2020,U+20A0-20AC,U+20AD-20C0,U+2113,U+2C7C,U+2C7F,U+A7FF;
183
- font-named-instance: 'Regular';
184
- }
185
- /* latin */
186
- @font-face {
187
- font-family: 'Inter var';
188
- font-style: normal;
189
- font-weight: 100 900;
190
- font-display: swap;
191
- src: url('Inter-roman.latin.var.woff2') format('woff2');
192
- unicode-range: U+0000-007F,U+00A0-0100,U+0131,U+0152-0154,U+02BB-02BD,U+02C6,U+02DA,U+02DC,U+2000-200C,U+2010-2028,U+202F-2060,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+FEFF;
193
- font-named-instance: 'Regular';
194
- }
@@ -1,22 +0,0 @@
1
- const defaultTheme = require('tailwindcss/defaultTheme')
2
-
3
- module.exports = {
4
- content: [
5
- './public/*.html',
6
- './app/helpers/**/*.rb',
7
- './app/javascript/**/*.js',
8
- './app/views/**/*.{erb,haml,html,slim}'
9
- ],
10
- theme: {
11
- extend: {
12
- fontFamily: {
13
- sans: ['Inter var', ...defaultTheme.fontFamily.sans],
14
- },
15
- },
16
- },
17
- plugins: [
18
- // require('@tailwindcss/forms'),
19
- // require('@tailwindcss/typography'),
20
- // require('@tailwindcss/container-queries'),
21
- ]
22
- }