Repos / s4g / b4e42aac1d
commit b4e42aac1dad3f3ba99ee9dd75562fc54baa1850
Author: Nhân <hi@imnhan.com>
Date: Sun Jul 16 23:19:43 2023 +0700
error message in html
diff --git a/Makefile b/Makefile
index 1171c44..6f30ab5 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,7 @@ build:
go build -o dist/
watch:
- find . -name '*.go' -or -name '*.js' -or -name 'livereload.html' \
- | entr -rc go run .
+ fd -E docs -E theme | entr -rc go run .
watch-theme:
find theme/* | entr -c rsync -av theme/ docs/_theme/
diff --git a/errors.go b/errors.go
new file mode 100644
index 0000000..8999864
--- /dev/null
+++ b/errors.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "fmt"
+ "html/template"
+)
+
+type SiteMetadataErr struct {
+ Field string
+ Msg string
+}
+
+func (e *SiteMetadataErr) Error() string {
+ return fmt.Sprintf("SiteMetadataErr - %s: %s", e.Field, e.Msg)
+}
+
+func (e *SiteMetadataErr) Html() template.HTML {
+ return template.HTML(fmt.Sprintf(
+ "<p>In file <b>%s</b>, field <b>%s</b>: %s </p>",
+ SiteFileName, e.Field, e.Msg,
+ ))
+}
diff --git a/livereload/error.go b/livereload/error.go
new file mode 100644
index 0000000..b8ed95d
--- /dev/null
+++ b/livereload/error.go
@@ -0,0 +1,26 @@
+package livereload
+
+import (
+ "bytes"
+ _ "embed"
+ "html/template"
+ "net/http"
+)
+
+//go:embed error.html
+var errorTmpl string
+
+var errTmpl = template.Must(template.New("error").Parse(errorTmpl))
+
+// Error that has a user-friendly HTML representation.
+type htmlErr interface {
+ error
+ Html() template.HTML
+}
+
+func serveError(w http.ResponseWriter, r *http.Request, err htmlErr) {
+ var buf bytes.Buffer
+ errTmpl.Execute(&buf, err)
+ body := withLiveReload(buf.Bytes())
+ w.Write(body)
+}
diff --git a/livereload/error.html b/livereload/error.html
index c2d392e..e59eb99 100644
--- a/livereload/error.html
+++ b/livereload/error.html
@@ -1,15 +1,15 @@
-<!DOCTYPE html>
+<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
- <title>Error</title>
+ <title>{{.Error}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
- <b>Error:</b> {{.}}
+ <h1>Error</h1>
+ {{.Html}}
<style>
- body {
- background-color: pink;
+ h1 {
color: red;
}
</style>
diff --git a/livereload/livereload.go b/livereload/livereload.go
index 898e6dd..b51105a 100644
--- a/livereload/livereload.go
+++ b/livereload/livereload.go
@@ -7,7 +7,6 @@
"net/http"
"strings"
"sync"
- "text/template"
"go.imnhan.com/webmaker2000/writablefs"
)
@@ -18,9 +17,6 @@
//go:embed livereload.html
var lrScript []byte
-//go:embed error.html
-var errorTmpl string
-
var pleaseReload = []byte("1")
var dontReload = []byte("0")
@@ -90,7 +86,7 @@ func Middleware(mux *http.ServeMux, root string, fsys writablefs.FS, f http.Hand
err = state.err
state.errMut.RUnlock()
if err != nil {
- serveError(w, r, err)
+ serveError(w, r, err.(htmlErr))
return
}
@@ -152,12 +148,3 @@ func withLiveReload(original []byte) []byte {
copy(result[bodyEndPos+len(lrScript):], original[bodyEndPos:])
return result
}
-
-var errTmpl = template.Must(template.New("error").Parse(errorTmpl))
-
-func serveError(w http.ResponseWriter, r *http.Request, err error) {
- var buf bytes.Buffer
- errTmpl.Execute(&buf, err.Error())
- body := withLiveReload(buf.Bytes())
- w.Write(body)
-}
diff --git a/main.go b/main.go
index 7eb15a6..6060cef 100644
--- a/main.go
+++ b/main.go
@@ -190,8 +190,10 @@ func regenerate(fsys writablefs.FS) (site *SiteMetadata, err error) {
for _, link := range site.NavbarLinks {
a, ok := articles[link]
if !ok {
- return nil,
- fmt.Errorf("%s: NavbarLinks: %s not found", FeedPath, link)
+ return nil, &SiteMetadataErr{
+ Field: "NavbarLinks",
+ Msg: fmt.Sprintf(`"%s" does not exist`, link),
+ }
}
articlesInNav = append(articlesInNav, a)
}
@@ -214,7 +216,10 @@ func regenerate(fsys writablefs.FS) (site *SiteMetadata, err error) {
for _, a := range articles {
fmt.Println(">", a.Path, "-", a.Title)
- a.WriteHtmlFile(site, articlesInNav, articlesInFeed, startYear)
+ err := a.WriteHtmlFile(site, articlesInNav, articlesInFeed, startYear)
+ if err != nil {
+ return nil, fmt.Errorf("Article %s: %w", a.Path, err)
+ }
generatedFiles[a.OutputPath] = true
}
fmt.Printf("Processed %d articles\n", len(articles))
@@ -282,15 +287,19 @@ func (a *Article) WriteHtmlFile(
articlesInNav []Article,
articlesInFeed []Article,
startYear int,
-) {
- // First generate the main content in html
+) error {
contentHtml := djot.ToHtml(a.DjotBody)
- // Then insert that content into the main template
- var buf bytes.Buffer
+ tmpl, err := template.ParseFS(a.Fs, a.TemplatePaths...)
// TODO: should probably reuse the template object for common cases
- tmpl := template.Must(template.ParseFS(a.Fs, a.TemplatePaths...))
- err := tmpl.Execute(&buf, struct {
+ if err != nil {
+ return fmt.Errorf(
+ "Failed to parse templates (%v): %w", a.Templates, err,
+ )
+ }
+
+ var buf bytes.Buffer
+ err = tmpl.Execute(&buf, struct {
Site *SiteMetadata
Content template.HTML
Title string
@@ -312,16 +321,17 @@ func (a *Article) WriteHtmlFile(
StartYear: startYear,
})
if err != nil {
- fmt.Println("Error in WriteHtmlFile:", err)
- return
+ return fmt.Errorf("Failed to execute templates (%v): %w", a.Templates, err)
}
fullHtml := buf.Bytes()
// Now write into an html with the same name as the original djot file
err = a.Fs.WriteFile(a.OutputPath, fullHtml)
if err != nil {
- panic(err)
+ return fmt.Errorf("Failed to write to %s: %w", a.OutputPath, err)
}
+
+ return nil
}
func findArticles(fsys writablefs.FS, site *SiteMetadata) map[string]Article {