diff --git a/app.go b/app.go
index 006fe4c..7269b8a 100644
--- a/app.go
+++ b/app.go
@@ -2,7 +2,6 @@ package main
import (
"crypto/rsa"
- "html/template"
"net/http"
"sync"
@@ -70,8 +69,6 @@ type goBlog struct {
min minify.Minifier
// Regex Redirects
regexRedirects []*regexRedirect
- // Rendering
- templates map[string]*template.Template
// Sessions
loginSessions, captchaSessions *dbSessionStore
// Shutdown
diff --git a/authentication.go b/authentication.go
index 98c77b9..f86c6ca 100644
--- a/authentication.go
+++ b/authentication.go
@@ -62,7 +62,7 @@ func (a *goBlog) authMiddleware(next http.Handler) http.Handler {
_ = r.ParseForm()
b = []byte(r.PostForm.Encode())
}
- a.renderNew(w, r, a.renderLogin, &renderData{
+ a.render(w, r, a.renderLogin, &renderData{
Data: &loginRenderData{
loginMethod: r.Method,
loginHeaders: base64.StdEncoding.EncodeToString(h),
diff --git a/blogroll.go b/blogroll.go
index f569e91..d42734b 100644
--- a/blogroll.go
+++ b/blogroll.go
@@ -29,7 +29,7 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
}
c := bc.Blogroll
can := bc.getRelativePath(defaultIfEmpty(c.Path, defaultBlogrollPath))
- a.renderNew(w, r, a.renderBlogroll, &renderData{
+ a.render(w, r, a.renderBlogroll, &renderData{
Canonical: a.getFullAddress(can),
Data: &blogrollRenderData{
title: c.Title,
diff --git a/blogstats.go b/blogstats.go
index ea6ee56..e243be1 100644
--- a/blogstats.go
+++ b/blogstats.go
@@ -25,7 +25,7 @@ func (a *goBlog) initBlogStats() {
func (a *goBlog) serveBlogStats(w http.ResponseWriter, r *http.Request) {
_, bc := a.getBlog(r)
canonical := bc.getRelativePath(defaultIfEmpty(bc.BlogStats.Path, defaultBlogStatsPath))
- a.renderNew(w, r, a.renderBlogStats, &renderData{
+ a.render(w, r, a.renderBlogStats, &renderData{
Canonical: a.getFullAddress(canonical),
Data: &blogStatsRenderData{
tableUrl: canonical + blogStatsTablePath,
@@ -43,7 +43,7 @@ func (a *goBlog) serveBlogStatsTable(w http.ResponseWriter, r *http.Request) {
return
}
// Render
- a.renderNew(w, r, a.renderBlogStatsTable, &renderData{
+ a.render(w, r, a.renderBlogStatsTable, &renderData{
Data: data,
})
}
diff --git a/captcha.go b/captcha.go
index ae1b66d..30fcf67 100644
--- a/captcha.go
+++ b/captcha.go
@@ -65,7 +65,7 @@ func (a *goBlog) captchaMiddleware(next http.Handler) http.Handler {
// Render captcha
_ = ses.Save(r, w)
w.Header().Set("Cache-Control", "no-store,max-age=0")
- a.renderNewWithStatusCode(w, r, http.StatusUnauthorized, a.renderCaptcha, &renderData{
+ a.renderWithStatusCode(w, r, http.StatusUnauthorized, a.renderCaptcha, &renderData{
Data: &captchaRenderData{
captchaMethod: r.Method,
captchaHeaders: base64.StdEncoding.EncodeToString(h),
diff --git a/comments.go b/comments.go
index 2b3eb71..73e74b2 100644
--- a/comments.go
+++ b/comments.go
@@ -41,7 +41,7 @@ func (a *goBlog) serveComment(w http.ResponseWriter, r *http.Request) {
return
}
_, bc := a.getBlog(r)
- a.renderNew(w, r, a.renderComment, &renderData{
+ a.render(w, r, a.renderComment, &renderData{
Canonical: a.getFullAddress(bc.getRelativePath(path.Join(commentPath, strconv.Itoa(id)))),
Data: comment,
})
diff --git a/commentsAdmin.go b/commentsAdmin.go
index bb6a612..d72aa42 100644
--- a/commentsAdmin.go
+++ b/commentsAdmin.go
@@ -70,13 +70,13 @@ func (a *goBlog) commentsAdmin(w http.ResponseWriter, r *http.Request) {
}
nextPath = fmt.Sprintf("%s/page/%d", commentsPath, nextPage)
// Render
- a.render(w, r, templateCommentsAdmin, &renderData{
- Data: map[string]interface{}{
- "Comments": comments,
- "HasPrev": hasPrev,
- "HasNext": hasNext,
- "Prev": prevPath,
- "Next": nextPath,
+ a.render(w, r, a.renderCommentsAdmin, &renderData{
+ Data: &commentsRenderData{
+ comments: comments,
+ hasPrev: hasPrev,
+ hasNext: hasNext,
+ prev: prevPath,
+ next: nextPath,
},
})
}
diff --git a/config.go b/config.go
index 5cc8cd1..f99bd0a 100644
--- a/config.go
+++ b/config.go
@@ -81,7 +81,6 @@ type configBlog struct {
Search *configSearch `mapstructure:"search"`
BlogStats *configBlogStats `mapstructure:"blogStats"`
Blogroll *configBlogroll `mapstructure:"blogroll"`
- CustomPages []*configCustomPage `mapstructure:"custompages"`
Telegram *configTelegram `mapstructure:"telegram"`
PostAsHome bool `mapstructure:"postAsHome"`
RandomPost *configRandomPost `mapstructure:"randomPost"`
@@ -148,14 +147,6 @@ type configBlogroll struct {
Description string `mapstructure:"description"`
}
-type configCustomPage struct {
- Path string `mapstructure:"path"`
- Template string `mapstructure:"template"`
- Cache bool `mapstructure:"cache"`
- CacheExpiration int `mapstructure:"cacheExpiration"`
- Data *interface{} `mapstructure:"data"`
-}
-
type configRandomPost struct {
Enabled bool `mapstructure:"enabled"`
Path string `mapstructure:"path"`
diff --git a/contact.go b/contact.go
index ae50365..63637c4 100644
--- a/contact.go
+++ b/contact.go
@@ -17,7 +17,7 @@ const defaultContactPath = "/contact"
func (a *goBlog) serveContactForm(w http.ResponseWriter, r *http.Request) {
_, bc := a.getBlog(r)
cc := bc.Contact
- a.renderNew(w, r, a.renderContact, &renderData{
+ a.render(w, r, a.renderContact, &renderData{
Data: &contactRenderData{
title: cc.Title,
description: cc.Description,
@@ -63,7 +63,7 @@ func (a *goBlog) sendContactSubmission(w http.ResponseWriter, r *http.Request) {
// Send notification
a.sendNotification(message.String())
// Give feedback
- a.renderNew(w, r, a.renderContact, &renderData{
+ a.render(w, r, a.renderContact, &renderData{
Data: &contactRenderData{
sent: true,
},
diff --git a/customPages.go b/customPages.go
deleted file mode 100644
index 84401e8..0000000
--- a/customPages.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package main
-
-import "net/http"
-
-const customPageContextKey = "custompage"
-
-func (a *goBlog) serveCustomPage(w http.ResponseWriter, r *http.Request) {
- page := r.Context().Value(customPageContextKey).(*configCustomPage)
- a.render(w, r, page.Template, &renderData{
- Canonical: a.getFullAddress(page.Path),
- Data: page.Data,
- })
-}
diff --git a/editor.go b/editor.go
index 7ad01af..6af594a 100644
--- a/editor.go
+++ b/editor.go
@@ -21,8 +21,8 @@ import (
const editorPath = "/editor"
func (a *goBlog) serveEditor(w http.ResponseWriter, r *http.Request) {
- a.render(w, r, templateEditor, &renderData{
- Data: map[string]interface{}{},
+ a.render(w, r, a.renderEditor, &renderData{
+ Data: &editorRenderData{},
})
}
@@ -89,10 +89,10 @@ func (a *goBlog) serveEditorPost(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, err.Error(), http.StatusBadRequest)
return
}
- a.render(w, r, templateEditor, &renderData{
- Data: map[string]interface{}{
- "UpdatePostURL": a.fullPostURL(post),
- "UpdatePostContent": a.postToMfItem(post).Properties.Content[0],
+ a.render(w, r, a.renderEditor, &renderData{
+ Data: &editorRenderData{
+ updatePostUrl: a.fullPostURL(post),
+ updatePostContent: a.postToMfItem(post).Properties.Content[0],
},
})
case "updatepost":
@@ -188,14 +188,13 @@ func (a *goBlog) editorMicropubPost(w http.ResponseWriter, r *http.Request, medi
_ = result.Body.Close()
}
-func (a *goBlog) editorPostTemplate(blog string) string {
+func (a *goBlog) editorPostTemplate(blog string, bc *configBlog) string {
var builder strings.Builder
marsh := func(param string, i interface{}) {
_ = yaml.NewEncoder(&builder).Encode(map[string]interface{}{
param: i,
})
}
- bc := a.cfg.Blogs[blog]
builder.WriteString("---\n")
marsh("blog", blog)
marsh("section", bc.DefaultSection)
@@ -210,8 +209,7 @@ func (a *goBlog) editorPostTemplate(blog string) string {
return builder.String()
}
-func (a *goBlog) editorPostDesc(blog string) string {
- bc := a.cfg.Blogs[blog]
+func (a *goBlog) editorPostDesc(bc *configBlog) string {
t := a.ts.GetTemplateStringVariant(bc.Lang, "editorpostdesc")
var paramBuilder, statusBuilder strings.Builder
for i, param := range []string{
diff --git a/editorFiles.go b/editorFiles.go
index 2f0fcf4..47aedfb 100644
--- a/editorFiles.go
+++ b/editorFiles.go
@@ -16,7 +16,7 @@ func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
}
// Check if files at all
if len(files) == 0 {
- a.renderNew(w, r, a.renderEditorFiles, &renderData{
+ a.render(w, r, a.renderEditorFiles, &renderData{
Data: &editorFilesRenderData{},
})
return
@@ -39,7 +39,7 @@ func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
return
}
// Serve HTML
- a.renderNew(w, r, a.renderEditorFiles, &renderData{
+ a.render(w, r, a.renderEditorFiles, &renderData{
Data: &editorFilesRenderData{
files: files,
uses: uses,
diff --git a/errors.go b/errors.go
index 240af4c..6fc0166 100644
--- a/errors.go
+++ b/errors.go
@@ -35,7 +35,7 @@ func (a *goBlog) serveError(w http.ResponseWriter, r *http.Request, message stri
http.Error(w, message, status)
return
}
- a.renderNewWithStatusCode(w, r, status, a.renderError, &renderData{
+ a.renderWithStatusCode(w, r, status, a.renderError, &renderData{
Data: &errorRenderData{
Title: fmt.Sprintf("%d %s", status, http.StatusText(status)),
Message: message,
diff --git a/example-config.yml b/example-config.yml
index b4bda79..c18893d 100644
--- a/example-config.yml
+++ b/example-config.yml
@@ -222,15 +222,6 @@ blogs:
authValue: abc # Authentication value for OPML
categories: # Optional, allow only these categories
- Blogs
- # Custom pages
- custompages:
- - path: /blogroll # Path
- template: blogroll # Template
- cache: true # Enable caching
- cacheExpiration: 600 # Cache expiration (default uses blog cache TTL)
- data: # Data to provide to template
- Title: Blogroll
- Description: "This are alphabetically sorted lists of blogs and sites I subscribe to."
# Redirect to random post
randomPost:
enabled: true # Enable
diff --git a/geoMap.go b/geoMap.go
index 9f15db4..0a2e6dc 100644
--- a/geoMap.go
+++ b/geoMap.go
@@ -25,7 +25,7 @@ func (a *goBlog) serveGeoMap(w http.ResponseWriter, r *http.Request) {
}
if len(allPostsWithLocation) == 0 {
- a.renderNew(w, r, a.renderGeoMap, &renderData{
+ a.render(w, r, a.renderGeoMap, &renderData{
Canonical: canonical,
Data: &geoMapRenderData{
noLocations: true,
@@ -85,7 +85,7 @@ func (a *goBlog) serveGeoMap(w http.ResponseWriter, r *http.Request) {
tracksJson = string(tracksJsonBytes)
}
- a.renderNew(w, r, a.renderGeoMap, &renderData{
+ a.render(w, r, a.renderGeoMap, &renderData{
Canonical: canonical,
Data: &geoMapRenderData{
locations: locationsJson,
diff --git a/go.mod b/go.mod
index 86d0eea..8d95d19 100644
--- a/go.mod
+++ b/go.mod
@@ -35,7 +35,7 @@ require (
github.com/kaorimatz/go-opml v0.0.0-20210201121027-bc8e2852d7f9
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/lopezator/migrator v0.3.0
- github.com/mattn/go-sqlite3 v1.14.10
+ github.com/mattn/go-sqlite3 v1.14.11
github.com/microcosm-cc/bluemonday v1.0.17
github.com/mmcdole/gofeed v1.1.3
github.com/paulmach/go.geojson v1.4.0
@@ -46,7 +46,7 @@ require (
github.com/spf13/cast v1.4.1
github.com/spf13/viper v1.10.1
github.com/stretchr/testify v1.7.0
- github.com/tdewolff/minify/v2 v2.9.29
+ github.com/tdewolff/minify/v2 v2.10.0
github.com/thoas/go-funk v0.9.1
github.com/tkrajina/gpxgo v1.2.0
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
@@ -55,8 +55,8 @@ require (
// master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01
- golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8
- golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba
+ golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
+ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
diff --git a/go.sum b/go.sum
index 099479c..8bac388 100644
--- a/go.sum
+++ b/go.sum
@@ -314,8 +314,8 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
-github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ=
+github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
github.com/mdlayher/ethtool v0.0.0-20211028163843-288d040e9d60 h1:tHdB+hQRHU10CfcK0furo6rSNgZ38JT8uPh70c/pFD8=
@@ -415,8 +415,8 @@ github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQ
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0=
github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8=
-github.com/tdewolff/minify/v2 v2.9.29 h1:QMVJaCJzWL0mXS33cX792YD074xz4lOhkyBS8hAzYAY=
-github.com/tdewolff/minify/v2 v2.9.29/go.mod h1:6XAjcHM46pFcRE0eztigFPm0Q+Cxsw8YhEWT+rDkcZM=
+github.com/tdewolff/minify/v2 v2.10.0 h1:ovVAHUcjfGrBDf1EIvsodRUVJiZK/28mMose08B7k14=
+github.com/tdewolff/minify/v2 v2.10.0/go.mod h1:6XAjcHM46pFcRE0eztigFPm0Q+Cxsw8YhEWT+rDkcZM=
github.com/tdewolff/parse/v2 v2.5.27 h1:PL3LzzXaOpmdrknnOlIeO2muIBHAwiKp6TxN1RbU5gI=
github.com/tdewolff/parse/v2 v2.5.27/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
@@ -472,8 +472,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU=
-golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA=
+golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -553,8 +553,8 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8=
-golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
diff --git a/httpRouters.go b/httpRouters.go
index 6775101..2b5428d 100644
--- a/httpRouters.go
+++ b/httpRouters.go
@@ -128,9 +128,6 @@ func (a *goBlog) blogRouter(blog string, conf *configBlog) func(r chi.Router) {
// Search
r.Group(a.blogSearchRouter(conf))
- // Custom pages
- r.Group(a.blogCustomPagesRouter(conf))
-
// Random post
r.Group(a.blogRandomRouter(conf))
@@ -295,29 +292,6 @@ func (a *goBlog) blogSearchRouter(conf *configBlog) func(r chi.Router) {
}
}
-// Blog - Custom pages
-func (a *goBlog) blogCustomPagesRouter(conf *configBlog) func(r chi.Router) {
- return func(r chi.Router) {
- r.Use(a.privateModeHandler)
- for _, cp := range conf.CustomPages {
- r.Group(func(r chi.Router) {
- r.Use(middleware.WithValue(customPageContextKey, cp))
- if cp.Cache {
- ce := cp.CacheExpiration
- if ce == 0 {
- ce = a.defaultCacheExpiration()
- }
- r.Use(
- a.cacheMiddleware,
- middleware.WithValue(cacheExpirationKey, ce),
- )
- }
- r.Get(cp.Path, a.serveCustomPage)
- })
- }
- }
-}
-
// Blog - Random
func (a *goBlog) blogRandomRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) {
diff --git a/indieAuthServer.go b/indieAuthServer.go
index f1859f1..73c4593 100644
--- a/indieAuthServer.go
+++ b/indieAuthServer.go
@@ -31,7 +31,7 @@ func (a *goBlog) indieAuthRequest(w http.ResponseWriter, r *http.Request) {
return
}
// Render page that let's the user authorize the app
- a.renderNew(w, r, a.renderIndieAuth, &renderData{
+ a.render(w, r, a.renderIndieAuth, &renderData{
Data: iareq,
})
}
diff --git a/main.go b/main.go
index 9e20df7..6dde00e 100644
--- a/main.go
+++ b/main.go
@@ -154,10 +154,6 @@ func (app *goBlog) initComponents(logging bool) {
app.logErrAndQuit("Failed to init template translations:", err.Error())
return
}
- if err = app.initRendering(); err != nil { // Needs assets and minify
- app.logErrAndQuit("Failed to init HTML rendering:", err.Error())
- return
- }
if err = app.initCache(); err != nil {
app.logErrAndQuit("Failed to init HTTP cache:", err.Error())
return
diff --git a/notifications.go b/notifications.go
index a82f382..a60f3f3 100644
--- a/notifications.go
+++ b/notifications.go
@@ -154,7 +154,7 @@ func (a *goBlog) notificationsAdmin(w http.ResponseWriter, r *http.Request) {
}
nextPath = fmt.Sprintf("%s/page/%d", notificationsPath, nextPage)
// Render
- a.renderNew(w, r, a.renderNotificationsAdmin, &renderData{
+ a.render(w, r, a.renderNotificationsAdmin, &renderData{
Data: ¬ificationsRenderData{
notifications: notifications,
hasPrev: hasPrev,
diff --git a/original-assets/styles/styles.scss b/original-assets/styles/styles.scss
index 3312476..6faf317 100644
--- a/original-assets/styles/styles.scss
+++ b/original-assets/styles/styles.scss
@@ -250,11 +250,7 @@ details summary {
margin-bottom: 5px;
}
-#map {
- height: 400px;
-}
-
-#post-actions, #posteditactions {
+.actions {
@extend .p;
display: flex;
flex-wrap: wrap;
@@ -265,6 +261,10 @@ details summary {
}
}
+#map {
+ height: 400px;
+}
+
#announcement {
@extend .invert;
padding: 5px;
diff --git a/posts.go b/posts.go
index 77e4e6d..ccf92bd 100644
--- a/posts.go
+++ b/posts.go
@@ -83,7 +83,7 @@ func (a *goBlog) servePost(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(string(p.Status), statusDeletedSuffix) {
status = http.StatusGone
}
- a.renderNewWithStatusCode(w, r, status, renderMethod, &renderData{
+ a.renderWithStatusCode(w, r, status, renderMethod, &renderData{
BlogString: p.Blog,
Canonical: canonical,
Data: p,
@@ -356,7 +356,7 @@ func (a *goBlog) serveIndex(w http.ResponseWriter, r *http.Request) {
if summaryTemplate == "" {
summaryTemplate = defaultSummary
}
- a.renderNew(w, r, a.renderIndex, &renderData{
+ a.render(w, r, a.renderIndex, &renderData{
Canonical: a.getFullAddress(path),
Data: &indexRenderData{
title: title,
diff --git a/render.go b/render.go
index 8a88967..c88a670 100644
--- a/render.go
+++ b/render.go
@@ -1,76 +1,12 @@
package main
import (
- "html/template"
"net/http"
- "os"
- "path"
- "path/filepath"
- "strings"
"go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
)
-const (
- templatesDir = "templates"
- templatesExt = ".gohtml"
-
- templateBase = "base"
- templateEditor = "editor"
- templateCommentsAdmin = "commentsadmin"
- templateWebmentionAdmin = "webmentionadmin"
-)
-
-func (a *goBlog) initRendering() error {
- a.templates = map[string]*template.Template{}
- templateFunctions := template.FuncMap{
- "md": a.safeRenderMarkdownAsHTML,
- "mdtitle": a.renderMdTitle,
- "html": wrapStringAsHTML,
- // Code based rendering
- "tor": func(rd *renderData) template.HTML {
- buf := bufferpool.Get()
- hb := newHtmlBuilder(buf)
- a.renderTorNotice(hb, rd)
- res := template.HTML(buf.String())
- bufferpool.Put(buf)
- return res
- },
- // Others
- "dateformat": dateFormat,
- "unixtodate": unixToLocalDateString,
- "now": localNowString,
- "asset": a.assetFileName,
- "string": a.ts.GetTemplateStringVariantFunc(),
- "absolute": a.getFullAddress,
- "opensearch": openSearchUrl,
- "editortemplate": a.editorPostTemplate,
- "editorpostdesc": a.editorPostDesc,
- }
- baseTemplate, err := template.New("base").Funcs(templateFunctions).ParseFiles(path.Join(templatesDir, templateBase+templatesExt))
- if err != nil {
- return err
- }
- err = filepath.Walk(templatesDir, func(p string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if info.Mode().IsRegular() && path.Ext(p) == templatesExt {
- if name := strings.TrimSuffix(path.Base(p), templatesExt); name != templateBase {
- if a.templates[name], err = template.Must(baseTemplate.Clone()).New(name).ParseFiles(p); err != nil {
- return err
- }
- }
- }
- return nil
- })
- if err != nil {
- return err
- }
- return nil
-}
-
type renderData struct {
BlogString string
Canonical string
@@ -91,31 +27,11 @@ func (d *renderData) LoggedIn() bool {
return d.app.isLoggedIn(d.req)
}
-func (a *goBlog) render(w http.ResponseWriter, r *http.Request, template string, data *renderData) {
- a.renderWithStatusCode(w, r, http.StatusOK, template, data)
+func (a *goBlog) render(w http.ResponseWriter, r *http.Request, f func(*htmlBuilder, *renderData), data *renderData) {
+ a.renderWithStatusCode(w, r, http.StatusOK, f, data)
}
-func (a *goBlog) renderWithStatusCode(w http.ResponseWriter, r *http.Request, statusCode int, template string, data *renderData) {
- // Check render data
- a.checkRenderData(r, data)
- // Set content type
- w.Header().Set(contentType, contenttype.HTMLUTF8)
- // Render template and write minified HTML
- buf := bufferpool.Get()
- defer bufferpool.Put(buf)
- if err := a.templates[template].ExecuteTemplate(buf, template, data); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- w.WriteHeader(statusCode)
- _ = a.min.Minify(contenttype.HTML, w, buf)
-}
-
-func (a *goBlog) renderNew(w http.ResponseWriter, r *http.Request, f func(*htmlBuilder, *renderData), data *renderData) {
- a.renderNewWithStatusCode(w, r, http.StatusOK, f, data)
-}
-
-func (a *goBlog) renderNewWithStatusCode(w http.ResponseWriter, r *http.Request, statusCode int, f func(*htmlBuilder, *renderData), data *renderData) {
+func (a *goBlog) renderWithStatusCode(w http.ResponseWriter, r *http.Request, statusCode int, f func(*htmlBuilder, *renderData), data *renderData) {
// Check render data
a.checkRenderData(r, data)
// Set content type
diff --git a/search.go b/search.go
index 7fa80e0..c38828f 100644
--- a/search.go
+++ b/search.go
@@ -26,7 +26,7 @@ func (a *goBlog) serveSearch(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(servePath, searchEncode(q)), http.StatusFound)
return
}
- a.renderNew(w, r, a.renderSearch, &renderData{
+ a.render(w, r, a.renderSearch, &renderData{
Canonical: a.getFullAddress(servePath),
})
}
diff --git a/sitemap.go b/sitemap.go
index feb41b0..36f10fe 100644
--- a/sitemap.go
+++ b/sitemap.go
@@ -102,12 +102,6 @@ func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request
Loc: a.getFullAddress(bc.getRelativePath(defaultIfEmpty(cc.Path, defaultContactPath))),
})
}
- // Custom pages
- for _, cp := range bc.CustomPages {
- sm.Add(&sitemap.URL{
- Loc: a.getFullAddress(cp.Path),
- })
- }
// Write sitemap
a.writeSitemapXML(w, sm)
}
diff --git a/taxonomies.go b/taxonomies.go
index bdd828e..5204b86 100644
--- a/taxonomies.go
+++ b/taxonomies.go
@@ -20,7 +20,7 @@ func (a *goBlog) serveTaxonomy(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
- a.renderNew(w, r, a.renderTaxonomy, &renderData{
+ a.render(w, r, a.renderTaxonomy, &renderData{
Canonical: a.getFullAddress(r.URL.Path),
Data: &taxonomyRenderData{
taxonomy: tax,
diff --git a/templates/assets/css/styles.css b/templates/assets/css/styles.css
index 515a575..b014cf3 100644
--- a/templates/assets/css/styles.css
+++ b/templates/assets/css/styles.css
@@ -144,7 +144,7 @@ details summary > *:first-child {
border-bottom: 1px solid var(--primary, #000);
}
-.p, #post-actions, #posteditactions, table {
+.p, .actions, table {
display: block;
margin-top: 1em;
margin-bottom: 1em;
@@ -210,19 +210,19 @@ details summary > *:first-child {
margin-bottom: 5px;
}
-#map {
- height: 400px;
-}
-
-#post-actions, #posteditactions {
+.actions {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
-#post-actions *, #posteditactions * {
+.actions * {
text-align: center;
}
+#map {
+ height: 400px;
+}
+
#announcement {
padding: 5px;
text-align: center;
diff --git a/templates/base.gohtml b/templates/base.gohtml
deleted file mode 100644
index f483103..0000000
--- a/templates/base.gohtml
+++ /dev/null
@@ -1,46 +0,0 @@
-{{ define "base" }}
-
-
-
-
-
- {{ with .Canonical }}{{ end }}
- {{ block "title" . }}
{{ mdtitle .Blog.Title }}{{ end }}
-
-
-
-
-
-
-
- {{ with .User }}{{ range .Identities }}{{ end }}{{ end }}
- {{ $os := opensearch .Blog }}
- {{ if $os }}{{ end }}
- {{ with .Blog.Announcement }}{{ with .Text }}{{ md . }}
{{ end }}{{ end }}
-
- {{ block "main" . }}{{ end }}
-
- {{ if .EasterEgg }}{{ end }}
-
-{{ end }}
\ No newline at end of file
diff --git a/templates/commentsadmin.gohtml b/templates/commentsadmin.gohtml
deleted file mode 100644
index 7455c54..0000000
--- a/templates/commentsadmin.gohtml
+++ /dev/null
@@ -1,36 +0,0 @@
-{{ define "title" }}
- {{ string .Blog.Lang "comments" }} - {{ mdtitle .Blog.Title }}
-{{ end }}
-
-{{ define "main" }}
-
- {{ string .Blog.Lang "comments" }}
- {{ $blog := .Blog }}
- {{ range $i, $comment := .Data.Comments }}
-
- {{ end }}
- {{ if .Data.HasPrev }}
- {{ string .Blog.Lang "prev" }}
- {{ end }}
- {{ if .Data.HasNext }}
- {{ string .Blog.Lang "next" }}
- {{ end }}
-
-{{ end }}
-
-{{ define "commentsadmin" }}
- {{ template "base" . }}
-{{ end }}
\ No newline at end of file
diff --git a/templates/editor.gohtml b/templates/editor.gohtml
deleted file mode 100644
index 3e9b4e6..0000000
--- a/templates/editor.gohtml
+++ /dev/null
@@ -1,66 +0,0 @@
-{{ define "title" }}
-
- {{ string .Blog.Lang "editor" }} - {{ mdtitle .Blog.Title }}
-{{ end }}
-
-{{ define "main" }}
-
- {{ string .Blog.Lang "editor" }}
- {{ string .Blog.Lang "create" }}
- {{ md (editorpostdesc .BlogString) }}
-
-
- {{ if .Data.UpdatePostURL }}
- {{ string .Blog.Lang "update" }}
-
- {{ end }}
-
- {{ string .Blog.Lang "posts" }}
- {{ string .Blog.Lang "drafts" }}
- {{ string .Blog.Lang "privateposts" }}
- {{ string .Blog.Lang "unlistedposts" }}
- {{ string .Blog.Lang "scheduledposts" }}
- {{ string .Blog.Lang "deletedposts" }}
-
- {{ string .Blog.Lang "upload" }}
-
- {{ string .Blog.Lang "mediafiles" }}
-
- {{ string .Blog.Lang "location" }}
-
-
- {{ string .Blog.Lang "gpxhelper" }}
- {{ string .Blog.Lang "gpxhelperdesc" }}
-
-
-
-
-
-
-{{ end }}
-
-{{ define "editor" }}
- {{ template "base" . }}
-{{ end }}
\ No newline at end of file
diff --git a/templates/webmentionadmin.gohtml b/templates/webmentionadmin.gohtml
deleted file mode 100644
index e083c0c..0000000
--- a/templates/webmentionadmin.gohtml
+++ /dev/null
@@ -1,43 +0,0 @@
-{{ define "title" }}
- {{ string .Blog.Lang "webmentions" }} - {{ mdtitle .Blog.Title }}
-{{ end }}
-
-{{ define "main" }}
-
- {{ string .Blog.Lang "webmentions" }}
- {{ $blog := .Blog }}
- {{ $current := .Data.Current }}
- {{ range $i, $mention := .Data.Mentions }}
-
- {{ end }}
- {{ if .Data.HasPrev }}
- {{ string .Blog.Lang "prev" }}
- {{ end }}
- {{ if .Data.HasNext }}
- {{ string .Blog.Lang "next" }}
- {{ end }}
-
-{{ end }}
-
-{{ define "webmentionadmin" }}
- {{ template "base" . }}
-{{ end }}
\ No newline at end of file
diff --git a/ui.go b/ui.go
index dfbc176..810677f 100644
--- a/ui.go
+++ b/ui.go
@@ -336,7 +336,7 @@ func (a *goBlog) renderComment(h *htmlBuilder, rd *renderData) {
hb.writeElementClose("main")
// Interactions
if rd.CommentsEnabled {
- a.renderInteractions(hb, rd.Blog, rd.Canonical)
+ a.renderInteractions(hb, rd)
}
},
)
@@ -448,7 +448,7 @@ func (a *goBlog) renderBlogStats(hb *htmlBuilder, rd *renderData) {
hb.writeElementClose("main")
// Interactions
if rd.CommentsEnabled {
- a.renderInteractions(hb, rd.Blog, rd.Canonical)
+ a.renderInteractions(hb, rd)
}
},
)
@@ -620,7 +620,7 @@ func (a *goBlog) renderGeoMap(hb *htmlBuilder, rd *renderData) {
}
hb.writeElementClose("main")
if rd.CommentsEnabled {
- a.renderInteractions(hb, rd.Blog, rd.Canonical)
+ a.renderInteractions(hb, rd)
}
},
)
@@ -695,7 +695,7 @@ func (a *goBlog) renderBlogroll(hb *htmlBuilder, rd *renderData) {
hb.writeElementClose("main")
// Interactions
if rd.CommentsEnabled {
- a.renderInteractions(hb, rd.Blog, rd.Canonical)
+ a.renderInteractions(hb, rd)
}
},
)
@@ -891,7 +891,7 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
// Post meta
a.renderPostMeta(hb, p, rd.Blog, "post")
// Post actions
- hb.writeElementOpen("div", "id", "post-actions")
+ hb.writeElementOpen("div", "class", "actions")
// Share button
hb.writeElementOpen("a", "class", "button", "href", fmt.Sprintf("https://www.addtoany.com/share#url=%s%s", a.shortPostURL(p), funk.ShortIf(p.RenderedTitle != "", "&title="+p.RenderedTitle, "")), "target", "_blank", "rel", "nofollow noopener noreferrer")
hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "share"))
@@ -964,7 +964,7 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
hb.writeElementClose("main")
// Post edit actions
if rd.LoggedIn() {
- hb.writeElementOpen("div", "id", "posteditactions")
+ hb.writeElementOpen("div", "class", "actions")
// Update
hb.writeElementOpen("form", "method", "post", "action", rd.Blog.RelativePath("/editor")+"#update")
hb.writeElementOpen("input", "type", "hidden", "name", "editoraction", "value", "loadupdate")
@@ -999,7 +999,7 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
}
// Comments
if rd.CommentsEnabled {
- a.renderInteractions(hb, rd.Blog, rd.Canonical)
+ a.renderInteractions(hb, rd)
}
},
)
@@ -1201,9 +1201,9 @@ func (a *goBlog) renderNotificationsAdmin(hb *htmlBuilder, rd *renderData) {
hb.writeElementClose("i")
hb.writeElementClose("p")
// Message
- a.renderMarkdownToWriter(hb, n.Text, false)
+ _ = a.renderMarkdownToWriter(hb, n.Text, false)
// Delete form
- hb.writeElementOpen("form", "method", "post", "action", "/notifications/delete")
+ hb.writeElementOpen("form", "class", "actions", "method", "post", "action", "/notifications/delete")
hb.writeElementOpen("input", "type", "hidden", "name", "notificationid", "value", n.ID)
hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "delete"))
hb.writeElementClose("form")
@@ -1215,3 +1215,320 @@ func (a *goBlog) renderNotificationsAdmin(hb *htmlBuilder, rd *renderData) {
},
)
}
+
+type commentsRenderData struct {
+ comments []*comment
+ hasPrev, hasNext bool
+ prev, next string
+}
+
+func (a *goBlog) renderCommentsAdmin(hb *htmlBuilder, rd *renderData) {
+ crd, ok := rd.Data.(*commentsRenderData)
+ if !ok {
+ return
+ }
+ a.renderBase(
+ hb, rd,
+ func(hb *htmlBuilder) {
+ a.renderTitleTag(hb, rd.Blog, a.ts.GetTemplateStringVariant(rd.Blog.Lang, "comments"))
+ },
+ func(hb *htmlBuilder) {
+ hb.writeElementOpen("main")
+ // Title
+ hb.writeElementOpen("h1")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "comments"))
+ hb.writeElementClose("h1")
+ // Notifications
+ for _, c := range crd.comments {
+ hb.writeElementOpen("div", "class", "p")
+ // ID, Target, Name
+ hb.writeElementOpen("p")
+ hb.writeEscaped("ID: ")
+ hb.writeEscaped(fmt.Sprintf("%d", c.ID))
+ hb.writeElementOpen("br")
+ hb.writeEscaped("Target: ")
+ hb.writeElementOpen("a", "href", c.Target, "target", "_blank")
+ hb.writeEscaped(c.Target)
+ hb.writeElementClose("a")
+ hb.writeElementOpen("br")
+ hb.writeEscaped("Name: ")
+ if c.Website != "" {
+ hb.writeElementOpen("a", "href", c.Website, "target", "_blank", "rel", "nofollow noopener noreferrer ugc")
+ }
+ hb.writeEscaped(c.Name)
+ if c.Website != "" {
+ hb.writeElementClose("a")
+ }
+ hb.writeElementClose("p")
+ // Comment
+ hb.writeElementOpen("p")
+ hb.write(c.Comment)
+ hb.writeElementClose("p")
+ // Delete form
+ hb.writeElementOpen("form", "class", "actions", "method", "post", "action", rd.Blog.getRelativePath("/comment/delete"))
+ hb.writeElementOpen("input", "type", "hidden", "name", "commentid", "value", c.ID)
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "delete"))
+ hb.writeElementClose("form")
+ hb.writeElementClose("div")
+ }
+ // Pagination
+ a.renderPagination(hb, rd.Blog, crd.hasPrev, crd.hasNext, crd.prev, crd.next)
+ hb.writeElementClose("main")
+ },
+ )
+}
+
+type webmentionRenderData struct {
+ mentions []*mention
+ hasPrev, hasNext bool
+ prev, current, next string
+}
+
+func (a *goBlog) renderWebmentionAdmin(hb *htmlBuilder, rd *renderData) {
+ wrd, ok := rd.Data.(*webmentionRenderData)
+ if !ok {
+ return
+ }
+ a.renderBase(
+ hb, rd,
+ func(hb *htmlBuilder) {
+ a.renderTitleTag(hb, rd.Blog, a.ts.GetTemplateStringVariant(rd.Blog.Lang, "webmentions"))
+ },
+ func(hb *htmlBuilder) {
+ hb.writeElementOpen("main")
+ // Title
+ hb.writeElementOpen("h1")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "webmentions"))
+ hb.writeElementClose("h1")
+ // Notifications
+ for _, m := range wrd.mentions {
+ hb.writeElementOpen("div", "id", fmt.Sprintf("mention-%d", m.ID), "class", "p")
+ hb.writeElementOpen("p")
+ // Source
+ hb.writeEscaped("From: ")
+ hb.writeElementOpen("a", "href", m.Source, "target", "_blank", "rel", "noopener noreferrer")
+ hb.writeEscaped(m.Source)
+ hb.writeElementClose("a")
+ hb.writeElementOpen("br")
+ // u-url
+ if m.Source != m.Url {
+ hb.writeEscaped("u-url: ")
+ hb.writeElementOpen("a", "href", m.Url, "target", "_blank", "rel", "noopener noreferrer")
+ hb.writeEscaped(m.Url)
+ hb.writeElementClose("a")
+ hb.writeElementOpen("br")
+ }
+ // Target
+ hb.writeEscaped("To: ")
+ hb.writeElementOpen("a", "href", m.Target, "target", "_blank")
+ hb.writeEscaped(m.Target)
+ hb.writeElementClose("a")
+ hb.writeElementOpen("br")
+ // Date
+ hb.writeEscaped("Created: ")
+ hb.writeEscaped(unixToLocalDateString(m.Created))
+ hb.writeElementOpen("br")
+ hb.writeElementOpen("br")
+ // Author
+ if m.Author != "" {
+ hb.writeEscaped(m.Author)
+ hb.writeElementOpen("br")
+ }
+ // Title
+ if m.Title != "" {
+ hb.writeElementOpen("strong")
+ hb.writeEscaped(m.Title)
+ hb.writeElementClose("strong")
+ hb.writeElementOpen("br")
+ }
+ // Content
+ if m.Content != "" {
+ hb.writeElementOpen("i")
+ hb.writeEscaped(m.Content)
+ hb.writeElementClose("i")
+ hb.writeElementOpen("br")
+ }
+ hb.writeElementClose("p")
+ // Actions
+ hb.writeElementOpen("form", "method", "post", "class", "actions")
+ hb.writeElementOpen("input", "type", "hidden", "name", "mentionid", "value", m.ID)
+ hb.writeElementOpen("input", "type", "hidden", "name", "redir", "value", fmt.Sprintf("%s#mention-%d", wrd.current, m.ID))
+ if m.Status == webmentionStatusVerified {
+ // Approve verified mention
+ hb.writeElementOpen("input", "type", "submit", "formaction", "/webmention/approve", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "approve"))
+ }
+ // Delete mention
+ hb.writeElementOpen("input", "type", "submit", "formaction", "/webmention/delete", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "delete"))
+ // Reverify mention
+ hb.writeElementOpen("input", "type", "submit", "formaction", "/webmention/reverify", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "reverify"))
+ hb.writeElementClose("form")
+ }
+ // Pagination
+ a.renderPagination(hb, rd.Blog, wrd.hasPrev, wrd.hasNext, wrd.prev, wrd.next)
+ hb.writeElementClose("main")
+ },
+ )
+}
+
+type editorRenderData struct {
+ updatePostUrl string
+ updatePostContent string
+}
+
+func (a *goBlog) renderEditor(hb *htmlBuilder, rd *renderData) {
+ edrd, ok := rd.Data.(*editorRenderData)
+ if !ok {
+ return
+ }
+ a.renderBase(
+ hb, rd,
+ func(hb *htmlBuilder) {
+ a.renderTitleTag(hb, rd.Blog, a.ts.GetTemplateStringVariant(rd.Blog.Lang, "editor"))
+ // Chroma CSS
+ hb.writeElementOpen("link", "rel", "stylesheet", "href", a.assetFileName("css/chroma.css"))
+ },
+ func(hb *htmlBuilder) {
+ hb.writeElementOpen("main")
+ // Title
+ hb.writeElementOpen("h1")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "editor"))
+ hb.writeElementClose("h1")
+
+ // Create
+ hb.writeElementOpen("h2")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "create"))
+ hb.writeElementClose("h2")
+ _ = a.renderMarkdownToWriter(hb, a.editorPostDesc(rd.Blog), false)
+ hb.writeElementOpen("form", "method", "post", "class", "fw p")
+ hb.writeElementOpen("input", "type", "hidden", "name", "h", "value", "entry")
+ hb.writeElementOpen(
+ "textarea",
+ "name", "content",
+ "class", "monospace h400p formcache mdpreview",
+ "id", "create-input",
+ "data-preview", "post-preview",
+ "data-previewws", rd.Blog.getRelativePath("/editor/preview"),
+ )
+ hb.writeEscaped(a.editorPostTemplate(rd.BlogString, rd.Blog))
+ hb.writeElementClose("textarea")
+ hb.writeElementOpen("div", "id", "post-preview", "class", "hide")
+ hb.writeElementClose("div")
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "create"))
+ hb.writeElementClose("form")
+
+ // Update
+ if edrd.updatePostUrl != "" {
+ hb.writeElementOpen("h2", "id", "#update")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "update"))
+ hb.writeElementClose("h2")
+ hb.writeElementOpen("form", "method", "post", "class", "fw p", "action", "#update")
+ hb.writeElementOpen("input", "type", "hidden", "name", "editoraction", "value", "updatepost")
+ hb.writeElementOpen("input", "type", "hidden", "name", "url", "value", edrd.updatePostUrl)
+ hb.writeElementOpen(
+ "textarea",
+ "name", "content",
+ "class", "monospace h400p mdpreview",
+ "data-preview", "update-preview",
+ "data-previewws", rd.Blog.getRelativePath("/editor/preview"),
+ )
+ hb.writeEscaped(edrd.updatePostContent)
+ hb.writeElementClose("textarea")
+ hb.writeElementOpen("div", "id", "update-preview", "class", "hide")
+ hb.writeElementClose("div")
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "update"))
+ hb.writeElementClose("form")
+ }
+
+ // Posts
+ hb.writeElementOpen("h2")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "posts"))
+ hb.writeElementClose("h2")
+ // Drafts
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/drafts"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "drafts"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+ // Private
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/private"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "privateposts"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+ // Unlisted
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/unlisted"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "unlistedposts"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+ // Scheduled
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/scheduled"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "scheduledposts"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+ // Deleted
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/deleted"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "deletedposts"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+
+ // Upload
+ hb.writeElementOpen("h2")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "upload"))
+ hb.writeElementClose("h2")
+ hb.writeElementOpen("form", "class", "fw p", "method", "post", "enctype", "multipart/form-data")
+ hb.writeElementOpen("input", "type", "hidden", "name", "editoraction", "value", "upload")
+ hb.writeElementOpen("input", "type", "file", "name", "file")
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "upload"))
+ hb.writeElementClose("form")
+ // Media files
+ hb.writeElementOpen("p")
+ hb.writeElementOpen("a", "href", rd.Blog.getRelativePath("/editor/files"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "mediafiles"))
+ hb.writeElementClose("a")
+ hb.writeElementClose("p")
+
+ // Location-Helper
+ hb.writeElementOpen("h2")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "location"))
+ hb.writeElementClose("h2")
+ hb.writeElementOpen("form", "class", "fw p")
+ hb.writeElementOpen(
+ "input", "id", "geobtn", "type", "button",
+ "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "locationget"),
+ "data-failed", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "locationfailed"),
+ "data-notsupported", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "locationnotsupported"),
+ )
+ hb.writeElementOpen("input", "id", "geostatus", "type", "text", "class", "hide", "readonly", "")
+ hb.writeElementClose("form")
+
+ // GPX-Helper
+ hb.writeElementOpen("h2")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "gpxhelper"))
+ hb.writeElementClose("h2")
+ hb.writeElementOpen("p")
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "gpxhelperdesc"))
+ hb.writeElementClose("p")
+ hb.writeElementOpen("form", "class", "fw p", "method", "post", "enctype", "multipart/form-data")
+ hb.writeElementOpen("input", "type", "hidden", "name", "editoraction", "value", "helpgpx")
+ hb.writeElementOpen("input", "type", "file", "name", "file")
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "upload"))
+ hb.writeElementClose("form")
+
+ hb.writeElementClose("main")
+
+ // Scripts
+ // Editor preview
+ hb.writeElementOpen("script", "src", a.assetFileName("js/mdpreview.js"), "defer", "")
+ hb.writeElementClose("script")
+ // Geohelper
+ hb.writeElementOpen("script", "src", a.assetFileName("js/geohelper.js"), "defer", "")
+ hb.writeElementClose("script")
+ // Formcache
+ hb.writeElementOpen("script", "src", a.assetFileName("js/formcache.js"), "defer", "")
+ hb.writeElementClose("script")
+ },
+ )
+}
diff --git a/uiComponents.go b/uiComponents.go
index 2cf6989..576ed14 100644
--- a/uiComponents.go
+++ b/uiComponents.go
@@ -236,15 +236,12 @@ func (a *goBlog) renderOldContentWarning(hb *htmlBuilder, p *post, b *configBlog
hb.writeElementClose("strong")
}
-func (a *goBlog) renderInteractions(hb *htmlBuilder, b *configBlog, canonical string) {
- if b == nil || canonical == "" {
- return
- }
+func (a *goBlog) renderInteractions(hb *htmlBuilder, rd *renderData) {
// Start accordion
hb.writeElementOpen("details", "class", "p", "id", "interactions")
hb.writeElementOpen("summary")
hb.writeElementOpen("strong")
- hb.writeEscaped(a.ts.GetTemplateStringVariant(b.Lang, "interactions"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "interactions"))
hb.writeElementClose("strong")
hb.writeElementClose("summary")
// Render mentions
@@ -278,24 +275,24 @@ func (a *goBlog) renderInteractions(hb *htmlBuilder, b *configBlog, canonical st
}
hb.writeElementClose("ul")
}
- renderMentions(a.db.getWebmentionsByAddress(canonical))
+ renderMentions(a.db.getWebmentionsByAddress(rd.Canonical))
// Show form to send a webmention
hb.writeElementOpen("form", "class", "fw p", "method", "post", "action", "/webmention")
hb.writeElementOpen("label", "for", "wm-source", "class", "p")
- hb.writeEscaped(a.ts.GetTemplateStringVariant(b.Lang, "interactionslabel"))
+ hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "interactionslabel"))
hb.writeElementClose("label")
hb.writeElementOpen("input", "id", "wm-source", "type", "url", "name", "source", "placeholder", "URL", "required", "")
- hb.writeElementOpen("input", "type", "hidden", "name", "target", "value", canonical)
- hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(b.Lang, "send"))
+ hb.writeElementOpen("input", "type", "hidden", "name", "target", "value", rd.Canonical)
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "send"))
hb.writeElementClose("form")
// Show form to create a new comment
hb.writeElementOpen("form", "class", "fw p", "method", "post", "action", "/comment")
- hb.writeElementOpen("input", "type", "hidden", "name", "target", "value", canonical)
- hb.writeElementOpen("input", "type", "text", "name", "name", "placeholder", a.ts.GetTemplateStringVariant(b.Lang, "nameopt"))
- hb.writeElementOpen("input", "type", "url", "name", "website", "placeholder", a.ts.GetTemplateStringVariant(b.Lang, "websiteopt"))
- hb.writeElementOpen("textarea", "name", "comment", "required", "", "placeholder", a.ts.GetTemplateStringVariant(b.Lang, "comment"))
+ hb.writeElementOpen("input", "type", "hidden", "name", "target", "value", rd.Canonical)
+ hb.writeElementOpen("input", "type", "text", "name", "name", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "nameopt"))
+ hb.writeElementOpen("input", "type", "url", "name", "website", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "websiteopt"))
+ hb.writeElementOpen("textarea", "name", "comment", "required", "", "placeholder", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "comment"))
hb.writeElementClose("textarea")
- hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(b.Lang, "docomment"))
+ hb.writeElementOpen("input", "type", "submit", "value", a.ts.GetTemplateStringVariant(rd.Blog.Lang, "docomment"))
hb.writeElementClose("form")
// Finish accordion
hb.writeElementClose("details")
diff --git a/ui_test.go b/ui_test.go
index 5218dc9..fe9be72 100644
--- a/ui_test.go
+++ b/ui_test.go
@@ -123,7 +123,10 @@ func Test_renderInteractions(t *testing.T) {
buf := &bytes.Buffer{}
hb := newHtmlBuilder(buf)
- app.renderInteractions(hb, app.cfg.Blogs["default"], "https://example.com/testpost1")
+ app.renderInteractions(hb, &renderData{
+ Blog: app.cfg.Blogs["default"],
+ Canonical: "https://example.com/testpost1",
+ })
res := buf.Bytes()
_, err = goquery.NewDocumentFromReader(bytes.NewReader(res))
diff --git a/utils.go b/utils.go
index 57b2eb4..3b9dd6e 100644
--- a/utils.go
+++ b/utils.go
@@ -5,7 +5,6 @@ import (
"crypto/sha256"
"errors"
"fmt"
- "html/template"
"io"
"net/http"
"net/http/httptest"
@@ -205,10 +204,6 @@ func charCount(s string) (count int) {
return count
}
-func wrapStringAsHTML(s string) template.HTML {
- return template.HTML(s)
-}
-
// Check if url has allowed file extension
func urlHasExt(rawUrl string, allowed ...string) (ext string, has bool) {
u, err := url.Parse(rawUrl)
diff --git a/webmentionAdmin.go b/webmentionAdmin.go
index 4410150..e3a2dce 100644
--- a/webmentionAdmin.go
+++ b/webmentionAdmin.go
@@ -95,14 +95,14 @@ func (a *goBlog) webmentionAdmin(w http.ResponseWriter, r *http.Request) {
query = "?" + params.Encode()
}
// Render
- a.render(w, r, templateWebmentionAdmin, &renderData{
- Data: map[string]interface{}{
- "Mentions": mentions,
- "HasPrev": hasPrev,
- "HasNext": hasNext,
- "Prev": prevPath + query,
- "Current": currentPath + query,
- "Next": nextPath + query,
+ a.render(w, r, a.renderWebmentionAdmin, &renderData{
+ Data: &webmentionRenderData{
+ mentions: mentions,
+ hasPrev: hasPrev,
+ hasNext: hasNext,
+ prev: prevPath + query,
+ current: currentPath + query,
+ next: nextPath + query,
},
})
}