Skip to content

Commit c79a23c

Browse files
committed
add task to generate the tailwind config safelist
1 parent f0ad74e commit c79a23c

File tree

8 files changed

+178
-26
lines changed

8 files changed

+178
-26
lines changed

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ task --list-all
2222
## Config
2323
For configuration see the `config.toml` passed in as the `--config` flag to app.
2424

25-
> [!TIP]
26-
> Generate new session auth keys ask [ChatGPT](https://chat.openai.com)
27-
>
28-
> "Could you generate random hex keys of 32 bytes and 16 bytes for me?"
29-
3025
create your dev config:
3126
```bash
3227
task setup:config
@@ -91,11 +86,24 @@ curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/t
9186
chmod +x tailwindcss-macos-arm64
9287
mv tailwindcss-macos-arm64 tmp/tailwindcss
9388
```
89+
9490
build and watch:
9591
```bash
9692
task gen:tailwind
9793
```
9894

95+
When content is in the database you will need a safelist of css classes.
96+
To do this there is a query in `pkg/storage/db/sqlc/tailwind.sql`, this returns a unique list
97+
of css classes found in the `page_html.html` field. You can expand this to fit further requirements.
98+
99+
running the following task will rebuild the `tailwind.config.js` file with an updated list of css classes.
100+
```bash
101+
task gen:tailwind-config
102+
```
103+
104+
to expand the config make sure you update the `tailwind.config.js.tmpl` file to include new settings.
105+
With the config rebuilt, re-run the main `gen:tailwind` task.
106+
99107
## Docker
100108
This can be used to build the app as a binary and run it in a container.
101109

Taskfile.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ tasks:
3939
cmds:
4040
- ./tmp/tailwindcss -i {{.CSS_IN}} -o {{.CSS_OUT}} --watch --minify
4141

42+
gen:tailwind-config:
43+
desc: "Generate tailwind config file with a safelist using html content in the database."
44+
cmds:
45+
- go run . tailwind --config {{.CONFIG}}
46+
4247
migrate:add:
4348
desc: "Create a new database migration file."
4449
vars:

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func init() {
3030
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is config.toml)")
3131
rootCmd.AddCommand(cmdServer)
3232
rootCmd.AddCommand(cmdMigrate)
33+
rootCmd.AddCommand(cmdTailwind)
3334
}
3435

3536
func initConfig() {

cmd/tailwind.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"echo.go.dev/pkg/storage/db/dbx"
7+
"fmt"
8+
"github.com/jackc/pgx/v5"
9+
"github.com/spf13/cobra"
10+
"os"
11+
"text/template"
12+
)
13+
14+
var (
15+
tailwindConfigTemplate = "tailwind.config.js.tmpl"
16+
tailwindConfig = "tailwind.config.js"
17+
)
18+
19+
var cmdTailwind = &cobra.Command{
20+
Use: "tailwind",
21+
Short: "Generate tailwind config file with a safelist using html content in the database",
22+
Run: func(cmd *cobra.Command, args []string) {
23+
runTailwind()
24+
},
25+
}
26+
27+
func runTailwind() {
28+
ctx := context.Background()
29+
30+
conn, err := pgx.Connect(ctx, cfg.Database.URL().String())
31+
if err != nil {
32+
fmt.Printf("Error connecting to the database: %v\n", err)
33+
os.Exit(1)
34+
}
35+
defer conn.Close(ctx)
36+
37+
queries := dbx.New(conn)
38+
39+
classes, err := queries.GetCSSClasses(ctx)
40+
if err != nil {
41+
fmt.Printf("Error getting classes: %v\n", err)
42+
os.Exit(1)
43+
}
44+
45+
if err = genTailwindConfig(classes); err != nil {
46+
fmt.Println("Failed to update config:", err)
47+
os.Exit(1)
48+
}
49+
}
50+
51+
func genTailwindConfig(classes []string) error {
52+
file, err := os.ReadFile(tailwindConfigTemplate)
53+
if err != nil {
54+
return err
55+
}
56+
57+
tmpl, err := template.New("").Parse(string(file))
58+
if err != nil {
59+
return err
60+
}
61+
62+
var buffer bytes.Buffer
63+
err = tmpl.Execute(&buffer, classes)
64+
if err != nil {
65+
return err
66+
}
67+
68+
err = os.WriteFile(tailwindConfig, buffer.Bytes(), 0644)
69+
if err != nil {
70+
return err
71+
}
72+
73+
fmt.Println("Updated Tailwind config written to", tailwindConfig)
74+
return nil
75+
}

pkg/storage/db/dbx/tailwind.sql.go

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/storage/db/sqlc/tailwind.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- name: GetCSSClasses :many
2+
-- returns a list of css classes found in the html content.
3+
WITH extracted AS (
4+
SELECT unnest(regexp_matches(html, 'class="([^"]*)"', 'g')) AS classes
5+
FROM page_html
6+
)
7+
SELECT DISTINCT unnest(string_to_array(classes, ' ')) AS class
8+
FROM extracted
9+
ORDER BY class;

tailwind.config.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ module.exports = {
44
theme: {
55
extend: {},
66
},
7-
safelist: [
8-
"bg-gray-100",
9-
"flex",
10-
"h-32",
11-
"h-4",
12-
"h-48",
13-
"items-center",
14-
"rounded",
15-
"rounded-full",
16-
"rounded-lg",
17-
"space-x-4",
18-
"space-y-2",
19-
"space-y-3",
20-
"space-y-6",
21-
"w-1/2",
22-
"w-1/3",
23-
"w-2/3",
24-
"w-32",
25-
"w-4/6",
26-
"w-5/6",
27-
"w-full"
7+
safelist: [
8+
"bg-gray-100"
9+
,"flex"
10+
,"h-32"
11+
,"h-4"
12+
,"h-48"
13+
,"items-center"
14+
,"rounded"
15+
,"rounded-full"
16+
,"rounded-lg"
17+
,"space-x-4"
18+
,"space-y-2"
19+
,"space-y-3"
20+
,"space-y-6"
21+
,"w-1/2"
22+
,"w-1/3"
23+
,"w-2/3"
24+
,"w-32"
25+
,"w-4/6"
26+
,"w-5/6"
27+
,"w-full"
2828
],
2929
plugins: [],
3030
}

tailwind.config.js.tmpl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/** @type {import('tailwindcss').Config} */
2+
module.exports = {
3+
content: ["./pkg/ui/**/*.templ"],
4+
theme: {
5+
extend: {},
6+
},
7+
safelist: [
8+
{{- range $index, $class := . }}
9+
{{ if $index }},{{ end }}"{{ $class }}"
10+
{{- end }}
11+
],
12+
plugins: [],
13+
}

0 commit comments

Comments
 (0)