Skip to content

Commit

Permalink
Merge branch 'functional'
Browse files Browse the repository at this point in the history
  • Loading branch information
will-wow committed Mar 3, 2024
2 parents 11c1e37 + 753664c commit 97d2c62
Show file tree
Hide file tree
Showing 61 changed files with 1,825 additions and 1,172 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"]
"go.lintFlags": ["--fast"],
"cSpell.words": ["gomponents"]
}
77 changes: 42 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ Well-documented Go functions for building [HTMX](https://htmx.org) attributes.
[![Go Reference](https://pkg.go.dev/badge/github.com/will-wow/typed-htmx-go.svg)](https://pkg.go.dev/github.com/will-wow/typed-htmx-go/hx)
![Code Coverage](./assets/badge.svg)

[htmx](https://htmx.org) is a powerful and simple tool for building dynamic, server-rendered web applications. It also pairs particularly well with [Templ](https://templ.guide), a JSX-like template builder for Go.
[htmx](https://htmx.org) is a powerful and simple tool for building dynamic, server-rendered web applications. It also pairs particularly well with [Templ](https://templ.guide) (a JSX-like template language for Go) and [Gomponents](https://www.gomponents.com/) (a Go-native view library).

However, when using it I have to have the [docs](https://htmx.org/reference) open, to look up the specifics of each modifier. I wanted the simplicity of HTMX, the editor support of Go, and beautiful integration with Templ, without sacrificing performance. I built typed-htmx-go.

`hx.New()` provides a builder struct that wraps all documented [HTMX attributes](https://htmx.org/reference/) with Go functions, and `.Build()` returns a map that conforms to [templ.Attributes](https://templ.guide/syntax-and-usage/attributes). This allows the result to be spread into a Templ element or be passed to a Templ component. However this library has no actual dependency of Templ, and can be used by anything that can render a `map[string]any` to HTML attributes. You can also use `.String()` to get a formatted string of HTML attributes to directly render in a template.
`hx.NewTempl()` provides an `hx` struct that exposes all documented [HTMX attributes](https://htmx.org/reference/) as Go functions, and returns either [templ.Attributes](https://templ.guide/syntax-and-usage/attributes) for to be spread into a Templ element, or an attribute `g.Node` for Gomponents. You can also support other templating libraries by simply passing a new attribute constructor to `HX{}`.

Each function and option includes a Godoc comment copied from the extensive HTMX docs, so you can access that documentation right from the comfort of your editor.

## Examples

Templ usage examples are in [examples/templ](./examples/templ) (hosted at [typed-htmx-go.vercel.app](https://typed-htmx-go.vercel.app/))
Usage examples are in [examples](./examples) (hosted at [typed-htmx-go.vercel.app](https://typed-htmx-go.vercel.app/))

## HTMX Version

`hx` strives to keep up with HTMX releases. It currently supports HTMX `v1.9.10`.
`typed-hx-go` strives to keep up with HTMX releases. It currently supports HTMX `v1.9.10`.

## Goals

Expand All @@ -39,9 +39,9 @@ That's necessary for a tool that embeds in standard HTML attributes, but it requ

Sometimes that means that `hx` will provide multiple functions for a single attribute. For instance, `hx` provides three methods for `hx-target`, stop you from doing `hx-target='this #element'` (which is invalid), and instead guide you towards valid options like:

- `.Target("#element")` => `hx-target="#element'`
- `.TargetNonStandard(hx.TargetThis)` => `hx-target='this'`
- `.TargetRelative(hx.TargetSelectorNext, "#element")` => `hx-target='next #element'`
- `hx.Target("#element")` => `hx-target="#element'`
- `hx.TargetNonStandard(hx.TargetThis)` => `hx-target='this'`
- `hx.TargetRelative(hx.TargetSelectorNext, "#element")` => `hx-target='next #element'`

As a corollary to this goal, it should also be difficult to create an invalid attribute. So if modifier must be accompanied by a selector (like the `next` in `hx-target`), then it must be exposed through a two-argument function.

Expand Down Expand Up @@ -73,29 +73,36 @@ This also means that written `hx` attributes should look like HTMX attributes. S
The `hx` equivalent should take the same names and values in the same order:

```go
// templ
<form
method="GET"
action="/page"
{ hx.New().
Get("/page").
Target("body").
ReplaceURL(true).
Swap(
{ hx.Get("/page")... }
{ hx.Target("body")... }
{ hx.ReplaceURL(true)... }
{ hx.Swap(
swap.New().
ScrollElement("#search-results", swap.Top).
Swap(time.Second),
).
Build()... }
)... }
>
```

### Templ compatibility

While this library isn't tied to Templ directly, it should always return attribute maps that work as [Templ attributes](https://templ.guide/syntax-and-usage/attributes) for spreading, and generally work nicely within Templ components.

However, it should also be possible to directly print attributes for use in a standard Go [html/template](https://pkg.go.dev/html/template#HTMLAttrhttps://pkg.go.dev/html/template) (with [HTMLAttr](https://pkg.go.dev/html/template#HTMLAttrhttps://pkg.go.dev/html/template#HTMLAttr)).

TODO: Figure out a safer method of including in an html/template.
```go
// gomponents
Form(
Method("GET"),
Action("/page"),
hx.Get("/page"),
hx.Target("body"),
hx.ReplaceURL(true),
hx.Swap(
swap.New().
ScrollElement("#search-results", swap.Top).
Swap(time.Second),
),
)
```

### Fully tested

Expand All @@ -111,34 +118,34 @@ go get github.com/will-wow/typed-htmx-go

```go
import (
"github.com/will-wow/typed-htmx-go/hx"
"github.com/will-wow/typed-htmx-go/hx/swap"
"github.com/will-wow/typed-htmx-go/htmx"
"github.com/will-wow/typed-htmx-go/htmx/swap"
)

var hx = htmx.NewTempl()

templ SearchInput(search string) {
<form
method="GET"
action="/page"
class="relative mb-2"
{ hx.New().
Get(currentPage).
Target("body").
ReplaceURL(true).
Swap(swap.New().ScrollElement("#search-results", swap.Top)).
Build()... }
{ hx.Get(currentPage)...}
{ hx.Target("body")...}
{ hx.ReplaceURL(true)...}
{ hx.Swap(swap.New().ScrollElement("#search-results", swap.Top))...}
>
@ui.Input(
hx.New().
Get(currentPage).
Trigger("input changed delay:500ms").
More(map[string]any{
htmx.TemplAttrs(
hx.Get(currentPage),
hx.Trigger("input changed delay:500ms"),
templ.Attributes{
"id": "search",
"placeholder": "Search (/)",
"type": "search",
"name": "search",
"value": search,
}).
Build(),
},
),
"peer")
<div class="absolute bottom-0 right-2 top-0 flex items-center leading-none peer-focus:hidden">
@icon.Search()
Expand Down
12 changes: 12 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ tasks:
fmt:go:
desc: Run goimports
cmds:
- go work sync
- go mod tidy
- go run golang.org/x/tools/cmd/[email protected] -w -local github.com/will-wow/typed-htmx-go .

Expand All @@ -69,9 +70,20 @@ tasks:
- task: fmt
- task: lint
- task: test:cover:badge
- task: examples:ready

tools:
desc: Install tools
cmds:
# Install prettier for formatting non-go files
- npm install

dev:
desc: Run the example server with a watch for templ, go, and static files
cmds:
- task: examples:dev

includes:
examples:
taskfile: ./examples/Taskfile.yml
dir: ./examples
2 changes: 1 addition & 1 deletion assets/badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
"import (",
" \"github.com/lithammer/dedent\"",
"",
" \"github.com/will-wow/typed-htmx-go/examples/templ/web/layout\"",
" \"github.com/will-wow/typed-htmx-go/examples/web/layout\"",
" \"github.com/will-wow/typed-htmx-go/hx\"",
" \"github.com/will-wow/typed-htmx-go/hx/swap\"",
" \"github.com/will-wow/typed-htmx-go/htmx/swap\"",
")",
"",
"templ page() {",
Expand Down
6 changes: 3 additions & 3 deletions examples/templ/Taskfile.yml → examples/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ tasks:
fmt:
desc: Run goimports
cmds:
- go mod tidy
- go run golang.org/x/tools/cmd/[email protected] -w -local github.com/will-wow/typed-htmx-go/examples/templ .
# - go mod tidy
- go run golang.org/x/tools/cmd/[email protected] -w -local github.com/will-wow/typed-htmx-go/examples .

test:
desc: Run test suite
Expand All @@ -44,7 +44,7 @@ tasks:
cmds:
- templ generate
# Re-format generated code
- go run golang.org/x/tools/cmd/[email protected] -w -local github.com/will-wow/typed-htmx-go/examples/templ ./
- go run golang.org/x/tools/cmd/[email protected] -w -local github.com/will-wow/typed-htmx-go/examples ./
sources:
- "**/*.templ"
generates:
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/templ/api/index.go → examples/api/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package api
import (
"net/http"

"github.com/will-wow/typed-htmx-go/examples/templ/web"
"github.com/will-wow/typed-htmx-go/examples/web"
)

func Index(w http.ResponseWriter, r *http.Request) {
Expand Down
1 change: 1 addition & 0 deletions examples/checksum/gen
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
234b8f866e8559473698c77116b5f561
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"os"
"time"

"github.com/will-wow/typed-htmx-go/examples/templ/web"
"github.com/will-wow/typed-htmx-go/examples/web"
)

func main() {
Expand Down
8 changes: 3 additions & 5 deletions examples/templ/go.mod → examples/go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
module github.com/will-wow/typed-htmx-go/examples/templ
module github.com/will-wow/typed-htmx-go/examples

go 1.22.0

require (
github.com/a-h/templ v0.2.543
github.com/will-wow/typed-htmx-go v0.0.3
)
require github.com/a-h/templ v0.2.543

require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/lithammer/dedent v1.1.0
github.com/maragudk/gomponents v0.20.2
)

require (
Expand Down
4 changes: 2 additions & 2 deletions examples/templ/go.sum → examples/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/will-wow/typed-htmx-go v0.0.3 h1:zF0ESFMm2Ry2OEe+mQ+2zcULM1aEqWaDwdyGEZWC/1w=
github.com/will-wow/typed-htmx-go v0.0.3/go.mod h1:vBV9acu4/cjaeLc1Z2z4ZruJYpF1KdCoFebp3CWNaPA=
github.com/maragudk/gomponents v0.20.2 h1:39FhnBNNCJzqNcD9Hmvp/5xj0otweFoyvVgFG6kXoy0=
github.com/maragudk/gomponents v0.20.2/go.mod h1:nHkNnZL6ODgMBeJhrZjkMHVvNdoYsfmpKB2/hjdQ0Hg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
Expand Down
65 changes: 0 additions & 65 deletions examples/templ/web/bulkupdate/bulkupdate.go

This file was deleted.

Loading

0 comments on commit 97d2c62

Please sign in to comment.