|
|
|
@ -6,6 +6,7 @@ import ( |
|
|
|
|
"html/template" |
|
|
|
|
"io/fs" |
|
|
|
|
"net/http" |
|
|
|
|
"net/url" |
|
|
|
|
"path/filepath" |
|
|
|
|
"strings" |
|
|
|
|
"time" |
|
|
|
@ -27,28 +28,28 @@ func mustReadTplFile(fileName string) string { |
|
|
|
|
return string(b) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) blogURL(path string, abs bool) string { |
|
|
|
|
func (a *api) blogURL(base *url.URL, path string, abs bool) string { |
|
|
|
|
// filepath.Join strips trailing slash, but we want to keep it
|
|
|
|
|
trailingSlash := strings.HasSuffix(path, "/") |
|
|
|
|
|
|
|
|
|
res := filepath.Join("/", a.params.PublicURL.Path, path) |
|
|
|
|
path = filepath.Join("/", base.Path, path) |
|
|
|
|
|
|
|
|
|
if trailingSlash && res != "/" { |
|
|
|
|
res += "/" |
|
|
|
|
if trailingSlash && path != "/" { |
|
|
|
|
path += "/" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if abs { |
|
|
|
|
u := *a.params.PublicURL |
|
|
|
|
u.Path = res |
|
|
|
|
res = u.String() |
|
|
|
|
if !abs { |
|
|
|
|
return path |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return res |
|
|
|
|
u := *base |
|
|
|
|
u.Path = path |
|
|
|
|
return u.String() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) postURL(id string, abs bool) string { |
|
|
|
|
path := filepath.Join("posts", id) |
|
|
|
|
return a.blogURL(path, abs) |
|
|
|
|
return a.blogURL(a.params.PublicURL, path, abs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) editPostURL(id string, abs bool) string { |
|
|
|
@ -56,21 +57,21 @@ func (a *api) editPostURL(id string, abs bool) string { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) managePostsURL(abs bool) string { |
|
|
|
|
return a.blogURL("posts?method=manage", abs) |
|
|
|
|
return a.blogURL(a.params.PublicURL, "posts?method=manage", abs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) manageAssetsURL(abs bool) string { |
|
|
|
|
return a.blogURL("assets?method=manage", abs) |
|
|
|
|
return a.blogURL(a.params.PublicURL, "assets?method=manage", abs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) assetURL(id string, abs bool) string { |
|
|
|
|
path := filepath.Join("assets", id) |
|
|
|
|
return a.blogURL(path, false) |
|
|
|
|
return a.blogURL(a.params.PublicURL, path, false) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) draftPostURL(id string, abs bool) string { |
|
|
|
|
path := filepath.Join("drafts", id) |
|
|
|
|
return a.blogURL(path, abs) |
|
|
|
|
return a.blogURL(a.params.PublicURL, path, abs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) editDraftPostURL(id string, abs bool) string { |
|
|
|
@ -78,42 +79,29 @@ func (a *api) editDraftPostURL(id string, abs bool) string { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) manageDraftPostsURL(abs bool) string { |
|
|
|
|
return a.blogURL("drafts", abs) + "?method=manage" |
|
|
|
|
return a.blogURL(a.params.PublicURL, "drafts", abs) + "?method=manage" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) draftsURL(abs bool) string { |
|
|
|
|
return a.blogURL("drafts", abs) |
|
|
|
|
return a.blogURL(a.params.PublicURL, "drafts", abs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (a *api) tplFuncs() template.FuncMap { |
|
|
|
|
return template.FuncMap{ |
|
|
|
|
"BlogURL": func(path string) string { |
|
|
|
|
return a.blogURL(path, false) |
|
|
|
|
}, |
|
|
|
|
"BlogURLAbs": func(path string) string { |
|
|
|
|
return a.blogURL(path, true) |
|
|
|
|
}, |
|
|
|
|
"StaticURL": func(path string) string { |
|
|
|
|
path = filepath.Join("static", path) |
|
|
|
|
return a.blogURL(path, false) |
|
|
|
|
}, |
|
|
|
|
"StaticInlineCSS": func(path string) (template.CSS, error) { |
|
|
|
|
path = filepath.Join("static", path) |
|
|
|
|
b, err := staticFS.ReadFile(path) |
|
|
|
|
return template.CSS(b), err |
|
|
|
|
}, |
|
|
|
|
"PostURL": func(id string) string { |
|
|
|
|
return a.postURL(id, false) |
|
|
|
|
}, |
|
|
|
|
"AssetURL": func(id string) string { |
|
|
|
|
return a.assetURL(id, false) |
|
|
|
|
}, |
|
|
|
|
"DraftURL": func(id string) string { |
|
|
|
|
return a.draftPostURL(id, false) |
|
|
|
|
}, |
|
|
|
|
"DateTimeFormat": func(t time.Time) string { |
|
|
|
|
return t.Format("2006-01-02") |
|
|
|
|
}, |
|
|
|
|
"SafeURL": func(u string) template.URL { |
|
|
|
|
return template.URL(u) |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -121,6 +109,7 @@ func (a *api) parseTpl(name, tplBody string) (*template.Template, error) { |
|
|
|
|
|
|
|
|
|
tpl := template.New(name) |
|
|
|
|
tpl = tpl.Funcs(a.tplFuncs()) |
|
|
|
|
tpl = tpl.Funcs(template.FuncMap(a.postPreprocessFuncs().ToFuncMap())) |
|
|
|
|
|
|
|
|
|
var err error |
|
|
|
|
|
|
|
|
@ -137,6 +126,7 @@ func (a *api) mustParseTpl(name string) *template.Template { |
|
|
|
|
|
|
|
|
|
func (a *api) mustParseBasedTpl(name string) *template.Template { |
|
|
|
|
tpl := a.mustParseTpl(name) |
|
|
|
|
tpl = template.Must(tpl.New("gemini-cta.html").Parse(mustReadTplFile("gemini-cta.html"))) |
|
|
|
|
tpl = template.Must(tpl.New("base.html").Parse(mustReadTplFile("base.html"))) |
|
|
|
|
return tpl |
|
|
|
|
} |
|
|
|
@ -145,15 +135,19 @@ type tplData struct { |
|
|
|
|
Payload interface{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func newTPLData(r *http.Request, payload interface{}) tplData { |
|
|
|
|
return tplData{ |
|
|
|
|
Payload: payload, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// executeTemplate expects to be the final action in an http.Handler
|
|
|
|
|
func executeTemplate( |
|
|
|
|
rw http.ResponseWriter, r *http.Request, |
|
|
|
|
tpl *template.Template, payload interface{}, |
|
|
|
|
) { |
|
|
|
|
|
|
|
|
|
tplData := tplData{ |
|
|
|
|
Payload: payload, |
|
|
|
|
} |
|
|
|
|
tplData := newTPLData(r, payload) |
|
|
|
|
|
|
|
|
|
if err := tpl.Execute(rw, tplData); err != nil { |
|
|
|
|
apiutil.InternalServerError( |
|
|
|
@ -178,7 +172,10 @@ func (a *api) renderDumbTplHandler(tplName string) http.Handler { |
|
|
|
|
tpl := a.mustParseBasedTpl(tplName) |
|
|
|
|
|
|
|
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
|
|
|
|
if err := tpl.Execute(rw, nil); err != nil { |
|
|
|
|
|
|
|
|
|
tplData := newTPLData(r, nil) |
|
|
|
|
|
|
|
|
|
if err := tpl.Execute(rw, tplData); err != nil { |
|
|
|
|
apiutil.InternalServerError( |
|
|
|
|
rw, r, fmt.Errorf("rendering %q: %w", tplName, err), |
|
|
|
|
) |
|
|
|
|