From 896d844cac976afd0ee8aa73dd2fb28e15e7ac79 Mon Sep 17 00:00:00 2001
From: Alan Pearce
Date: Tue, 18 Mar 2025 22:40:46 +0100
Subject: feat: Convert templ components to gomponents
---
.editorconfig | 2 +-
.gitignore | 3 -
.golangci.yaml | 5 ++
go.mod | 3 +-
go.sum | 4 +-
gomod2nix.toml | 9 +-
internal/components/combined.go | 56 ++++++++++++
internal/components/combined.templ | 47 ----------
internal/components/data.go | 10 +++
internal/components/detail.go | 22 +++++
internal/components/detail.templ | 20 -----
internal/components/dev.go | 23 +++++
internal/components/dev.templ | 18 ----
internal/components/error.go | 17 ++++
internal/components/error.templ | 18 ----
internal/components/markdown.go | 15 ++++
internal/components/markdown.templ | 33 -------
internal/components/optionDetail.go | 71 +++++++++++++++
internal/components/optionDetail.templ | 58 ------------
internal/components/options.go | 50 +++++++++++
internal/components/options.templ | 45 ----------
internal/components/packageDetail.go | 120 +++++++++++++++++++++++++
internal/components/packageDetail.templ | 109 -----------------------
internal/components/packages.go | 53 +++++++++++
internal/components/packages.templ | 48 ----------
internal/components/page.go | 152 ++++++++++++++++++++++++++++++++
internal/components/page.templ | 123 --------------------------
internal/components/results.go | 65 ++++++++++++++
internal/components/results.templ | 64 --------------
internal/components/search.go | 63 +++++++++++++
internal/components/search.templ | 44 ---------
internal/nix/option.go | 17 ++++
internal/server/error.go | 4 +-
internal/server/mux.go | 12 ++-
modd.conf | 5 +-
nix/dev-shell.nix | 1 -
nix/package.nix | 1 -
nix/pre-commit-checks.nix | 36 +-------
staticcheck.conf | 1 +
39 files changed, 764 insertions(+), 683 deletions(-)
create mode 100644 internal/components/combined.go
delete mode 100644 internal/components/combined.templ
create mode 100644 internal/components/detail.go
delete mode 100644 internal/components/detail.templ
create mode 100644 internal/components/dev.go
delete mode 100644 internal/components/dev.templ
create mode 100644 internal/components/error.go
delete mode 100644 internal/components/error.templ
create mode 100644 internal/components/markdown.go
delete mode 100644 internal/components/markdown.templ
create mode 100644 internal/components/optionDetail.go
delete mode 100644 internal/components/optionDetail.templ
create mode 100644 internal/components/options.go
delete mode 100644 internal/components/options.templ
create mode 100644 internal/components/packageDetail.go
delete mode 100644 internal/components/packageDetail.templ
create mode 100644 internal/components/packages.go
delete mode 100644 internal/components/packages.templ
create mode 100644 internal/components/page.go
delete mode 100644 internal/components/page.templ
create mode 100644 internal/components/results.go
delete mode 100644 internal/components/results.templ
create mode 100644 internal/components/search.go
delete mode 100644 internal/components/search.templ
create mode 100644 staticcheck.conf
diff --git a/.editorconfig b/.editorconfig
index d0afaf3..34e76d0 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,7 +8,7 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
-[{justfile,go.mod,go.sum,*.go,*.templ,.gitmodules}]
+[{justfile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
[*.yaml]
diff --git a/.gitignore b/.gitignore
index f92bc49..4953924 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,3 @@ go.work
/frontend/static/base.css
/data/
/config.toml
-
-*_templ.go
-*_templ.txt
diff --git a/.golangci.yaml b/.golangci.yaml
index df90b0a..e44d5d8 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -36,3 +36,8 @@ linters-settings:
- .WithMessagef(
- .WithStack(
- (context.Context).Err(
+issues:
+ exclude-rules:
+ - linters: [revive]
+ path: internal/components
+ text: "dot-imports"
diff --git a/go.mod b/go.mod
index 106a618..eb4fc3f 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,6 @@ go 1.23.6
require (
badc0de.net/pkg/flagutil v1.0.1
- github.com/a-h/templ v0.3.833
github.com/andybalholm/brotli v1.1.1
github.com/bcicen/jstream v1.0.1
github.com/blevesearch/bleve/v2 v2.4.4
@@ -18,6 +17,7 @@ require (
github.com/stoewer/go-strcase v1.3.0
github.com/yuin/goldmark v1.7.8
gitlab.com/tozd/go/errors v0.10.0
+ go.alanpearce.eu/gomponents v1.2.0
go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a
go.uber.org/zap v1.27.0
golang.org/x/net v0.33.0
@@ -65,6 +65,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
+ golang.org/x/tools v0.24.0 // indirect
google.golang.org/protobuf v1.36.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.55.3 // indirect
diff --git a/go.sum b/go.sum
index 60f4bba..54fa61a 100644
--- a/go.sum
+++ b/go.sum
@@ -5,8 +5,6 @@ github.com/Code-Hex/dd v1.1.0 h1:VEtTThnS9l7WhpKUIpdcWaf0B8Vp0LeeSEsxA1DZseI=
github.com/Code-Hex/dd v1.1.0/go.mod h1:VaMyo/YjTJ3d4qm/bgtrUkT2w+aYwJ07Y7eCWyrJr1w=
github.com/RoaringBitmap/roaring v1.9.4 h1:yhEIoH4YezLYT04s1nHehNO64EKFTop/wBhxv2QzDdQ=
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
-github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
-github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/bcicen/jstream v1.0.1 h1:BXY7Cu4rdmc0rhyTVyT3UkxAiX3bnLpKLas9btbH5ck=
@@ -142,6 +140,8 @@ github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
gitlab.com/tozd/go/errors v0.10.0 h1:A98kL+gaDvWnY6ZB/u8zP+sYaWsWUGBHeFMtamvW/74=
gitlab.com/tozd/go/errors v0.10.0/go.mod h1:q3Ugr0C8dCzMEkrzjjlV2qNsm9e0KvqBjwcbcjCpBe4=
+go.alanpearce.eu/gomponents v1.2.0 h1:5SoLlMMc04xvLcmHVgnScjX1DzBM4mbwyTDa0cOPiD8=
+go.alanpearce.eu/gomponents v1.2.0/go.mod h1:uX96UAsHCut1cKMAYVWWxQ9ADt1CAPI8LpyAu0LRQPs=
go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a h1:NUv3AzGxwMVSq26takww8/nyl+sPO2BsESoVSU8G49U=
go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a/go.mod h1:FRM6J9HMQ/RV2Q5j+6RKBYWh/YNeEUriGSqDRchiHuQ=
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
diff --git a/gomod2nix.toml b/gomod2nix.toml
index 0f6e067..9079679 100644
--- a/gomod2nix.toml
+++ b/gomod2nix.toml
@@ -10,9 +10,6 @@ schema = 3
[mod."github.com/RoaringBitmap/roaring"]
version = "v1.9.4"
hash = "sha256-OKOLQ/PsH6630Vb5/9yG28TLIPGxdG9WDbAZxgK8EcI="
- [mod."github.com/a-h/templ"]
- version = "v0.3.833"
- hash = "sha256-OSGAJDVPYqgb72DZXeemLp37aGrrxMt+PQNKW5voKQ0="
[mod."github.com/andybalholm/brotli"]
version = "v1.1.1"
hash = "sha256-kCt+irK1gvz2lGQUeEolYa5+FbLsfWlJMCd5hm+RPgQ="
@@ -154,6 +151,9 @@ schema = 3
[mod."gitlab.com/tozd/go/errors"]
version = "v0.10.0"
hash = "sha256-oW37KsieVKJOWk9ZXbGuQvuU4nyJCZzgYrTZHFkoCs4="
+ [mod."go.alanpearce.eu/gomponents"]
+ version = "v1.2.0"
+ hash = "sha256-pF+3We63loSMwhTUafgIdmBYc4cj5yVIVQRyaX1sWB4="
[mod."go.alanpearce.eu/x"]
version = "v0.0.0-20241203124832-a29434dba11a"
hash = "sha256-ojqWkz3VqeAOevFxOTO5S3acRItCA4pUrTaul887+x8="
@@ -175,6 +175,9 @@ schema = 3
[mod."golang.org/x/text"]
version = "v0.21.0"
hash = "sha256-QaMwddBRnoS2mv9Y86eVC2x2wx/GZ7kr2zAJvwDeCPc="
+ [mod."golang.org/x/tools"]
+ version = "v0.24.0"
+ hash = "sha256-2LBEW//aW8qrHc26F6Ma7CsYJRaCALfi0xQl2KgWems="
[mod."google.golang.org/protobuf"]
version = "v1.36.0"
hash = "sha256-7LfDxB2/x6sSzJdQ3sixWMaY0WZ/juwuz3rPBJxNzXQ="
diff --git a/internal/components/combined.go b/internal/components/combined.go
new file mode 100644
index 0000000..d8c6fea
--- /dev/null
+++ b/internal/components/combined.go
@@ -0,0 +1,56 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/config"
+ "go.alanpearce.eu/searchix/internal/index"
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func CombinedData(data nix.Importable) g.Node {
+ switch data.(type) {
+ case nix.Option:
+ if o := convertMatch[nix.Option](data); o != nil {
+ return firstSentence(o.Description)
+ }
+ case nix.Package:
+ if p := convertMatch[nix.Package](data); p != nil {
+ return g.Text(firstSentence(p.Description))
+ }
+ }
+
+ return g.Text("")
+}
+
+func Combined(result *index.Result) g.Node {
+ return Table(
+ THead(
+ Tr(
+ Th(Scope("col"), g.Text("Attribute")),
+ Th(Scope("col"), g.Text("Description")),
+ g.If(config.DevMode,
+ Th(Scope("col"), g.Text("Score")),
+ ),
+ ),
+ ),
+ TBody(
+ g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+ return Tr(
+ Td(
+ openCombinedDialogLink(nix.GetKey(hit.Data)),
+ ),
+ Td(
+ CombinedData(hit.Data),
+ ),
+ g.If(config.DevMode,
+ Td(
+ Score(hit),
+ ),
+ ),
+ )
+ }),
+ ),
+ )
+}
diff --git a/internal/components/combined.templ b/internal/components/combined.templ
deleted file mode 100644
index 3beddcd..0000000
--- a/internal/components/combined.templ
+++ /dev/null
@@ -1,47 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/config"
- "go.alanpearce.eu/searchix/internal/index"
- "go.alanpearce.eu/searchix/internal/nix"
-)
-
-templ Combined(result *index.Result) {
-
-
-
- Attribute |
- Description |
- if config.DevMode {
- Score |
- }
-
-
-
- for _, hit := range result.Hits {
-
-
- @openCombinedDialogLink(nix.GetKey(hit.Data))
- |
-
- switch hit.Data.(type) {
- case nix.Option:
- if o := convertMatch[nix.Option](hit.Data); o != nil {
- @markdown(firstSentence(o.Description))
- }
- case nix.Package:
- if o := convertMatch[nix.Package](hit.Data); o != nil {
- { firstSentence(o.Description) }
- }
- }
- |
- if config.DevMode {
-
- @score(hit)
- |
- }
-
- }
-
-
-}
diff --git a/internal/components/data.go b/internal/components/data.go
index c34dfb8..977b90e 100644
--- a/internal/components/data.go
+++ b/internal/components/data.go
@@ -4,6 +4,7 @@ import (
"go.alanpearce.eu/searchix/frontend"
"go.alanpearce.eu/searchix/internal/config"
search "go.alanpearce.eu/searchix/internal/index"
+ "go.alanpearce.eu/searchix/internal/nix"
)
type TemplateData struct {
@@ -24,3 +25,12 @@ type ResultData struct {
Next string
All string
}
+
+func convertMatch[I nix.Importable](m nix.Importable) *I {
+ i, ok := m.(I)
+ if !ok {
+ return nil
+ }
+
+ return &i
+}
diff --git a/internal/components/detail.go b/internal/components/detail.go
new file mode 100644
index 0000000..e6164fa
--- /dev/null
+++ b/internal/components/detail.go
@@ -0,0 +1,22 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+)
+
+func Detail(thing nix.Importable) g.Node {
+ switch t := thing.(type) {
+ case nix.Option:
+ return OptionDetail(t)
+ case nix.Package:
+ return PackageDetail(t)
+ default:
+ return nil
+ }
+}
+
+func DetailPage(tdata TemplateData, thing nix.Importable) g.Node {
+ return Page(tdata, Detail(thing))
+}
diff --git a/internal/components/detail.templ b/internal/components/detail.templ
deleted file mode 100644
index fa7206c..0000000
--- a/internal/components/detail.templ
+++ /dev/null
@@ -1,20 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/nix"
-)
-
-templ Detail(thing nix.Importable) {
- switch thing.(type) {
- case nix.Option:
- @OptionDetail(thing.(nix.Option))
- case nix.Package:
- @PackageDetail(thing.(nix.Package))
- }
-}
-
-templ DetailPage(tdata TemplateData, thing nix.Importable) {
- @Page(tdata) {
- @Detail(thing)
- }
-}
diff --git a/internal/components/dev.go b/internal/components/dev.go
new file mode 100644
index 0000000..3d77094
--- /dev/null
+++ b/internal/components/dev.go
@@ -0,0 +1,23 @@
+package components
+
+import (
+ "strconv"
+
+ "go.alanpearce.eu/searchix/internal/index"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Score(h index.DocumentMatch) g.Node {
+ return g.Group([]g.Node{
+ A(
+ Class("open-sibling-dialog"),
+ g.Text(strconv.FormatFloat(h.Score, 'f', 2, 64)),
+ ),
+ Dialog(
+ Button(AutoFocus(), g.Text("Close")),
+ Pre(g.Text(h.Expl.String())),
+ ),
+ })
+}
diff --git a/internal/components/dev.templ b/internal/components/dev.templ
deleted file mode 100644
index a03eb4b..0000000
--- a/internal/components/dev.templ
+++ /dev/null
@@ -1,18 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/index"
- "strconv"
-)
-
-templ score(h index.DocumentMatch) {
-
- { strconv.FormatFloat(h.Score, 'f', 2, 64) }
-
-
-}
diff --git a/internal/components/error.go b/internal/components/error.go
new file mode 100644
index 0000000..fe34919
--- /dev/null
+++ b/internal/components/error.go
@@ -0,0 +1,17 @@
+package components
+
+import (
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Error(tdata TemplateData) g.Node {
+ return P(
+ Class("notice error"),
+ g.Textf("%d %s", tdata.Code, tdata.Message),
+ )
+}
+
+func ErrorPage(tdata TemplateData) g.Node {
+ return Page(tdata, Error(tdata))
+}
diff --git a/internal/components/error.templ b/internal/components/error.templ
deleted file mode 100644
index 8e45095..0000000
--- a/internal/components/error.templ
+++ /dev/null
@@ -1,18 +0,0 @@
-package components
-
-import (
- "strconv"
-)
-
-templ Error(tdata TemplateData) {
-
- { strconv.Itoa(tdata.Code) }
- { tdata.Message }
-
-}
-
-templ ErrorPage(tdata TemplateData) {
- @Page(tdata) {
- @Error(tdata)
- }
-}
diff --git a/internal/components/markdown.go b/internal/components/markdown.go
new file mode 100644
index 0000000..405ab52
--- /dev/null
+++ b/internal/components/markdown.go
@@ -0,0 +1,15 @@
+package components
+
+import (
+ "regexp"
+)
+
+var firstSentenceRegexp = regexp.MustCompile(`^.*?\.[[:space:]]`)
+
+func firstSentence[T ~string](text T) T {
+ if fs := firstSentenceRegexp.FindString(string(text)); fs != "" {
+ return T(fs)
+ }
+
+ return text
+}
diff --git a/internal/components/markdown.templ b/internal/components/markdown.templ
deleted file mode 100644
index 21b0aa0..0000000
--- a/internal/components/markdown.templ
+++ /dev/null
@@ -1,33 +0,0 @@
-package components
-
-import (
- "context"
- "io"
- "regexp"
-
- "github.com/yuin/goldmark"
- "github.com/yuin/goldmark/extension"
-
- "go.alanpearce.eu/searchix/internal/nix"
-)
-
-var (
- md = goldmark.New(
- goldmark.WithExtensions(extension.NewLinkify()),
- )
- firstSentenceRegexp = regexp.MustCompile(`^.*?\.[[:space:]]`)
-)
-
-func firstSentence[T ~string](text T) T {
- if fs := firstSentenceRegexp.FindString(string(text)); fs != "" {
- return T(fs)
- }
-
- return text
-}
-
-func markdown(text nix.Markdown) templ.Component {
- return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
- return md.Convert([]byte(text), w)
- })
-}
diff --git a/internal/components/optionDetail.go b/internal/components/optionDetail.go
new file mode 100644
index 0000000..d5f0c24
--- /dev/null
+++ b/internal/components/optionDetail.go
@@ -0,0 +1,71 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func OptionDetail(option nix.Option) g.Node {
+ return g.Group([]g.Node{
+ H2(g.Text(option.Name)),
+ option.Description,
+ Dl(
+ g.If(option.Type != "",
+ g.Group([]g.Node{
+ Dt(g.Text("Type")),
+ Dd(Code(g.Text(option.Type))),
+ }),
+ ),
+ g.Iff(option.Default != nil,
+ func() g.Node {
+ return g.Group([]g.Node{
+ Dt(g.Text("Default")),
+ Dd(
+ g.If(option.Default.Markdown != "",
+ option.Default.Markdown,
+ Pre(Code(g.Text(option.Default.Text))),
+ ),
+ ),
+ })
+ },
+ ),
+ g.Iff(option.Example != nil,
+ func() g.Node {
+ return g.Group([]g.Node{
+ Dt(g.Text("Example")),
+ Dd(
+ g.If(option.Example.Markdown != "",
+ option.Example.Markdown,
+ Pre(Code(g.Text(option.Example.Text))),
+ ),
+ ),
+ })
+ },
+ ),
+ g.If(option.RelatedPackages != "",
+ g.Group([]g.Node{
+ Dt(g.Text("Related Packages")),
+ Dd(
+ option.RelatedPackages,
+ ),
+ }),
+ ),
+ g.If(len(option.Declarations) > 0,
+ g.Group([]g.Node{
+ Dt(g.Text("Declared")),
+ g.Map(option.Declarations, func(d nix.Link) g.Node {
+ return Dd(
+ A(Href(d.URL), g.Text(d.Name)),
+ )
+ }),
+ }),
+ ),
+ ),
+ })
+}
+
+func OptionDetailPage(tdata TemplateData, option nix.Option) g.Node {
+ return Page(tdata, OptionDetail(option))
+}
diff --git a/internal/components/optionDetail.templ b/internal/components/optionDetail.templ
deleted file mode 100644
index 6eaafb4..0000000
--- a/internal/components/optionDetail.templ
+++ /dev/null
@@ -1,58 +0,0 @@
-package components
-
-import "go.alanpearce.eu/searchix/internal/nix"
-
-templ OptionDetail(option nix.Option) {
- { option.Name }
- @markdown(option.Description)
-
- if option.Type != "" {
- - Type
- { option.Type }
- }
- if option.Default != nil {
- if option.Default.Text != "" || option.Default.Markdown != "" {
- - Default
- -
- if option.Default.Markdown != "" {
- @markdown(option.Default.Markdown)
- } else {
-
{ option.Default.Text }
- }
-
- }
- }
- if option.Example != nil {
- if option.Example.Text != "" || option.Example.Markdown != "" {
- - Example
- -
- if option.Example.Markdown != "" {
- @markdown(option.Example.Markdown)
- } else {
-
{ option.Example.Text }
- }
-
- }
- }
- if option.RelatedPackages != "" {
- - Related Packages
- -
- @markdown(option.RelatedPackages)
-
- }
- if len(option.Declarations) > 0 {
- - Declared
- for _, d := range option.Declarations {
- -
- { d.Name }
-
- }
- }
-
-}
-
-templ OptionDetailPage(tdata TemplateData, option nix.Option) {
- @Page(tdata) {
- @OptionDetail(option)
- }
-}
diff --git a/internal/components/options.go b/internal/components/options.go
new file mode 100644
index 0000000..af6c73f
--- /dev/null
+++ b/internal/components/options.go
@@ -0,0 +1,50 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/config"
+ "go.alanpearce.eu/searchix/internal/index"
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Options(result *index.Result) g.Node {
+ return Table(
+ THead(
+ Tr(
+ Th(Scope("col"), g.Text("Title")),
+ Th(Scope("col"), g.Text("Description")),
+ g.If(config.DevMode,
+ Th(Scope("col"), g.Text("Score")),
+ ),
+ ),
+ ),
+ TBody(
+ g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+ if m := convertMatch[nix.Option](hit.Data); m != nil {
+ return optionRow(hit, *m)
+ }
+
+ return nil
+ }),
+ ),
+ )
+}
+
+func optionRow(hit index.DocumentMatch, o nix.Option) g.Node {
+ return Tr(
+ Td(
+ openDialogLink(o.Name),
+ ),
+ Td(
+ firstSentence(o.Description),
+ Dialog(ID(o.Name)),
+ ),
+ g.If(config.DevMode,
+ Td(
+ Score(hit),
+ ),
+ ),
+ )
+}
diff --git a/internal/components/options.templ b/internal/components/options.templ
deleted file mode 100644
index 097f66f..0000000
--- a/internal/components/options.templ
+++ /dev/null
@@ -1,45 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/config"
- "go.alanpearce.eu/searchix/internal/index"
- "go.alanpearce.eu/searchix/internal/nix"
-)
-
-templ Options(result *index.Result) {
-
-
-
- Title |
- Description |
- if config.DevMode {
- Score |
- }
-
-
-
- for _, hit := range result.Hits {
- if m := convertMatch[nix.Option](hit.Data); m != nil {
- @optionRow(hit, *m)
- }
- }
-
-
-}
-
-templ optionRow(hit index.DocumentMatch, o nix.Option) {
-
-
- @openDialogLink(o.Name)
- |
-
- @markdown(firstSentence(o.Description))
-
- |
- if config.DevMode {
-
- @score(hit)
- |
- }
-
-}
diff --git a/internal/components/packageDetail.go b/internal/components/packageDetail.go
new file mode 100644
index 0000000..01b1f4d
--- /dev/null
+++ b/internal/components/packageDetail.go
@@ -0,0 +1,120 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func licenseName(l nix.License) string {
+ if l.FullName != "" {
+ return l.FullName
+ }
+
+ return l.Name
+}
+
+func PackageDetail(pkg nix.Package) g.Node {
+ return g.Group([]g.Node{
+ H2(
+ g.If(pkg.Broken,
+ Del(g.Text(pkg.Attribute)),
+ g.Text(pkg.Attribute),
+ ),
+ ),
+ g.If(pkg.LongDescription != "",
+ pkg.LongDescription,
+ P(g.Text(pkg.Description)),
+ ),
+ Dl(
+ g.If(pkg.MainProgram != "",
+ g.Group([]g.Node{
+ Dt(g.Text("Main Program")),
+ Dd(Code(g.Text(pkg.MainProgram))),
+ }),
+ ),
+ g.If(len(pkg.Programs) > 0,
+ g.Group([]g.Node{
+ Dt(g.Text("Programs")),
+ Dd(
+ Ul(
+ g.Map(pkg.Programs, func(p string) g.Node {
+ return Li(Code(g.Text(p)))
+ }),
+ ),
+ ),
+ }),
+ ),
+ g.If(len(pkg.Homepages) > 0,
+ g.Group([]g.Node{
+ Dt(g.Text("Homepage")),
+ Dd(
+ Ul(
+ g.Map(pkg.Homepages, func(u string) g.Node {
+ return Li(A(Href(u), g.Text(u)))
+ }),
+ ),
+ ),
+ }),
+ ),
+ g.If(pkg.Version != "",
+ g.Group([]g.Node{
+ Dt(g.Text("Version")),
+ Dd(g.Text(pkg.Version)),
+ }),
+ ),
+ g.If(len(pkg.Licenses) > 0,
+ g.Group([]g.Node{
+ Dt(g.Text("License")),
+ Dd(
+ Ul(
+ g.Map(pkg.Licenses, func(l nix.License) g.Node {
+ return Li(
+ g.If(l.URL != "",
+ A(Href(l.URL), g.Text(licenseName(l))),
+ g.Text(licenseName(l)),
+ ),
+ g.If(l.AppendixURL != "",
+ A(Href(l.AppendixURL), g.Text("Appendix")),
+ ),
+ )
+ }),
+ ),
+ ),
+ }),
+ ),
+ g.If(len(pkg.Maintainers) > 0,
+ g.Group([]g.Node{
+ Dt(g.Text("Maintainers")),
+ Dd(
+ Ul(
+ g.Map(pkg.Maintainers, func(m nix.Maintainer) g.Node {
+ return Li(
+ g.If(
+ m.Github != "",
+ A(
+ Href(joinPath("https://github.com", m.Github)),
+ g.Text(m.Name),
+ ),
+ g.Text(m.Name),
+ ),
+ )
+ }),
+ ),
+ ),
+ }),
+ ),
+ g.If(pkg.Definition != "",
+ g.Group([]g.Node{
+ Dt(g.Text("Defined")),
+ Dd(A(Href(pkg.Definition), g.Text("Source"))),
+ }),
+ ),
+ ),
+ })
+}
+
+func PackageDetailPage(tdata TemplateData, pkg nix.Package) g.Node {
+ return Page(tdata, PackageDetail(pkg))
+}
diff --git a/internal/components/packageDetail.templ b/internal/components/packageDetail.templ
deleted file mode 100644
index 84d2bdf..0000000
--- a/internal/components/packageDetail.templ
+++ /dev/null
@@ -1,109 +0,0 @@
-package components
-
-import "go.alanpearce.eu/searchix/internal/nix"
-
-func licenseName(l nix.License) string {
- if l.FullName != "" {
- return l.FullName
- } else {
- return l.Name
- }
-}
-
-templ PackageDetail(pkg nix.Package) {
-
- if pkg.Broken {
- { pkg.Attribute }
- } else {
- { pkg.Attribute }
- }
-
- if pkg.LongDescription != "" {
- @markdown(pkg.LongDescription)
- } else {
- { pkg.Description }
- }
-
- if pkg.MainProgram != "" {
- - Main Program
- -
-
{ pkg.MainProgram }
-
- }
- if len(pkg.Programs) > 0 {
- - Programs
- -
-
- for _, p := range pkg.Programs {
- -
-
{ p }
-
- }
-
-
- }
- if len(pkg.Homepages) > 0 {
- - Homepage
- -
-
- for _, u := range pkg.Homepages {
- -
- { u }
-
- }
-
-
- }
- if pkg.Version != "" {
- - Version
- - { pkg.Version }
- }
- if len(pkg.Licenses) > 0 {
- - License
- -
-
- for _, l := range pkg.Licenses {
- -
- if l.URL != "" {
- { licenseName(l) }
- } else {
- { licenseName(l) }
- }
- if l.AppendixURL != "" {
- Appendix
- }
-
- }
-
-
- }
- if len(pkg.Maintainers) > 0 {
- - Maintainers
- -
-
- for _, m := range pkg.Maintainers {
- -
- if m.Github != "" {
- { m.Name }
- } else {
- { m.Name }
- }
-
- }
-
-
- }
- if pkg.Definition != "" {
- - Defined
- -
- Source
-
- }
-
-}
-
-templ PackageDetailPage(tdata TemplateData, pkg nix.Package) {
- @Page(tdata) {
- @PackageDetail(pkg)
- }
-}
diff --git a/internal/components/packages.go b/internal/components/packages.go
new file mode 100644
index 0000000..9bc3f99
--- /dev/null
+++ b/internal/components/packages.go
@@ -0,0 +1,53 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/config"
+ "go.alanpearce.eu/searchix/internal/index"
+ "go.alanpearce.eu/searchix/internal/nix"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Packages(result *index.Result) g.Node {
+ return Table(
+ THead(
+ Tr(
+ Th(Scope("col"), g.Text("Attribute")),
+ Th(Scope("col"), g.Text("Name")),
+ Th(Scope("col"), g.Text("Description")),
+ g.If(config.DevMode,
+ Th(Scope("col"), g.Text("Score")),
+ ),
+ ),
+ ),
+ TBody(
+ g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+ if m := convertMatch[nix.Package](hit.Data); m != nil {
+ return packageRow(hit, *m)
+ }
+
+ return nil
+ }),
+ ),
+ )
+}
+
+func packageRow(hit index.DocumentMatch, p nix.Package) g.Node {
+ return Tr(
+ Td(
+ openDialogLink(p.Attribute),
+ ),
+ Td(
+ g.Text(p.Name),
+ ),
+ Td(
+ g.Text(p.Description),
+ ),
+ g.If(config.DevMode,
+ Td(
+ Score(hit),
+ ),
+ ),
+ )
+}
diff --git a/internal/components/packages.templ b/internal/components/packages.templ
deleted file mode 100644
index 6e14026..0000000
--- a/internal/components/packages.templ
+++ /dev/null
@@ -1,48 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/config"
- "go.alanpearce.eu/searchix/internal/index"
- "go.alanpearce.eu/searchix/internal/nix"
-)
-
-templ Packages(result *index.Result) {
-
-
-
- Attribute |
- Name |
- Description |
- if config.DevMode {
- Score |
- }
-
-
-
- for _, hit := range result.Hits {
- if m := convertMatch[nix.Package](hit.Data); m != nil {
- @packageRow(hit, *m)
- }
- }
-
-
-}
-
-templ packageRow(hit index.DocumentMatch, p nix.Package) {
-
-
- @openDialogLink(p.Attribute)
- |
-
- { p.Name }
- |
-
- { p.Description }
- |
- if config.DevMode {
-
- @score(hit)
- |
- }
-
-}
diff --git a/internal/components/page.go b/internal/components/page.go
new file mode 100644
index 0000000..5cfa4ff
--- /dev/null
+++ b/internal/components/page.go
@@ -0,0 +1,152 @@
+package components
+
+import (
+ "net/url"
+
+ "go.alanpearce.eu/searchix/frontend"
+ "go.alanpearce.eu/searchix/internal/config"
+
+ g "go.alanpearce.eu/gomponents"
+ c "go.alanpearce.eu/gomponents/components"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Page(tdata TemplateData, children ...g.Node) g.Node {
+ return Doctype(
+ HTML(
+ Lang("en-GB"),
+ Head(
+ Meta(Charset("utf-8")),
+ Meta(Name("viewport"), Content("width=device-width, initial-scale=1")),
+ TitleEl(g.Text("Searchix"), g.If(config.DevMode, g.Text(" (Dev)"))),
+ g.Map(tdata.Assets.Stylesheets, css),
+ g.Raw(tdata.ExtraHeadHTML),
+ Link(
+ Rel("search"),
+ Type("application/opensearchdescription+xml"),
+ TitleAttr("Searchix "+sourceNameAndType(nil)),
+ Href(joinPath("opensearch.xml")),
+ ),
+ g.Map(tdata.Sources, func(source *config.Source) g.Node {
+ return Link(
+ Rel("search"),
+ Type("application/opensearchdescription+xml"),
+ TitleAttr("Searchix "+sourceNameAndType(source)),
+ Href(joinPath("/", source.Importer.String(), source.Key, "opensearch.xml")),
+ )
+ }),
+ ),
+ Body(
+ Header(
+ Nav(
+ H1(A(Href("/"), g.Text("Searchix"))),
+ A(
+ c.Classes{
+ "current": tdata.Source == nil,
+ },
+ g.If(
+ tdata.Source == nil,
+ Href("/"),
+ Href(joinPathQuery("/", tdata.Query)),
+ ),
+ g.Text("All"),
+ ),
+ g.Map(tdata.Sources, func(source *config.Source) g.Node {
+ if tdata.Source != nil && tdata.Source.Name == source.Name {
+ return A(
+ Class("current"),
+ Href(
+ joinPath(
+ "/",
+ source.Importer.String(),
+ source.Key,
+ "search",
+ ),
+ ),
+ g.Text(source.Name),
+ )
+ }
+
+ return A(
+ Href(
+ joinPathQuery(
+ joinPath(
+ "/",
+ source.Importer.String(),
+ source.Key,
+ "search",
+ ),
+ tdata.Query,
+ ),
+ ),
+ g.Text(source.Name),
+ )
+ }),
+ ),
+ ),
+ Main(children...),
+ Footer(
+ g.If(config.Version != "",
+ g.Group([]g.Node{
+ g.Text("Searchix "),
+ A(
+ Href("https://git.sr.ht/~alanpearce/searchix/refs/"+config.Version),
+ g.Text(config.Version),
+ ),
+ }),
+ ),
+ g.Text("Made by "),
+ A(Href("https://alanpearce.eu"), g.Text("Alan Pearce")),
+ g.Text(". "),
+ A(Href("https://git.sr.ht/~alanpearce/searchix"), g.Text("Source code")),
+ A(Href("https://todo.sr.ht/~alanpearce/searchix"), g.Text("Report issues")),
+ ),
+ ),
+ ),
+ )
+}
+
+func css(css *frontend.Asset) g.Node {
+ return Link(Href(css.URL), Rel("stylesheet"),
+ Integrity("sha256-"+css.Base64SHA256))
+}
+
+func script(s *frontend.Asset) g.Node {
+ return Script(
+ Src(s.URL),
+ Defer(),
+ g.Attr("integrity", "sha256-"+s.Base64SHA256),
+ )
+}
+
+func sourceNameAndType(source *config.Source) string {
+ if source == nil {
+ return "Combined"
+ }
+
+ switch source.Importer {
+ case config.Options:
+ return source.Name + " " + source.Importer.String()
+ case config.Packages:
+ return source.Name
+ }
+
+ return ""
+}
+
+func joinPath(base string, parts ...string) string {
+ u, err := url.JoinPath(base, parts...)
+ if err != nil {
+ panic(err)
+ }
+
+ return u
+}
+
+func joinPathQuery(path string, query string) string {
+ if query == "" {
+ return path
+ }
+
+ return path + "?query=" + url.QueryEscape(query)
+}
diff --git a/internal/components/page.templ b/internal/components/page.templ
deleted file mode 100644
index 62b2937..0000000
--- a/internal/components/page.templ
+++ /dev/null
@@ -1,123 +0,0 @@
-package components
-
-import (
- "context"
- "io"
- "net/url"
-
- "go.alanpearce.eu/searchix/frontend"
- "go.alanpearce.eu/searchix/internal/config"
-)
-
-templ Page(tdata TemplateData) {
-
-
-
-
-
-
- Searchix
- if config.DevMode {
- (Dev)
- }
-
- for _, sheet := range tdata.Assets.Stylesheets {
-
- }
- @Unsafe(tdata.ExtraHeadHTML)
-
- for _, source := range tdata.Sources {
-
- }
-
-
-
-
- { children... }
-
-
-
-
-}
-
-templ script(s *frontend.Asset) {
-
-}
-
-func Unsafe(html string) templ.Component {
- return templ.ComponentFunc(func(_ context.Context, w io.Writer) (err error) {
- _, err = io.WriteString(w, html)
- return
- })
-}
-
-func sourceNameAndType(source *config.Source) string {
- if source == nil {
- return "Combined"
- }
-
- switch source.Importer {
- case config.Options:
- return source.Name + " " + source.Importer.String()
- case config.Packages:
- return source.Name
- }
- return ""
-}
-
-func joinPath(base string, parts ...string) templ.SafeURL {
- u, err := url.JoinPath(base, parts...)
- if err != nil {
- panic(err)
- }
- return templ.SafeURL(u)
-}
-
-func joinPathQuery[T ~string](path T, query string) templ.SafeURL {
- if query == "" {
- return templ.SafeURL(path)
- }
- return templ.SafeURL(string(path) + "?query=" + url.QueryEscape(query))
-}
diff --git a/internal/components/results.go b/internal/components/results.go
new file mode 100644
index 0000000..4f07a78
--- /dev/null
+++ b/internal/components/results.go
@@ -0,0 +1,65 @@
+package components
+
+import (
+ "go.alanpearce.eu/searchix/internal/config"
+
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Results(r ResultData) g.Node {
+ if r.Query == "" {
+ return Br()
+ }
+
+ if r.Results == nil || r.Results.Total == 0 {
+ return Span(Role("status"), g.Text("Nothing found"))
+ }
+
+ var content g.Node
+ if r.Source != nil {
+ switch r.Source.Importer {
+ case config.Options:
+ content = Options(r.Results)
+ case config.Packages:
+ content = Packages(r.Results)
+ }
+ } else {
+ content = Combined(r.Results)
+ }
+
+ return g.Group([]g.Node{
+ content,
+ Footer(
+ g.Attr("aria-label", "pagination"),
+ Nav(
+ ID("pagination"),
+ g.If(r.Prev != "",
+ A(Class("button"), Href(r.Prev), Rel("prev"), g.Text("Prev")),
+ ),
+ g.If(r.Next != "",
+ A(Class("button"), Href(r.Next), Rel("next"), g.Text("Next")),
+ ),
+ ),
+ Span(
+ Role("status"),
+ g.Textf("%d results", r.Results.Total),
+ ),
+ g.If(r.Next != r.Prev && r.Results.Total < config.MaxResultsShowAll,
+ A(Href(r.All), g.Text("Show All")),
+ ),
+ ),
+ })
+}
+
+func ResultsPage(r ResultData) g.Node {
+ return SearchPage(r.TemplateData, r, Results(r))
+}
+
+func openDialogLink(attr string) g.Node {
+ return A(Class("open-dialog"), Href(attr), g.Text(attr))
+}
+
+func openCombinedDialogLink(attr string) g.Node {
+ return A(Class("open-dialog"), Href("/"+attr), g.Text(attr))
+}
diff --git a/internal/components/results.templ b/internal/components/results.templ
deleted file mode 100644
index fee211c..0000000
--- a/internal/components/results.templ
+++ /dev/null
@@ -1,64 +0,0 @@
-package components
-
-import (
- "go.alanpearce.eu/searchix/internal/config"
- "go.alanpearce.eu/searchix/internal/nix"
- "strconv"
-)
-
-func convertMatch[I nix.Importable](m nix.Importable) *I {
- i, ok := m.(I)
- if !ok {
- return nil
- }
- return &i
-}
-
-templ Results(r ResultData) {
- if r.Query != "" {
- if r.Results != nil && r.Results.Total > 0 {
- if r.Source != nil {
- switch r.Source.Importer {
- case config.Options:
- @Options(r.Results)
- case config.Packages:
- @Packages(r.Results)
- }
- } else {
- @Combined(r.Results)
- }
-
- } else {
- Nothing found
- }
- } else {
-
- }
-}
-
-templ ResultsPage(r ResultData) {
- @SearchPage(r.TemplateData, r) {
- @Results(r)
- }
-}
-
-templ openDialogLink(attr string) {
- { attr }
-}
-
-templ openCombinedDialogLink(attr string) {
- { attr }
-}
diff --git a/internal/components/search.go b/internal/components/search.go
new file mode 100644
index 0000000..0a7c991
--- /dev/null
+++ b/internal/components/search.go
@@ -0,0 +1,63 @@
+package components
+
+import (
+ g "go.alanpearce.eu/gomponents"
+ . "go.alanpearce.eu/gomponents/html"
+)
+
+func Search(tdata TemplateData, r ResultData) g.Node {
+ return Form(
+ ID("search"),
+ Role("search"),
+ FieldSet(
+ Legend(
+ ID("legend"),
+ H2(g.Textf("%s search", sourceNameAndType(tdata.Source))),
+ ),
+ Input(
+ ID("query"),
+ Aria("labelledby", "legend"),
+ Name("query"),
+ Type("search"),
+ Value(r.Query),
+ AutoFocus(),
+ g.Attr("spellcheck", "false"),
+ g.Attr("autocapitalize", "none"),
+ ),
+ Button(g.Text("Search")),
+ ),
+ )
+}
+
+func SearchPage(tdata TemplateData, r ResultData, children ...g.Node) g.Node {
+ return Page(
+ tdata,
+ P(
+ g.Text("Search Nix packages and options from "),
+ A(Href("https://nixos.org"), g.Text("NixOS")),
+ g.Text(", "),
+ A(Href("https://github.com/LnL7/nix-darwin"), g.Text("nix-darwin")),
+ g.Text(" and "),
+ A(Href("https://github.com/nix-community/home-manager"), g.Text("home-manager")),
+ ),
+ script(tdata.Assets.ByPath["/static/search.js"]),
+ Search(tdata, r),
+ Section(
+ ID("results"),
+ Role("list"),
+ Aria("label", "search results"),
+ g.Group(children),
+ ),
+ Dialog(
+ ID("dialog"),
+ Button(AutoFocus(), g.Text("Close")),
+ ),
+ NoScript(
+ P(
+ Class("notice"),
+ g.Text("Everything should work fine without JavaScript. If that is not the case, "),
+ A(Href("https://todo.sr.ht/~alanpearce/searchix"), g.Text("report an issue")),
+ ),
+ ),
+ )
+}
diff --git a/internal/components/search.templ b/internal/components/search.templ
deleted file mode 100644
index 7076772..0000000
--- a/internal/components/search.templ
+++ /dev/null
@@ -1,44 +0,0 @@
-package components
-
-templ Search(tdata TemplateData, r ResultData) {
-
-}
-
-templ SearchPage(tdata TemplateData, r ResultData) {
- @Page(tdata) {
-
- Search Nix packages and options from NixOS, nix-darwin
- and home-manager
-
- @script(tdata.Assets.ByPath["/static/search.js"])
- @Search(tdata, r)
-
-
-
- }
-}
diff --git a/internal/nix/option.go b/internal/nix/option.go
index c1cc4c3..96c4546 100644
--- a/internal/nix/option.go
+++ b/internal/nix/option.go
@@ -1,5 +1,13 @@
package nix
+import (
+ "io"
+
+ "github.com/yuin/goldmark"
+ "github.com/yuin/goldmark/extension"
+ "gitlab.com/tozd/go/errors"
+)
+
type Markdown string
type Value struct {
@@ -35,3 +43,12 @@ func (p Option) GetName() string {
func (p Option) GetSource() string {
return p.Source
}
+
+var md = goldmark.New(
+ goldmark.WithExtensions(extension.NewLinkify()),
+)
+
+// implements gomponent.Node
+func (text Markdown) Render(w io.Writer) error {
+ return errors.WithStack(md.Convert([]byte(text), w))
+}
diff --git a/internal/server/error.go b/internal/server/error.go
index c2acf48..b51cfa9 100644
--- a/internal/server/error.go
+++ b/internal/server/error.go
@@ -29,9 +29,9 @@ func createErrorHandler(
w.Header().Del("Vary")
w.WriteHeader(code)
if r.Header.Get("Fetch") == "true" {
- err = components.Error(indexData).Render(r.Context(), w)
+ err = components.Error(indexData).Render(w)
} else {
- err = components.ErrorPage(indexData).Render(r.Context(), w)
+ err = components.ErrorPage(indexData).Render(w)
}
if err != nil {
log.Error(
diff --git a/internal/server/mux.go b/internal/server/mux.go
index 1507860..2bbff8e 100644
--- a/internal/server/mux.go
+++ b/internal/server/mux.go
@@ -44,8 +44,6 @@ func applyDevModeOverrides(cfg *config.Config) {
}
cfg.Web.ContentSecurityPolicy.ScriptSrc = append(
cfg.Web.ContentSecurityPolicy.ScriptSrc,
- cfg.Web.BaseURL.JoinPath("_templ/reload/script.js").String(),
- "http://localhost:7331",
"'unsafe-inline'",
)
}
@@ -174,9 +172,9 @@ func NewMux(
var baseErr error
if r.Header.Get("Fetch") == "true" {
w.Header().Add("Content-Type", "text/html; charset=utf-8")
- baseErr = components.Results(tdata).Render(r.Context(), w)
+ baseErr = components.Results(tdata).Render(w)
} else {
- baseErr = components.ResultsPage(tdata).Render(r.Context(), w)
+ baseErr = components.ResultsPage(tdata).Render(w)
}
if baseErr != nil {
log.Error("template error", "template", importerType, "error", baseErr)
@@ -192,7 +190,7 @@ func NewMux(
Assets: frontend.Assets,
},
components.ResultData{},
- ).Render(r.Context(), w)
+ ).Render(w)
if err != nil {
errorHandler(w, r, err.Error(), http.StatusInternalServerError)
@@ -248,9 +246,9 @@ func NewMux(
var baseErr error
if r.Header.Get("Fetch") == "true" {
w.Header().Add("Content-Type", "text/html; charset=utf-8")
- baseErr = components.Detail(*doc).Render(r.Context(), w)
+ baseErr = components.Detail(*doc).Render(w)
} else {
- baseErr = components.DetailPage(tdata, *doc).Render(r.Context(), w)
+ baseErr = components.DetailPage(tdata, *doc).Render(w)
}
if baseErr != nil {
log.Error("template error", "template", importerSingular, "error", baseErr)
diff --git a/modd.conf b/modd.conf
index e26c754..0a3e6a1 100644
--- a/modd.conf
+++ b/modd.conf
@@ -2,7 +2,6 @@ internal/index/indexer.go {
prep +onchange: "just reindex"
}
-**/*.go !**/*_templ.go config.toml {
- daemon +sigint: templ generate --watch --proxy="http://localhost:3000" --open-browser=false \
- --cmd="go run ./cmd/searchix-web --dev --config config.toml"
+**/*.go config.toml {
+ daemon +sigint: go run ./cmd/searchix-web --dev --config config.toml
}
diff --git a/nix/dev-shell.nix b/nix/dev-shell.nix
index 7d21e9d..b9ede6c 100644
--- a/nix/dev-shell.nix
+++ b/nix/dev-shell.nix
@@ -12,7 +12,6 @@ mkShell {
goEnv
sd
- templ
modd
brotli
bleve
diff --git a/nix/package.nix b/nix/package.nix
index 081ddab..9bef057 100644
--- a/nix/package.nix
+++ b/nix/package.nix
@@ -37,7 +37,6 @@ buildGoApplication {
patchPhase = ''
rm -f frontend/static/base.css
cp ${css} frontend/static/base.css
- ${pkgs.templ}/bin/templ generate
'';
tags = [ "embed" ];
ldflags = [
diff --git a/nix/pre-commit-checks.nix b/nix/pre-commit-checks.nix
index 7e53f30..6bee0ae 100644
--- a/nix/pre-commit-checks.nix
+++ b/nix/pre-commit-checks.nix
@@ -4,38 +4,10 @@ rec {
hooks = {
gotest.enable = false;
golangci-lint.enable = true;
- staticcheck =
- let
- wrapper = pkgs.symlinkJoin {
- name = "staticcheck-wrapped";
- paths = [ pkgs.go-tools ];
- nativeBuildInputs = [ pkgs.makeWrapper ];
- postBuild = ''
- wrapProgram $out/bin/staticcheck \
- --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.go ]}
- '';
- };
- in
- {
- enable = true;
- package = wrapper;
- entry =
- let
- script = pkgs.writeShellScript "precommit-staticcheck" ''
- err=0
- for dir in $(echo "$@" | xargs -n1 dirname | sort -u); do
- ${hooks.staticcheck.package}/bin/staticcheck ./"$dir"
- code="$?"
- if [[ "$err" -eq 0 ]]; then
- err="$code"
- fi
- done
- exit $err
- '';
- in
- builtins.toString script;
- };
+ staticcheck = {
+ enable = true;
+ };
statix = {
enable = true;
# ignore is a glob
@@ -57,7 +29,7 @@ rec {
check-symlinks.enable = true;
editorconfig-checker = {
enable = true;
- excludes = [ "\.md$" ];
+ excludes = [ "\.md$" "\.ya?ml$" ];
};
prettier = {
enable = true;
diff --git a/staticcheck.conf b/staticcheck.conf
new file mode 100644
index 0000000..8d86ee2
--- /dev/null
+++ b/staticcheck.conf
@@ -0,0 +1 @@
+dot_import_whitelist = ["go.alanpearce.eu/gomponents/html"]
--
cgit 1.4.1