diff --git a/src/cmd/mediocre-blog/main.go b/src/cmd/mediocre-blog/main.go
index d6a6b56..d8ba768 100644
--- a/src/cmd/mediocre-blog/main.go
+++ b/src/cmd/mediocre-blog/main.go
@@ -112,6 +112,7 @@ func main() {
httpParams.PostAssetStore = postAssetStore
httpParams.PostDraftStore = postDraftStore
httpParams.MailingList = ml
+ httpParams.GeminiPublicURL = gmiParams.PublicURL
logger.Info(ctx, "starting http api")
httpAPI, err := http.New(httpParams)
diff --git a/src/gmi/tpl.go b/src/gmi/tpl.go
index 566ace0..5777024 100644
--- a/src/gmi/tpl.go
+++ b/src/gmi/tpl.go
@@ -161,6 +161,9 @@ func (a *api) tplHandler() (gemini.Handler, error) {
BlogHTTPURL: func(path string) string {
return blogURL(a.params.HTTPPublicURL, path, true)
},
+ BlogGeminiURL: func(path string) string {
+ return blogURL(a.params.PublicURL, path, true)
+ },
AssetURL: func(id string) string {
path := filepath.Join("assets", id)
return blogURL(a.params.PublicURL, path, false)
@@ -193,12 +196,9 @@ func (a *api) tplHandler() (gemini.Handler, error) {
allTpls := template.New("")
- allTpls.Funcs(preprocessFuncs.ToFuncsMap())
+ allTpls.Funcs(preprocessFuncs.ToFuncMap())
allTpls.Funcs(template.FuncMap{
- "BlogURLAbs": func(path string) string {
- return blogURL(a.params.PublicURL, path, true)
- },
"PostURLAbs": func(id string) string {
path := filepath.Join("posts", id) + ".gmi"
return blogURL(a.params.PublicURL, path, true)
diff --git a/src/gmi/tpl/feed.xml b/src/gmi/tpl/feed.xml
index a33e42f..aa596b7 100644
--- a/src/gmi/tpl/feed.xml
+++ b/src/gmi/tpl/feed.xml
@@ -3,11 +3,11 @@
mediocregopher's lil web corner
- {{ BlogURLAbs "/" }}
+ {{ BlogGeminiURL "/" }}
{{ if gt (len $posts) 0 -}}
{{ (index $posts 0).PublishedAt.Format "2006-01-02T15:04:05Z07:00" }}
{{ end -}}
-
+
mediocregopher
diff --git a/src/http/feed.go b/src/http/feed.go
index 918eb86..deaeb80 100644
--- a/src/http/feed.go
+++ b/src/http/feed.go
@@ -3,7 +3,6 @@ package http
import (
"fmt"
"net/http"
- "path/filepath"
"github.com/gorilla/feeds"
"github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil"
@@ -54,7 +53,7 @@ func (a *api) renderFeedHandler() http.Handler {
feed.Updated = post.LastUpdatedAt
}
- postURL := publicURL + filepath.Join("/posts", post.ID)
+ postURL := a.postURL(post.ID, true)
item := &feeds.Item{
Title: post.Title,
diff --git a/src/http/http.go b/src/http/http.go
index d51671d..da404dc 100644
--- a/src/http/http.go
+++ b/src/http/http.go
@@ -44,6 +44,10 @@ type Params struct {
// PublicURL is the base URL which site visitors can navigate to.
PublicURL *url.URL
+ // GeminiPublicURL is the base URL which gemini site visitors can navigate
+ // to.
+ GeminiPublicURL *url.URL
+
// ListenProto and ListenAddr are passed into net.Listen to create the
// API's listener. Both "tcp" and "unix" protocols are explicitly
// supported.
diff --git a/src/http/posts.go b/src/http/posts.go
index 8cb8472..2c6f896 100644
--- a/src/http/posts.go
+++ b/src/http/posts.go
@@ -66,14 +66,16 @@ type postTplPayload struct {
Body template.HTML
}
-func (a *api) postToPostTplPayload(storedPost post.StoredPost) (postTplPayload, error) {
-
- preprocessFuncs := post.PreprocessFunctions{
+func (a *api) postPreprocessFuncs() post.PreprocessFunctions {
+ return post.PreprocessFunctions{
BlogURL: func(path string) string {
- return a.blogURL(path, false)
+ return a.blogURL(a.params.PublicURL, path, false)
},
BlogHTTPURL: func(path string) string {
- return a.blogURL(path, false)
+ return a.blogURL(a.params.PublicURL, path, true)
+ },
+ BlogGeminiURL: func(path string) string {
+ return a.blogURL(a.params.GeminiPublicURL, path, true)
},
AssetURL: func(id string) string {
return a.assetURL(id, false)
@@ -83,10 +85,15 @@ func (a *api) postToPostTplPayload(storedPost post.StoredPost) (postTplPayload,
},
StaticURL: func(path string) string {
path = filepath.Join("static", path)
- return a.blogURL(path, false)
+ return a.blogURL(a.params.PublicURL, path, false)
},
Image: a.postPreprocessFuncImage,
}
+}
+
+func (a *api) postToPostTplPayload(storedPost post.StoredPost) (postTplPayload, error) {
+
+ preprocessFuncs := a.postPreprocessFuncs()
bodyBuf := new(bytes.Buffer)
diff --git a/src/http/tpl.go b/src/http/tpl.go
index 5fc54f3..4af715a 100644
--- a/src/http/tpl.go
+++ b/src/http/tpl.go
@@ -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,36 +79,20 @@ 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)
},
@@ -121,6 +106,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
diff --git a/src/http/tpl/follow.html b/src/http/tpl/follow.html
index c0e4980..132706b 100644
--- a/src/http/tpl/follow.html
+++ b/src/http/tpl/follow.html
@@ -114,7 +114,7 @@ emailSubscribe.onclick = async () => {
- {{ BlogURLAbs "feed.xml" }}
+ {{ BlogHTTPURL "feed.xml" }}
diff --git a/src/post/preprocess.go b/src/post/preprocess.go
index 3ec54ca..77aea81 100644
--- a/src/post/preprocess.go
+++ b/src/post/preprocess.go
@@ -17,12 +17,19 @@ type PreprocessFunctions struct {
// The given path should not have a leading slash.
BlogURL func(path string) string
- // BlogURL returns the given string, rooted to the base URL of the blog's
- // HTTP server (which may or may not include path components itself).
+ // BlogHTTPURL returns the given string, rooted to the base URL of the
+ // blog's HTTP server (which may or may not include path components itself).
//
// The given path should not have a leading slash.
BlogHTTPURL func(path string) string
+ // BlogGeminiURL returns the given string, rooted to the base URL of the
+ // blog's gemini server (which may or may not include path components
+ // itself).
+ //
+ // The given path should not have a leading slash.
+ BlogGeminiURL func(path string) string
+
// AssetURL returns the URL of the asset with the given ID.
AssetURL func(id string) string
@@ -43,14 +50,15 @@ type PreprocessFunctions struct {
Image func(args ...string) (string, error)
}
-func (funcs PreprocessFunctions) ToFuncsMap() template.FuncMap {
+func (funcs PreprocessFunctions) ToFuncMap() template.FuncMap {
return template.FuncMap{
- "BlogURL": funcs.BlogURL,
- "BlogHTTPURL": funcs.BlogHTTPURL,
- "AssetURL": funcs.AssetURL,
- "PostURL": funcs.PostURL,
- "StaticURL": funcs.StaticURL,
- "Image": funcs.Image,
+ "BlogURL": funcs.BlogURL,
+ "BlogHTTPURL": funcs.BlogHTTPURL,
+ "BlogGeminiURL": funcs.BlogGeminiURL,
+ "AssetURL": funcs.AssetURL,
+ "PostURL": funcs.PostURL,
+ "StaticURL": funcs.StaticURL,
+ "Image": funcs.Image,
}
}
@@ -61,7 +69,7 @@ func (p Post) PreprocessBody(into io.Writer, funcs PreprocessFunctions) error {
tpl := template.New("")
- tpl.Funcs(funcs.ToFuncsMap())
+ tpl.Funcs(funcs.ToFuncMap())
tpl, err := tpl.Parse(p.Body)