Skip to content

Commit 0fe7243

Browse files
committed
Removed Tailwind CSS 3.x support.
1 parent 07c5523 commit 0fe7243

File tree

12 files changed

+183
-345
lines changed

12 files changed

+183
-345
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## 4.2.0
4+
5+
> [!WARNING]
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+
> it is not recommended to use it for new projects.
9+
10+
- Default fallback version is now 4.1.3.
11+
- 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.
12+
313
## 4.1.0
414

515
- TAILWIND_CLI_VERSION defaults to "latest" now. In case it is set to this value,

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
[![Downloads](https://static.pepy.tech/badge/django-tailwind-cli)](https://pepy.tech/project/django-tailwind-cli)
1111
[![Downloads / Month](https://pepy.tech/badge/django-tailwind-cli/month)](<https://pepy.tech/project/django-tailwind-cli>)
1212

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 supported Tailwind CSS 3.x, but
16+
> it is not recommended to use it for new projects.
17+
1318
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).
1419

1520
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.

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
mkdocs-material
2+
markdown-callouts

docs/settings.md

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ your project.
2121

2222
For example:
2323
```python
24-
TAILWIND_CLI_VERSION = "3.4.17"
24+
TAILWIND_CLI_VERSION = "4.1.3"
2525
```
2626

2727
`TAILWIND_CLI_PATH`
@@ -73,12 +73,7 @@ your project.
7373
Enable or disable the automatic downloading of the official CLI to your machine.
7474

7575
`TAILWIND_CLI_SRC_CSS`
76-
: **Default** (for Tailwind 3.x): `None`<br>**Default** (for Tailwind 4.x): `css/source.css`
77-
78-
!!! warning
79-
This setting is optional for Tailwind CSS 3.x. For Tailwind CSS 4.x it must not be empty.
80-
81-
For **Tailwind CSS 3.x** this optional file is used to define addition CSS rules for your project.
76+
**Default** (for Tailwind 4.x): `css/source.css`
8277

8378
For **Tailwind CSS 4.x** this required file is used to configure Tailwind CSS and also add
8479
additional CSS rules for your project. This file is stored relative to the first element of
@@ -89,44 +84,3 @@ your project.
8984

9085
The name of the output file. This file is stored relative to the first element of the
9186
`STATICFILES_DIRS` array.
92-
93-
`TAILWIND_CLI_CONFIG_FILE`
94-
: **Default**: `"tailwind.config.js"`
95-
96-
!!! danger
97-
98-
Is only required for Tailwind CSS 3.x. If you use it with Tailwind CSS 4.x, it is ignored
99-
and also raises an exception to force you to remove it.
100-
101-
The name of the Tailwind CLI config file. The file is stored relative to the `BASE_DIR` defined
102-
in your settings.
103-
104-
## `tailwind.config.js` (Tailwind CSS 3.x only)
105-
106-
If you don't create a `tailwind.config.js` file yourself, the management commands will create a sane default for you inside the `BASE_DIR` of your project. The default activates all the official plugins for Tailwind CSS and adds a minimal plugin to support some variants for [HTMX](https://htmx.org/).
107-
108-
### Default version
109-
110-
```javascript title="tailwind.config.js"
111-
/** @type {import('tailwindcss').Config} */
112-
const plugin = require("tailwindcss/plugin");
113-
114-
module.exports = {
115-
content: ["./templates/**/*.html", "**/templates/**/*.html", '**/*.py'],
116-
theme: {
117-
extend: {},
118-
},
119-
plugins: [
120-
require("@tailwindcss/typography"),
121-
require("@tailwindcss/forms"),
122-
require("@tailwindcss/aspect-ratio"),
123-
require("@tailwindcss/container-queries"),
124-
plugin(function ({ addVariant }) {
125-
addVariant("htmx-settling", ["&.htmx-settling", ".htmx-settling &"]);
126-
addVariant("htmx-request", ["&.htmx-request", ".htmx-request &"]);
127-
addVariant("htmx-swapping", ["&.htmx-swapping", ".htmx-swapping &"]);
128-
addVariant("htmx-added", ["&.htmx-added", ".htmx-added &"]);
129-
}),
130-
],
131-
};
132-
```

docs/usage.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ hide:
99

1010
**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.
1111

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-
1612
!!! question "Do I have to create my own `css/source.css` for Tailwind 4.x?"
1713

1814
**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.

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ VENV_DIRNAME := ".venv"
4141

4242
# serve docs during development
4343
@serve-docs: check_uv
44-
uvx --with mkdocs-material mkdocs serve
44+
uvx --with markdown-callouts --with mkdocs-material mkdocs serve

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ markdown_extensions:
4242
- footnotes
4343
- tables
4444
- sane_lists
45+
- github-callouts
4546
- pymdownx.snippets:
4647
check_paths: true
4748
extra:

src/django_tailwind_cli/config.py

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.conf import settings
99
from semver import Version
1010

11-
FALLBACK_VERSION = "4.0.6"
11+
FALLBACK_VERSION = "4.1.3"
1212

1313

1414
@dataclass
@@ -20,7 +20,6 @@ class Config:
2020
dist_css: Path
2121
dist_css_base: str
2222
src_css: Optional[Path]
23-
config_file: Optional[Path]
2423
automatic_download: bool = True
2524

2625
@property
@@ -46,9 +45,6 @@ def build_cmd(self) -> list[str]:
4645
"--minify",
4746
]
4847

49-
if self.config_file:
50-
result.extend(["--config", str(self.config_file)])
51-
5248
if self.src_css:
5349
result.extend(["--input", str(self.src_css)])
5450

@@ -68,18 +64,27 @@ def get_version() -> tuple[str, Version]:
6864
"latest".
6965
"""
7066
version_str = getattr(settings, "TAILWIND_CLI_VERSION", "latest")
67+
repo_url = getattr(settings, "TAILWIND_CLI_SRC_REPO", "tailwindlabs/tailwindcss")
68+
if not repo_url:
69+
raise ValueError("TAILWIND_CLI_SRC_REPO must not be None.")
7170

7271
if version_str == "latest":
73-
repo_url = getattr(settings, "TAILWIND_CLI_SRC_REPO", "tailwindlabs/tailwindcss")
74-
if not repo_url:
75-
raise ValueError("TAILWIND_CLI_SRC_REPO must not be None.")
7672
r = requests.get(f"https://github.com/{repo_url}/releases/latest/", timeout=2)
73+
print(r.headers)
7774
if r.ok and "location" in r.headers:
7875
version_str = r.headers["location"].rstrip("/").split("/")[-1].replace("v", "")
76+
return version_str, Version.parse(version_str)
7977
else:
80-
version_str = FALLBACK_VERSION
81-
82-
return version_str, Version.parse(version_str)
78+
return FALLBACK_VERSION, Version.parse(FALLBACK_VERSION)
79+
elif repo_url == "tailwindlabs/tailwindcss":
80+
version = Version.parse(version_str)
81+
if version.major < 4:
82+
raise ValueError(
83+
"Tailwind CSS 3.x is not supported by this version. Use version 2.21.1 if you want to use Tailwind 3."
84+
)
85+
return version_str, version
86+
else:
87+
return version_str, Version.parse(version_str)
8388

8489

8590
def get_config() -> Config:
@@ -124,27 +129,9 @@ def get_config() -> Config:
124129
dist_css = Path(settings.STATICFILES_DIRS[0]) / dist_css_base
125130

126131
# Determine the full path to the source css file.
127-
# It is optional for Tailwind CSS < 4.0.0, but required for >= 4.0.0.
128-
if version >= Version.parse("4.0.0"):
129-
if not (src_css := getattr(settings, "TAILWIND_CLI_SRC_CSS", "css/source.css")):
130-
raise ValueError("TAILWIND_CLI_SRC_CSS must not be None.")
131-
src_css = Path(settings.STATICFILES_DIRS[0]) / src_css
132-
else:
133-
if not (src_css := getattr(settings, "TAILWIND_CLI_SRC_CSS", None)):
134-
src_css = None
135-
else:
136-
src_css = Path(settings.STATICFILES_DIRS[0]) / src_css
137-
138-
# Determine the full path to the config file.
139-
# It is optional for Tailwind CSS >= 4.0.0, but required for < 4.0.0.
140-
if version < Version.parse("4.0.0"):
141-
if not (config_file := getattr(settings, "TAILWIND_CLI_CONFIG_FILE", "tailwind.config.js")):
142-
raise ValueError("TAILWIND_CLI_CONFIG_FILE must not be None.")
143-
config_file = Path(settings.BASE_DIR) / config_file
144-
else:
145-
if config_file := getattr(settings, "TAILWIND_CLI_CONFIG_FILE", None):
146-
raise ValueError("TAILWIND_CLI_CONFIG_FILE is not used by this library with Tailwind CSS >= 4.x.")
147-
config_file = None
132+
if not (src_css := getattr(settings, "TAILWIND_CLI_SRC_CSS", "css/source.css")):
133+
raise ValueError("TAILWIND_CLI_SRC_CSS must not be None.")
134+
src_css = Path(settings.STATICFILES_DIRS[0]) / src_css
148135

149136
# Determine if the CLI should be downloaded automatically
150137
automatic_download = getattr(settings, "TAILWIND_CLI_AUTOMATIC_DOWNLOAD", True)
@@ -158,6 +145,5 @@ def get_config() -> Config:
158145
dist_css=dist_css,
159146
dist_css_base=dist_css_base,
160147
src_css=src_css,
161-
config_file=config_file,
162148
automatic_download=automatic_download,
163149
)

src/django_tailwind_cli/management/commands/tailwind.py

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,14 @@ def build() -> None:
2929

3030
try:
3131
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)
3233
except KeyboardInterrupt:
3334
typer.secho("Canceled building production stylesheet.", fg=typer.colors.RED)
34-
return
35-
except subprocess.CalledProcessError as e: # pragma: no cover
36-
typer.secho(
37-
f"Failed to build production stylesheet: {e.stderr}",
38-
fg=typer.colors.RED,
39-
)
35+
except subprocess.CalledProcessError as e:
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)
4038
sys.exit(1)
4139

42-
typer.secho(
43-
f"Built production stylesheet '{config.dist_css}'.",
44-
fg=typer.colors.GREEN,
45-
)
46-
4740

4841
@app.command()
4942
def watch():
@@ -57,10 +50,8 @@ def watch():
5750
except KeyboardInterrupt:
5851
typer.secho("Stopped watching for changes.", fg=typer.colors.RED)
5952
except subprocess.CalledProcessError as e: # pragma: no cover
60-
typer.secho(
61-
f"Failed to start in watch mode: {e.stderr.decode()}",
62-
fg=typer.colors.RED,
63-
)
53+
typer.secho(f"Failed to start in watch mode: {e.stderr.decode()}", fg=typer.colors.RED)
54+
sys.exit(1)
6455

6556

6657
@app.command(name="list_templates")
@@ -287,52 +278,20 @@ def _download_cli(*, force_download: bool = False) -> None:
287278
typer.secho(f"Downloaded Tailwind CSS CLI to '{c.cli_path}'.", fg=typer.colors.GREEN)
288279

289280

290-
DEFAULT_TAILWIND_CONFIG = """/** @type {import('tailwindcss').Config} */
291-
const plugin = require("tailwindcss/plugin");
292-
293-
module.exports = {
294-
content: ["./templates/**/*.html", "**/templates/**/*.html",'**/*.py'],
295-
theme: {
296-
extend: {},
297-
},
298-
plugins: [
299-
require("@tailwindcss/typography"),
300-
require("@tailwindcss/forms"),
301-
require("@tailwindcss/aspect-ratio"),
302-
require("@tailwindcss/container-queries"),
303-
plugin(function ({ addVariant }) {
304-
addVariant("htmx-settling", ["&.htmx-settling", ".htmx-settling &"]);
305-
addVariant("htmx-request", ["&.htmx-request", ".htmx-request &"]);
306-
addVariant("htmx-swapping", ["&.htmx-swapping", ".htmx-swapping &"]);
307-
addVariant("htmx-added", ["&.htmx-added", ".htmx-added &"]);
308-
}),
309-
],
310-
};
311-
"""
312-
313281
DEFAULT_SOURCE_CSS = '@import "tailwindcss";\n'
314282

315283

316284
def _create_standard_config() -> None:
317285
"""Create a standard Tailwind CSS config file."""
318286
c = get_config()
319287

320-
if c.version.major >= 4:
321-
if c.src_css and not c.src_css.exists():
322-
c.src_css.parent.mkdir(parents=True, exist_ok=True)
323-
c.src_css.write_text(DEFAULT_SOURCE_CSS)
324-
typer.secho(
325-
f"Created Tailwind Source CSS at '{c.src_css}'",
326-
fg=typer.colors.GREEN,
327-
)
328-
else:
329-
if c.config_file and not c.config_file.exists():
330-
c.config_file.parent.mkdir(parents=True, exist_ok=True)
331-
c.config_file.write_text(DEFAULT_TAILWIND_CONFIG)
332-
typer.secho(
333-
f"Created Tailwind CSS config at '{c.config_file}'",
334-
fg=typer.colors.GREEN,
335-
)
288+
if c.src_css and not c.src_css.exists():
289+
c.src_css.parent.mkdir(parents=True, exist_ok=True)
290+
c.src_css.write_text(DEFAULT_SOURCE_CSS)
291+
typer.secho(
292+
f"Created Tailwind Source CSS at '{c.src_css}'",
293+
fg=typer.colors.GREEN,
294+
)
336295

337296

338297
def get_runserver_options(

0 commit comments

Comments
 (0)