django-tailwind-cli 4.1.0__tar.gz → 4.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.pre-commit-config.yaml +8 -3
  2. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/CHANGELOG.md +29 -0
  3. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/PKG-INFO +11 -3
  4. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/README.md +9 -2
  5. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/installation.md +0 -9
  6. django_tailwind_cli-4.2.0/docs/requirements.txt +2 -0
  7. django_tailwind_cli-4.2.0/docs/settings.md +101 -0
  8. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/usage.md +32 -4
  9. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/justfile +1 -1
  10. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/mkdocs.yml +1 -0
  11. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/pyproject.toml +4 -3
  12. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/config.py +55 -41
  13. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/management/commands/tailwind.py +18 -53
  14. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/test_config.py +62 -94
  15. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/test_management_commands.py +15 -31
  16. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tox.ini +1 -1
  17. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/uv.lock +122 -109
  18. django_tailwind_cli-4.1.0/docs/requirements.txt +0 -1
  19. django_tailwind_cli-4.1.0/docs/settings.md +0 -132
  20. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.github/dependabot.yml +0 -0
  21. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.github/workflows/release.yml +0 -0
  22. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.github/workflows/test.yml +0 -0
  23. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.gitignore +0 -0
  24. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/.readthedocs.yml +0 -0
  25. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/CODE_OF_CONDUCT.md +0 -0
  26. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/LICENSE +0 -0
  27. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/base_template.md +0 -0
  28. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/changelog.md +0 -0
  29. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/index.md +0 -0
  30. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/docs/template_tags.md +0 -0
  31. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/__init__.py +0 -0
  32. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/apps.py +0 -0
  33. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/management/__init__.py +0 -0
  34. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/management/commands/__init__.py +0 -0
  35. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/py.typed +0 -0
  36. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/templates/tailwind_cli/base.html +0 -0
  37. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/templates/tailwind_cli/tailwind_css.html +0 -0
  38. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/templatetags/__init__.py +0 -0
  39. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/src/django_tailwind_cli/templatetags/tailwind_cli.py +0 -0
  40. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/.gitignore +0 -0
  41. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/__init__.py +0 -0
  42. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/assets/css/.gitkeep +0 -0
  43. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/assets/css/tailwind.css +0 -0
  44. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/conftest.py +0 -0
  45. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/settings.py +0 -0
  46. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/templates/tests/base.html +0 -0
  47. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/templates/tests/dummy.email +0 -0
  48. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/test_get_runserver_options.py +0 -0
  49. {django_tailwind_cli-4.1.0 → django_tailwind_cli-4.2.0}/tests/test_tailwind_css_tag.py +0 -0
@@ -16,19 +16,19 @@ repos:
16
16
  - id: check-json
17
17
 
18
18
  - repo: https://github.com/charliermarsh/ruff-pre-commit
19
- rev: "v0.7.4"
19
+ rev: "v0.11.2"
20
20
  hooks:
21
21
  - id: ruff
22
22
  - id: ruff-format
23
23
 
24
24
  - repo: https://github.com/asottile/pyupgrade
25
- rev: v3.19.0
25
+ rev: v3.19.1
26
26
  hooks:
27
27
  - id: pyupgrade
28
28
  args: [--py39-plus]
29
29
 
30
30
  - repo: https://github.com/adamchainz/django-upgrade
31
- rev: "1.22.1"
31
+ rev: "1.23.1"
32
32
  hooks:
33
33
  - id: django-upgrade
34
34
  args: [--target-version, "4.2"]
@@ -38,3 +38,8 @@ repos:
38
38
  hooks:
39
39
  - id: djade
40
40
  args: [--target-version, "4.2"]
41
+
42
+ - repo: https://github.com/owenlamont/uv-secure
43
+ rev: 0.9.0
44
+ hooks:
45
+ - id: uv-secure
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.2.0 (Unreleased)
4
+
5
+ > [!CAUTION]
6
+ > Version 4.2.x and onward only support Tailwind CSS 4.x. If you are using Tailwind CSS 3.x,
7
+ > please use version 2.21.1 of this library. Version 4.0.x or 4.1.x still support Tailwind CSS 3.x, but
8
+ > these versions are not recommended to use for new projects.
9
+
10
+ > [!CAUTION]
11
+ > This version includes changes to the handling of `TAILWIND_CLI_PATH` and `TAILWIND_CLI_SRC_CSS`.
12
+
13
+ - Default fallback version is now 4.1.3.
14
+ - Removed support for Tailwind CSS 3.x. The main reason is that this makes the library easier to maintain and also add better support for custom CLI builds which support DaisyUI and other plugins.
15
+ - django-tailwind-cli now uses proper platform directories to store the CLI binary.
16
+
17
+ * The proper directories are powered by [platformdirs](https://pypi.org/project/platformdirs/).
18
+ * `TAILWIND_CLI_PATH` is now optional by default.
19
+ * If `TAILWIND_CLI_PATH` is None, the binary is stored in `user_data_dir("django-tailwind-cli", "django-commons")`.
20
+ * The library doesn't rely anylonger on a properly set `settings.BASE_DIR`.
21
+
22
+ - `TAILWIND_CLI_ASSET_NAME` is also used for the downloaded CLI to distinguish between `tailwindcss` and `tailwindcss-extra`.
23
+ - The behaviour of `TAILWIND_CLI_SRC_CSS` has been changed. The reasoning behind this change was, less default code inside the project and whitenoise had issues with a CSS file inside an asset folder referencing non-existing imports.
24
+
25
+ * It defaults to `None`.
26
+ * If it is `None` the default input file is created in the user cache directory.
27
+ * If it is a relative path, this path is considered relative to `settings.BASE_DIR`.
28
+ * The last option is an absolute path.
29
+
30
+ - Proper daisyUI support using [tailwind-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra).
31
+
3
32
  ## 4.1.0
4
33
 
5
34
  - TAILWIND_CLI_VERSION defaults to "latest" now. In case it is set to this value,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-tailwind-cli
3
- Version: 4.1.0
3
+ Version: 4.2.0
4
4
  Summary: Django and Tailwind integration based on the prebuilt Tailwind CSS CLI.
5
5
  Project-URL: Home, https://django-tailwind-cli.rtfd.io/
6
6
  Project-URL: Documentation, https://django-tailwind-cli.rtfd.io/
@@ -47,6 +47,7 @@ Classifier: Topic :: Utilities
47
47
  Requires-Python: >=3.9
48
48
  Requires-Dist: django-typer>=2.1.2
49
49
  Requires-Dist: django>=4.0
50
+ Requires-Dist: platformdirs>=4.3.7
50
51
  Requires-Dist: requests>=2.32.3
51
52
  Requires-Dist: semver>=3.0.4
52
53
  Provides-Extra: django-extensions
@@ -66,6 +67,11 @@ Description-Content-Type: text/markdown
66
67
  [![Downloads](https://static.pepy.tech/badge/django-tailwind-cli)](https://pepy.tech/project/django-tailwind-cli)
67
68
  [![Downloads / Month](https://pepy.tech/badge/django-tailwind-cli/month)](<https://pepy.tech/project/django-tailwind-cli>)
68
69
 
70
+ > [!WARNING]
71
+ > Version 4.2.x and onward only support Tailwind CSS 4.x. If you are using Tailwind CSS 3.x,
72
+ > please use version 2.21.1 of this library. Version 4.0.x or 4.1.x still support Tailwind CSS 3.x, but
73
+ > these versions are not recommended to use for new projects.
74
+
69
75
  This library provides an integration of [Tailwind CSS](https://tailwindcss.com) for Django that is using on the precompiled versions of the [Tailwind CSS CLI](https://tailwindcss.com/blog/standalone-cli).
70
76
 
71
77
  The goal of this library is to provided the simplest possible Tailwind integration for your Django project. It took its inspiration from the [Tailwind integration for Phoenix](https://github.com/phoenixframework/tailwind) which completely skips the neccesity of a node installation.
@@ -120,7 +126,9 @@ if you want to activate browser reload or the `runserver_plus` management comman
120
126
  ## Features
121
127
 
122
128
  - Simplest possible integration.
123
- - Support Tailwind CSS 3.x and 4.x. Check the [update instructions](https://django-tailwind-cli.rtfd.io/latest/installation/#upgrade-from-tailwind-css-3x-to-4x).
129
+ - Support Tailwind CSS 4.x.
130
+ - Proper support for DaisyUI via [tailwindcss-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra). Settings are described in the [usage guide](https://django-tailwind-cli.readthedocs.io/latest/usage/#use-with-daisyui).
131
+ - Or bring your own version of Tailwind CSS CLI.
124
132
  - Management commands:
125
133
 
126
134
  * To start the Tailwind CLI in watch mode during development.
@@ -130,7 +138,7 @@ if you want to activate browser reload or the `runserver_plus` management comman
130
138
  - Configuration options to adapt the library to your project, when the defaults don't fit you.
131
139
  - A template tag to include the Tailwind CSS file in your project.
132
140
  - A base template for your project.
133
- - Sane default configurations for Tailwind 3.x and Tailwinc 4.x.
141
+ - Sane default configurations for Tailwinc 4.x.
134
142
 
135
143
  ## Requirements
136
144
 
@@ -10,6 +10,11 @@
10
10
  [![Downloads](https://static.pepy.tech/badge/django-tailwind-cli)](https://pepy.tech/project/django-tailwind-cli)
11
11
  [![Downloads / Month](https://pepy.tech/badge/django-tailwind-cli/month)](<https://pepy.tech/project/django-tailwind-cli>)
12
12
 
13
+ > [!WARNING]
14
+ > Version 4.2.x and onward only support Tailwind CSS 4.x. If you are using Tailwind CSS 3.x,
15
+ > please use version 2.21.1 of this library. Version 4.0.x or 4.1.x still support Tailwind CSS 3.x, but
16
+ > these versions are not recommended to use for new projects.
17
+
13
18
  This library provides an integration of [Tailwind CSS](https://tailwindcss.com) for Django that is using on the precompiled versions of the [Tailwind CSS CLI](https://tailwindcss.com/blog/standalone-cli).
14
19
 
15
20
  The goal of this library is to provided the simplest possible Tailwind integration for your Django project. It took its inspiration from the [Tailwind integration for Phoenix](https://github.com/phoenixframework/tailwind) which completely skips the neccesity of a node installation.
@@ -64,7 +69,9 @@ if you want to activate browser reload or the `runserver_plus` management comman
64
69
  ## Features
65
70
 
66
71
  - Simplest possible integration.
67
- - Support Tailwind CSS 3.x and 4.x. Check the [update instructions](https://django-tailwind-cli.rtfd.io/latest/installation/#upgrade-from-tailwind-css-3x-to-4x).
72
+ - Support Tailwind CSS 4.x.
73
+ - Proper support for DaisyUI via [tailwindcss-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra). Settings are described in the [usage guide](https://django-tailwind-cli.readthedocs.io/latest/usage/#use-with-daisyui).
74
+ - Or bring your own version of Tailwind CSS CLI.
68
75
  - Management commands:
69
76
 
70
77
  * To start the Tailwind CLI in watch mode during development.
@@ -74,7 +81,7 @@ if you want to activate browser reload or the `runserver_plus` management comman
74
81
  - Configuration options to adapt the library to your project, when the defaults don't fit you.
75
82
  - A template tag to include the Tailwind CSS file in your project.
76
83
  - A base template for your project.
77
- - Sane default configurations for Tailwind 3.x and Tailwinc 4.x.
84
+ - Sane default configurations for Tailwinc 4.x.
78
85
 
79
86
  ## Requirements
80
87
 
@@ -120,12 +120,3 @@ If you enjoy automatic reloading during development. Install the [django-browser
120
120
  The middleware should be listed after any that encodes the response, such as Django’s GZipMiddleware.
121
121
 
122
122
  The middleware automatically inserts the required script tag on HTML responses before </body> when DEBUG is True. It does so to every HTML response, meaning it will be included on Django’s debug pages, admin pages, etc. If you want more control, you can instead insert the script tag in your templates—see below.
123
-
124
- ## Upgrade from Tailwind CSS 3.x to 4.x
125
-
126
- In order to upgrade this package from using Tailwind CSS 3.x to 4.x, you have to follow some simple
127
- steps.
128
-
129
- - Remove or change the setting `TAILWIND_CLI_VERSION` if it is set.
130
- - Remove the setting `TAILWIND_CLI_CONFIG_FILE` if it is set.
131
- - Remove the `tailwind.config.js` from your project.
@@ -0,0 +1,2 @@
1
+ mkdocs-material
2
+ markdown-callouts
@@ -0,0 +1,101 @@
1
+ ---
2
+ hide:
3
+ - navigation
4
+ ---
5
+
6
+ # Settings & Configuration
7
+
8
+ ## Settings
9
+
10
+ The package can be configured by a few settings, which can be overwritten in the `settings.py` of
11
+ your project.
12
+
13
+ `TAILWIND_CLI_VERSION`
14
+ : **Default**: `"latest"`
15
+
16
+ This defines the version of the CLI and of Tailwind CSS you want to use in your project.
17
+
18
+ If it is set to `latest`, the management commands try to determine the most recent version of Tailwind CSS by placing a request to GitHub and parse the location header of the redirect. If this is not possible a fallback version is used. This version is defined in the module `django_tailwind_cli.config`.
19
+
20
+ If you want to pinpoint your setup to certain version of Tailwind CSS, then you can set `TAILWIND_CLI_VERSION`to a fixed version number.
21
+
22
+ For example:
23
+ ```python
24
+ TAILWIND_CLI_VERSION = "4.1.0"
25
+ ```
26
+
27
+ `TAILWIND_CLI_PATH`
28
+ : **Default**: `None`
29
+
30
+ This allows you to override the default of the library where to store the CLI binary.
31
+
32
+ The default behaviour is to store the CLI binary in the directory returned by this call `platformdirs.user_data_dir("django-tailwind-cli", "django-commons")`. Checkout [platformdirs](https://pypi.org/project/platformdirs/) for details.
33
+
34
+ But if you want to store it elsewhere or plan to use a custom build binary stored locally, change this setting either to a path to a directory or the full path to the binary. If it points to a directory, this is the download destination otherwise it directly tries to use the referenced binary.
35
+
36
+ > [!Warning]
37
+ > If you use the new option from **2.7.0** but haven't installed a binary before running any of the management commands, these commands will treat the configured path as a directory and create it, if it is missing. Afterwards the official CLI will be downloaded to this path.
38
+ >
39
+ > In case you want to use the new behaviour, it is highly recommended to also set the new setting `TAILWIND_CLI_AUTOMATIC_DOWNLOAD` to `False`.
40
+
41
+ `TAILWIND_CLI_AUTOMATIC_DOWNLOAD`
42
+ : **Default**: `True`
43
+
44
+ Enable or disable the automatic downloading of the official CLI to your machine.
45
+
46
+ `TAILWIND_CLI_SRC_REPO`
47
+ : **Default**: `"tailwindlabs/tailwindcss"`
48
+
49
+ Specifies the repository from which the CLI is downloaded. This is useful if you are using a customized version of the CLI, such as [tailwind-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra).
50
+
51
+ > [!Warning]
52
+ > If you use this option, ensure that you update the `TAILWIND_CLI_VERSION` to match the version of the customized CLI you are using. Additionally, you may need to update the `TAILWIND_CLI_ASSET_NAME` if the asset name is different. See the example below.
53
+
54
+ `TAILWIND_CLI_ASSET_NAME`:
55
+ : **Default**: `"tailwindcss"`
56
+
57
+ Specifies the name of the asset to download from the repository.
58
+
59
+ This option is particularly useful if the customized repository you are using has a different name for the Tailwind CLI asset. For example, the asset name for [tailwind-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra/releases/latest/) is `tailwindcss-extra`.
60
+
61
+ > [!Note]
62
+ > Here is a full example of using a custom repository and asset name:
63
+ > ```python
64
+ > TAILWIND_CLI_SRC_REPO = "dobicinaitis/tailwind-cli-extra"
65
+ > TAILWIND_CLI_ASSET_NAME = "tailwindcss-extra"
66
+ > ```
67
+
68
+ `TAILWIND_CLI_SRC_CSS`
69
+ **Default**: `None`
70
+
71
+ This variable can be set to `None`, a relative path and an absolute path.
72
+
73
+ If it is set to `None`, the library creates file with the name `source.css` in the directory returned by this call `platformdirs.user_cache_dir("django-tailwind-cli", "django-commons")`. Checkout [platformdirs](https://pypi.org/project/platformdirs/) for details.
74
+
75
+ If it is a relative path it is assumed to be relative to `settings.BASE_DIR`. If `settings.BASE_DIR` is not defined or the file doesn't exist a `ValueError` is raised.
76
+
77
+ If it is an absolute path, this path is used as the input file for Tailwind CSS CLI. If the path doesn't exist, a `ValueError`is raised.
78
+
79
+ `TAILWIND_CLI_DIST_CSS`
80
+ : **Default**: `"css/tailwind.css"`
81
+
82
+ The name of the output file. This file is stored relative to the first element of the
83
+ `STATICFILES_DIRS` array.
84
+
85
+ `TAILWIND_CLI_USE_DAISY_UI`:
86
+ : **Default**: `False`
87
+
88
+ This switch determines what content is written to `TAILWIND_CLI_SRC_CSS` if it is automatically created by the library.
89
+
90
+ The default is:
91
+ ```css
92
+ @import "tailwindcss";
93
+ ```
94
+
95
+ If `TAILWIND_CLI_USE_DAISY_UI = True` is put into the `settings.py` of your project, this is the output:
96
+ ```css
97
+ @import "tailwindcss";
98
+ @plugin "daisyui";
99
+ ```
100
+
101
+ This switch can also be used as a shortcut to activate daisyUI and change `TAILWIND_CLI_SRC_REPO` and `TAILWIND_CLI_ASSET_NAME` as described above to fetch [tailwind-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra/releases/latest/).
@@ -9,10 +9,6 @@ hide:
9
9
 
10
10
  **No.** The management commands of this library handle the download and installation of the Tailwind CLI. You don't have to deal with this. But you can configure the installation location and the version of the CLI you want to use. Take a look at the [settings](settings.md) section.
11
11
 
12
- !!! question "Do I have to create my own `tailwind.config.js` for Tailwind 3.x?"
13
-
14
- **No.** The management commands also take care of this step. If no `tailwind.config.js` is present in your project, a new one with sane defaults will be created. Afterwards this file will be used and be customized by you. The default location for the file is the `BASE_DIR` of your project, but you can change this. Take a look at the [settings](settings.md) section.
15
-
16
12
  !!! question "Do I have to create my own `css/source.css` for Tailwind 4.x?"
17
13
 
18
14
  **No.** The management commands also take care of this step. If no `css/source.css` is present in your project, a new one with sane defaults will be created. Afterwards this file will be used and be customized by you. The default location for the file is first folder from the `STATICFILES_DIRS` of your project, but you can change this. Take a look at the [settings](settings.md) section.
@@ -106,3 +102,35 @@ tailwind-sidecar:
106
102
  command: python manage.py tailwind watch
107
103
  tty: true
108
104
  ```
105
+
106
+ ## Use with daisyUI
107
+
108
+ If you plan to use [daisyUI](https://daisyui.com), there is an easy way to solve this with this library.
109
+
110
+ ```python
111
+ TAILWIND_CLI_USE_DAISY_UI = True
112
+ ```
113
+
114
+ Setting this, the library switches from using the default TailwindCSS CLI to the one provided by [Andris Dobičinaitis](https://github.com/dobicinaitis) and his [tailwind-cli-extra](https://github.com/dobicinaitis/tailwind-cli-extra) project. It also causes the library to create a proper default config that activates the daisyUI plugin.
115
+
116
+ But of course you can do it manually, too. Just configure a repository where the library should pull the CLI from and activate the daisyUI support.
117
+
118
+ ```python
119
+ TAILWIND_CLI_SRC_REPO = "dobicinaitis/tailwind-cli-extra"
120
+ TAILWIND_CLI_ASSET_NAME = "tailwindcss-extra"
121
+ TAILWIND_CLI_USE_DAISY_UI = True
122
+ ```
123
+
124
+ Or provide your custom configuration, too.
125
+
126
+ ```python
127
+ TAILWIND_CLI_SRC_REPO = "dobicinaitis/tailwind-cli-extra"
128
+ TAILWIND_CLI_ASSET_NAME = "tailwindcss-extra"
129
+ TAILWIND_CLI_SRC_CSS = "etc/source.css"
130
+ ```
131
+
132
+ ## Use with WhiteNoise
133
+
134
+ If you are using [WhiteNoise](https://whitenoise.readthedocs.io/en/latest/) to serve your static assets, you must not put your custom Tailwind configuration file inside any of the directories for static files. WhiteNoise stumbles across the `@import "tailwindcss";` statement, because it can't resolve it.
135
+
136
+ If you want to use a custom configuration for Tailwind CSS, put it somewhere else in the project.
@@ -41,4 +41,4 @@ VENV_DIRNAME := ".venv"
41
41
 
42
42
  # serve docs during development
43
43
  @serve-docs: check_uv
44
- uvx --with mkdocs-material mkdocs serve
44
+ uvx --with markdown-callouts --with mkdocs-material mkdocs serve
@@ -42,6 +42,7 @@ markdown_extensions:
42
42
  - footnotes
43
43
  - tables
44
44
  - sane_lists
45
+ - github-callouts
45
46
  - pymdownx.snippets:
46
47
  check_paths: true
47
48
  extra:
@@ -30,6 +30,7 @@ requires-python = ">=3.9"
30
30
  dependencies = [
31
31
  "django>=4.0",
32
32
  "django-typer>=2.1.2",
33
+ "platformdirs>=4.3.7",
33
34
  "requests>=2.32.3",
34
35
  "semver>=3.0.4",
35
36
  ]
@@ -77,7 +78,7 @@ strict_settings = false
77
78
 
78
79
  # Ruff
79
80
  [tool.ruff]
80
- target-version = "py38"
81
+ target-version = "py39"
81
82
  line-length = 120
82
83
 
83
84
  [tool.ruff.format]
@@ -115,13 +116,13 @@ unfixable = [
115
116
  ]
116
117
 
117
118
  [tool.ruff.lint.isort]
118
- known-first-party = ["solomon"]
119
+ known-first-party = ["django_tailwind_cli"]
119
120
 
120
121
  [tool.ruff.lint.flake8-tidy-imports]
121
122
  ban-relative-imports = "all"
122
123
 
123
124
  [tool.ruff.lint.per-file-ignores]
124
- "tests/**/*" = ["PLR2004", "S101", "TID252", "ARG001"]
125
+ "tests/**/*" = ["PLR2004", "S101", "TID252", "ARG001", "FBT001"]
125
126
  "tests/snapshots/*" = ["ALL"]
126
127
  "**/migrations/*" = ["ALL"]
127
128
 
@@ -4,11 +4,12 @@ from dataclasses import dataclass
4
4
  from pathlib import Path
5
5
  from typing import Optional
6
6
 
7
+ import platformdirs
7
8
  import requests
8
9
  from django.conf import settings
9
10
  from semver import Version
10
11
 
11
- FALLBACK_VERSION = "4.0.6"
12
+ FALLBACK_VERSION = "4.1.3"
12
13
 
13
14
 
14
15
  @dataclass
@@ -20,35 +21,33 @@ class Config:
20
21
  dist_css: Path
21
22
  dist_css_base: str
22
23
  src_css: Optional[Path]
23
- config_file: Optional[Path]
24
24
  automatic_download: bool = True
25
+ use_daisy_ui: bool = False
25
26
 
26
27
  @property
27
28
  def watch_cmd(self) -> list[str]:
28
29
  result = [
29
30
  str(self.cli_path),
31
+ "--input",
32
+ str(self.src_css),
30
33
  "--output",
31
34
  str(self.dist_css),
32
35
  "--watch",
33
36
  ]
34
37
 
35
- if self.src_css:
36
- result.extend(["--input", str(self.src_css)])
37
-
38
38
  return result
39
39
 
40
40
  @property
41
41
  def build_cmd(self) -> list[str]:
42
42
  result = [
43
43
  str(self.cli_path),
44
+ "--input",
45
+ str(self.src_css),
44
46
  "--output",
45
47
  str(self.dist_css),
46
48
  "--minify",
47
49
  ]
48
50
 
49
- if self.src_css:
50
- result.extend(["--input", str(self.src_css)])
51
-
52
51
  return result
53
52
 
54
53
 
@@ -64,25 +63,41 @@ def get_version() -> tuple[str, Version]:
64
63
  ValueError: If the TAILWIND_CLI_SRC_REPO setting is None when the version is set to
65
64
  "latest".
66
65
  """
66
+ use_daisy_ui = getattr(settings, "TAILWIND_CLI_USE_DAISY_UI", False)
67
67
  version_str = getattr(settings, "TAILWIND_CLI_VERSION", "latest")
68
+ repo_url = getattr(
69
+ settings,
70
+ "TAILWIND_CLI_SRC_REPO",
71
+ "tailwindlabs/tailwindcss" if not use_daisy_ui else "dobicinaitis/tailwind-cli-extra",
72
+ )
73
+ if not repo_url:
74
+ raise ValueError("TAILWIND_CLI_SRC_REPO must not be None.")
68
75
 
69
76
  if version_str == "latest":
70
- repo_url = getattr(settings, "TAILWIND_CLI_SRC_REPO", "tailwindlabs/tailwindcss")
71
- if not repo_url:
72
- raise ValueError("TAILWIND_CLI_SRC_REPO must not be None.")
73
77
  r = requests.get(f"https://github.com/{repo_url}/releases/latest/", timeout=2)
74
78
  if r.ok and "location" in r.headers:
75
79
  version_str = r.headers["location"].rstrip("/").split("/")[-1].replace("v", "")
80
+ return version_str, Version.parse(version_str)
76
81
  else:
77
- version_str = FALLBACK_VERSION
78
-
79
- return version_str, Version.parse(version_str)
82
+ return FALLBACK_VERSION, Version.parse(FALLBACK_VERSION)
83
+ elif repo_url == "tailwindlabs/tailwindcss":
84
+ version = Version.parse(version_str)
85
+ if version.major < 4:
86
+ raise ValueError(
87
+ "Tailwind CSS 3.x is not supported by this version. Use version 2.21.1 if you want to use Tailwind 3."
88
+ )
89
+ return version_str, version
90
+ else:
91
+ return version_str, Version.parse(version_str)
80
92
 
81
93
 
82
94
  def get_config() -> Config:
83
95
  if settings.STATICFILES_DIRS is None or len(settings.STATICFILES_DIRS) == 0:
84
96
  raise ValueError("STATICFILES_DIRS is empty. Please add a path to your static files.")
85
97
 
98
+ # daisyUI support
99
+ use_daisy_ui = getattr(settings, "TAILWIND_CLI_USE_DAISY_UI", False)
100
+
86
101
  # Determine the system and machine we are running on
87
102
  system = platform.system().lower()
88
103
  system = "macos" if system == "darwin" else system
@@ -99,18 +114,30 @@ def get_config() -> Config:
99
114
  # Read version from settings
100
115
  version_str, version = get_version()
101
116
 
117
+ # Determine the asset name
118
+ if not (
119
+ asset_name := getattr(
120
+ settings, "TAILWIND_CLI_ASSET_NAME", "tailwindcss" if not use_daisy_ui else "tailwindcss-extra"
121
+ )
122
+ ):
123
+ raise ValueError("TAILWIND_CLI_ASSET_NAME must not be None.")
124
+
102
125
  # Determine the full path to the CLI
103
- cli_path = Path(getattr(settings, "TAILWIND_CLI_PATH", "~/.local/bin/") or settings.BASE_DIR)
126
+ cli_path = Path(
127
+ getattr(settings, "TAILWIND_CLI_PATH", None)
128
+ or platformdirs.user_data_dir("django-tailwind-cli", "django-commons")
129
+ )
104
130
  if cli_path.exists() and cli_path.is_file() and os.access(cli_path, os.X_OK):
105
131
  cli_path = cli_path.expanduser().resolve()
106
132
  else:
107
- cli_path = cli_path.expanduser() / f"tailwindcss-{system}-{machine}-{version_str}{extension}"
133
+ cli_path = cli_path.expanduser() / f"{asset_name}-{system}-{machine}-{version_str}{extension}"
108
134
 
109
135
  # Determine the download url for the cli
110
- if not (asset_name := getattr(settings, "TAILWIND_CLI_ASSET_NAME", "tailwindcss")):
111
- raise ValueError("TAILWIND_CLI_ASSET_NAME must not be None.")
112
- if not (repo_url := getattr(settings, "TAILWIND_CLI_SRC_REPO", "tailwindlabs/tailwindcss")):
113
- raise ValueError("TAILWIND_CLI_SRC_REPO must not be None.")
136
+ repo_url = getattr(
137
+ settings,
138
+ "TAILWIND_CLI_SRC_REPO",
139
+ "tailwindlabs/tailwindcss" if not use_daisy_ui else "dobicinaitis/tailwind-cli-extra",
140
+ )
114
141
  download_url = (
115
142
  f"https://github.com/{repo_url}/releases/download/v{version_str}/{asset_name}-{system}-{machine}{extension}"
116
143
  )
@@ -121,27 +148,14 @@ def get_config() -> Config:
121
148
  dist_css = Path(settings.STATICFILES_DIRS[0]) / dist_css_base
122
149
 
123
150
  # Determine the full path to the source css file.
124
- # It is optional for Tailwind CSS < 4.0.0, but required for >= 4.0.0.
125
- if version >= Version.parse("4.0.0"):
126
- if not (src_css := getattr(settings, "TAILWIND_CLI_SRC_CSS", "css/source.css")):
127
- raise ValueError("TAILWIND_CLI_SRC_CSS must not be None.")
128
- src_css = Path(settings.STATICFILES_DIRS[0]) / src_css
129
- else:
130
- if not (src_css := getattr(settings, "TAILWIND_CLI_SRC_CSS", None)):
131
- src_css = None
132
- else:
133
- src_css = Path(settings.STATICFILES_DIRS[0]) / src_css
134
-
135
- # Determine the full path to the config file.
136
- # It is optional for Tailwind CSS >= 4.0.0, but required for < 4.0.0.
137
- if version < Version.parse("4.0.0"):
138
- if not (config_file := getattr(settings, "TAILWIND_CLI_CONFIG_FILE", "tailwind.config.js")):
139
- raise ValueError("TAILWIND_CLI_CONFIG_FILE must not be None.")
140
- config_file = Path(settings.BASE_DIR) / config_file
151
+ src_css = getattr(settings, "TAILWIND_CLI_SRC_CSS", None)
152
+ if not src_css:
153
+ user_cache_dir = platformdirs.user_cache_dir("django-tailwind-cli", "django-commons")
154
+ src_css = Path(user_cache_dir) / "source.css"
141
155
  else:
142
- if config_file := getattr(settings, "TAILWIND_CLI_CONFIG_FILE", None):
143
- raise ValueError("TAILWIND_CLI_CONFIG_FILE is not used by this library with Tailwind CSS >= 4.x.")
144
- config_file = None
156
+ src_css = Path(src_css)
157
+ if not src_css.is_absolute():
158
+ src_css = Path(settings.BASE_DIR) / src_css
145
159
 
146
160
  # Determine if the CLI should be downloaded automatically
147
161
  automatic_download = getattr(settings, "TAILWIND_CLI_AUTOMATIC_DOWNLOAD", True)
@@ -155,6 +169,6 @@ def get_config() -> Config:
155
169
  dist_css=dist_css,
156
170
  dist_css_base=dist_css_base,
157
171
  src_css=src_css,
158
- config_file=config_file,
159
172
  automatic_download=automatic_download,
173
+ use_daisy_ui=use_daisy_ui,
160
174
  )
@@ -23,24 +23,19 @@ app = Typer(name="tailwind", help="Create and manage a Tailwind CSS theme.") #
23
23
  @app.command()
24
24
  def build() -> None:
25
25
  """Build a minified production ready CSS file."""
26
- c = get_config()
26
+ config = get_config()
27
27
  _download_cli()
28
28
  _create_standard_config()
29
29
 
30
30
  try:
31
- subprocess.run(c.build_cmd, cwd=settings.BASE_DIR, check=True, capture_output=True)
31
+ subprocess.run(config.build_cmd, cwd=settings.BASE_DIR, check=True, capture_output=True, text=True)
32
+ typer.secho(f"Built production stylesheet '{config.dist_css}'.", fg=typer.colors.GREEN)
32
33
  except KeyboardInterrupt:
33
34
  typer.secho("Canceled building production stylesheet.", fg=typer.colors.RED)
34
35
  except subprocess.CalledProcessError as e: # pragma: no cover
35
- typer.secho(
36
- f"Failed to build production stylesheet: {e.stderr.decode()}",
37
- fg=typer.colors.RED,
38
- )
39
- else:
40
- typer.secho(
41
- f"Built production stylesheet '{c.dist_css}'.",
42
- fg=typer.colors.GREEN,
43
- )
36
+ error_message = e.stderr if e.stderr else "An unknown error occurred."
37
+ typer.secho(f"Failed to build production stylesheet: {error_message}", fg=typer.colors.RED)
38
+ sys.exit(1)
44
39
 
45
40
 
46
41
  @app.command()
@@ -55,10 +50,8 @@ def watch():
55
50
  except KeyboardInterrupt:
56
51
  typer.secho("Stopped watching for changes.", fg=typer.colors.RED)
57
52
  except subprocess.CalledProcessError as e: # pragma: no cover
58
- typer.secho(
59
- f"Failed to start in watch mode: {e.stderr.decode()}",
60
- fg=typer.colors.RED,
61
- )
53
+ typer.secho(f"Failed to start in watch mode: {e.stderr.decode()}", fg=typer.colors.RED)
54
+ sys.exit(1)
62
55
 
63
56
 
64
57
  @app.command(name="list_templates")
@@ -285,52 +278,24 @@ def _download_cli(*, force_download: bool = False) -> None:
285
278
  typer.secho(f"Downloaded Tailwind CSS CLI to '{c.cli_path}'.", fg=typer.colors.GREEN)
286
279
 
287
280
 
288
- DEFAULT_TAILWIND_CONFIG = """/** @type {import('tailwindcss').Config} */
289
- const plugin = require("tailwindcss/plugin");
290
-
291
- module.exports = {
292
- content: ["./templates/**/*.html", "**/templates/**/*.html",'**/*.py'],
293
- theme: {
294
- extend: {},
295
- },
296
- plugins: [
297
- require("@tailwindcss/typography"),
298
- require("@tailwindcss/forms"),
299
- require("@tailwindcss/aspect-ratio"),
300
- require("@tailwindcss/container-queries"),
301
- plugin(function ({ addVariant }) {
302
- addVariant("htmx-settling", ["&.htmx-settling", ".htmx-settling &"]);
303
- addVariant("htmx-request", ["&.htmx-request", ".htmx-request &"]);
304
- addVariant("htmx-swapping", ["&.htmx-swapping", ".htmx-swapping &"]);
305
- addVariant("htmx-added", ["&.htmx-added", ".htmx-added &"]);
306
- }),
307
- ],
308
- };
309
- """
310
-
311
281
  DEFAULT_SOURCE_CSS = '@import "tailwindcss";\n'
282
+ DAISY_UI_SOURCE_CSS = '@import "tailwindcss";\n@plugin "daisyui";\n'
312
283
 
313
284
 
314
285
  def _create_standard_config() -> None:
315
286
  """Create a standard Tailwind CSS config file."""
316
287
  c = get_config()
317
288
 
318
- if c.version.major >= 4:
319
- if c.src_css and not c.src_css.exists():
320
- c.src_css.parent.mkdir(parents=True, exist_ok=True)
289
+ if c.src_css and not c.src_css.exists():
290
+ c.src_css.parent.mkdir(parents=True, exist_ok=True)
291
+ if c.use_daisy_ui:
292
+ c.src_css.write_text(DAISY_UI_SOURCE_CSS)
293
+ else:
321
294
  c.src_css.write_text(DEFAULT_SOURCE_CSS)
322
- typer.secho(
323
- f"Created Tailwind Source CSS at '{c.src_css}'",
324
- fg=typer.colors.GREEN,
325
- )
326
- else:
327
- if c.config_file and not c.config_file.exists():
328
- c.config_file.parent.mkdir(parents=True, exist_ok=True)
329
- c.config_file.write_text(DEFAULT_TAILWIND_CONFIG)
330
- typer.secho(
331
- f"Created Tailwind CSS config at '{c.config_file}'",
332
- fg=typer.colors.GREEN,
333
- )
295
+ typer.secho(
296
+ f"Created Tailwind Source CSS at '{c.src_css}'",
297
+ fg=typer.colors.GREEN,
298
+ )
334
299
 
335
300
 
336
301
  def get_runserver_options(