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)