Merge pull request #8 from maddalax/remove-echo

wip - swap out echo with std lib + chi router
This commit is contained in:
maddalax 2024-09-26 12:55:23 -07:00 committed by GitHub
commit 4d003b6db2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 244 additions and 480 deletions

View file

@ -5,6 +5,7 @@ go 1.23.0
require ( require (
github.com/dave/jennifer v1.7.1 github.com/dave/jennifer v1.7.1
github.com/fsnotify/fsnotify v1.7.0 github.com/fsnotify/fsnotify v1.7.0
github.com/google/uuid v1.6.0
golang.org/x/mod v0.21.0 golang.org/x/mod v0.21.0
golang.org/x/net v0.29.0 golang.org/x/net v0.29.0
golang.org/x/sys v0.25.0 golang.org/x/sys v0.25.0

View file

@ -27,7 +27,8 @@ type Partial struct {
} }
const GeneratedDirName = "__htmgo" const GeneratedDirName = "__htmgo"
const EchoModuleName = "github.com/labstack/echo/v4" const HttpModuleName = "net/http"
const ChiModuleName = "github.com/go-chi/chi/v5"
const ModuleName = "github.com/maddalax/htmgo/framework/h" const ModuleName = "github.com/maddalax/htmgo/framework/h"
var PackageName = fmt.Sprintf("package %s", GeneratedDirName) var PackageName = fmt.Sprintf("package %s", GeneratedDirName)
@ -198,7 +199,7 @@ func buildGetPartialFromContext(builder *CodeBuilder, partials []Partial) {
fName := "GetPartialFromContext" fName := "GetPartialFromContext"
body := ` body := `
path := ctx.Request().URL.Path path := r.URL.Path
` `
if len(partials) == 0 { if len(partials) == 0 {
@ -215,7 +216,7 @@ func buildGetPartialFromContext(builder *CodeBuilder, partials []Partial) {
body += fmt.Sprintf(` body += fmt.Sprintf(`
if path == "%s" || path == "%s" { if path == "%s" || path == "%s" {
cc := ctx.(*h.RequestContext) cc := r.Context().Value(h.RequestContextKey).(*h.RequestContext)
return %s(cc) return %s(cc)
} }
`, f.FuncName, path, caller) `, f.FuncName, path, caller)
@ -226,7 +227,7 @@ func buildGetPartialFromContext(builder *CodeBuilder, partials []Partial) {
f := Function{ f := Function{
Name: fName, Name: fName,
Parameters: []NameType{ Parameters: []NameType{
{Name: "ctx", Type: "echo.Context"}, {Name: "r", Type: "*http.Request"},
}, },
Return: []ReturnType{ Return: []ReturnType{
{Type: "*h.Partial"}, {Type: "*h.Partial"},
@ -237,14 +238,15 @@ func buildGetPartialFromContext(builder *CodeBuilder, partials []Partial) {
builder.Append(builder.BuildFunction(f)) builder.Append(builder.BuildFunction(f))
registerFunction := fmt.Sprintf(` registerFunction := fmt.Sprintf(`
func RegisterPartials(f *echo.Echo) { func RegisterPartials(router *chi.Mux) {
f.Any("%s/partials*", func(ctx echo.Context) error { router.Handle("/%s/partials*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
partial := GetPartialFromContext(ctx) partial := GetPartialFromContext(r)
if partial == nil { if partial == nil {
return ctx.NoContent(404) w.WriteHeader(404)
} return
return h.PartialView(ctx, partial) }
}) h.PartialView(w, partial)
}))
} }
`, moduleName) `, moduleName)
@ -267,7 +269,8 @@ func writePartialsFile() {
builder.AppendLine(GeneratedFileLine) builder.AppendLine(GeneratedFileLine)
builder.AppendLine(PackageName) builder.AppendLine(PackageName)
builder.AddImport(ModuleName) builder.AddImport(ModuleName)
builder.AddImport(EchoModuleName) builder.AddImport(HttpModuleName)
builder.AddImport(ChiModuleName)
moduleName := GetModuleName() moduleName := GetModuleName()
for _, partial := range partials { for _, partial := range partials {
@ -307,7 +310,8 @@ func writePagesFile() {
builder := NewCodeBuilder(nil) builder := NewCodeBuilder(nil)
builder.AppendLine(GeneratedFileLine) builder.AppendLine(GeneratedFileLine)
builder.AppendLine(PackageName) builder.AppendLine(PackageName)
builder.AddImport(EchoModuleName) builder.AddImport(HttpModuleName)
builder.AddImport(ChiModuleName)
pages, _ := findPublicFuncsReturningHPage("pages") pages, _ := findPublicFuncsReturningHPage("pages")
@ -331,18 +335,20 @@ func writePagesFile() {
for _, page := range pages { for _, page := range pages {
call := fmt.Sprintf("%s.%s", page.Package, page.FuncName) call := fmt.Sprintf("%s.%s", page.Package, page.FuncName)
body += fmt.Sprintf(` body += fmt.Sprintf(
f.GET("%s", func(ctx echo.Context) error { `
cc := ctx.(*h.RequestContext) router.Get("%s", func(writer http.ResponseWriter, request *http.Request) {
return h.HtmlView(ctx, %s(cc)) cc := request.Context().Value(h.RequestContextKey).(*h.RequestContext)
h.HtmlView(writer, %s(cc))
}) })
`, formatRoute(page.Path), call) `, formatRoute(page.Path), call,
)
} }
f := Function{ f := Function{
Name: fName, Name: fName,
Parameters: []NameType{ Parameters: []NameType{
{Name: "f", Type: "*echo.Echo"}, {Name: "router", Type: "*chi.Mux"},
}, },
Body: body, Body: body,
} }
@ -377,19 +383,20 @@ func GenAst(flags ...process.RunFlag) error {
writePagesFile() writePagesFile()
WriteFile("__htmgo/setup-generated.go", func(content *ast.File) string { WriteFile("__htmgo/setup-generated.go", func(content *ast.File) string {
return `
return fmt.Sprintf(`
// Package __htmgo THIS FILE IS GENERATED. DO NOT EDIT. // Package __htmgo THIS FILE IS GENERATED. DO NOT EDIT.
package __htmgo package __htmgo
import ( import (
"github.com/labstack/echo/v4" "%s"
) )
func Register(e *echo.Echo) { func Register(r *chi.Mux) {
RegisterPartials(e) RegisterPartials(r)
RegisterPages(e) RegisterPages(r)
} }
` `, ChiModuleName)
}) })
return nil return nil

View file

@ -1,13 +0,0 @@
// Package __htmgo THIS FILE IS GENERATED. DO NOT EDIT.
package __htmgo
import "github.com/labstack/echo/v4"
import "github.com/maddalax/htmgo/framework/h"
import "todolist/pages"
func RegisterPages(f *echo.Echo) {
f.GET("/", func(ctx echo.Context) error {
cc := ctx.(*h.RequestContext)
return h.HtmlView(ctx, pages.TaskListPage(cc))
})
}

View file

@ -1,49 +0,0 @@
// Package __htmgo THIS FILE IS GENERATED. DO NOT EDIT.
package __htmgo
import "github.com/maddalax/htmgo/framework/h"
import "github.com/labstack/echo/v4"
import "todolist/partials/task"
func GetPartialFromContext(ctx echo.Context) *h.Partial {
path := ctx.Request().URL.Path
if path == "UpdateName" || path == "/todolist/partials/task.UpdateName" {
cc := ctx.(*h.RequestContext)
return task.UpdateName(cc)
}
if path == "EditNameForm" || path == "/todolist/partials/task.EditNameForm" {
cc := ctx.(*h.RequestContext)
return task.EditNameForm(cc)
}
if path == "ToggleCompleted" || path == "/todolist/partials/task.ToggleCompleted" {
cc := ctx.(*h.RequestContext)
return task.ToggleCompleted(cc)
}
if path == "CompleteAll" || path == "/todolist/partials/task.CompleteAll" {
cc := ctx.(*h.RequestContext)
return task.CompleteAll(cc)
}
if path == "ClearCompleted" || path == "/todolist/partials/task.ClearCompleted" {
cc := ctx.(*h.RequestContext)
return task.ClearCompleted(cc)
}
if path == "Create" || path == "/todolist/partials/task.Create" {
cc := ctx.(*h.RequestContext)
return task.Create(cc)
}
if path == "ChangeTab" || path == "/todolist/partials/task.ChangeTab" {
cc := ctx.(*h.RequestContext)
return task.ChangeTab(cc)
}
return nil
}
func RegisterPartials(f *echo.Echo) {
f.Any("todolist/partials*", func(ctx echo.Context) error {
partial := GetPartialFromContext(ctx)
if partial == nil {
return ctx.NoContent(404)
}
return h.PartialView(ctx, partial)
})
}

View file

@ -1,11 +0,0 @@
// Package __htmgo THIS FILE IS GENERATED. DO NOT EDIT.
package __htmgo
import (
"github.com/labstack/echo/v4"
)
func Register(e *echo.Echo) {
RegisterPartials(e)
RegisterPages(e)
}

View file

@ -4,9 +4,9 @@ go 1.23.0
require ( require (
entgo.io/ent v0.14.1 entgo.io/ent v0.14.1
github.com/go-chi/chi/v5 v5.1.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/labstack/echo/v4 v4.12.0 github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f
github.com/maddalax/htmgo/framework v0.0.0-20240924182609-b2c6b5207510
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16
) )
@ -17,16 +17,8 @@ require (
github.com/go-openapi/inflect v0.19.0 // indirect github.com/go-openapi/inflect v0.19.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/hashicorp/hcl/v2 v2.13.0 // indirect github.com/hashicorp/hcl/v2 v2.13.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/mod v0.20.0 // indirect golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect golang.org/x/text v0.18.0 // indirect
) )

View file

@ -10,6 +10,8 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
@ -31,19 +33,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f h1:A4MEslfWXKvqsZt1DbvZpguzVAbyjCRclEZNt6TjSRw=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f/go.mod h1:JBHqkKSv6frIsSlT1itIU0hUTW9NgDcyM6Cf6npK0bQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/maddalax/htmgo/framework v0.0.0-20240923034654-e82ed0497052 h1:iEtAIL0zLDI3hp56VzHAccC4c6Iuem6dMARr9/aki9I=
github.com/maddalax/htmgo/framework v0.0.0-20240923034654-e82ed0497052/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240924182609-b2c6b5207510 h1:Gl9QRbIr008Qgvcsnsnkn1Q7Fusw3Hn6dPEbiV8M8wk=
github.com/maddalax/htmgo/framework v0.0.0-20240924182609-b2c6b5207510/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
@ -54,28 +45,16 @@ github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

View file

@ -2,11 +2,11 @@ package main
import ( import (
"embed" "embed"
"github.com/labstack/echo/v4"
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"github.com/maddalax/htmgo/framework/service" "github.com/maddalax/htmgo/framework/service"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"io/fs" "io/fs"
"net/http"
"todolist/__htmgo" "todolist/__htmgo"
"todolist/ent" "todolist/ent"
"todolist/infrastructure/db" "todolist/infrastructure/db"
@ -22,18 +22,22 @@ func main() {
return db.Provide() return db.Provide()
}) })
sub, err := fs.Sub(StaticAssets, "assets/dist")
if err != nil {
panic(err)
}
h.Start(h.AppOpts{ h.Start(h.AppOpts{
ServiceLocator: locator, ServiceLocator: locator,
LiveReload: true, LiveReload: true,
Register: func(e *echo.Echo) { Register: func(app *h.App) {
e.StaticFS("/public", sub)
__htmgo.Register(e) sub, err := fs.Sub(StaticAssets, "assets/dist")
if err != nil {
panic(err)
}
http.FileServerFS(sub)
app.Router.Handle("/public/*", http.StripPrefix("/public", http.FileServerFS(sub)))
__htmgo.Register(app.Router)
}, },
}) })
} }

View file

@ -8,6 +8,10 @@ func RootPage(children ...h.Ren) h.Ren {
return h.Html( return h.Html(
h.HxExtension(h.BaseExtensions()), h.HxExtension(h.BaseExtensions()),
h.Head( h.Head(
h.Meta("viewport", "width=device-width, initial-scale=1"),
h.Meta("title", "htmgo todo mvc"),
h.Meta("description", "an example of how to build a todo mvc app with htmgo"),
h.Meta("charset", "utf-8"),
h.Link("/public/main.css", "stylesheet"), h.Link("/public/main.css", "stylesheet"),
h.Script("/public/htmgo.js"), h.Script("/public/htmgo.js"),
), ),

View file

@ -68,9 +68,9 @@ func CompleteAllIcon(list []*ent.Task) *h.Element {
})) }))
return h.Div( return h.Div(
h.ClassX("absolute top-0 left-0 p-4 rotate-90 text-2xl cursor-pointer", map[string]bool{ h.ClassX("absolute top-1 left-5 p-2 rotate-90 text-3xl cursor-pointer", map[string]bool{
"text-slate-400": notCompletedCount > 0, "text-slate-400": notCompletedCount > 0,
}), h.Text(""), }), h.Text("›"),
h.PostPartialWithQs(CompleteAll, h.NewQs("complete", h.Ternary(notCompletedCount > 0, "true", "false"))), h.PostPartialWithQs(CompleteAll, h.NewQs("complete", h.Ternary(notCompletedCount > 0, "true", "false"))),
) )
} }

View file

@ -2,18 +2,9 @@ module github.com/maddalax/htmgo/framework-ui
go 1.23.0 go 1.23.0
require github.com/maddalax/htmgo/framework v0.1.0 require github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f
require ( require (
github.com/go-chi/chi/v5 v5.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/labstack/echo/v4 v4.12.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
) )

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,6 @@ let lastVersion = "";
htmx.defineExtension("livereload", { htmx.defineExtension("livereload", {
init: function () { init: function () {
const host = window.location.host;
let enabled = false let enabled = false
for (const element of Array.from(htmx.findAll("[hx-ext]"))) { for (const element of Array.from(htmx.findAll("[hx-ext]"))) {
@ -21,25 +20,25 @@ htmx.defineExtension("livereload", {
} }
console.log('livereload extension initialized.'); console.log('livereload extension initialized.');
// Create a new EventSource object and point it to your SSE endpoint
createWebSocketClient({ const eventSource = new EventSource('/dev/livereload');
url: `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${host}/dev/livereload`, // Listen for messages from the server
onOpen: () => { eventSource.onmessage = function(event) {
}, const message = event.data
onMessage: (message) => { // Log the message data received from the server
if(lastVersion === "") { if(lastVersion === "") {
lastVersion = message; lastVersion = message;
}
if(lastVersion !== message) {
lastVersion = message;
reload()
}
},
onError: (error) => {
},
onClose: () => {
} }
}) if(lastVersion !== message) {
lastVersion = message;
reload()
}
};
// Handle errors (e.g., when the connection is closed)
eventSource.onerror = function(error) {
console.error('EventSource error:', error);
};
}, },
// @ts-ignore // @ts-ignore
onEvent: function (name, evt) { onEvent: function (name, evt) {
@ -49,14 +48,4 @@ htmx.defineExtension("livereload", {
function reload() { function reload() {
window.location.reload() window.location.reload()
// fetch(window.location.href).then(response => {
// return response.text();
// }).then(html => {
// document.open();
// document.write(html);
// document.close();
// }).catch(err => {
// console.log('failed to fetch live reload', err)
// setTimeout(reload, 100)
// })
} }

View file

@ -3,22 +3,13 @@ module github.com/maddalax/htmgo/framework
go 1.23.0 go 1.23.0
require ( require (
github.com/go-chi/chi/v5 v5.1.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/labstack/echo/v4 v4.12.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
golang.org/x/net v0.29.0
) )
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View file

@ -1,34 +1,13 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View file

@ -1,18 +1,20 @@
package h package h
import ( import (
"context"
"fmt" "fmt"
"github.com/labstack/echo/v4" "github.com/go-chi/chi/v5"
"github.com/maddalax/htmgo/framework/hx" "github.com/maddalax/htmgo/framework/hx"
"github.com/maddalax/htmgo/framework/service" "github.com/maddalax/htmgo/framework/service"
"log/slog" "log/slog"
"net/http"
"os/exec" "os/exec"
"runtime" "runtime"
"time" "time"
) )
type RequestContext struct { type RequestContext struct {
echo.Context *http.Request
locator *service.Locator locator *service.Locator
isBoosted bool isBoosted bool
currentBrowserUrl string currentBrowserUrl string
@ -21,6 +23,25 @@ type RequestContext struct {
hxTargetId string hxTargetId string
hxTriggerName string hxTriggerName string
hxTriggerId string hxTriggerId string
kv map[string]interface{}
}
func (c *RequestContext) QueryParam(key string) string {
return c.Request.URL.Query().Get(key)
}
func (c *RequestContext) Set(key string, value interface{}) {
if c.kv == nil {
c.kv = make(map[string]interface{})
}
c.kv[key] = value
}
func (c *RequestContext) Get(key string) interface{} {
if c.kv == nil {
return nil
}
return c.kv[key]
} }
func (c *RequestContext) ServiceLocator() *service.Locator { func (c *RequestContext) ServiceLocator() *service.Locator {
@ -30,65 +51,72 @@ func (c *RequestContext) ServiceLocator() *service.Locator {
type AppOpts struct { type AppOpts struct {
LiveReload bool LiveReload bool
ServiceLocator *service.Locator ServiceLocator *service.Locator
Register func(echo *echo.Echo) Register func(app *App)
} }
type App struct { type App struct {
Opts AppOpts Opts AppOpts
Echo *echo.Echo Router *chi.Mux
}
var instance *App
func GetApp() *App {
if instance == nil {
panic("App instance not initialized")
}
return instance
} }
func Start(opts AppOpts) { func Start(opts AppOpts) {
e := echo.New() router := chi.NewRouter()
instance := App{ instance := App{
Opts: opts, Opts: opts,
Echo: e, Router: router,
} }
instance.start() instance.start()
} }
const RequestContextKey = "htmgo.request.context"
func populateHxFields(cc *RequestContext) { func populateHxFields(cc *RequestContext) {
cc.isBoosted = cc.Request().Header.Get(hx.BoostedHeader) == "true" cc.isBoosted = cc.Request.Header.Get(hx.BoostedHeader) == "true"
cc.currentBrowserUrl = cc.Request().Header.Get(hx.CurrentUrlHeader) cc.isBoosted = cc.Request.Header.Get(hx.BoostedHeader) == "true"
cc.hxPromptResponse = cc.Request().Header.Get(hx.PromptResponseHeader) cc.currentBrowserUrl = cc.Request.Header.Get(hx.CurrentUrlHeader)
cc.isHxRequest = cc.Request().Header.Get(hx.RequestHeader) == "true" cc.hxPromptResponse = cc.Request.Header.Get(hx.PromptResponseHeader)
cc.hxTargetId = cc.Request().Header.Get(hx.TargetIdHeader) cc.isHxRequest = cc.Request.Header.Get(hx.RequestHeader) == "true"
cc.hxTriggerName = cc.Request().Header.Get(hx.TriggerNameHeader) cc.hxTargetId = cc.Request.Header.Get(hx.TargetIdHeader)
cc.hxTriggerId = cc.Request().Header.Get(hx.TriggerIdHeader) cc.hxTriggerName = cc.Request.Header.Get(hx.TriggerNameHeader)
cc.hxTriggerId = cc.Request.Header.Get(hx.TriggerIdHeader)
} }
func (a App) start() { func (app *App) UseWithContext(h func(w http.ResponseWriter, r *http.Request, context map[string]any)) {
app.Router.Use(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cc := r.Context().Value(RequestContextKey).(*RequestContext)
h(w, r, cc.kv)
handler.ServeHTTP(w, r)
})
})
}
if a.Opts.Register != nil { func (app *App) start() {
a.Opts.Register(a.Echo)
}
a.Echo.Use(func(next echo.HandlerFunc) echo.HandlerFunc { app.Router.Use(func(h http.Handler) http.Handler {
return func(c echo.Context) error { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cc := &RequestContext{ cc := &RequestContext{
Context: c, locator: app.Opts.ServiceLocator,
locator: a.Opts.ServiceLocator, Request: r,
kv: make(map[string]interface{}),
} }
populateHxFields(cc) populateHxFields(cc)
return next(cc) ctx := context.WithValue(r.Context(), RequestContextKey, cc)
} h.ServeHTTP(w, r.WithContext(ctx))
})
}) })
if a.Opts.LiveReload && IsDevelopment() { if app.Opts.Register != nil {
AddLiveReloadHandler("/dev/livereload", a.Echo) app.Opts.Register(app)
}
if app.Opts.LiveReload && IsDevelopment() {
app.AddLiveReloadHandler("/dev/livereload")
} }
port := ":3000" port := ":3000"
err := a.Echo.Start(port) slog.Info(fmt.Sprintf("Server started on port %s", port))
err := http.ListenAndServe(port, app.Router)
if err != nil { if err != nil {
// If we are in watch mode, just try to kill any processes holding that port // If we are in watch mode, just try to kill any processes holding that port
@ -103,7 +131,7 @@ func (a App) start() {
cmd.Run() cmd.Run()
} }
time.Sleep(time.Millisecond * 50) time.Sleep(time.Millisecond * 50)
err = a.Echo.Start(port) err = http.ListenAndServe(":3000", app.Router)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -114,46 +142,38 @@ func (a App) start() {
} }
} }
func HtmlView(c echo.Context, page *Page) error { func writeHtml(w http.ResponseWriter, element Ren) error {
root := page.Root w.Header().Set("Content-Type", "text/html")
return c.HTML(200, _, err := fmt.Fprint(w, Render(element))
Render( return err
root,
),
)
} }
func PartialViewWithHeaders(c echo.Context, headers *Headers, partial *Partial) error { func HtmlView(w http.ResponseWriter, page *Page) error {
return writeHtml(w, page.Root)
}
func PartialViewWithHeaders(w http.ResponseWriter, headers *Headers, partial *Partial) error {
if partial.Headers != nil { if partial.Headers != nil {
for s, a := range *partial.Headers { for s, a := range *partial.Headers {
c.Set(s, a) w.Header().Set(s, a)
} }
} }
if headers != nil { if headers != nil {
for s, a := range *headers { for s, a := range *headers {
c.Response().Header().Set(s, a) w.Header().Set(s, a)
} }
} }
return c.HTML(200, return writeHtml(w, partial.Root)
Render(
partial,
),
)
} }
func PartialView(c echo.Context, partial *Partial) error { func PartialView(w http.ResponseWriter, partial *Partial) error {
c.Set(echo.HeaderContentType, echo.MIMETextHTML)
if partial.Headers != nil { if partial.Headers != nil {
for s, a := range *partial.Headers { for s, a := range *partial.Headers {
c.Response().Header().Set(s, a) w.Header().Set(s, a)
} }
} }
return c.HTML(200, return writeHtml(w, partial.Root)
Render(
partial,
),
)
} }

View file

@ -37,7 +37,7 @@ func IfElseLazy[T any](condition bool, cb1 func() T, cb2 func() T) T {
} }
func IfHtmxRequest(ctx *RequestContext, node Ren) Ren { func IfHtmxRequest(ctx *RequestContext, node Ren) Ren {
if ctx.Get("HX-Request") != "" { if ctx.isHxRequest {
return node return node
} }
return Empty() return Empty()

View file

@ -34,7 +34,7 @@ func CombineHeaders(headers ...*Headers) *Headers {
} }
func CurrentPath(ctx *RequestContext) string { func CurrentPath(ctx *RequestContext) string {
current := ctx.Request().Header.Get(hx.CurrentUrlHeader) current := ctx.Header.Get(hx.CurrentUrlHeader)
parsed, err := url.Parse(current) parsed, err := url.Parse(current)
if err != nil { if err != nil {
return "" return ""

View file

@ -1,30 +1,41 @@
package h package h
import ( import (
"fmt"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4" "net/http"
"golang.org/x/net/websocket"
"time" "time"
) )
var Version = uuid.NewString() var Version = uuid.NewString()
func handler(c echo.Context) error { func sseHandler(w http.ResponseWriter, r *http.Request) {
websocket.Handler(func(ws *websocket.Conn) { // Set the necessary headers
defer ws.Close() w.Header().Set("Content-Type", "text/event-stream")
_ = websocket.Message.Send(ws, Version) w.Header().Set("Cache-Control", "no-cache")
// keep ws alive w.Header().Set("Connection", "keep-alive")
for { w.Header().Set("Access-Control-Allow-Origin", "*") // Optional for CORS
err := websocket.Message.Send(ws, Version)
if err != nil { // Flush the headers immediately
return flusher, ok := w.(http.Flusher)
}
time.Sleep(500 * time.Millisecond) if !ok {
http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
return
}
for {
// Write an event to the stream
_, err := fmt.Fprintf(w, "data: %s\n\n", Version)
if err != nil {
break
} }
}).ServeHTTP(c.Response(), c.Request()) // Flush the response to ensure the client gets it immediately
return nil flusher.Flush()
time.Sleep(500 * time.Millisecond)
}
} }
func AddLiveReloadHandler(path string, app *echo.Echo) { func (app *App) AddLiveReloadHandler(path string) {
app.GET(path, handler) app.Router.Get(path, sseHandler)
} }

View file

@ -49,8 +49,8 @@ func (q *Qs) ToString() string {
} }
func GetQueryParam(ctx *RequestContext, key string) string { func GetQueryParam(ctx *RequestContext, key string) string {
value := ctx.QueryParam(key) value, ok := ctx.URL.Query()[key]
if value == "" { if value == nil || !ok {
current := ctx.currentBrowserUrl current := ctx.currentBrowserUrl
if current != "" { if current != "" {
u, err := url.Parse(current) u, err := url.Parse(current)
@ -59,7 +59,10 @@ func GetQueryParam(ctx *RequestContext, key string) string {
} }
} }
} }
return value if len(value) == 0 {
return ""
}
return value[0]
} }
func SetQueryParams(href string, qs *Qs) string { func SetQueryParams(href string, qs *Qs) string {

View file

@ -3,7 +3,9 @@ module htmgo-site
go 1.23.0 go 1.23.0
require ( require (
github.com/labstack/echo/v4 v4.12.0 github.com/go-chi/chi/v5 v5.1.0
github.com/google/uuid v1.6.0
github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f
github.com/yuin/goldmark v1.7.4 github.com/yuin/goldmark v1.7.4
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
) )
@ -11,15 +13,4 @@ require (
require ( require (
github.com/alecthomas/chroma/v2 v2.2.0 // indirect github.com/alecthomas/chroma/v2 v2.2.0 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/maddalax/htmgo/framework v0.0.0-20240925160932-90c8201519b5 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
) )

View file

@ -8,62 +8,23 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f h1:A4MEslfWXKvqsZt1DbvZpguzVAbyjCRclEZNt6TjSRw=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f/go.mod h1:JBHqkKSv6frIsSlT1itIU0hUTW9NgDcyM6Cf6npK0bQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/maddalax/htmgo v0.0.1-alpha h1:xT1nMFneyNR1VDYrCYDBk/JQEt3PJ7+hGymLclBvy80=
github.com/maddalax/htmgo v0.0.1-alpha/go.mod h1:I7jCNNdzGH0+0BqrY9U+h72/dzY1KB0T8zAYl8+bedI=
github.com/maddalax/htmgo/framework v0.0.0-20240923170417-9e23e7cf2bea h1:TcZtFXyrJ86nPK6YBeOtkzjYbFMxiPNDJzvmaKRfB/c=
github.com/maddalax/htmgo/framework v0.0.0-20240923170417-9e23e7cf2bea/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240924173916-2b8ba6e1aa58 h1:xvBCxG0r2XJHPIb5q994lbZJVPxIOxCRsxoFj5mtlO4=
github.com/maddalax/htmgo/framework v0.0.0-20240924173916-2b8ba6e1aa58/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240924182609-b2c6b5207510 h1:Gl9QRbIr008Qgvcsnsnkn1Q7Fusw3Hn6dPEbiV8M8wk=
github.com/maddalax/htmgo/framework v0.0.0-20240924182609-b2c6b5207510/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240924201008-83760397d146 h1:bPiww6JmlY0o157e1upjRDo1MAxzwjmxm1hjuswHym8=
github.com/maddalax/htmgo/framework v0.0.0-20240924201008-83760397d146/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240924203546-811f64f4619f h1:UN0jPr20S+ac5P4eYX4V27fobbhVqYOlbLsQJ7UrYh0=
github.com/maddalax/htmgo/framework v0.0.0-20240924203546-811f64f4619f/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240925034103-16736e34eb9c h1:3ubRmGOGUItHhDYIct3B431f+igTBUWqj6gXiAowC4U=
github.com/maddalax/htmgo/framework v0.0.0-20240925034103-16736e34eb9c/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240925160031-488b415f8850 h1:fHqxuyKXBc5bjfnUXQEuJLbirltD5ni11IhnOTJaXq0=
github.com/maddalax/htmgo/framework v0.0.0-20240925160031-488b415f8850/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240925160932-90c8201519b5 h1:ZTo0FzJFYKKKSylYMbFNntXjyVeYknuNZXdkOq/nT4c=
github.com/maddalax/htmgo/framework v0.0.0-20240925160932-90c8201519b5/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View file

@ -1,12 +1,12 @@
package main package main
import ( import (
"github.com/labstack/echo/v4"
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"github.com/maddalax/htmgo/framework/service" "github.com/maddalax/htmgo/framework/service"
"htmgo-site/__htmgo" "htmgo-site/__htmgo"
"htmgo-site/internal/markdown" "htmgo-site/internal/markdown"
"io/fs" "io/fs"
"net/http"
) )
func main() { func main() {
@ -19,21 +19,23 @@ func main() {
h.Start(h.AppOpts{ h.Start(h.AppOpts{
ServiceLocator: locator, ServiceLocator: locator,
LiveReload: true, LiveReload: true,
Register: func(e *echo.Echo) { Register: func(app *h.App) {
app.UseWithContext(func(w http.ResponseWriter, r *http.Request, context map[string]any) {
context["embeddedMarkdown"] = markdownAssets
})
sub, err := fs.Sub(staticAssets, "assets/dist") sub, err := fs.Sub(staticAssets, "assets/dist")
if err != nil { if err != nil {
panic(err) panic(err)
} }
e.StaticFS("/public", sub)
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { http.FileServerFS(sub)
return func(c echo.Context) error {
c.Set("embeddedMarkdown", markdownAssets)
return next(c)
}
})
__htmgo.Register(e) app.Router.Handle("/public/*", http.StripPrefix("/public", http.FileServerFS(sub)))
__htmgo.Register(app.Router)
}, },
}) })
} }

View file

@ -22,14 +22,14 @@ func HelloHtmgoPage(ctx *h.RequestContext) *h.Page {
} }
``` ```
htmgo uses [Echo Go](https://echo.labstack.com/docs/context) as its web server, ***h.RequestContext** is a thin wrapper around **echo.Context**. A page htmgo uses [std http](https://pkg.go.dev/net/http) with chi router as its web server, ***h.RequestContext** is a thin wrapper around ***http.Request**. A page
must return *h.Page, and accept *h.RequestContext as a parameter must return *h.Page, and accept *h.RequestContext as a parameter
<br> <br>
**Auto Registration** **Auto Registration**
htmgo uses file based routing. This means that we will automatically generate and register your routes with echo based on the files you have in the 'pages' directory. htmgo uses file based routing. This means that we will automatically generate and register your routes with chi based on the files you have in the 'pages' directory.
For example, if you have a directory structure such as: For example, if you have a directory structure such as:
@ -40,7 +40,7 @@ pages
users.$id //id parameter can be accessed in your page with ctx.Param("id") users.$id //id parameter can be accessed in your page with ctx.Param("id")
``` ```
it will get registered into Echo as follows: it will get registered into chi router as follows:
```bash ```bash
/ /

View file

@ -1,15 +0,0 @@
package pages
import (
"github.com/labstack/echo/v4"
"htmgo-site/internal/dirwalk"
"io/fs"
)
func RegisterMarkdown(app *echo.Echo, dir string, system fs.FS, handler func(ctx echo.Context, path string) error) {
for _, page := range dirwalk.WalkPages(dir, system) {
app.GET(page.RoutePath, func(ctx echo.Context) error {
return handler(ctx, page.FilePath)
})
}
}

View file

@ -1,41 +0,0 @@
dev:
just run-gen && just build-css && air & just watch-js & just watch-gen & just watch-css
bundle:
rm -rf dist
rm -rf assets/dist
mkdir -p dist/assets/dist
just run-gen
GOOS=linux GOARCH=amd64 go build -o dist/htmgo .
cd assets/js && npm run build
just build-css
cp -r assets/dist/* dist/assets/dist
tar -czvf htmgo-release.tar.gz ./dist
rm -rf dist
mkdir -p dist
mv htmgo-release.tar.gz dist
release-version := '1.0.0'
release:
just bundle
gh release create {{release-version}} dist/htmgo-release.tar.gz --title "Release {{release-version}}" --prerelease --notes "new release"
run-gen:
go run ./tooling/astgen
watch-gen:
go run ./tooling/watch.go --command 'go run ./tooling/astgen'
watch-js:
cd assets/js && npm run build && npm run watch
setup-tailwind-cli:
cd assets/css && curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64
cd assets/css && chmod +x tailwindcss-macos-arm64
cd assets/css && mv tailwindcss-macos-arm64 tailwindcss
watch-css:
cd assets/css && ./tailwindcss -i input.css -o ./../dist/main.css --watch
build-css:
cd assets/css && ./tailwindcss -i input.css -o ./../dist/main.css --minify

View file

@ -3,19 +3,8 @@ module starter-template
go 1.23.0 go 1.23.0
require ( require (
github.com/labstack/echo/v4 v4.12.0 github.com/go-chi/chi/v5 v5.1.0
github.com/maddalax/htmgo/framework v0.0.0-20240926164716-6b4ccf76046e github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f
) )
require ( require github.com/google/uuid v1.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
)

View file

@ -1,39 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f h1:A4MEslfWXKvqsZt1DbvZpguzVAbyjCRclEZNt6TjSRw=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/maddalax/htmgo/framework v0.0.0-20240926194146-5bbd35d2728f/go.mod h1:JBHqkKSv6frIsSlT1itIU0hUTW9NgDcyM6Cf6npK0bQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/maddalax/htmgo/framework v0.0.0-20240925165909-2b970ea49a5d h1:I//B7/DdrAYrC8K/uxwmMG0xgjGB1CI9YLN8T05flf0=
github.com/maddalax/htmgo/framework v0.0.0-20240925165909-2b970ea49a5d/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.0.0-20240926164716-6b4ccf76046e h1:VgcbjOEdUlplWwPt99o0WVYRbPjHtfnwCmbq09LEKdU=
github.com/maddalax/htmgo/framework v0.0.0-20240926164716-6b4ccf76046e/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/maddalax/htmgo/framework v0.1.0 h1:bWMPlCCuoW2Fa++YUk7yhpRLHyU3d5GcvQ0gp+bDO+g=
github.com/maddalax/htmgo/framework v0.1.0/go.mod h1:TA7KCaKhurpXceQrzClJOHqRsUSd5NL64ZngSg+I3oc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -2,10 +2,10 @@ package main
import ( import (
"embed" "embed"
"github.com/labstack/echo/v4"
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"github.com/maddalax/htmgo/framework/service" "github.com/maddalax/htmgo/framework/service"
"io/fs" "io/fs"
"net/http"
"starter-template/__htmgo" "starter-template/__htmgo"
) )
@ -15,18 +15,20 @@ var StaticAssets embed.FS
func main() { func main() {
locator := service.NewLocator() locator := service.NewLocator()
sub, err := fs.Sub(StaticAssets, "assets/dist")
if err != nil {
panic(err)
}
h.Start(h.AppOpts{ h.Start(h.AppOpts{
ServiceLocator: locator, ServiceLocator: locator,
LiveReload: true, LiveReload: true,
Register: func(e *echo.Echo) { Register: func(app *h.App) {
e.StaticFS("/public", sub) sub, err := fs.Sub(StaticAssets, "assets/dist")
__htmgo.Register(e)
if err != nil {
panic(err)
}
http.FileServerFS(sub)
app.Router.Handle("/public/*", http.StripPrefix("/public", http.FileServerFS(sub)))
__htmgo.Register(app.Router)
}, },
}) })
} }