diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 5be0ae7..f05704d 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -1,4 +1,4 @@
-name: Go
+name: Go Build and Cypress Tests
on:
push:
@@ -29,5 +29,27 @@ jobs:
go install github.com/a-h/templ/cmd/templ@latest
templ generate
- - name: Build
- run: go build .
+ - name: Build & Run
+ run: |
+ go build .
+ go run . &
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+
+ - name: Clone cypress-example-todomvc
+ run: git clone https://github.com/cypress-io/cypress-example-todomvc.git cypress-example-todomvc
+
+ - name: Install Dependencies
+ run: |
+ cd cypress-example-todomvc
+ npm install
+
+ - name: Run Cypress Tests
+ run: |
+ cd cypress-example-todomvc
+ npm run cypress:run
+
+ - name: Stop Go Application
+ run: pkill -f "go run ."
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1088c96..62ef1c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
todomvc_templ.go
+tpl/*.go
go-templ-htmx-_hyperscript.exe
\ No newline at end of file
diff --git a/README.md b/README.md
index 0b942ef..f75b73e 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,13 @@
===========================================================
Build with GO, TEMPL, HTMX & _HYPERSCRIPT
[![Go](https://github.com/syarul/todomvc-go-templ-htmx-_hyperscript/actions/workflows/go.yml/badge.svg)](https://github.com/syarul/todomvc-go-templ-htmx-_hyperscript/actions/workflows/go.yml)
+
+### Testing
+As evidence of HTMX's capabilities in emulating the functionalities of modern frameworks, I have incorporated [unit test](https://github.com/syarul/todomvc-go-templ-htmx-_hyperscript/actions/runs/7412273948/job/20168687544) from https://github.com/cypress-io/cypress-example-todomvc. This demonstration serves to showcase that HTMX, when paired with _hyperscript, can replicate all the behaviors typically associated with most modern client frameworks.
+
+### Security
+Check on [this link](https://templ.guide/security/) when using `templ` as HTML template engine. At anytime as developer `Do not blame the farmer if you cook the rice til it burns.`
+
### Usage
- install go if you don't have
- run `go mod tidy` to fetch all needed modules
@@ -19,4 +26,8 @@
- alternatively you can compile into executable with `go build .`
### HTMX
-Visit [https://github.com/rajasegar/awesome-htmx](https://github.com/rajasegar/awesome-htmx) to look for HTMX curated infos
\ No newline at end of file
+Visit [https://github.com/rajasegar/awesome-htmx](https://github.com/rajasegar/awesome-htmx) to look for HTMX curated infos
+
+###
+Todo
+- Use behavior to modular the _hyperscript scripts
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 6d51836..705d6de 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,4 @@ module todomvc/go-templ-htmx-_hyperscript
go 1.21.5
-require (
- github.com/a-h/templ v0.2.501
- github.com/google/uuid v1.5.0
-)
+require github.com/a-h/templ v0.2.501
diff --git a/go.sum b/go.sum
index b655ae7..8a08e7c 100644
--- a/go.sum
+++ b/go.sum
@@ -2,5 +2,3 @@ github.com/a-h/templ v0.2.501 h1:9rIo5u+B+NDJIkbHGthckUGRguCuWKY/7ri8e2ckn9M=
github.com/a-h/templ v0.2.501/go.mod h1:9gZxTLtRzM3gQxO8jr09Na0v8/jfliS97S9W5SScanM=
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/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
diff --git a/main.go b/main.go
index 11fc95e..a4dcb95 100644
--- a/main.go
+++ b/main.go
@@ -1,12 +1,16 @@
package main
import (
+ "crypto/rand"
+ "encoding/base64"
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"strings"
+ "time"
+ "todomvc/go-templ-htmx-_hyperscript/tpl"
"github.com/a-h/templ"
)
@@ -14,9 +18,9 @@ import (
var idCounter uint64
type Todo struct {
- id uint64
+ Id uint64 `json:"id"`
title string
- done bool
+ Done bool `json:"done"`
editing bool
}
@@ -50,7 +54,7 @@ func (t *todos) crudOps(action Action, todo Todo) Todo {
index := -1
if action != Create {
for i, r := range *t {
- if r.id == todo.id {
+ if r.Id == todo.Id {
index = i
break
}
@@ -61,7 +65,7 @@ func (t *todos) crudOps(action Action, todo Todo) Todo {
*t = append(*t, todo)
return todo
case Toggle:
- (*t)[index].done = todo.done
+ (*t)[index].Done = todo.Done
case Update:
title := strings.Trim(todo.title, " ")
if len(title) != 0 {
@@ -88,12 +92,14 @@ func main() {
t := &todos{}
// Register the routes.
- http.Handle("/get-hash", http.HandlerFunc(t.getHash))
+ // http.Handle("/get-hash", http.HandlerFunc(t.getHash))
+ http.Handle("/set-hash", http.HandlerFunc(setHash))
http.Handle("/learn.json", http.HandlerFunc(learnHandler))
http.Handle("/update-counts", http.HandlerFunc(t.updateCounts))
http.Handle("/toggle-all", http.HandlerFunc(t.toggleAllHandler))
http.Handle("/completed", http.HandlerFunc(t.clearCompleted))
+ http.Handle("/footer", http.HandlerFunc(t.footerHandler))
http.Handle("/", http.HandlerFunc(t.pageHandler))
@@ -105,15 +111,18 @@ func main() {
http.Handle("/toggle-main", http.HandlerFunc(t.toggleMainHandler))
http.Handle("/toggle-footer", http.HandlerFunc(t.toggleFooterHandler))
+ http.Handle("/todo-list", http.HandlerFunc(t.todoListHandler))
+ http.Handle("/todo-json", http.HandlerFunc(t.getJSON))
+ http.Handle("/todo-item", http.HandlerFunc(t.todoItemHandler))
- // Specify the directory containing your static files
- dir := "./assets"
+ // this is used to serve axe-core for the todomvc test
+ dir := "./cypress-example-todomvc/node_modules"
// Use the http.FileServer to create a handler for serving static files
fs := http.FileServer(http.Dir(dir))
// Use the http.Handle to register the file server handler for a specific route
- http.Handle("/assets/", http.StripPrefix("/assets/", fs))
+ http.Handle("/node_modules/", http.StripPrefix("/node_modules/", fs))
// start the server.
addr := os.Getenv("LISTEN_ADDRESS")
@@ -133,7 +142,7 @@ func main() {
func countNotDone(todos []Todo) int {
count := 0
for _, todo := range todos {
- if !todo.done {
+ if !todo.Done {
count++
}
}
@@ -155,7 +164,7 @@ func defChecked(todos []Todo) bool {
// has completeTask checks if there is any completed task in the Todos slice
func hasCompleteTask(todos []Todo) bool {
for _, todo := range todos {
- if todo.done {
+ if todo.Done {
return true
}
}
@@ -183,29 +192,30 @@ func learnHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(emptyJSON)
}
-// getHash handles the GET request for the #/:name route.
-// it updates the selected field of each filter based on the name query parameter.
-// on initial fetch when todos is empty it will send "empty string" which usually
-// ignored by htmx, the reason here we want to make use templ rendering to behave
-// efficiently by rendering only needed html, this use case usually available in
-// modern client framework i.e., in React you can do
-// <>{todo.length &&