diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..403b3087
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+ - package-ecosystem: "bundler"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2f065403..3822e414 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,21 +1,63 @@
name: CI
-on: [push, pull_request]
+concurrency:
+ group: "${{github.workflow}}-${{github.ref}}"
+ cancel-in-progress: true
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ tags:
+ - v*.*.*
+ pull_request:
+ types: [opened, synchronize]
+ branches:
+ - '*'
+
jobs:
tests:
runs-on: ubuntu-latest
strategy:
+ fail-fast: false
matrix:
- ruby: [2.7, "3.0", 3.1]
-
+ ruby: ["3.1", "3.2", "3.3", "3.4", "head"]
steps:
- - uses: actions/checkout@v2
-
- - name: Set up Ruby
- uses: ruby/setup-ruby@v1
+ - uses: actions/checkout@v4
+ - run: rm Gemfile.lock
+ - uses: ruby/setup-ruby@v1
with:
- ruby-version: ${{ matrix.ruby }}
+ ruby-version: ${{matrix.ruby}}
bundler: latest
bundler-cache: true
-
- name: Run tests
run: bin/test
+
+ user-install:
+ strategy:
+ fail-fast: false
+ matrix:
+ plat: ["ubuntu", "windows", "macos"]
+ runs-on: ${{matrix.plat}}-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.4"
+ bundler: latest
+ - run: test/integration/user_install_test.sh
+ shell: bash
+
+ user-upgrade:
+ strategy:
+ fail-fast: false
+ matrix:
+ plat: ["ubuntu", "macos"] # TODO: on windows the tailwind upgrader tests are failing
+ runs-on: ${{matrix.plat}}-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.4"
+ bundler: latest
+ - run: test/integration/user_upgrade_test.sh
+ shell: bash
diff --git a/.github/workflows/gem-install.yml b/.github/workflows/gem-install.yml
deleted file mode 100644
index a4a2f500..00000000
--- a/.github/workflows/gem-install.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-name: Native Gems
-on: [push, pull_request]
-jobs:
- package:
- strategy:
- fail-fast: false
- matrix:
- platform: ["ruby", "x64-mingw32", "x86_64-darwin", "x86_64-linux"]
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: "3.0"
- bundler: latest
- bundler-cache: true
- - run: "bundle exec rake gem:${{matrix.platform}}"
- - uses: actions/upload-artifact@v2
- with:
- name: gem-${{matrix.platform}}
- path: pkg
- retention-days: 1
-
- vanilla-install:
- needs: ["package"]
- runs-on: ubuntu-latest
- steps:
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: "3.0"
- - uses: actions/download-artifact@v2
- with:
- name: gem-ruby
- path: pkg
- - run: "gem install pkg/tailwindcss-rails-*.gem"
- - run: "tailwindcss 2>&1 | fgrep 'ERROR: Cannot find the tailwindcss executable'"
-
- linux-install:
- needs: ["package"]
- runs-on: ubuntu-latest
- steps:
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: "3.0"
- - uses: actions/download-artifact@v2
- with:
- name: gem-x86_64-linux
- path: pkg
- - run: "gem install pkg/tailwindcss-rails-*.gem"
- - run: "tailwindcss --help"
-
- darwin-install:
- needs: ["package"]
- runs-on: macos-latest
- steps:
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: "3.0"
- - uses: actions/download-artifact@v2
- with:
- name: gem-x86_64-darwin
- path: pkg
- - run: "gem install pkg/tailwindcss-rails-*.gem"
- - run: "tailwindcss --help"
-
- windows-install:
- needs: ["package"]
- runs-on: windows-latest
- steps:
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: "3.0"
- - uses: actions/download-artifact@v2
- with:
- name: gem-x64-mingw32
- path: pkg
- - run: "gem install pkg/tailwindcss-rails-*.gem"
- - run: "tailwindcss --help"
diff --git a/.github/workflows/update-tailwind.yml b/.github/workflows/update-tailwind.yml
deleted file mode 100644
index 8d65ee36..00000000
--- a/.github/workflows/update-tailwind.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-name: Update Tailwind
-
-on:
- schedule:
- - cron: '0 3 * * *'
- workflow_dispatch:
-
-jobs:
- build:
- runs-on: ubuntu-latest
- timeout-minutes: 10
- steps:
- - uses: actions/checkout@master
-
- - name: Update tailwind.css
- run: |
- yarn upgrade tailwindcss
- yarn build
-
- - name: Commit changes
- run: |
- git config --local user.email "github-actions@example.com"
- git config --local user.name "GitHub Actions"
- git diff --quiet app/assets || git commit -am "Update tailwind.css"
-
- - name: Push changes
- uses: ad-m/github-push-action@master
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- branch: ${{ github.ref }}
diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml
new file mode 100644
index 00000000..e1b12dea
--- /dev/null
+++ b/.github/workflows/upstream.yml
@@ -0,0 +1,73 @@
+name: upstream
+concurrency:
+ group: "${{github.workflow}}-${{github.ref}}"
+ cancel-in-progress: true
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "0 8 * * 3" # At 08:00 on Wednesday # https://crontab.guru/#0_8_*_*_3
+ pull_request:
+ types: [opened, synchronize]
+ branches:
+ - '*'
+
+jobs:
+ tests:
+ name: "tests (rails main)"
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ ruby: ["3.3"]
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{matrix.ruby}}
+ - run: |
+ rm Gemfile.lock
+ bundle remove actionmailer
+ git clone --depth 1 --branch main https://github.com/rails/rails
+ bundle add actionmailer --path=rails
+ bundle add railties --path=rails
+ bundle install
+ - name: Run tests
+ run: bin/test
+
+ user-install:
+ name: "user-install (rails ${{ matrix.ref }})"
+ runs-on: ${{matrix.plat}}-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ plat: ["ubuntu"]
+ ref: ["7-2-stable", "8-0-stable", "main"]
+ env:
+ RAILSOPTS: --git=https://github.com/rails/rails --ref=${{ matrix.ref }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.3"
+ bundler: latest
+ - run: test/integration/user_install_test.sh
+ shell: bash
+
+ user-upgrade:
+ name: "user-upgrade (rails ${{ matrix.ref }})"
+ runs-on: ${{matrix.plat}}-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ plat: ["ubuntu"]
+ ref: ["7-2-stable", "8-0-stable", "main"]
+ env:
+ RAILSOPTS: --git=https://github.com/rails/rails --ref=${{ matrix.ref }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: "3.3"
+ bundler: latest
+ - run: test/integration/user_upgrade_test.sh
+ shell: bash
diff --git a/.gitignore b/.gitignore
index b2a14451..de5dc1de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,4 +13,3 @@
*.gem
.idea/
**/tmp/
-/exe/*/tailwindcss
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..d662d7a9
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,451 @@
+# `tailwindcss-rails` Changelog
+
+## v4.2.3 / 2025-05-02
+
+### Improved
+
+* The "tailwindcss:upgrade" task now pins to v4.1.4 of the `@tailwindcss/upgrade` tool. #544 @flavorjones
+
+
+## v4.2.2 / 2025-04-05
+
+### Improved
+
+* The "tailwindcss:upgrade" task now uses the latest version of the `@tailwindcss/upgrade` tool. #529 @flavorjones
+* The "verbose" flag on Rails tasks now emits additional tailwind CLI debugging info (e.g., `bin/rails tailwindcss:build[verbose]`). #530 @flavorjones
+* Simplified the scaffold templates, removing unnecessary `div` tags. @523 @patriciomacadden
+
+
+## v4.2.1 / 2025-03-19
+
+### Fixed
+
+* Fix styles for form errors in some scaffold fields. #513 @patriciomacadden
+* Update scaffold system tests to handle the "Destroy" confirmation prompt when Turbo is enabled. Fixes #519. #520 @patriciomacadden @flavorjones
+
+
+## v4.2.0 / 2025-03-02
+
+### Features
+
+* Improve the view templates to display better on mobile devices. #503 @patriciomacadden
+* Support for environment variable `TAILWINDCSS_DEBUG` to turn off CSS minification. #504 @r-sierra
+
+
+## v4.1.0 / 2025-02-19
+
+### View template improvements
+
+* Field outlines are no longer hidden, and the focus border is brighter. #489 @rubys
+* Boolean fields are improved (checkbox labels aligned, "Yes"/"No" instead of "true"/"false"). #454 @patriciomacadden
+* Attachment links are consistently spaced and styled. #460 @patriciomacadden
+* Index page links to Show, Edit, and Destroy for each resource. #460 @patriciomacadden @flavorjones
+* Turbo confirm prompt added to Destroy links. #498 @patriciomacadden
+
+
+## v4.0.0 / 2025-02-01
+
+### Upgrade to Tailwind CSS v4
+
+General changes:
+
+- The dependency on `tailwindcss-ruby` is set to `~> 4.0`.
+- The location of (optional) `postcss.config.js` has moved from the `config/` directory to the app root.
+- The input file `app/assets/tailwind/application.tailwind.css` has been renamed to `app/assets/tailwind/application.css`.
+- If Propshaft is being used, `app/assets/tailwind` will be excluded from its asset handling.
+- The Inter font is no longer packaged with the gem.
+- Some Tailwind class names in the generated ERB templates are updated for v4.
+- The README is updated to contain verbose instructions on upgrading.
+
+Changes to the `tailwindcss:install` task:
+
+- The `tailwindcss:install` task no longer installs `config/tailwind.config.js`, as v4 recommends placing Tailwind configuration in the CSS file.
+- The Inter font is no longer configured in the application layout.
+- The "tailwind" stylesheet link tag will only be added to the application layout if Propshaft isn't in use and therefore already handling `app/assets/build/tailwind.css`. Previously it was always injected, resulting in the tag being rendered twice if Propshaft was in use.
+
+New task `tailwindcss:upgrade` upgrades many apps cleanly:
+
+- Cleans up `config/tailwind.config.js` and references it from the CSS file as recommended for v4 upgrades.
+- Runs the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended).
+- Removes configuration for the Inter font from the application layout.
+- If present, moves `config/postcss.config.js` to the root directory.
+- The "tailwind" stylesheet link tag will be removed if Propshaft is in use and already handling `app/assets/build/tailwind.css`.
+- The input file `app/assets/tailwind/application.tailwind.css` will be moved to `app/assets/tailwind/application.css`.
+
+Thanks to @EricGusmao, @patriciomacadden, @excid3, and @brunoprietog for their feedback, contributions, and advice on v4 support.
+
+### Other changes
+
+- The gem's Rails generators are now hidden in the `rails g --help` output. #483 @patriciomacadden
+
+## v3.3.1 / 2025-01-23
+
+* Pin the dependency on `tailwindcss-ruby` to `~> 3.0` to prevent users from upgrading Tailwind while still on v3 of this gem.
+
+ While it was useful during the Tailwind v4 beta period to allow users to float this dependency to try upgrading, we know (now that v4.0.0.rc1 of this gem is out) that not everything will work well if combining Tailwind v4 with `tailwindcss-rails` v3. Pinning this dependency should protect developers against unexpected issues.
+
+
+## v3.3.0 / 2025-01-19
+
+* Add support for using the puma plugin in a standalone puma process (outside of `rails server`). (#458) @flavorjones
+
+
+## v3.2.0 / 2025-01-10
+
+* Improve the scaffold views by making positions, padding, and sizes more consistent, add titles to all pages, add hover states and semantic colors to buttons and links, and change border and focus colors on fields with errors. (#452) @patriciomacadden
+
+
+## v3.1.0 / 2024-12-29
+
+### Notable changes
+
+The tailwindcss plugins "form", "typography", and "container-queries" have been dropped from the default generated `tailwind.config.js` file. If you'd like to use them, you can re-add them to your project by uncommenting the appropriate lines in your config file. (#446) @flavorjones
+
+
+## v3.0.0 / 2024-10-15
+
+### Notable changes
+
+* The upstream `tailwindcss` executable has been extracted from this gem into a new dependency, `tailwindcss-ruby`. @flavorjones
+
+ In advance of the upcoming TailwindCSS v4 release, we are decoupling the `tailwindcss` executable from the Rails integration. This will allow users to upgrade TailwindCSS at a time of their choosing, and allow early adopters to start using the beta releases.
+
+
+## v2.7.9 / 2024-10-10
+
+* Fix the scaffold form template to render text forms and check boxes properly in all versions of Rails. (#418) @Earlopain
+
+
+## v2.7.8 / 2024-10-08
+
+* Fix the scaffold form template to render checkboxes properly. (#416) @enderahmetyurt
+
+
+## v2.7.7 / 2024-10-02
+
+* Proactively support changes to Rails's authentication templates shipping in Rails 8.0.0.beta2 (which is not yet released). (#407, #408) @seanpdoyle @flavorjones
+
+
+## v2.7.6 / 2024-09-23
+
+* Update to [Tailwind CSS v3.4.13](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.13) @flavorjones
+
+
+## v2.7.5 / 2024-09-18
+
+* Update to [Tailwind CSS v3.4.12](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.12) @flavorjones
+
+
+## v2.7.4 / 2024-09-13
+
+* Update to [Tailwind CSS v3.4.11](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.11) @flavorjones
+
+
+## v2.7.3 / 2024-08-14
+
+* Update to [Tailwind CSS v3.4.10](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.10) @flavorjones
+
+
+## v2.7.2 / 2024-08-08
+
+* Update to [Tailwind CSS v3.4.9](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.9) @flavorjones
+
+
+## v2.7.1 / 2024-08-07
+
+* Update to [Tailwind CSS v3.4.8](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.8) @flavorjones
+
+
+## v2.7.0 / 2024-08-05
+
+* Add specialized views for the new authentication generator coming in Rails 8. (#384) @yshmarov @dhh @flavorjones
+
+
+## v2.6.5 / 2024-07-30
+
+* During installation, clobber the Rails v8 default `bin/dev` file without requiring human intervention. (#385) @jeromedalbert
+
+
+## v2.6.4 / 2024-07-27
+
+* Update to [Tailwind CSS v3.4.7](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.7) (#383) @flavorjones
+
+
+## v2.6.3 / 2024-07-16
+
+* Update to [Tailwind CSS v3.4.6](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.6) (#381) @flavorjones
+
+
+## v2.6.2 / 2024-07-15
+
+* Update to [Tailwind CSS v3.4.5](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.5) (#380) @flavorjones
+
+
+## v2.6.1 / 2024-06-05
+
+* Update to [Tailwind CSS v3.4.4](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.4) (#373) @flavorjones
+
+
+## v2.6.0 / 2024-05-04
+
+* Increase form input field border contrast. (#356) @olivierlacan
+* Bring the scaffold templates up to date with rails/rails. (#357, #359) @kinsomicrote
+* Drop support for Rails 6.0, which reached end-of-life in June 2023. (#358) @flavorjones
+* Drop feature and bug fix support for Rails 6.1. The previous minor release will still receive security support while Rails 6.1 is supported. (#359) @flavorjones
+
+
+## v2.5.0 / 2024-04-27
+
+* Remove the `@tailwindcss/aspect-ratio` plugin from the `tailwind.config.js` that gets installed by the generator. This plugin was originally a polyfill until Safari 15 was released (in Fall 2021), and so is beyond its useful lifetime for anyone not targetting ancient browsers. (#344) @flavorjones @searls
+
+
+## v2.4.1 / 2024-04-25
+
+* Fix debugger repl when using the Puma plugin. (#349) @tompng
+
+
+## v2.4.0 / 2024-04-08
+
+* Update to [Tailwind CSS v3.4.3](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.3) from v3.4.1 by @flavorjones
+* The `tailwindcss:watch` task handles interrupts more cleanly. (#318, #336) @davidcelis
+
+
+## v2.3.0 / 2024-01-10
+
+* Allow applications to override the generator templates. (#314) @flavorjones
+* Support using PostCSS as a preprocessor. (#316) @ahmeij
+
+
+## v2.2.1 / 2024-01-07
+
+* Update to [Tailwind CSS v3.4.1](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.1) from v3.4.0 by @flavorjones
+* Fix `password` form field styling in generated scaffold forms. (#304, #307) @flavorjones
+* Fix namespaced mailer generation. (#272, #308) @flavorjones
+* Allow overriding the generator templates by placing application templates in either `lib/templates/tailwindcss/{scaffold,mailer,controller}` or `lib/templates/erb/{scaffold,mailer,controller}`. (#164, #314) @flavorjones
+
+
+## v2.2.0 / 2024-01-04
+
+* Introduce a Puma plugin to manage the Tailwind "watch" process from `rails server`. (#300) @npezza93
+* Lazily load the debugger gem when running `bin/dev` (#292) @elia
+* Allow choosing a custom port with a `PORT` environment variable when running `bin/dev` (#292) @elia
+
+
+## v2.1.0 / 2023-12-19
+
+* Update to [Tailwind CSS v3.4.0](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.0) from v3.3.6 by @flavorjones
+
+
+## v2.0.33 / 2023-12-09
+
+* Update to [Tailwind CSS v3.3.6](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.6) from v3.3.5 by @flavorjones
+
+
+## v2.0.32 / 2023-10-27
+
+* Update to [Tailwind CSS v3.3.5](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.5) from v3.3.3 by @flavorjones
+ * Also see [v3.3.4 release notes](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.4)
+* Restore support for Ruby 2.7, broken in v2.0.31, by explicitly setting `required_rubygems_version = ">= 3.2.0"`. (#286) by @flavorjones
+
+
+## v2.0.31 / 2023-10-10
+
+* Update Procfile.dev to run foreman with `--open` option allowing remote sessions with `rdbg --attach` (#281) by @duduribeiro
+* Address Rubygems 3.5.0 deprecation warnings (#280) by @lylo
+
+
+## v2.0.30 / 2023-07-13
+
+* Update to [Tailwind CSS v3.3.3](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.3) by @flavorjones
+* If defined, the `spec:prepare` rake task will be decorated with `tailwindcss:build` (#271) by @rmehner
+
+
+## v2.0.29 / 2023-04-26
+
+* Update to [Tailwind CSS v3.3.2](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.2) by @flavorjones
+
+
+## v2.0.28 / 2023-04-21
+
+* The `watch` task accepts an `always` argument to keep the watcher alive when stdin is closed: `rails tailwindcss:watch[always]`. #262 by @GoodForOneFare
+
+
+## v2.0.27 / 2023-04-02
+
+* Update to [Tailwind CSS v3.3.1](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.1) by @flavorjones
+
+
+## v2.0.26 / 2023-03-30
+
+* Update to [Tailwind CSS v3.3.0](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.0) by @tysongach
+* Use a locally-installed `tailwindcss` executable by setting a `TAILWINDCSS_INSTALL_DIR` environment variable. (#224, #226) by @flavorjones
+
+
+## v2.0.25 / 2023-03-14
+
+* Installer now includes all 5 official Tailwind plugins (adding `line-clamp` and `container-queries`). (#254) by @Kentasmic
+
+
+## v2.0.24 / 2023-03-05
+
+* When Rails CSS compression is on, avoid generating minified tailwindcss assets. (#253) by [@flavorjones](https://github.com/flavorjones).
+
+
+## v2.0.23 / 2023-02-19
+
+* Update to [Tailwind CSS v3.2.7](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.7) by [@flavorjones](https://github.com/flavorjones).
+
+
+## v2.0.22 / 2023-02-08
+
+* Update to [Tailwind CSS v3.2.6](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.6) by [@flavorjones](https://github.com/flavorjones).
+* Introduce a `verbose` task argument, and put verbose logging behind it by [@ghiculescu](https://github.com/ghiculescu).
+* Fix scaffold view generation for nested models (#227) by [@dixpac](https://github.com/dixpac).
+* Improved documentation by [@ghiculescu](https://github.com/ghiculescu) and [@flavorjones](https://github.com/flavorjones).
+
+
+## v2.0.21 / 2022-11-11
+
+* Update to [Tailwind CSS v3.2.4](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.4) by [@flavorjones](https://github.com/flavorjones).
+
+
+## v2.0.20 / 2022-11-10
+
+* Update to [Tailwind CSS v3.2.3](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.3) by [@willcosgrove](https://github.com/willcosgrove).
+
+
+## v2.0.19 / 2022-11-08
+
+* Update `bin/dev` script to stay in sync with other Rails installers' versions (e.g, `cssbundling-rails` and `dartsass-rails`). Use `sh` instead of `bash` for vanilla Alpine support, and use `exec` to run foreman for better interrupt handling. [#219](https://github.com/rails/tailwindcss-rails/pull/219) by [@marcoroth](https://github.com/marcoroth).
+
+
+## v2.0.18 / 2022-11-07
+
+* Update to [Tailwind CSS v3.2.2](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.2) by [@AlexKovynev](https://github.com/AlexKovynev).
+
+
+## v2.0.17 / 2022-11-01
+
+* Add `arm-linux` support. [#218](https://github.com/rails/tailwindcss-rails/pull/218) by [@flavorjones](https://github.com/flavorjones).
+
+
+## v2.0.16 / 2022-10-21
+
+* Update to [Tailwind CSS v3.2.1](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.1) by [@AlexKovynev](https://github.com/AlexKovynev) in [#213](https://github.com/rails/tailwindcss-rails/pull/213).
+
+
+## v2.0.15 / 2022-10-20
+
+* Update to [Tailwind CSS v3.2.0](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.0) by [@domchristie](https://github.com/domchristie) in [#209](https://github.com/rails/tailwindcss-rails/pull/209).
+
+
+## v2.0.14 / 2022-09-19
+
+* Work around [upstream rubygems issue](https://github.com/rubygems/rubygems/issues/5938) on `musl` platforms. [[#200](https://github.com/rails/tailwindcss-rails/issues/200)]
+
+
+## v2.0.13 / 2022-09-05
+
+* Correctly handle paths with embedded spaces. [#184](https://github.com/rails/tailwindcss-rails/issues/184) by [@flavorjones](https://github.com/flavorjones)
+* The `build` and `watch` tasks accept a `debug` argument to generate unminified assets: `rails tailwindcss:build[debug]` or `rails tailwindcss:watch[debug]`. [#198](https://github.com/rails/tailwindcss-rails/pull/198) by [@flavorjones](https://github.com/flavorjones)
+* The `watch` task accepts a `poll` argument to use polling instead of file system events: `rails tailwindcss:watch[poll]`. [#199](https://github.com/rails/tailwindcss-rails/pull/199) by [@flavorjones](https://github.com/flavorjones)
+
+
+## v2.0.12 / 2022-08-10
+
+* Address issue when running commands with #exec by [@blerchin](https://github.com/blerchin) in [#189](https://github.com/rails/tailwindcss-rails/issues/189)
+
+
+## v2.0.11 / 2022-08-09
+
+* Use exec to run tailwind binary, so return codes pass through by [@blerchin](https://github.com/blerchin) in [#181](https://github.com/rails/tailwindcss-rails/issues/181)
+* Update to Tailwind CSS v3.1.8 by [@TastyPi](https://github.com/TastyPi) in [#186](https://github.com/rails/tailwindcss-rails/issues/186)
+
+
+## v2.0.10 / 2022-06-19
+
+* Fixed that released gems include the correct version of Tailwind CSS (3.1.3, not 3.0.3) by [@dhh](https://github.com/dhh)
+
+
+## v2.0.9 / 2022-06-18
+
+* Update to Tailwind CSS v3.1.3 by [@cover](https://github.com/cover) in [#174](https://github.com/rails/tailwindcss-rails/issues/174)
+* Add the `public/*.html` path to tailwind content config: by [@Edouard-chin](https://github.com/Edouard-chin) in [#178](https://github.com/rails/tailwindcss-rails/issues/178)
+* Allow for spaces in the working directory for build/watch task by [@rakaur](https://github.com/rakaur) in [#176](https://github.com/rails/tailwindcss-rails/issues/176)
+* support x64-mingw-ucrt for Ruby 3.1 users ([#172](https://github.com/rails/tailwindcss-rails/issues/172)) by [@flavorjones](https://github.com/flavorjones) in [#173](https://github.com/rails/tailwindcss-rails/issues/173)
+
+
+## v2.0.8 / 2022-03-10
+
+* Restrict views to common template formats by [@pixeltrix](https://github.com/pixeltrix) in [#155](https://github.com/rails/tailwindcss-rails/issues/155)
+* Update rake build command to work with Windows by [@pietmichal](https://github.com/pietmichal) in [#156](https://github.com/rails/tailwindcss-rails/issues/156)
+* Upgrade to Tailwind 3.0.23 by [@dhh](https://github.com/dhh)
+
+
+## v2.0.7 / 2022-02-22
+
+* Installer: don't add main in existing projects by [@shafy](https://github.com/shafy) in [#146](https://github.com/rails/tailwindcss-rails/issues/146)
+* Delete legacy tailwind.css by [@HusseinMorsy](https://github.com/HusseinMorsy) in [#148](https://github.com/rails/tailwindcss-rails/issues/148)
+
+
+## v2.0.6 / 2022-02-19
+
+* Update tailwindcss to v3.0.22 by [@dukex](https://github.com/dukex) in [#143](https://github.com/rails/tailwindcss-rails/issues/143)
+* Minify output by default by [@dhh](https://github.com/dhh) in [c76f5d22](https://github.com/rails/tailwindcss-rails/commit/c76f5d22f9344d1ffe205352f189b75d3871d78e)
+
+
+## v2.0.5 / 2022-01-16
+
+* Upgrade to Tailwind CSS v3.0.15
+* Fix: Insert centring container around the yield by [@dixpac](https://github.com/dixpac) in [#106](https://github.com/rails/tailwindcss-rails/issues/106)
+* Add description to watch task by [@RolandStuder](https://github.com/RolandStuder) in [#130](https://github.com/rails/tailwindcss-rails/issues/130)
+* Fix the wrong indentation by [@dixpac](https://github.com/dixpac) in [#132](https://github.com/rails/tailwindcss-rails/issues/132)
+
+
+## v2.0.3 / 2022-01-03
+
+* fix: name the platform using just architecture and os by [@flavorjones](https://github.com/flavorjones) in [#103](https://github.com/rails/tailwindcss-rails/issues/103)
+* Add tailwindcss-linux-arm64 support (make docker on Apple Silicon M1 workflow possible) by [@schmidp](https://github.com/schmidp) in [#112](https://github.com/rails/tailwindcss-rails/issues/112)
+
+### New Contributors
+* [@schmidp](https://github.com/schmidp) made their first contribution in [#112](https://github.com/rails/tailwindcss-rails/issues/112)
+
+
+## v2.0.2 / 2021-12-19
+
+* Upgrade to [Tailwind CSS 3.0.7](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.0.7) by [@dhh](https://github.com/dhh)
+* Remove setting the `dark-mode` explicitly by [@dixpac](https://github.com/dixpac) in [#100](https://github.com/rails/tailwindcss-rails/issues/100)
+
+
+## v2.0.1 / 2021-12-19
+
+* Remove redundant font-size class from generators by [@marcushwz](https://github.com/marcushwz) in [#97](https://github.com/rails/tailwindcss-rails/issues/97)
+* Add error messages on unsupported platforms or when bundler platforms aren't correct by [@flavorjones](https://github.com/flavorjones) in [#102](https://github.com/rails/tailwindcss-rails/issues/102)
+
+
+## v2.0.0 / 2021-12-18
+
+Tailwind CSS for Rails now uses [the standalone executables made for Tailwind 3](https://tailwindcss.com/blog/standalone-cli). These executables are platform specific, so there's actually separate underlying gems per platform, but the correct gem will automatically be picked for your platform. Supported platforms are Linux x64, macOS arm64, macOS x64, and Windows x64. (Note that due to this setup, you must install the actual gems – you can't pin your gem to the github repo.)
+
+This is a completely different approach from previous versions of tailwindcss-rails. Gone is Ruby-powered purger. Everything now works as it would if you had installed the Node version of Tailwind. But without the Node!
+
+This setup requires a separate watch process to run, which is configured and modeled after the approach used in [cssbundling-rails](https://github.com/rails/cssbundling-rails). Look at the README for more details.
+
+Huge thanks to [@flavorjones](https://github.com/flavorjones) for creating the platform-specific gem setup 🙏
+
+
+## v1.0.0 / 2021-12-14
+
+Nothing. But we're promote 0.5.4 to 1.0.0 to go along with the final release of Rails 7.0. Because as a new sanctioned default option of Rails 7, we should stick to the API, and this communicates that 🚀🥳
+
+
+## v0.5.4 / 2021-12-03
+
+* Only depends on the `railties` gem.
+
+
+## v0.5.3 / 2021-12-03
+
+* Match button label for destroy with text used by regular Rails templates by [@dhh](https://github.com/dhh)
+
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..c2e8746f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+# Contributing to tailwindcss-rails
+
+This doc is a brief introduction on modifying and maintaining this gem.
+
+
+## Testing this gem
+
+### Running the test suite
+
+The unit tests are run with `bundle exec rake test`
+
+There is an additional integration test which runs in CI, `test/integration/user_install_test.sh` which you may also want to run.
+
+
+### Testing in a Rails app
+
+If you want to test modifications to this gem, you must run `rake download` once to download the upstream `tailwindcss` executables.
+
+Then you can point your Rails application's `Gemfile` at the local version of the gem as you normally would:
+
+``` ruby
+gem "tailwindcss-rails", path: "/path/to/tailwindcss-rails"
+```
+
+
+## Cutting a release of tailwindcss-rails
+
+- bump the version
+ - [ ] update `lib/tailwindcss/version.rb`
+ - [ ] update `CHANGELOG.md`
+ - [ ] commit and create a git tag
+- package and push
+ - [ ] `bundle exec rake build`
+ - [ ] `gem push pkg/*.gem`
+ - [ ] `git push && git push --tags`
+- announce
+ - [ ] create a release at https://github.com/rails/tailwindcss-rails/releases
diff --git a/Gemfile b/Gemfile
index 5db3afed..46788894 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,9 +2,8 @@ source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gemspec
-gem "sqlite3"
gem "debug", ">= 1.0.0"
group :test do
- gem "actionmailer", ">= 6.0.0"
+ gem "actionmailer", ">= 7.0.0"
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 77c713c4..f84bada9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,99 +1,170 @@
PATH
remote: .
specs:
- tailwindcss-rails (2.0.8)
- railties (>= 6.0.0)
+ tailwindcss-rails (4.2.2)
+ railties (>= 7.0.0)
+ tailwindcss-ruby (~> 4.0)
GEM
remote: https://rubygems.org/
specs:
- actionmailer (6.1.4.1)
- actionpack (= 6.1.4.1)
- actionview (= 6.1.4.1)
- activejob (= 6.1.4.1)
- activesupport (= 6.1.4.1)
- mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 2.0)
- actionpack (6.1.4.1)
- actionview (= 6.1.4.1)
- activesupport (= 6.1.4.1)
- rack (~> 2.0, >= 2.0.9)
+ actionmailer (8.0.2)
+ actionpack (= 8.0.2)
+ actionview (= 8.0.2)
+ activejob (= 8.0.2)
+ activesupport (= 8.0.2)
+ mail (>= 2.8.0)
+ rails-dom-testing (~> 2.2)
+ actionpack (8.0.2)
+ actionview (= 8.0.2)
+ activesupport (= 8.0.2)
+ nokogiri (>= 1.8.5)
+ rack (>= 2.2.4)
+ rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
- rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actionview (6.1.4.1)
- activesupport (= 6.1.4.1)
+ rails-dom-testing (~> 2.2)
+ rails-html-sanitizer (~> 1.6)
+ useragent (~> 0.16)
+ actionview (8.0.2)
+ activesupport (= 8.0.2)
builder (~> 3.1)
- erubi (~> 1.4)
- rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.1.4.1)
- activesupport (= 6.1.4.1)
+ erubi (~> 1.11)
+ rails-dom-testing (~> 2.2)
+ rails-html-sanitizer (~> 1.6)
+ activejob (8.0.2)
+ activesupport (= 8.0.2)
globalid (>= 0.3.6)
- activesupport (6.1.4.1)
- concurrent-ruby (~> 1.0, >= 1.0.2)
+ activesupport (8.0.2)
+ base64
+ benchmark (>= 0.3)
+ bigdecimal
+ concurrent-ruby (~> 1.0, >= 1.3.1)
+ connection_pool (>= 2.2.5)
+ drb
i18n (>= 1.6, < 2)
+ logger (>= 1.4.2)
minitest (>= 5.1)
- tzinfo (~> 2.0)
- zeitwerk (~> 2.3)
- builder (3.2.4)
- concurrent-ruby (1.1.9)
+ securerandom (>= 0.3)
+ tzinfo (~> 2.0, >= 2.0.5)
+ uri (>= 0.13.1)
+ base64 (0.2.0)
+ benchmark (0.4.0)
+ bigdecimal (3.1.9)
+ builder (3.3.0)
+ concurrent-ruby (1.3.5)
+ connection_pool (2.5.0)
crass (1.0.6)
- debug (1.1.0)
- irb
- reline (>= 0.2.7)
- erubi (1.10.0)
- globalid (1.0.0)
- activesupport (>= 5.0)
- i18n (1.8.11)
+ date (3.4.1)
+ debug (1.10.0)
+ irb (~> 1.10)
+ reline (>= 0.3.8)
+ drb (2.2.1)
+ erubi (1.13.1)
+ globalid (1.2.1)
+ activesupport (>= 6.1)
+ i18n (1.14.7)
concurrent-ruby (~> 1.0)
- io-console (0.5.9)
- irb (1.3.7)
- reline (>= 0.2.7)
- loofah (2.12.0)
+ io-console (0.8.0)
+ irb (1.15.1)
+ pp (>= 0.6.0)
+ rdoc (>= 4.0.0)
+ reline (>= 0.4.2)
+ logger (1.6.6)
+ loofah (2.24.0)
crass (~> 1.0.2)
- nokogiri (>= 1.5.9)
- mail (2.7.1)
+ nokogiri (>= 1.12.0)
+ mail (2.8.1)
mini_mime (>= 0.1.1)
- method_source (1.0.0)
- mini_mime (1.1.2)
- mini_portile2 (2.6.1)
- minitest (5.14.4)
- nokogiri (1.12.5)
- mini_portile2 (~> 2.6.1)
+ net-imap
+ net-pop
+ net-smtp
+ mini_mime (1.1.5)
+ mini_portile2 (2.8.8)
+ minitest (5.25.5)
+ net-imap (0.5.6)
+ date
+ net-protocol
+ net-pop (0.1.2)
+ net-protocol
+ net-protocol (0.2.2)
+ timeout
+ net-smtp (0.5.1)
+ net-protocol
+ nokogiri (1.18.4)
+ mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- racc (1.6.0)
- rack (2.2.3)
- rack-test (1.1.0)
- rack (>= 1.0, < 3)
- rails-dom-testing (2.0.3)
- activesupport (>= 4.2.0)
+ nokogiri (1.18.4-aarch64-linux-gnu)
+ racc (~> 1.4)
+ nokogiri (1.18.4-arm-linux-gnu)
+ racc (~> 1.4)
+ nokogiri (1.18.4-arm64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.18.4-x86_64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.18.4-x86_64-linux-gnu)
+ racc (~> 1.4)
+ pp (0.6.2)
+ prettyprint
+ prettyprint (0.2.0)
+ psych (5.2.3)
+ date
+ stringio
+ racc (1.8.1)
+ rack (3.1.12)
+ rack-session (2.1.0)
+ base64 (>= 0.1.0)
+ rack (>= 3.0.0)
+ rack-test (2.2.0)
+ rack (>= 1.3)
+ rackup (2.2.1)
+ rack (>= 3)
+ rails-dom-testing (2.2.0)
+ activesupport (>= 5.0.0)
+ minitest
nokogiri (>= 1.6)
- rails-html-sanitizer (1.4.2)
- loofah (~> 2.3)
- railties (6.1.4.1)
- actionpack (= 6.1.4.1)
- activesupport (= 6.1.4.1)
- method_source
- rake (>= 0.13)
- thor (~> 1.0)
- rake (13.0.6)
- reline (0.2.7)
+ rails-html-sanitizer (1.6.2)
+ loofah (~> 2.21)
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
+ railties (8.0.2)
+ actionpack (= 8.0.2)
+ activesupport (= 8.0.2)
+ irb (~> 1.13)
+ rackup (>= 1.0.0)
+ rake (>= 12.2)
+ thor (~> 1.0, >= 1.2.2)
+ zeitwerk (~> 2.6)
+ rake (13.2.1)
+ rdoc (6.12.0)
+ psych (>= 4.0.0)
+ reline (0.6.0)
io-console (~> 0.5)
- sqlite3 (1.4.2)
- thor (1.2.1)
- tzinfo (2.0.4)
+ securerandom (0.4.1)
+ stringio (3.1.5)
+ tailwindcss-ruby (4.1.6)
+ tailwindcss-ruby (4.1.6-aarch64-linux-gnu)
+ tailwindcss-ruby (4.1.6-arm64-darwin)
+ tailwindcss-ruby (4.1.6-x86_64-darwin)
+ tailwindcss-ruby (4.1.6-x86_64-linux-gnu)
+ thor (1.3.2)
+ timeout (0.4.3)
+ tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
- zeitwerk (2.5.1)
+ uri (1.0.3)
+ useragent (0.16.11)
+ zeitwerk (2.7.2)
PLATFORMS
- ruby
+ aarch64-linux
+ arm-linux
+ arm64-darwin
+ x86-linux
+ x86_64-darwin
+ x86_64-linux
DEPENDENCIES
- actionmailer (>= 6.0.0)
+ actionmailer (>= 7.0.0)
debug (>= 1.0.0)
- sqlite3
tailwindcss-rails!
BUNDLED WITH
- 2.2.32
+ 2.5.23
diff --git a/LICENSE-DEPENDENCIES b/LICENSE-DEPENDENCIES
deleted file mode 100644
index 93a34024..00000000
--- a/LICENSE-DEPENDENCIES
+++ /dev/null
@@ -1,26 +0,0 @@
-tailwindcss-rails may redistribute executables from the https://github.com/tailwindlabs/tailwindcss project
-
-The license for that software can be found at https://github.com/tailwindlabs/tailwindcss/blob/master/LICENSE which is reproduced here for your convenience:
-
- MIT License
-
- Copyright (c) Adam Wathan
- Copyright (c) Jonathan Reinink
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
diff --git a/README.md b/README.md
index 3ed4dc4d..158b1750 100644
--- a/README.md
+++ b/README.md
@@ -2,100 +2,469 @@
[Tailwind CSS](https://tailwindcss.com) is a utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup.
-This gem wraps [the standalone executable version](https://tailwindcss.com/blog/standalone-cli) of the Tailwind CSS 3 framework. These executables are platform specific, so there are actually separate underlying gems per platform, but the correct gem will automatically be picked for your platform. Supported platforms are Linux x64, macOS arm64, macOS x64, and Windows x64. (Note that due to this setup, you must install the actual gems – you can't pin your gem to the github repo.)
+
+
+
+
+- [Installation](#installation)
+ * [Choosing a specific version of `tailwindcss`](#choosing-a-specific-version-of-tailwindcss)
+ * [Using a local installation of `tailwindcss`](#using-a-local-installation-of-tailwindcss)
+- [Upgrading your application from Tailwind v3 to v4](#upgrading-your-application-from-tailwind-v3-to-v4)
+ * [You don't _have_ to upgrade](#you-dont-_have_-to-upgrade)
+ * [Upgrade steps](#upgrade-steps)
+ * [Troubleshooting a v4 upgrade](#troubleshooting-a-v4-upgrade)
+ * [Updating CSS class names for v4](#updating-css-class-names-for-v4)
+- [Developing with Tailwindcss](#developing-with-tailwindcss)
+ * [Configuration and commands](#configuration-and-commands)
+ * [Building for production](#building-for-production)
+ * [Building for testing](#building-for-testing)
+ * [Building unminified assets](#building-unminified-assets)
+ * [Live rebuild](#live-rebuild)
+ * [Using Tailwind plugins](#using-tailwind-plugins)
+ * [Using with PostCSS](#using-with-postcss)
+ * [Custom inputs or outputs](#custom-inputs-or-outputs)
+- [Troubleshooting](#troubleshooting)
+ * [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)
+ * [Running in a docker container exits prematurely](#running-in-a-docker-container-exits-prematurely)
+ * [Conflict with sassc-rails](#conflict-with-sassc-rails)
+ * [Class names must be spelled out](#class-names-must-be-spelled-out)
+ * [`ERROR: Cannot find the tailwindcss executable` for supported platform](#error-cannot-find-the-tailwindcss-executable-for-supported-platform)
+ * [Using asset-pipeline assets](#using-asset-pipeline-assets)
+- [License](#license)
+
+
-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.
+## Installation
-The installer will create your 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. When you run `rails tailwindcss:build`, this 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).
+With Rails 7 you can generate a new application preconfigured with Tailwind CSS by using `--css tailwind`. If you're adding Tailwind later, you need to:
-If you need to use a custom input or output file, you can run `bundle exec tailwindcss` to access the platform-specific executable, and give it your own build options.
+1. Run `./bin/bundle add tailwindcss-rails`
+2. Run `./bin/rails tailwindcss:install`
-When you're developing your application, you want to run Tailwind in watch mode, so changes are automatically reflected in the generated CSS output. You can do this either by running `rails tailwindcss:watch` as a separate process, or by running `./bin/dev` which uses [foreman](https://github.com/ddollar/foreman) to starts both the Tailwind watch process and the rails server in development mode. If you are running `rails tailwindcss:watch` as a process in a Docker container, set `tty: true` in `docker-compose.yml` for the appropriate container to keep the watch process running.
+This gem depends on the `tailwindcss-ruby` gem to install a working Tailwind CLI executable.
-## Installation
+### Choosing a specific version of `tailwindcss`
-With Rails 7 you can generate a new application preconfigured with Tailwind by using `--css tailwind`. If you're adding Tailwind later, you need to:
+The `tailwindcss-ruby` gem is declared as a floating dependency of this gem, so by default you will get the most recent stable version. However, you can select a specific version of Tailwind CSS by pinning that gem to the analogous version in your application's `Gemfile`. For example,
-1. Run `./bin/bundle add tailwindcss-rails`
-2. Run `./bin/rails tailwindcss:install`
+``` ruby
+gem "tailwindcss-rails"
+# pin to tailwindcss version 3.4.13
+gem "tailwindcss-ruby", "3.4.13"
+```
-## Building in production
+### Using a local installation of `tailwindcss`
-The `tailwindcss:build` is automatically attached to `assets:precompile`, so before the asset pipeline digests the files, the Tailwind output will be generated.
+You can also use a local (npm-based) installation if you prefer, please go to https://github.com/flavorjones/tailwindcss-ruby for more information.
-## Building for testing
-The `tailwindcss:build` is automatically attached to `test:prepare`, which runs before Rails tests. (Note that this currently only applies to rails `test:*` tasks (like `test:all` or `test:controllers`), not "rails test", as that doesn't load `test:prepare`).
+## Upgrading your application from Tailwind v3 to v4
-## Conflict with sassc-rails
+v4.x of this gem has been updated to work with Tailwind v4, including providing some help with upgrading your application.
-Tailwind uses modern CSS features that are not recognized by the `sassc-rails` extension that was included by default in the Gemfile for Rails 6. In order to avoid any errors like `SassC::SyntaxError`, you must remove that gem from your Gemfile.
+A full explanation of a Tailwind CSS v4 upgrade is out of scope for this README, so we **strongly urge** you to read the [official Tailwind CSS v4 upgrade guide](https://tailwindcss.com/docs/upgrade-guide) before embarking on an upgrade to an existing large app.
-## Class names must be spelled out
+This gem will help with some of the mechanics of the upgrade:
-For Tailwind to work, your class names need to be spelled out. They can't be programmatically composed. So no "text-gray-#{grade}", only "text-gray-500".
+- update some generated files to handle breaking changes in v4 of this gem,
+- update some local project files to meet some Tailwind CSS v4 conventions,
+- attempt to run the [upstream v4 upgrade tool](https://tailwindcss.com/docs/upgrade-guide#using-the-upgrade-tool).
-## Troubleshooting
-Some common problems experienced by users ...
+### You don't _have_ to upgrade
+
+Keep in mind that you don't _need_ to upgrade. You can stay on Tailwind CSS v3 for the foreseeable future if you prefer not to migrate now, or if your migration runs into problems.
-### ERROR: Cannot find the tailwindcss executable for <supported platform>
+If you don't want to upgrade, then pin your application to v3.3.1 of this gem:
-Some users are reporting this error even when running on one of the supported native platforms:
+``` ruby
+# Gemfile
+gem "tailwindcss-rails", "~> 3.3.1" # which transitively pins tailwindcss-ruby to v3
+```
-- arm64-darwin
-- x64-mingw32
-- x86_64-darwin
-- x86_64-linux
-- aarch64-linux
+If you're on an earlier version of this gem, `<= 3.3.0`, then make sure you're pinning the version of **both** `tailwindcss-rails` and `tailwindcss-ruby`:
+
+``` ruby
+# Gemfile
+gem "tailwindcss-rails", "~> 3.3"
+gem "tailwindcss-ruby", "~> 3.4" # only necessary with tailwindcss-rails <= 3.3.0
+```
-#### Check Bundler PLATFORMS
-A possible cause of this is that Bundler has not been told to include native gems for your current platform. Please check your `Gemfile.lock` file to see whether your native platform is included in the `PLATFORMS` section. If necessary, run:
+### Upgrade steps
+
+> [!WARNING]
+> In applications using Tailwind plugins without JavaScript tooling, these upgrade steps may fail to fully migrate `tailwind.config.js` because the upstream upgrade tool needs the Tailwind plugins to be installed and available through a JavaScript package manager. If you see errors from the upstream upgrade tool, you should try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4) which will help you install (temporarily!) the necessary packages and clean up afterwards.
+
+First, update to `tailwindcss-rails` v4.0.0 or higher. This will also ensure you're transitively depending on `tailwindcss-ruby` v4.
+
+```html
+# Gemfile
+gem "tailwindcss-rails", "~> 4.0" # which transitively pins tailwindcss-ruby to v4
+```
+
+**Update** path references to any existing css files imported in `app/assets/stylesheets/application.tailwind.css` so that they will resolve when the file is moved to `app/assets/tailwind/application.css`.
+
+```diff
+-@import "pagy.css";
++@import "../stylesheets/pagy.css";
+```
+
+If you want to migrate CSS class names for v4 (this is an optional step!), jump to [Updating CSS class names for v4](#updating-css-class-names-for-v4) before continuing.
+
+Then, run `bin/rails tailwindcss:upgrade`. 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.
+
+
+Here's a detailed list of what the upgrade task does.
+
+- Cleans up some things in the generated `config/tailwind.config.js`.
+- If present, moves `config/postcss.config.js` to the root directory.
+- If present, moves `app/assets/stylesheets/application.tailwind.css` to `app/assets/tailwind/application.css`.
+- Removes unnecessary `stylesheet_link_tag "tailwindcss"` tags from the application layout.
+- Removes references to the Inter font from the application layout.
+- Runs v4.1.4 of the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended).
+
+
+
+
+Here's what that upgrade looks like on a vanilla Rails app.
``` sh
-bundle lock --add-platform
+$ bin/rails tailwindcss:upgrade
+ apply /path/to/tailwindcss-rails/lib/install/upgrade_tailwindcss.rb
+ Removing references to 'defaultTheme' from /home/user/myapp/config/tailwind.config.js
+ gsub config/tailwind.config.js
+ Strip Inter font CSS from application layout
+ gsub app/views/layouts/application.html.erb
+ Remove unnecessary stylesheet_link_tag from application layout
+ gsub app/views/layouts/application.html.erb
+ Moving /home/user/myapp/app/assets/stylesheets/application.tailwind.css to /home/user/myapp/app/assets/tailwind/application.css
+ create app/assets/tailwind/application.css
+ remove app/assets/stylesheets/application.tailwind.css
+10.9.0
+ Running the upstream Tailwind CSS upgrader
+ run npx @tailwindcss/upgrade@4.1.4 --force --config /home/user/myapp/config/tailwind.config.js from "."
+≈ tailwindcss v4.0.0
+│ Searching for CSS files in the current directory and its subdirectories…
+│ ↳ Linked `./config/tailwind.config.js` to `./app/assets/tailwind/application.css`
+│ Migrating JavaScript configuration files…
+│ ↳ The configuration file at `./config/tailwind.config.js` could not be automatically migrated to the new CSS
+│ configuration format, so your CSS has been updated to load your existing configuration file.
+│ Migrating templates…
+│ ↳ Migrated templates for configuration file: `./config/tailwind.config.js`
+│ Migrating stylesheets…
+│ ↳ Migrated stylesheet: `./app/assets/tailwind/application.css`
+│ ↳ No PostCSS config found, skipping migration.
+│ Updating dependencies…
+│ Could not detect a package manager. Please manually update `tailwindcss` to v4.
+│ Verify the changes and commit them to your repository.
+ Compile initial Tailwind build
+ run rails tailwindcss:build from "."
+≈ tailwindcss v4.0.0
+Done in 56ms
+ run bundle install --quiet
+```
+
+
+
+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) and try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4).
+
+
+### Troubleshooting a v4 upgrade
+
+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.
+
+We know there are some cases we haven't addressed with the upgrade task:
+
+- In applications using Tailwind plugins without JavaScript tooling, these upgrade steps may fail to fully migrate `tailwind.config.js` because the upstream upgrade tool needs the Tailwind plugins to be installed and available through a JavaScript package manager. If you see errors from the upstream upgrade tool, you should try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4) which will help you install (temporarily!) the necessary packages and clean up afterwards.
+
+We'll try to improve the upgrade process over time, but for now you may need to do some manual work to upgrade.
+
+
+### Updating CSS class names for v4
+
+> [!NOTE]
+> If you'd like to help automate these steps, please drop a note to the maintainers in [this discussion thread](https://github.com/rails/tailwindcss-rails/discussions/450).
+
+With some additional manual work the upstream upgrade tool will update your application's CSS class names to v4 conventions. **This is an optional step that requires a JavaScript toolchain.**
+
+**Add** the following line to the `.gitignore` file, to prevent the upstream upgrade tool from accessing node_modules files.
+
+```gitignore
+/node_modules
+```
+
+**Create** or **update** a `package.json` in the root of the project:
+
+```jsonc
+{
+ "name": "app_name",
+ "version": "1.0.0",
+ "dependencies": {
+ "tailwindcss": "^3.4.17", // Mandatory!!
+ // Install all plugins and modules that are referenced in tailwind.config.js
+ "@tailwindcss/aspect-ratio": "^0.4.2",
+ "@tailwindcss/container-queries": "^0.1.1",
+ "@tailwindcss/forms": "^0.5.10",
+ "@tailwindcss/typography": "^0.5.16"
+ // And so on...
+ }
+}
+```
+
+**Run** `npm install` (or `yarn install` if using `yarn`)
+
+**Update** `config/tailwind.config.js` and temporarily change the `content` part to have an additional `.` on all paths so they are relative to the config file:
+
+```js
+ content: [
+ '../public/*.html',
+ '../app/helpers/**/*.rb',
+ '../app/javascript/**/*.js',
+ '../app/views/**/*.{erb,haml,html,slim}'
+ ],
+```
+
+(Just add an additional `.` to all the paths referenced)
+
+**Run** the upstream upgrader as instructed above.
+
+Then, once you've run that successfully, clean up:
+
+- **Review** `package.json` to remove unnecessary modules.
+ - This includes modules added for the period of upgrade.
+ - If you don't need any modules besides `tailwindcss` itself, **delete** `package.json`, `node_modules/` and `package-lock.json` (or `yarn.lock`), plus remove `/node_modules` from `.gitignore`.
+- **Go** to your CSS file and remove the following line (if present):
+ ```css
+ @plugin '@tailwindcss/container-queries';
+ ```
+- **Revert** the changes to `config/tailwind.config.js` so that paths are once again relative to the application root.
+
+## Developing with Tailwindcss
+
+### Configuration and commands
+
+#### Input file: `app/assets/tailwind/application.css`
+
+The `tailwindcss:install` task will generate a Tailwind input file in `app/assets/tailwind/application.css`. This is where you import the plugins you want to use and where you can setup your custom `@apply` rules.
+
+⚠ The location of this file changed in v4, from `app/assets/stylesheets/application.tailwind.css` to `app/assets/tailwind/application.css`. The `tailwindcss:upgrade` task will move it for you.
+
+#### Output file: `app/assets/builds/tailwind.css`
+
+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.
+
+#### Commands
+
+This gem makes several Rails tasks available, some of which have multiple options which can be combined.
+
+Synopsis:
+
+- `bin/rails tailwindcss:install` - installs the configuration file, output file, and `Procfile.dev`
+- `bin/rails tailwindcss:build` - generate the output file
+ - `bin/rails tailwindcss:build[debug]` - generate unminimized output
+- `bin/rails tailwindcss:watch` - start live rebuilds, generating output on file changes
+ - `bin/rails tailwindcss:watch[debug]` - generate unminimized output
+ - `bin/rails tailwindcss:watch[poll]` - for systems without file system events
+ - `bin/rails tailwindcss:watch[always]` - for systems without TTY (e.g., some docker containers)
+
+Note that you can combine task options, e.g. `rails tailwindcss:watch[debug,poll]`.
+
+This gem also makes available a Puma plugin to manage a live rebuild process when you run `rails server` (see "Live Rebuild" section below).
+
+This gem also generates a `Procfile.dev` file which will run both the rails server and a live rebuild process (see "Live Rebuild" section below).
+
+### Building for production
+
+The `tailwindcss:build` is automatically attached to `assets:precompile`, so before the asset pipeline digests the files, the Tailwind output will be generated.
+
+
+### Building for testing
+
+The `tailwindcss:build` task is automatically attached to the `test:prepare` Rake task. This task runs before test commands. If you run `bin/rails test` in your CI environment, your Tailwind output will be generated before tests run.
+
+
+### Building unminified assets
+
+If you want unminified assets, you can:
+
+- pass a `debug` argument to the rake task, i.e. `rails tailwindcss:build[debug]` or `rails tailwindcss:watch[debug]`.
+- set an environment variable named `TAILWINDCSS_DEBUG` with a non-blank value
+
+If both values are set, the environment variable will take precedence over the rake task argument.
+
+### Live rebuild
+
+While you're developing your application, you want to run Tailwind in "watch" mode, so changes are automatically reflected in the generated CSS output. You can do this in a few different ways:
+
+- use this gem's [Puma](https://puma.io/) plugin to integrate "watch" with `rails server`,
+- or run `rails tailwindcss:watch` as a separate process,
+- or run `bin/dev` which uses [Foreman](https://github.com/ddollar/foreman)
+
+
+#### Puma plugin
+
+This gem ships with a Puma plugin. To use it, add this line to your `puma.rb` configuration:
+
+```ruby
+plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development"
```
-and re-bundle.
+and then running `rails server` (or just `puma`) will run the Tailwind watch process in the background.
-#### Check BUNDLE_FORCE_RUBY_PLATFORM
+#### Run `rails tailwindcss:watch`
-Another common cause of this is that bundler is configured to always use the "ruby" platform via the
-`BUNDLE_FORCE_RUBY_PLATFORM` config parameter being set to `true`. Please remove this configuration:
+This is a flexible command, which can be run with a few different options.
+
+If you are running `rails tailwindcss:watch` on a system that doesn't fully support file system events, pass a `poll` argument to the task to instruct tailwindcss to instead use polling:
+
+```
+rails tailwindcss:watch[poll]
+```
+
+(If you use `bin/dev` then you should modify your `Procfile.dev` to use the `poll` option.)
+
+If you are running `rails tailwindcss:watch` as a process in a Docker container, set `tty: true` in `docker-compose.yml` for the appropriate container to keep the watch process running.
+
+If you are running `rails tailwindcss:watch` in a docker container without a tty, pass the `always` argument to the task to instruct tailwindcss to keep the watcher alive even when `stdin` is closed: `rails tailwindcss:watch[always]`. If you use `bin/dev` then you should modify your `Procfile.dev`.
+
+
+#### Foreman
+
+Running `bin/dev` invokes Foreman to start both the Tailwind watch process and the rails server in development mode based on your `Procfile.dev` file.
+
+
+### Using Tailwind plugins
+
+If you want to use Tailwind plugins, they can be installed using `package.json`.
+
+Using Yarn:
+
+``` sh
+[ ! -f package.json ] && yarn init
+yarn add daisyui # example
+```
+
+Using npm:
``` sh
-bundle config unset force_ruby_platform
-# or
-bundle config set --local force_ruby_platform false
+npm init
+npm add daisyui # example
+```
+
+Than use `@plugin` annotation in `app/assets/tailwind/application.css`:
+
+``` css
+@import "tailwindcss";
+@plugin "daisyui";
+```
+
+
+### Using with PostCSS
+
+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.
+
+For example, to enable nesting:
+
+```js
+// postcss.config.js
+export default {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ }
+}
```
-and re-bundle.
+⚠ Note that PostCSS is a JavaScript tool with its own prerequisites! By default `tailwindcss-rails` does not require any JavaScript tooling, so in order to use PostCSS, a `package.json` with dependencies for your plugins and a package manager like `yarn` or `npm` is required, for example:
+
+```json
+// package.json
+{
+ "name": "my app",
+ "private": true,
+ "dependencies": {
+ "@tailwindcss/postcss": "^4.0.0",
+ "tailwindcss": "^4.0.0",
+ "postcss": "^8.5.1"
+ }
+}
+```
-See https://bundler.io/man/bundle-config.1.html for more information.
+Then you can use yarn or npm to install the dependencies.
-### "No such file or directory" running on Alpine (musl)
+### Custom inputs or outputs
-When running `tailwindcss` on an Alpine system, some users report a "No such file or directory" error message.
+If you need to use a custom input or output file, you can run `bundle exec tailwindcss` to access the platform-specific executable, and give it your own build options.
-#### Install gnu libc compatibility
+## Troubleshooting
+
+When having trouble with `tailwindcss:build` or `tailwindcss:watch`, the first thing you should do is collect some diagnostic information by setting the "verbose" flag, which will emit:
-The cause of this is the upstream `tailwindcss` binary executables being built on a gnu libc system, making them incompatible with standard musl libc systems.
+1. the command being run (so you can try running `tailwindcss` yourself without the gem's help)
+2. additional debugging output from `tailwindcss` by setting the env var `DEBUG=1`
-A fix for this has been proposed upstream at https://github.com/tailwindlabs/tailwindcss/discussions/6785, but in the meantime a workaround is to install compatibility libraries:
+Here's what that looks like:
``` sh
-apk add build-base gcompat
+$ bin/rails tailwindcss:build[verbose]
+
+Running: /path/to/tailwindcss-ruby-4.0.17-x86_64-linux-gnu/exe/x86_64-linux-gnu/tailwindcss -i /home/flavorjones/code/oss/tailwindcss-rails/My Workspace/test-install/app/assets/tailwind/application.css -o /home/flavorjones/code/oss/tailwindcss-rails/My Workspace/test-install/app/assets/builds/tailwind.css --minify
+≈ tailwindcss v4.0.17
+
+Done in 37ms
+
+[38.22ms] [@tailwindcss/cli] (initial build)
+[11.90ms] ↳ Setup compiler
+[ 6.52ms] ↳ Scan for candidates
+[10.39ms] ↳ Build CSS
+[ 1.69ms] ↳ Optimize CSS
+[ 5.80ms] ↳ Write output
```
+### The `watch` command is hanging
+
+There is a [known issue](https://github.com/tailwindlabs/tailwindcss/issues/17246#issuecomment-2753067488) running `tailwindcss -w` (that's the CLI in watch mode) when the utility `watchman` is also installed.
+
+Please try uninstalling `watchman` and try running the watch task again.
+
+
+### Lost keystrokes or hanging when using terminal-based debugging tools (e.g. IRB, Pry, `ruby/debug`...etc.) with the Puma plugin
+
+We've addressed the issue and you can avoid the problem by upgrading `tailwindcss-rails` to [v2.4.1](https://github.com/rails/tailwindcss-rails/releases/tag/v2.4.1) or later versions.
+
+
+### Running in a docker container exits prematurely
+
+If you are running `rails tailwindcss:watch` as a process in a Docker container, set `tty: true` in `docker-compose.yml` for the appropriate container to keep the watch process running.
+
+If you are running `rails tailwindcss:watch` in a docker container without a tty, pass the `always` argument to the task to instruct tailwindcss to keep the watcher alive even when `stdin` is closed: `rails tailwindcss:watch[always]`. If you use `bin/dev` then you should modify your `Procfile.dev`.
+
+
+### Conflict with sassc-rails
+
+Tailwind uses modern CSS features that are not recognized by the `sassc-rails` extension that was included by default in the Gemfile for Rails 6. In order to avoid any errors like `SassC::SyntaxError`, you must remove that gem from your Gemfile.
+
+
+### Class names must be spelled out
+
+For Tailwind to work, your class names need to be spelled out. If you need to make sure Tailwind generates class names that don't exist in your content files or that are programmatically composed, use the [safelist option](https://tailwindcss.com/docs/content-configuration#safelisting-classes).
+
+
+### `ERROR: Cannot find the tailwindcss executable` for supported platform
+
+See https://github.com/flavorjones/tailwindcss-ruby for help.
+
+
### Using asset-pipeline assets
-In Rails, you want to use [assets from the asset pipeline to get fingerprinting](https://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark). However, Tailwind isn't aware of those assets. To use assets from the pipeline, use `url(image.svg)`. [Since Sprockets v3.3.0](https://github.com/rails/sprockets-rails/pull/476) `url(image.svg)` will then automatically be rewritten to `/path/to/assets/image-7801e7538c6f1cc57aa75a5876ab0cac.svg`. So the output CSS will have the correct path to those assets.
+In Rails, you want to use [assets from the asset pipeline to get fingerprinting](https://guides.rubyonrails.org/asset_pipeline.html#fingerprinting-versioning-with-digest-based-urls). However, Tailwind isn't aware of those assets.
+
+To use assets from the pipeline, use `url(image.svg)`. [Since Sprockets v3.3.0](https://github.com/rails/sprockets-rails/pull/476) `url(image.svg)` is rewritten to `/path/to/assets/image-7801e7538c6f1cc57aa75a5876ab0cac.svg` so output CSS will have the correct path to those assets.
```js
module.exports = {
@@ -118,5 +487,3 @@ The inline version also works:
## License
Tailwind for Rails is released under the [MIT License](https://opensource.org/licenses/MIT).
-Tailwind CSS is released under the [MIT License](https://opensource.org/licenses/MIT).
-The Inter font is released under the [SIL Open Font License, Version 1.1](https://github.com/rsms/inter/blob/master/LICENSE.txt).
diff --git a/Rakefile b/Rakefile
index 83a3a2fe..30b6a94c 100644
--- a/Rakefile
+++ b/Rakefile
@@ -12,3 +12,15 @@ Rake::TestTask.new(:test) do |t|
end
task default: :test
+
+namespace "format" do
+ desc "Regenerate table of contents in README"
+ task "toc" do
+ require "mkmf"
+ if find_executable0("markdown-toc")
+ sh "markdown-toc --maxdepth=3 -i README.md"
+ else
+ puts "WARN: cannot find markdown-toc, skipping. install with 'npm install markdown-toc'"
+ end
+ end
+end
diff --git a/app/assets/fonts/Inter-italic.alternates.var.woff2 b/app/assets/fonts/Inter-italic.alternates.var.woff2
deleted file mode 100644
index cbeb7846..00000000
Binary files a/app/assets/fonts/Inter-italic.alternates.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.cyrillic.var.woff2 b/app/assets/fonts/Inter-italic.cyrillic.var.woff2
deleted file mode 100644
index 90930a09..00000000
Binary files a/app/assets/fonts/Inter-italic.cyrillic.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.extra.var.woff2 b/app/assets/fonts/Inter-italic.extra.var.woff2
deleted file mode 100644
index cbeb7846..00000000
Binary files a/app/assets/fonts/Inter-italic.extra.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.greek.var.woff2 b/app/assets/fonts/Inter-italic.greek.var.woff2
deleted file mode 100644
index c0684d11..00000000
Binary files a/app/assets/fonts/Inter-italic.greek.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.latin-ext.var.woff2 b/app/assets/fonts/Inter-italic.latin-ext.var.woff2
deleted file mode 100644
index be543c42..00000000
Binary files a/app/assets/fonts/Inter-italic.latin-ext.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.latin.var.woff2 b/app/assets/fonts/Inter-italic.latin.var.woff2
deleted file mode 100644
index 5066cfdf..00000000
Binary files a/app/assets/fonts/Inter-italic.latin.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.symbols.var.woff2 b/app/assets/fonts/Inter-italic.symbols.var.woff2
deleted file mode 100644
index 1542bc95..00000000
Binary files a/app/assets/fonts/Inter-italic.symbols.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-italic.vietnamese.var.woff2 b/app/assets/fonts/Inter-italic.vietnamese.var.woff2
deleted file mode 100644
index badcf325..00000000
Binary files a/app/assets/fonts/Inter-italic.vietnamese.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.alternates.var.woff2 b/app/assets/fonts/Inter-roman.alternates.var.woff2
deleted file mode 100644
index f2ee9eeb..00000000
Binary files a/app/assets/fonts/Inter-roman.alternates.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.cyrillic.var.woff2 b/app/assets/fonts/Inter-roman.cyrillic.var.woff2
deleted file mode 100644
index a9378e78..00000000
Binary files a/app/assets/fonts/Inter-roman.cyrillic.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.extra.var.woff2 b/app/assets/fonts/Inter-roman.extra.var.woff2
deleted file mode 100644
index f2ee9eeb..00000000
Binary files a/app/assets/fonts/Inter-roman.extra.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.greek.var.woff2 b/app/assets/fonts/Inter-roman.greek.var.woff2
deleted file mode 100644
index 8604c8a0..00000000
Binary files a/app/assets/fonts/Inter-roman.greek.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.latin-ext.var.woff2 b/app/assets/fonts/Inter-roman.latin-ext.var.woff2
deleted file mode 100644
index ac92ffba..00000000
Binary files a/app/assets/fonts/Inter-roman.latin-ext.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.latin.var.woff2 b/app/assets/fonts/Inter-roman.latin.var.woff2
deleted file mode 100644
index 9503ba17..00000000
Binary files a/app/assets/fonts/Inter-roman.latin.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.symbols.var.woff2 b/app/assets/fonts/Inter-roman.symbols.var.woff2
deleted file mode 100644
index c8da0889..00000000
Binary files a/app/assets/fonts/Inter-roman.symbols.var.woff2 and /dev/null differ
diff --git a/app/assets/fonts/Inter-roman.vietnamese.var.woff2 b/app/assets/fonts/Inter-roman.vietnamese.var.woff2
deleted file mode 100644
index b65ab546..00000000
Binary files a/app/assets/fonts/Inter-roman.vietnamese.var.woff2 and /dev/null differ
diff --git a/app/assets/stylesheets/inter-font.css b/app/assets/stylesheets/inter-font.css
deleted file mode 100644
index ddeabaf5..00000000
--- a/app/assets/stylesheets/inter-font.css
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *= link_directory ../fonts
- */
-
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.extra.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Italic';
-}
-/* alternates */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.alternates.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Italic';
-}
-/* symbols */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.symbols.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-
-/* extra */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.extra.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Italic';
-}
-/* alternates */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.alternates.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Italic';
-}
-/* symbols */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.symbols.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-/* cyrillic */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.cyrillic.var.woff2') format('woff2');
- unicode-range: U+0400-049E,U+04A0-0500,U+052F,U+20B4,U+2116,U+2DFF,U+A69F;
- font-named-instance: 'Italic';
-}
-/* greek */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.greek.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-/* vietnamese */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.vietnamese.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-/* latin-ext */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.latin-ext.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-/* latin */
-@font-face {
- font-family: 'Inter var';
- font-style: italic;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-italic.latin.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Italic';
-}
-/* extra */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.extra.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Regular';
-}
-/* alternates */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.alternates.var.woff2') format('woff2');
- unicode-range: U+E000,U+E002-E081,U+E093-E097,U+E0A5-E0E7,U+E0F3-E11D,U+E11E-E165,U+EE01,U+F6C3;
- font-named-instance: 'Regular';
-}
-/* symbols */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.symbols.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Regular';
-}
-/* cyrillic */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.cyrillic.var.woff2') format('woff2');
- unicode-range: U+0400-049E,U+04A0-0500,U+052F,U+20B4,U+2116,U+2DFF,U+A69F;
- font-named-instance: 'Regular';
-}
-/* greek */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.greek.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Regular';
-}
-/* vietnamese */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.vietnamese.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Regular';
-}
-/* latin-ext */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.latin-ext.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Regular';
-}
-/* latin */
-@font-face {
- font-family: 'Inter var';
- font-style: normal;
- font-weight: 100 900;
- font-display: swap;
- src: url('Inter-roman.latin.var.woff2') format('woff2');
- 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;
- font-named-instance: 'Regular';
-}
\ No newline at end of file
diff --git a/exe/tailwindcss b/exe/tailwindcss
deleted file mode 100755
index 4e957483..00000000
--- a/exe/tailwindcss
+++ /dev/null
@@ -1,46 +0,0 @@
-#! /usr/bin/env ruby
-# because rubygems shims assume a gem's executables are Ruby
-
-require "shellwords"
-require "tailwindcss/upstream"
-
-supported_platforms = Tailwindcss::Upstream::NATIVE_PLATFORMS.keys
-platform = [:cpu, :os].map { |m| Gem::Platform.local.send(m) }.join("-")
-
-if supported_platforms.none? { |supported_platform| Gem::Platform.match(supported_platform) }
- STDERR.puts(<<~ERRMSG)
- ERROR: tailwindcss-rails does not support the #{platform} platform
- Please install tailwindcss following instructions at https://tailwindcss.com/docs/installation
- ERRMSG
- exit 1
-end
-
-exe_path = Dir.glob(File.join(__dir__, "*", "tailwindcss")).find do |f|
- Gem::Platform.match(File.basename(File.dirname(f)))
-end
-if exe_path.nil?
- STDERR.puts(<<~ERRMSG)
- ERROR: Cannot find the tailwindcss executable for #{platform} in #{__dir__}
- If you're using bundler, please make sure you're on the latest bundler version:
-
- gem install bundler
- bundle update --bundler
-
- Then make sure your lock file includes this platform by running:
-
- bundle lock --add-platform #{platform}
- bundle install
-
- See `bundle lock --help` output for details.
-
- If you're still seeing this message after taking those steps, try running
- `bundle config` and ensure `force_ruby_platform` isn't set to `true`. See
- https://github.com/rails/tailwindcss-rails#check-bundle_force_ruby_platform
- for more details.
- ERRMSG
- exit 1
-end
-
-command = Shellwords.join([exe_path, ARGV].flatten)
-puts "+ #{command}"
-exec(command)
diff --git a/lib/generators/tailwindcss/authentication/authentication_generator.rb b/lib/generators/tailwindcss/authentication/authentication_generator.rb
new file mode 100644
index 00000000..756f1d7b
--- /dev/null
+++ b/lib/generators/tailwindcss/authentication/authentication_generator.rb
@@ -0,0 +1,11 @@
+require "rails/generators/erb/authentication/authentication_generator"
+
+module Tailwindcss
+ module Generators
+ class AuthenticationGenerator < Erb::Generators::AuthenticationGenerator
+ hide!
+
+ source_root File.expand_path("templates", __dir__)
+ end
+ end
+end
diff --git a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb
new file mode 100644
index 00000000..7096a5bc
--- /dev/null
+++ b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb
@@ -0,0 +1,21 @@
+
+ <%% if alert = flash[:alert] %>
+
<%%= alert %>
+ <%% end %>
+
+
Update your password
+
+ <%%= form_with url: password_path(params[:token]), method: :put, class: "contents" do |form| %>
+
+ <%%= 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 focus:outline-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%%= 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 focus:outline-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%%= form.submit "Save", 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" %>
+
+ <%% end %>
+
diff --git a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb
new file mode 100644
index 00000000..36dff837
--- /dev/null
+++ b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb
@@ -0,0 +1,17 @@
+
+ <%% if alert = flash[:alert] %>
+
<%%= alert %>
+ <%% end %>
+
+
Forgot your password?
+
+ <%%= form_with url: passwords_path, class: "contents" do |form| %>
+
+ <%%= 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-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%%= form.submit "Email reset instructions", class: "w-full sm:w-auto text-center rounded-lg 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/authentication/templates/app/views/sessions/new.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb
new file mode 100644
index 00000000..30fb0d91
--- /dev/null
+++ b/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb
@@ -0,0 +1,31 @@
+
+ <%% if alert = flash[:alert] %>
+
<%%= alert %>
+ <%% end %>
+
+ <%% if notice = flash[:notice] %>
+
<%%= notice %>
+ <%% end %>
+
+
Sign in
+
+ <%%= form_with url: session_url, class: "contents" do |form| %>
+
+ <%%= 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" %>
+
+
+
+ <%%= 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" %>
+
+
+
+
+ <%%= 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" %>
+
+
+
+ <%%= link_to "Forgot password?", new_password_path, class: "text-gray-700 underline hover:no-underline" %>
+
+
+ <%% end %>
+
diff --git a/lib/generators/tailwindcss/controller/controller_generator.rb b/lib/generators/tailwindcss/controller/controller_generator.rb
index 77cc4cc5..1022bff6 100644
--- a/lib/generators/tailwindcss/controller/controller_generator.rb
+++ b/lib/generators/tailwindcss/controller/controller_generator.rb
@@ -3,7 +3,8 @@
module Tailwindcss
module Generators
class ControllerGenerator < Erb::Generators::ControllerGenerator
- source_root File.expand_path("../templates", __FILE__)
+ source_root File.expand_path("templates", __dir__)
+ source_paths << "lib/templates/erb/controller"
end
end
end
diff --git a/lib/generators/tailwindcss/mailer/mailer_generator.rb b/lib/generators/tailwindcss/mailer/mailer_generator.rb
index 730b78c2..b0c9b5d6 100644
--- a/lib/generators/tailwindcss/mailer/mailer_generator.rb
+++ b/lib/generators/tailwindcss/mailer/mailer_generator.rb
@@ -3,7 +3,8 @@
module Tailwindcss
module Generators
class MailerGenerator < Erb::Generators::MailerGenerator
- source_root File.expand_path("../templates", __FILE__)
+ source_root File.expand_path("templates", __dir__)
+ source_paths << "lib/templates/erb/mailer"
end
end
end
diff --git a/lib/generators/tailwindcss/mailer/templates/layout.html.erb.tt b/lib/generators/tailwindcss/mailer/templates/layout.html.erb.tt
new file mode 100644
index 00000000..116e625b
--- /dev/null
+++ b/lib/generators/tailwindcss/mailer/templates/layout.html.erb.tt
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+ <%%= yield %>
+
+
diff --git a/lib/generators/tailwindcss/mailer/templates/layout.text.erb.tt b/lib/generators/tailwindcss/mailer/templates/layout.text.erb.tt
new file mode 100644
index 00000000..6363733e
--- /dev/null
+++ b/lib/generators/tailwindcss/mailer/templates/layout.text.erb.tt
@@ -0,0 +1 @@
+<%%= yield %>
diff --git a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
index 3ae3c99d..8748210d 100644
--- a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
+++ b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb
@@ -1,12 +1,14 @@
-require 'rails/generators/erb/scaffold/scaffold_generator'
+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
class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
include Rails::Generators::ResourceHelpers
- source_root File.expand_path("../templates", __FILE__)
+ source_root File.expand_path("templates", __dir__)
+ source_paths << "lib/templates/erb/scaffold"
argument :attributes, type: :array, default: [], banner: "field:type field:type"
@@ -22,7 +24,7 @@ def copy_view_files
end
end
- template "partial.html.erb", File.join("app/views", controller_file_path, "_#{singular_table_name}.html.erb")
+ template "partial.html.erb", File.join("app/views", controller_file_path, "_#{singular_name}.html.erb")
end
private
@@ -31,4 +33,4 @@ def available_views
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
index ed1a4e1c..1821201c 100644
--- a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
@@ -1,9 +1,9 @@
<%%= form_with(model: <%= model_resource_name %>, class: "contents") do |form| %>
<%% if <%= singular_table_name %>.errors.any? %>
-
+
<%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:
-
+
<%% <%= singular_table_name %>.errors.each do |error| %>
- <%%= error.full_message %>
<%% end %>
@@ -12,32 +12,32 @@
<%% end %>
<% attributes.each do |attribute| -%>
-
+
">
<% if attribute.password_digest? -%>
<%%= form.label :password %>
- <%%= form.password_field :password %>
-
+ <%%= 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 rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
+ <%%= 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 rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
+ <%%= 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 == :text_area -%>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
-<% elsif attribute.field_type == :check_box -%>
- <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "block mt-2 h-5 w-5" %>
+<% 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 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 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 rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
+ <%%= 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-lg py-3 px-5 bg-blue-600 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 34756518..08d92d3a 100644
--- a/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt
@@ -1,8 +1,10 @@
-
+<%% content_for :title, "Editing <%= human_name.downcase %>" %>
+
+
Editing <%= human_name.downcase %>
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
- <%%= link_to "Show this <%= human_name.downcase %>", @<%= singular_table_name %>, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
- <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 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 c65409fa..12a0db16 100644
--- a/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt
@@ -1,14 +1,29 @@
+<%% content_for :title, "<%= human_name.pluralize %>" %>
+
<%% if notice.present? %>
-
<%%= notice %>
+
<%%= notice %>
<%% end %>
<%= human_name.pluralize %>
- <%%= link_to 'New <%= human_name.downcase %>', new_<%= singular_route_name %>_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
+ <%%= 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" %>
-
- <%%= render @<%= plural_table_name %> %>
+
+ <%% if @<%= plural_table_name %>.any? %>
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
+
+ <%%= 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.
+ <%% end %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
index 1f7870f6..32ad9b83 100644
--- a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt
@@ -1,7 +1,9 @@
-
+<%% content_for :title, "New <%= human_name.downcase %>" %>
+
+
New <%= human_name.downcase %>
<%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
- <%%= link_to 'Back to <%= human_name.pluralize.downcase %>', <%= index_helper %>_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 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 301d82f2..433b7a33 100644
--- a/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt
@@ -1,22 +1,18 @@
-
+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
-
+
<%= attribute.human_name %>:
<% if attribute.attachment? -%>
- <%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %> if <%= singular_table_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_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
-
<%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %>
+ <%% <%= singular_name %>.<%= attribute.column_name %>.each do |<%= 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_table_name %>.<%= attribute.column_name %> %>
+ <%%= <%= singular_name %>.<%= attribute.column_name %> %>
<% end -%>
-
-
+
<% end -%>
- <%% if action_name != "show" %>
- <%%= link_to "Show this <%= human_name.downcase %>", <%= singular_table_name %>, class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
- <%%= link_to 'Edit this <%= human_name.downcase %>', edit_<%= singular_table_name %>_path(<%= singular_table_name %>), class: "rounded-lg py-3 ml-2 px-5 bg-gray-100 inline-block font-medium" %>
-
- <%% end %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
index 4bf94e8f..2b6687d2 100644
--- a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
@@ -1,15 +1,15 @@
-
-
- <%% if notice.present? %>
-
<%%= notice %>
- <%% end %>
-
- <%%= render @<%= singular_table_name %> %>
-
- <%%= link_to 'Edit this <%= singular_table_name %>', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
-
- <%%= button_to 'Destroy this <%= singular_table_name %>', <%= singular_table_name %>_path(@<%= singular_table_name %>), method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
-
- <%%= link_to 'Back to <%= plural_table_name %>', <%= index_helper %>_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
-
+<%% content_for :title, "Showing <%= human_name.downcase %>" %>
+
+
+ <%% if notice.present? %>
+
<%%= notice %>
+ <%% end %>
+
+
Showing <%= human_name.downcase %>
+
+ <%%= render @<%= singular_table_name %> %>
+
+ <%%= 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..ff809b32
--- /dev/null
+++ b/lib/generators/test_unit/scaffold/scaffold_generator.rb
@@ -0,0 +1,21 @@
+require "rails/generators/test_unit/scaffold/scaffold_generator"
+
+module TestUnit # :nodoc:
+ module Generators # :nodoc:
+ class ScaffoldGenerator < Base # :nodoc:
+ def fix_system_test
+ if turbo_defined?
+ gsub_file File.join("test/system", class_path, "#{file_name.pluralize}_test.rb"),
+ /(click_on.*Destroy this.*)$/,
+ "accept_confirm { \\1 }"
+ end
+ end
+
+ private
+
+ def turbo_defined?
+ defined?(Turbo)
+ end
+ end
+ end
+end
diff --git a/lib/install/Procfile.dev b/lib/install/Procfile.dev
index 023e98a0..da151fee 100644
--- a/lib/install/Procfile.dev
+++ b/lib/install/Procfile.dev
@@ -1,2 +1,2 @@
-web: bin/rails server -p 3000
+web: bin/rails server
css: bin/rails tailwindcss:watch
diff --git a/lib/install/application.css b/lib/install/application.css
new file mode 100644
index 00000000..f1d8c73c
--- /dev/null
+++ b/lib/install/application.css
@@ -0,0 +1 @@
+@import "tailwindcss";
diff --git a/lib/install/application.tailwind.css b/lib/install/application.tailwind.css
deleted file mode 100644
index 8666d2f3..00000000
--- a/lib/install/application.tailwind.css
+++ /dev/null
@@ -1,13 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/*
-
-@layer components {
- .btn-primary {
- @apply py-2 px-4 bg-blue-200;
- }
-}
-
-*/
diff --git a/lib/install/dev b/lib/install/dev
index 2daf7764..ad72c7d5 100755
--- a/lib/install/dev
+++ b/lib/install/dev
@@ -1,9 +1,16 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
-if ! command -v foreman &> /dev/null
-then
+if ! gem list foreman -i --silent; then
echo "Installing foreman..."
gem install foreman
fi
-foreman start -f Procfile.dev
+# Default to port 3000 if not specified
+export PORT="${PORT:-3000}"
+
+# Let the debug gem allow remote connections,
+# but avoid loading until `debugger` is called
+export RUBY_DEBUG_OPEN="true"
+export RUBY_DEBUG_LAZY="true"
+
+exec foreman start -f Procfile.dev "$@"
diff --git a/lib/install/tailwindcss.rb b/lib/install/install_tailwindcss.rb
similarity index 61%
rename from lib/install/tailwindcss.rb
rename to lib/install/install_tailwindcss.rb
index 413f86b8..3d471d07 100644
--- a/lib/install/tailwindcss.rb
+++ b/lib/install/install_tailwindcss.rb
@@ -1,19 +1,23 @@
APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
CENTERING_CONTAINER_INSERTION_POINT = /^\s*<%= yield %>/.freeze
+TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css")
if APPLICATION_LAYOUT_PATH.exist?
- say "Add Tailwindcss include tags and container element in application layout"
- insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(4), before: /^\s*<%= stylesheet_link_tag/
- <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
- ERB
+ unless File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag :app/)
+ say "Add Tailwindcss include tags in application layout"
+ insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(4), before: /^\s*<%= stylesheet_link_tag/
+ <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
+ ERB
+ end
+ say "Add Tailwindcss container element in application layout"
if File.open(APPLICATION_LAYOUT_PATH).read =~ /\n\s*<%= yield %>\n\s*<\/body>/
insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(
\n ), before: CENTERING_CONTAINER_INSERTION_POINT
insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(\n ), after: CENTERING_CONTAINER_INSERTION_POINT
end
else
say "Default application.html.erb is missing!", :red
- say %( Add <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> within the tag in your custom layout.)
+ say %( Add <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> within the tag in your custom layout.)
end
say "Build into app/assets/builds"
@@ -28,14 +32,9 @@
append_to_file(".gitignore", %(\n/app/assets/builds/*\n!/app/assets/builds/.keep\n))
end
-unless Rails.root.join("config/tailwind.config.js").exist?
- say "Add default config/tailwindcss.config.js"
- copy_file "#{__dir__}/tailwind.config.js", "config/tailwind.config.js"
-end
-
-unless Rails.root.join("app/assets/stylesheets/application.tailwind.css").exist?
- say "Add default app/assets/stylesheets/application.tailwind.css"
- copy_file "#{__dir__}/application.tailwind.css", "app/assets/stylesheets/application.tailwind.css"
+unless TAILWIND_ASSET_PATH.exist?
+ say "Add default #{TAILWIND_ASSET_PATH}"
+ copy_file "#{__dir__}/application.css", TAILWIND_ASSET_PATH
end
if Rails.root.join("Procfile.dev").exist?
@@ -49,7 +48,7 @@
end
say "Add bin/dev to start foreman"
-copy_file "#{__dir__}/dev", "bin/dev"
+copy_file "#{__dir__}/dev", "bin/dev", force: true
chmod "bin/dev", 0755, verbose: false
say "Compile initial Tailwind build"
diff --git a/lib/install/tailwind.config.js b/lib/install/tailwind.config.js
deleted file mode 100644
index 34c0c842..00000000
--- a/lib/install/tailwind.config.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const defaultTheme = require('tailwindcss/defaultTheme')
-
-module.exports = {
- content: [
- './app/helpers/**/*.rb',
- './app/javascript/**/*.js',
- './app/views/**/*.{erb,haml,html,slim}'
- ],
- theme: {
- extend: {
- fontFamily: {
- sans: ['Inter var', ...defaultTheme.fontFamily.sans],
- },
- },
- },
- plugins: [
- require('@tailwindcss/forms'),
- require('@tailwindcss/aspect-ratio'),
- require('@tailwindcss/typography'),
- ]
-}
diff --git a/lib/install/upgrade_tailwindcss.rb b/lib/install/upgrade_tailwindcss.rb
new file mode 100644
index 00000000..d6ecadab
--- /dev/null
+++ b/lib/install/upgrade_tailwindcss.rb
@@ -0,0 +1,69 @@
+TAILWIND_CONFIG_PATH = Rails.root.join("config/tailwind.config.js")
+APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
+POSTCSS_CONFIG_PATH = Rails.root.join("config/postcss.config.js")
+OLD_TAILWIND_ASSET_PATH = Rails.root.join("app/assets/stylesheets/application.tailwind.css")
+TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css")
+
+unless TAILWIND_CONFIG_PATH.exist?
+ say "Default tailwind.config.js is missing!", :red
+ abort
+end
+
+if File.read(TAILWIND_CONFIG_PATH).match?(/defaultTheme/)
+ say "Removing references to 'defaultTheme' from #{TAILWIND_CONFIG_PATH}"
+ gsub_file TAILWIND_CONFIG_PATH.to_s, /^(.*defaultTheme)/, "// \\1"
+end
+
+if POSTCSS_CONFIG_PATH.exist?
+ say "Moving PostCSS configuration to application root directory"
+ copy_file POSTCSS_CONFIG_PATH, Rails.root.join("postcss.config.js")
+ remove_file POSTCSS_CONFIG_PATH
+end
+
+if APPLICATION_LAYOUT_PATH.exist?
+ if File.read(APPLICATION_LAYOUT_PATH).match?(/"inter-font"/)
+ say "Strip Inter font CSS from application layout"
+ gsub_file APPLICATION_LAYOUT_PATH.to_s, %r{, "inter-font"}, ""
+ else
+ say "Inter font CSS not detected.", :green
+ end
+
+ if File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag :app/) &&
+ File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag "tailwind"/)
+ say "Remove unnecessary stylesheet_link_tag from application layout"
+ gsub_file APPLICATION_LAYOUT_PATH.to_s, %r{^\s*<%= stylesheet_link_tag "tailwind".*%>$}, ""
+ end
+else
+ say "Default application.html.erb is missing!", :red
+ say %( Please check your layouts and remove any "inter-font" stylesheet links.)
+end
+
+if OLD_TAILWIND_ASSET_PATH.exist?
+ say "Moving #{OLD_TAILWIND_ASSET_PATH} to #{TAILWIND_ASSET_PATH}"
+ copy_file OLD_TAILWIND_ASSET_PATH, TAILWIND_ASSET_PATH
+ remove_file OLD_TAILWIND_ASSET_PATH
+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@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
+ say %( You probably need to update your configuration. Please read the error messages,)
+ say %( and check the Tailwind CSS upgrade guide at https://tailwindcss.com/docs/upgrade-guide.)
+ abort
+ end
+else
+ say "Could not run the Tailwind upgrade tool. Please see https://tailwindcss.com/docs/upgrade-guide for manual instructions.", :red
+ abort
+end
+
+say "Compile initial Tailwind build"
+run "rails tailwindcss:build"
diff --git a/lib/puma/plugin/tailwindcss.rb b/lib/puma/plugin/tailwindcss.rb
new file mode 100644
index 00000000..4624d7e8
--- /dev/null
+++ b/lib/puma/plugin/tailwindcss.rb
@@ -0,0 +1,72 @@
+require "puma/plugin"
+require "tailwindcss/commands"
+
+Puma::Plugin.create do
+ attr_reader :puma_pid, :tailwind_pid, :log_writer
+
+ def start(launcher)
+ @log_writer = launcher.log_writer
+ @puma_pid = $$
+ @tailwind_pid = fork do
+ Thread.new { monitor_puma }
+ # Using IO.popen(command, 'r+') will avoid watch_command read from $stdin.
+ # 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.copy_stream(io, $stdout)
+ end
+ rescue Interrupt
+ end
+ end
+
+ launcher.events.on_stopped { stop_tailwind }
+
+ in_background do
+ monitor_tailwind
+ end
+ end
+
+ private
+ def stop_tailwind
+ Process.waitpid(tailwind_pid, Process::WNOHANG)
+ log "Stopping tailwind..."
+ Process.kill(:INT, tailwind_pid) if tailwind_pid
+ Process.wait(tailwind_pid)
+ rescue Errno::ECHILD, Errno::ESRCH
+ end
+
+ def monitor_puma
+ monitor(:puma_dead?, "Detected Puma has gone away, stopping tailwind...")
+ end
+
+ def monitor_tailwind
+ monitor(:tailwind_dead?, "Detected tailwind has gone away, stopping Puma...")
+ end
+
+ def monitor(process_dead, message)
+ loop do
+ if send(process_dead)
+ log message
+ Process.kill(:INT, $$)
+ break
+ end
+ sleep 2
+ end
+ end
+
+ def tailwind_dead?
+ Process.waitpid(tailwind_pid, Process::WNOHANG)
+ false
+ rescue Errno::ECHILD, Errno::ESRCH
+ true
+ end
+
+ def puma_dead?
+ Process.ppid != puma_pid
+ end
+
+ def log(...)
+ log_writer.log(...)
+ end
+end
diff --git a/lib/tailwindcss-rails.rb b/lib/tailwindcss-rails.rb
index 198aac3d..2b86ff1c 100644
--- a/lib/tailwindcss-rails.rb
+++ b/lib/tailwindcss-rails.rb
@@ -1,6 +1,6 @@
module Tailwindcss
end
-require "tailwindcss/upstream"
-require "tailwindcss/version"
-require "tailwindcss/engine"
+require_relative "tailwindcss/version"
+require_relative "tailwindcss/engine"
+require_relative "tailwindcss/commands"
diff --git a/lib/tailwindcss/commands.rb b/lib/tailwindcss/commands.rb
new file mode 100644
index 00000000..99ad30e0
--- /dev/null
+++ b/lib/tailwindcss/commands.rb
@@ -0,0 +1,43 @@
+require "tailwindcss/ruby"
+
+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 = [
+ Tailwindcss::Ruby.executable(**kwargs),
+ "-i", rails_root.join("app/assets/tailwind/application.css").to_s,
+ "-o", rails_root.join("app/assets/builds/tailwind.css").to_s,
+ ]
+
+ command << "--minify" unless (debug || rails_css_compressor?)
+
+ postcss_path = rails_root.join("postcss.config.js")
+ command += ["--postcss", postcss_path.to_s] if File.exist?(postcss_path)
+
+ command
+ end
+
+ def watch_command(always: false, poll: 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
+
+ def rails_css_compressor?
+ defined?(Rails) && Rails&.application&.config&.assets&.css_compressor.present?
+ end
+ end
+ end
+end
diff --git a/lib/tailwindcss/engine.rb b/lib/tailwindcss/engine.rb
index 4b9b9fdc..7b88c5f1 100644
--- a/lib/tailwindcss/engine.rb
+++ b/lib/tailwindcss/engine.rb
@@ -2,14 +2,16 @@
module Tailwindcss
class Engine < ::Rails::Engine
- initializer "tailwindcss.assets" do
- Rails.application.config.assets.precompile += %w( inter-font.css )
- end
-
initializer "tailwindcss.disable_generator_stylesheets" do
Rails.application.config.generators.stylesheets = false
end
+ initializer "tailwindcss.exclude_asset_path", before: "propshaft.append_assets_path" do
+ if Rails.application.config.assets.excluded_paths # the app may not be using Propshaft
+ Rails.application.config.assets.excluded_paths << Rails.root.join("app/assets/tailwind")
+ end
+ end
+
config.app_generators do |g|
g.template_engine :tailwindcss
end
diff --git a/lib/tailwindcss/upstream.rb b/lib/tailwindcss/upstream.rb
index 489bbe4a..358db1c0 100644
--- a/lib/tailwindcss/upstream.rb
+++ b/lib/tailwindcss/upstream.rb
@@ -1,15 +1,6 @@
module Tailwindcss
- # constants describing the upstream tailwindcss project
module Upstream
- VERSION = "v3.0.23"
-
- # rubygems platform name => upstream release filename
- NATIVE_PLATFORMS = {
- "arm64-darwin" => "tailwindcss-macos-arm64",
- "x64-mingw32" => "tailwindcss-windows-x64.exe",
- "x86_64-darwin" => "tailwindcss-macos-x64",
- "x86_64-linux" => "tailwindcss-linux-x64",
- "aarch64-linux" => "tailwindcss-linux-arm64",
- }
+ VERSION = Tailwindcss::Ruby::Upstream::VERSION
+ deprecate_constant :VERSION
end
end
diff --git a/lib/tailwindcss/version.rb b/lib/tailwindcss/version.rb
index 62f41fb6..7ab2db8d 100644
--- a/lib/tailwindcss/version.rb
+++ b/lib/tailwindcss/version.rb
@@ -1,3 +1,3 @@
module Tailwindcss
- VERSION = "2.0.8"
+ VERSION = "4.2.3"
end
diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake
index 760a478e..603c8059 100644
--- a/lib/tasks/build.rake
+++ b/lib/tasks/build.rake
@@ -1,14 +1,30 @@
-TAILWIND_COMPILE_COMMAND = "#{RbConfig.ruby} #{Pathname.new(__dir__).to_s}/../../exe/tailwindcss -i #{Rails.root.join("app/assets/stylesheets/application.tailwind.css")} -o #{Rails.root.join("app/assets/builds/tailwind.css")} -c #{Rails.root.join("config/tailwind.config.js")} --minify"
-
namespace :tailwindcss do
desc "Build your Tailwind CSS"
- task :build do
- system TAILWIND_COMPILE_COMMAND
+ task build: :environment do |_, args|
+ debug = args.extras.include?("debug")
+ verbose = args.extras.include?("verbose")
+
+ command = Tailwindcss::Commands.compile_command(debug: debug)
+ 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 do
- system "#{TAILWIND_COMPILE_COMMAND} -w"
+ task watch: :environment do |_, args|
+ debug = args.extras.include?("debug")
+ poll = args.extras.include?("poll")
+ always = args.extras.include?("always")
+ verbose = args.extras.include?("verbose")
+
+ command = Tailwindcss::Commands.watch_command(always: always, debug: debug, poll: poll)
+ 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
end
@@ -16,6 +32,8 @@ Rake::Task["assets:precompile"].enhance(["tailwindcss:build"])
if Rake::Task.task_defined?("test:prepare")
Rake::Task["test:prepare"].enhance(["tailwindcss:build"])
+elsif Rake::Task.task_defined?("spec:prepare")
+ Rake::Task["spec:prepare"].enhance(["tailwindcss:build"])
elsif Rake::Task.task_defined?("db:test:prepare")
Rake::Task["db:test:prepare"].enhance(["tailwindcss:build"])
end
diff --git a/lib/tasks/install.rake b/lib/tasks/install.rake
index 2a571cad..f94ec2a1 100644
--- a/lib/tasks/install.rake
+++ b/lib/tasks/install.rake
@@ -1,6 +1,6 @@
namespace :tailwindcss do
desc "Install Tailwind CSS into the app"
task :install do
- system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/tailwindcss.rb", __dir__)}"
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install_tailwindcss.rb", __dir__)}"
end
end
diff --git a/lib/tasks/upgrade.rake b/lib/tasks/upgrade.rake
new file mode 100644
index 00000000..05047523
--- /dev/null
+++ b/lib/tasks/upgrade.rake
@@ -0,0 +1,6 @@
+namespace :tailwindcss do
+ desc "Upgrade app from Tailwind CSS v3 to v4"
+ task :upgrade do
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/upgrade_tailwindcss.rb", __dir__)}"
+ end
+end
diff --git a/rakelib/package.rake b/rakelib/package.rake
deleted file mode 100644
index a7970e67..00000000
--- a/rakelib/package.rake
+++ /dev/null
@@ -1,108 +0,0 @@
-# coding: utf-8
-#
-# Rake tasks to manage native gem packages with binary executables from tailwindlabs/tailwindcss
-#
-# TL;DR: run "rake package"
-#
-# The native platform gems (defined by Tailwindcss::Upstream::NATIVE_PLATFORMS) will each contain
-# two files in addition to what the vanilla ruby gem contains:
-#
-# exe/
-# ├── tailwindcss # generic ruby script to find and run the binary
-# └──
/
-# └── tailwindcss # the tailwindcss binary executable
-#
-# The ruby script `exe/tailwindcss` is installed into the user's path, and it simply locates the
-# binary and executes it. Note that this script is required because rubygems requires that
-# executables declared in a gemspec must be Ruby scripts.
-#
-# As a concrete example, an x86_64-linux system will see these files on disk after installing
-# tailwindcss-rails-1.x.x-x86_64-linux.gem:
-#
-# exe/
-# ├── tailwindcss
-# └── x86_64-linux/
-# └── tailwindcss
-#
-# So the full set of gem files created will be:
-#
-# - pkg/tailwindcss-rails-1.0.0.gem
-# - pkg/tailwindcss-rails-1.0.0-aarch64-linux.gem
-# - pkg/tailwindcss-rails-1.0.0-arm64-darwin.gem
-# - pkg/tailwindcss-rails-1.0.0-x64-mingw32.gem
-# - pkg/tailwindcss-rails-1.0.0-x86_64-darwin.gem
-# - pkg/tailwindcss-rails-1.0.0-x86_64-linux.gem
-#
-# Note that in addition to the native gems, a vanilla "ruby" gem will also be created without
-# either the `exe/tailwindcss` script or a binary executable present.
-#
-#
-# New rake tasks created:
-#
-# - rake gem:ruby # Build the ruby gem
-# - rake gem:aarch64-linux # Build the aarch64-linux gem
-# - rake gem:arm64-darwin # Build the arm64-darwin gem
-# - rake gem:x64-mingw32 # Build the x64-mingw32 gem
-# - rake gem:x86_64-darwin # Build the x86_64-darwin gem
-# - rake gem:x86_64-linux # Build the x86_64-linux gem
-# - rake download # Download all tailwindcss binaries
-#
-# Modified rake tasks:
-#
-# - rake gem # Build all the gem files
-# - rake package # Build all the gem files (same as `gem`)
-# - rake repackage # Force a rebuild of all the gem files
-#
-# Note also that the binary executables will be lazily downloaded when needed, but you can
-# explicitly download them with the `rake download` command.
-#
-require "rubygems/package_task"
-require "open-uri"
-require_relative "../lib/tailwindcss/upstream"
-
-def tailwindcss_download_url(filename)
- "https://github.com/tailwindlabs/tailwindcss/releases/download/#{Tailwindcss::Upstream::VERSION}/#{filename}"
-end
-
-TAILWINDCSS_RAILS_GEMSPEC = Bundler.load_gemspec("tailwindcss-rails.gemspec")
-
-gem_path = Gem::PackageTask.new(TAILWINDCSS_RAILS_GEMSPEC).define
-desc "Build the ruby gem"
-task "gem:ruby" => [gem_path]
-
-exepaths = []
-Tailwindcss::Upstream::NATIVE_PLATFORMS.each do |platform, filename|
- TAILWINDCSS_RAILS_GEMSPEC.dup.tap do |gemspec|
- exedir = File.join(gemspec.bindir, platform) # "exe/x86_64-linux"
- exepath = File.join(exedir, "tailwindcss") # "exe/x86_64-linux/tailwindcss"
- exepaths << exepath
-
- # modify a copy of the gemspec to include the native executable
- gemspec.platform = platform
- gemspec.files += [exepath, "LICENSE-DEPENDENCIES"]
-
- # create a package task
- gem_path = Gem::PackageTask.new(gemspec).define
- desc "Build the #{platform} gem"
- task "gem:#{platform}" => [gem_path]
-
- directory exedir
- file exepath => [exedir] do
- release_url = tailwindcss_download_url(filename)
- warn "Downloading #{exepath} from #{release_url} ..."
-
- # lazy, but fine for now.
- URI.open(release_url) do |remote|
- File.open(exepath, "wb") do |local|
- local.write(remote.read)
- end
- end
- FileUtils.chmod(0755, exepath, verbose: true)
- end
- end
-end
-
-desc "Download all tailwindcss binaries"
-task "download" => exepaths
-
-CLOBBER.add(exepaths.map { |p| File.dirname(p) })
diff --git a/tailwindcss-rails.gemspec b/tailwindcss-rails.gemspec
index 672c9885..45c19c28 100644
--- a/tailwindcss-rails.gemspec
+++ b/tailwindcss-rails.gemspec
@@ -14,9 +14,24 @@ Gem::Specification.new do |spec|
"rubygems_mfa_required" => "true"
}
+ spec.required_rubygems_version = ">= 3.2.0" # for Gem::Platform#match_gem?
+
spec.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
- spec.bindir = "exe"
- spec.executables << "tailwindcss"
- spec.add_dependency "railties", ">= 6.0.0"
+ 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
new file mode 100755
index 00000000..bfd7a87c
--- /dev/null
+++ b/test/integration/user_install_test.sh
@@ -0,0 +1,76 @@
+#! /usr/bin/env bash
+# reproduce the documented user journey for installing and running tailwindcss-rails
+# this is run in the CI pipeline, non-zero exit code indicates a failure
+
+set -o pipefail
+set -eux
+
+# set up dependencies
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
+bundle add rails --skip-install ${RAILSOPTS:-}
+bundle install --prefer-local
+
+# 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
+bundle exec rails new test-install --skip-bundle
+pushd test-install
+
+# make sure to use the same version of rails (e.g., install from git source if necessary)
+bundle remove rails --skip-install
+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
+
+# install tailwindcss
+bin/rails tailwindcss:install
+
+# TEST: tailwind was installed correctly
+grep -q "<> Rakefile
+task :still_here do
+ puts "Rake process did not exit early"
+end
+EOF
+
+cat >> app/assets/tailwind/application.css < "Rails 8.0.0.beta" ]] ; then
+ # TEST: presence of the generated file
+ bin/rails generate authentication
+ grep -q PasswordsController app/controllers/passwords_controller.rb
+fi
+
+# TEST: presence of the generated file
+bin/rails generate scaffold post title:string body:text published:boolean
+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]
+grep -q "py-2" app/assets/builds/tailwind.css
+
+# TEST: contents include application.css directives
+grep -q "#abc12399" app/assets/builds/tailwind.css
+
+echo "OK"
diff --git a/test/integration/user_upgrade_test.sh b/test/integration/user_upgrade_test.sh
new file mode 100755
index 00000000..d6017efc
--- /dev/null
+++ b/test/integration/user_upgrade_test.sh
@@ -0,0 +1,90 @@
+#! /usr/bin/env bash
+# reproduce the documented user journey for installing and running tailwindcss-rails
+# this is run in the CI pipeline, non-zero exit code indicates a failure
+
+set -o pipefail
+set -eux
+
+# set up dependencies
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
+bundle add rails --skip-install ${RAILSOPTS:-}
+bundle install --prefer-local
+
+# 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
+bundle exec rails new test-upgrade --skip-bundle
+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
+bundle add rails --skip-install ${RAILSOPTS:-}
+
+# set up app with tailwindcss-rails v3 and tailwindcss-ruby v3
+bundle add tailwindcss-rails --skip-install --version 3.3.0
+bundle add tailwindcss-ruby --skip-install --version 3.4.17
+bundle install --prefer-local
+bundle show --paths | fgrep tailwind
+bundle binstubs --all
+
+# install tailwindcss
+bin/rails tailwindcss:install
+grep -q inter-font app/views/layouts/application.html.erb
+
+if [[ $(rails -v) > "Rails 8.0.0.beta" ]] ; then
+ # install auth templates
+ bin/rails generate authentication
+ grep -q PasswordsController app/controllers/passwords_controller.rb
+fi
+
+# install scaffold templates
+bin/rails generate scaffold post title:string body:text published:boolean
+grep -q "Show this post" app/views/posts/index.html.erb
+
+# upgrade time!
+bundle remove tailwindcss-rails --skip-install
+bundle remove tailwindcss-ruby --skip-install
+
+bundle add tailwindcss-rails --skip-install --path="../.."
+bundle add tailwindcss-ruby --skip-install ${TAILWINDCSSOPTS:---version 4.0.0}
+
+bundle install --prefer-local
+bundle show --paths | fgrep tailwind
+bundle binstubs --all
+
+# create a postcss file
+cat < config/postcss.config.js
+module.exports = {
+ plugins: {
+ autoprefixer: {},
+ },
+}
+EOF
+
+bin/rails tailwindcss:upgrade
+
+# TEST: removal of inter-font CSS
+if grep -q inter-font app/views/layouts/application.html.erb ; then
+ echo "FAIL: inter-font CSS not removed"
+ exit 1
+fi
+
+# TEST: moving the postcss file
+test ! -a config/postcss.config.js
+test -a postcss.config.js
+
+# TEST: moving application.tailwind.css
+test ! -a app/assets/stylesheets/application.tailwind.css
+test -a app/assets/tailwind/application.css
+
+# generate CSS
+bin/rails tailwindcss:build[verbose]
+grep -q "py-2" app/assets/builds/tailwind.css
+
+echo "OK"
diff --git a/test/lib/generators/tailwindcss/authentication_generator_test.rb b/test/lib/generators/tailwindcss/authentication_generator_test.rb
new file mode 100644
index 00000000..bdf712b0
--- /dev/null
+++ b/test/lib/generators/tailwindcss/authentication_generator_test.rb
@@ -0,0 +1,16 @@
+require "test_helper"
+
+if Rails::VERSION::MAJOR >= 8
+ require "generators/tailwindcss/authentication/authentication_generator"
+
+ class Tailwindcss::Generators::AuthenticationGeneratorTest < Rails::Generators::TestCase
+ tests Tailwindcss::Generators::AuthenticationGenerator
+ destination TAILWINDCSS_TEST_APP_ROOT
+
+ test "generates the new session template" do
+ run_generator
+
+ assert_file "app/views/sessions/new.html.erb"
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/controller_generator_test.rb b/test/lib/generators/tailwindcss/controller_generator_test.rb
index 42b67ec6..62f3b1ee 100644
--- a/test/lib/generators/tailwindcss/controller_generator_test.rb
+++ b/test/lib/generators/tailwindcss/controller_generator_test.rb
@@ -3,14 +3,45 @@
class Tailwindcss::Generators::ControllerGeneratorTest < Rails::Generators::TestCase
tests Tailwindcss::Generators::ControllerGenerator
- destination Dir.mktmpdir
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(Messages index show)
test "generates correct view templates" do
run_generator
- assert_file "app/views/messages/index.html.erb"
- assert_file "app/views/messages/show.html.erb"
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+ end
+
+ test "generates correct view templates when namespaced" do
+ run_generator ["admin/messages", "index", "show"]
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/admin/messages/#{view}.html.erb"
+ end
end
-end
+ [
+ "lib/templates/erb/controller",
+ "lib/templates/tailwindcss/controller",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "view.html.erb"), "w") { |f| f.puts "This is a custom template" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/messages/#{view}.html.erb" do |body|
+ assert_match("This is a custom template", body, "index custom template should be used")
+ end
+ end
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/mailer_generator_test.rb b/test/lib/generators/tailwindcss/mailer_generator_test.rb
index db604bd3..e6fa61cc 100644
--- a/test/lib/generators/tailwindcss/mailer_generator_test.rb
+++ b/test/lib/generators/tailwindcss/mailer_generator_test.rb
@@ -3,8 +3,8 @@
require "generators/tailwindcss/mailer/mailer_generator"
class Tailwindcss::Generators::MailerGeneratorTest < Rails::Generators::TestCase
- tests Rails::Generators::MailerGenerator
- destination Dir.mktmpdir
+ tests Tailwindcss::Generators::MailerGenerator
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(Notifications invoice)
@@ -20,6 +20,60 @@ class Tailwindcss::Generators::MailerGeneratorTest < Rails::Generators::TestCase
assert_match %r(app/views/notifications_mailer/invoice\.text\.erb), view
assert_match(/\= @greeting/, view)
end
+
+ assert_file "app/views/layouts/mailer.text.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+
+ assert_file "app/views/layouts/mailer.html.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
end
-end
+ test "generates correct mailer view templates with namespace" do
+ run_generator ["admin/notifications", "invoice"]
+
+ assert_file "app/views/admin/notifications_mailer/invoice.html.erb" do |view|
+ assert_match %r(app/views/admin/notifications_mailer/invoice\.html\.erb), view
+ assert_match(/\= @greeting/, view)
+ end
+
+ assert_file "app/views/admin/notifications_mailer/invoice.text.erb" do |view|
+ assert_match %r(app/views/admin/notifications_mailer/invoice\.text\.erb), view
+ assert_match(/\= @greeting/, view)
+ end
+
+ assert_file "app/views/layouts/admin/mailer.text.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+
+ assert_file "app/views/layouts/admin/mailer.html.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+ end
+
+ [
+ "lib/templates/erb/mailer",
+ "lib/templates/tailwindcss/mailer",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "view.html.erb"), "w") { |f| f.puts "This is a custom template" }
+ File.open(File.join(override_dir, "layout.html.erb"), "w") { |f| f.puts "This is a custom layout" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ assert_file "app/views/notifications_mailer/invoice.html.erb" do |view|
+ assert_match("This is a custom template", view)
+ end
+
+ assert_file "app/views/layouts/mailer.html.erb" do |view|
+ assert_match("This is a custom layout", view)
+ end
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/scaffold_generator_test.rb b/test/lib/generators/tailwindcss/scaffold_generator_test.rb
index 2973a7a4..fb7db462 100644
--- a/test/lib/generators/tailwindcss/scaffold_generator_test.rb
+++ b/test/lib/generators/tailwindcss/scaffold_generator_test.rb
@@ -3,13 +3,47 @@
class Tailwindcss::Generators::ScaffoldGeneratorTest < Rails::Generators::TestCase
tests Tailwindcss::Generators::ScaffoldGenerator
- destination Dir.mktmpdir
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(message title:string content:text)
- test "generates correct view templates" do
+ test "generates view templates" do
run_generator
- %w(index edit new show _form _message).each { |view| assert_file "app/views/messages/#{view}.html.erb" }
+ %w(index edit new show _form _message).each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+ end
+
+ test "generates view templates with namespace" do
+ run_generator [ "admin/role", "name:string", "description:string" ]
+
+ %w(index edit new show _form _role).each do |view|
+ assert_file "app/views/admin/roles/#{view}.html.erb"
+ end
+ end
+
+ [
+ "lib/templates/tailwindcss/scaffold",
+ "lib/templates/erb/scaffold",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "index.html.erb"), "w") { |f| f.puts "This is a custom template" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ %w(edit new show _form _message).each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+
+ assert_file "app/views/messages/index.html.erb" do |body|
+ assert_match("This is a custom template", body, "index custom template should be used")
+ end
+ end
end
end
diff --git a/test/lib/tailwindcss/commands_test.rb b/test/lib/tailwindcss/commands_test.rb
new file mode 100644
index 00000000..d09481a4
--- /dev/null
+++ b/test/lib/tailwindcss/commands_test.rb
@@ -0,0 +1,129 @@
+require "test_helper"
+require "minitest/mock"
+
+class Tailwindcss::CommandsTest < ActiveSupport::TestCase
+ attr_accessor :executable
+
+ def setup
+ super
+ @executable = Tailwindcss::Ruby.executable
+ end
+
+ test ".compile_command" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-i")
+ assert_includes(actual, "-o")
+ end
+ end
+
+ test ".compile_command debug flag" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ refute_includes(actual, "--minify")
+ 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
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+ end
+
+ Tailwindcss::Commands.stub(:rails_css_compressor?, false) do
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+ end
+ end
+ end
+
+ test ".compile_command when postcss.config.js exists" do
+ Dir.mktmpdir do |tmpdir|
+ Rails.stub(:root, Pathname.new(tmpdir)) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ refute_includes(actual, "--postcss")
+
+ config_file = Rails.root.join("postcss.config.js")
+ FileUtils.touch(config_file)
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "--postcss")
+ postcss_index = actual.index("--postcss")
+ assert_equal(actual[postcss_index + 1], config_file.to_s)
+ end
+ end
+ end
+
+ test ".watch_command" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.watch_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-w")
+ refute_includes(actual, "-p")
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.watch_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-w")
+ 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)
+ assert_includes(actual, "-w")
+ assert_includes(actual, "always")
+ end
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index da96cabe..68614219 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -4,10 +4,22 @@
require "rails"
require "rails/test_help"
require "debug"
-require_relative "../lib/tailwindcss-rails"
require "rails/test_unit/reporter"
Rails::TestUnitReporter.executable = "bin/test"
+TAILWINDCSS_TEST_APP_ROOT = Dir.mktmpdir
+Rails::Generators.templates_path << File.join(TAILWINDCSS_TEST_APP_ROOT, "lib/templates")
+
class ActiveSupport::TestCase
+ def setup
+ FileUtils.rm_rf(TAILWINDCSS_TEST_APP_ROOT)
+ FileUtils.mkdir_p(TAILWINDCSS_TEST_APP_ROOT)
+ end
+
+ def teardown
+ FileUtils.rm_rf(TAILWINDCSS_TEST_APP_ROOT)
+ end
end
+
+require_relative "../lib/tailwindcss-rails"