summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Picciano <mediocregopher@gmail.com>2024-05-18 18:29:19 +0200
committerBrian Picciano <mediocregopher@gmail.com>2024-05-18 18:29:19 +0200
commit0665d0c65974533fbd313f4e0b062b5103057aeb (patch)
tree5287795eed9767bd959a5139b77ef78b4024216d
parentffa26298c95451639a6e01db6692d02d50b3d518 (diff)
Replace all URL rendering within templates by a URLConstructor
-rw-r--r--src/gmi/gmi.go4
-rw-r--r--src/gmi/tpl.go2
-rw-r--r--src/gmi/tpl/feed.xml8
-rw-r--r--src/gmi/tpl/footer.gmi4
-rw-r--r--src/gmi/tpl/index.gmi8
-rw-r--r--src/gmi/tpl/posts/index.gmi11
-rw-r--r--src/gmi/tpl/posts/post.gmi10
-rw-r--r--src/http/http.go5
-rw-r--r--src/http/posts.go6
-rw-r--r--src/http/tpl.go2
-rw-r--r--src/http/tpl/admin.html6
-rw-r--r--src/http/tpl/base.html22
-rw-r--r--src/http/tpl/draft-posts-manage.html14
-rw-r--r--src/http/tpl/follow.html2
-rw-r--r--src/http/tpl/gemini-cta.html6
-rw-r--r--src/http/tpl/image.html4
-rw-r--r--src/http/tpl/index.html6
-rw-r--r--src/http/tpl/post-assets-manage.html8
-rw-r--r--src/http/tpl/post-edit.html16
-rw-r--r--src/http/tpl/post.html4
-rw-r--r--src/http/tpl/posts-manage.html14
-rw-r--r--src/http/tpl/posts.html8
-rw-r--r--src/render/methods.go14
-rw-r--r--src/render/url.go168
24 files changed, 269 insertions, 83 deletions
diff --git a/src/gmi/gmi.go b/src/gmi/gmi.go
index e37ca74..89c35bc 100644
--- a/src/gmi/gmi.go
+++ b/src/gmi/gmi.go
@@ -58,7 +58,9 @@ func (p *Params) SetupCfg(cfg *cfg.Cfg) {
var err error
- *publicURLStr = strings.TrimSuffix(*publicURLStr, "/")
+ if !strings.HasSuffix(*publicURLStr, "/") {
+ *publicURLStr += "/"
+ }
if p.PublicURL, err = url.Parse(*publicURLStr); err != nil {
return fmt.Errorf("parsing -gemini-public-url: %w", err)
diff --git a/src/gmi/tpl.go b/src/gmi/tpl.go
index f6c1754..cdf9535 100644
--- a/src/gmi/tpl.go
+++ b/src/gmi/tpl.go
@@ -175,6 +175,8 @@ func (a *api) tplHandler() (gemini.Handler, error) {
ctx,
r.URL,
a.params.PublicURL,
+ a.params.HTTPPublicURL,
+ a.params.PublicURL, // geminiURL
a.params.HTTPGeminiGatewayURL,
a.params.PostStore,
nil, // asset.Store, not supported by gemini endpoint
diff --git a/src/gmi/tpl/feed.xml b/src/gmi/tpl/feed.xml
index aa596b7..2935327 100644
--- a/src/gmi/tpl/feed.xml
+++ b/src/gmi/tpl/feed.xml
@@ -3,11 +3,11 @@
<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">
<title>mediocregopher's lil web corner</title>
- <id>{{ BlogGeminiURL "/" }}</id>
+ <id>{{ .RootURL.Absolute }}</id>
{{ if gt (len $posts) 0 -}}
<updated>{{ (index $posts 0).PublishedAt.Format "2006-01-02T15:04:05Z07:00" }}</updated>
{{ end -}}
- <link href="{{ BlogGeminiURL "/" }}"></link>
+ <link href="{{ .RootURL.Absolute }}"></link>
<author>
<name>mediocregopher</name>
</author>
@@ -15,8 +15,8 @@
<entry>
<title>{{ .Title }}</title>
<updated>{{ .PublishedAt.Format "2006-01-02T15:04:05Z07:00" }}</updated>
- <id>{{ PostURLAbs .ID }}</id>
- <link href="{{ PostURLAbs .ID }}" rel="alternate"></link>
+ <id>{{ $.RootURL.Absolute.Post .ID }}</id>
+ <link href="{{ $.RootURL.Absolute.Post .ID }}" rel="alternate"></link>
{{ if .Description -}}
<summary type="html">{{ .Description }}</summary>
{{ end -}}
diff --git a/src/gmi/tpl/footer.gmi b/src/gmi/tpl/footer.gmi
index 15ee7b6..04a6562 100644
--- a/src/gmi/tpl/footer.gmi
+++ b/src/gmi/tpl/footer.gmi
@@ -1,10 +1,10 @@
========================================
{{ if ne .GetPath "index.gmi" -}}
-=> {{ BlogURL "/" }} Home
+=> {{ .RootURL }} Home
{{ end -}}
=> https://dev.mediocregopher.com/mediocre-blog.git Source
-=> {{ BlogURL "wtfpl.txt" }} License for all content, if you must have one
+=> {{ .RootURL.Path "wtfpl.txt" }} License for all content, if you must have one
diff --git a/src/gmi/tpl/index.gmi b/src/gmi/tpl/index.gmi
index b854481..6a70607 100644
--- a/src/gmi/tpl/index.gmi
+++ b/src/gmi/tpl/index.gmi
@@ -2,16 +2,16 @@
This here's my little corner of the web, where I publish posts about projects I'm working on and things that interest me (which you can follow, if you like).
-=> {{ BlogURL "posts/" }} Browse all posts
+=> {{ .RootURL.Posts }} Browse all posts
{{ $getPostsRes := .GetPosts 0 1 -}}
{{ if gt (len $getPostsRes.Posts) 0 -}}
{{ $post := index $getPostsRes.Posts 0 -}}
-=> {{ PostURL $post.ID }} (Latest post: {{ $post.Title }})
+=> {{ .RootURL.Post $post.ID }} (Latest post: {{ $post.Title }})
{{ end -}}
-=> {{ BlogURL "feed.xml" }} RSS feed
+=> {{ .RootURL.Path "feed.xml" }} RSS feed
Below you'll find other information and links related to me.
@@ -21,7 +21,7 @@ Feel free to hmu over email or Signal if you'd like to get in touch.
=> mailto:me@mediocregopher Email: me@mediocregopher.com
-=> {{ BlogURL "me@mediocregopher.com.gpg" }} GPG Key
+=> {{ .RootURL.Path "me@mediocregopher.com.gpg" }} GPG Key
=> https://signal.me/#eu/x5psueq2E3WfFwwEgFDoWeSZx9k4u8vFBaiMSa4Lo0cvluHkb-dIpJp1wfdJsdie Signal: mediocregopher.01
diff --git a/src/gmi/tpl/posts/index.gmi b/src/gmi/tpl/posts/index.gmi
index 2ff296a..873222b 100644
--- a/src/gmi/tpl/posts/index.gmi
+++ b/src/gmi/tpl/posts/index.gmi
@@ -1,29 +1,28 @@
# 👻 mediocregopher's Posts
{{ $page := .GetQueryIntValue "page" 0 -}}
+{{ $getPostsRes := .GetPosts $page 20 -}}
{{ if eq $page 0 -}}
Here you'll find an archive of all published posts. The content varies almost as much as the quality!
{{ end -}}
-{{ $getPostsRes := .GetPosts $page 20 -}}
-
{{ if gt $page 0 -}}
-=> {{ BlogURL "posts" }}/?page={{ .Add $page -1 }} Previous Page
+=> {{ .RootURL.Posts.Page (.Add $page -1) }} Previous Page
{{ end -}}
{{ range $getPostsRes.Posts -}}
-=> {{ PostURL .ID }} {{ .PublishedAt.Format "2006-01-02" }} - {{ .Title }}
+=> {{ $.RootURL.Post .ID }} {{ .PublishedAt.Format "2006-01-02" }} - {{ .Title }}
{{ end -}}
{{ if $getPostsRes.HasMore -}}
-=> {{ BlogURL "posts" }}/?page={{ .Add $page 1 }} Next page
+=> {{ .RootURL.Posts.Page (.Add $page 1) }} Next page
{{ end }}
========================================
-=> {{ BlogURL "feed.xml" }} RSS feed
+=> {{ .RootURL.Path "feed.xml" }} RSS feed
{{ template "footer.gmi" . }}
diff --git a/src/gmi/tpl/posts/post.gmi b/src/gmi/tpl/posts/post.gmi
index b568044..eafa76c 100644
--- a/src/gmi/tpl/posts/post.gmi
+++ b/src/gmi/tpl/posts/post.gmi
@@ -3,7 +3,7 @@
{{ if eq $post.Format "md" -}}
This post has been translated from it's original markdown format, if it seems busted it might appear better over HTTP:
-=> {{ PostHTTPURL $post.ID }}
+=> {{ .RootURL.HTTP.Post $post.ID }}
{{ end -}}
@@ -26,18 +26,18 @@ Published {{ $post.PublishedAt.Format "2006-01-02" }} by mediocregopher
This post is part of a series!
{{ if $seriesNextPrev.Next -}}
-=> {{ BlogURL "posts" }}/{{ $seriesNextPrev.Next.ID }}.gmi Next in the series: {{ $seriesNextPrev.Next.Title }}
+=> {{ .RootURL.Post $seriesNextPrev.Next.ID }} Next in the series: {{ $seriesNextPrev.Next.Title }}
{{ end -}}
{{ if $seriesNextPrev.Previous -}}
-=> {{ BlogURL "posts" }}/{{ $seriesNextPrev.Previous.ID }}.gmi Prevous in the series: {{ $seriesNextPrev.Previous.Title }}
+=> {{ .RootURL.Post $seriesNextPrev.Previous.ID }} Prevous in the series: {{ $seriesNextPrev.Previous.Title }}
{{ end -}}
{{ end -}}
{{ else }}{{/* newline */}}
{{ end }}
-=> {{ BlogURL "posts/" }} Browse all posts
+=> {{ .RootURL.Posts }} Browse all posts
-=> {{ BlogURL "feed.xml" }} RSS feed
+=> {{ .RootURL.Path "feed.xml" }} RSS feed
{{ template "footer.gmi" . }}
diff --git a/src/http/http.go b/src/http/http.go
index 9bfed59..93cc043 100644
--- a/src/http/http.go
+++ b/src/http/http.go
@@ -89,7 +89,10 @@ func (p *Params) SetupCfg(cfg *cfg.Cfg) {
return fmt.Errorf("unmarshaling -http-auth-ratelimit: %w", err)
}
- *publicURLStr = strings.TrimSuffix(*publicURLStr, "/")
+ if !strings.HasSuffix(*publicURLStr, "/") {
+ *publicURLStr += "/"
+ }
+
if p.PublicURL, err = url.Parse(*publicURLStr); err != nil {
return fmt.Errorf("parsing -http-public-url: %w", err)
}
diff --git a/src/http/posts.go b/src/http/posts.go
index 14224f2..42e5b4a 100644
--- a/src/http/posts.go
+++ b/src/http/posts.go
@@ -40,10 +40,16 @@ func (a *api) postPreprocessFuncImage(args ...string) (string, error) {
tpl = txttpl.Must(tpl.Parse(mustReadTplFile("image.html")))
tplPayload := struct {
+ RootURL render.URLBuilder
ID string
Descr string
Resizable bool
}{
+ RootURL: render.NewURLBuilder(
+ a.params.PublicURL,
+ a.params.PublicURL, // httpURL
+ a.params.GeminiPublicURL,
+ ),
ID: id,
Descr: descr,
Resizable: asset.IsImageResizable(id),
diff --git a/src/http/tpl.go b/src/http/tpl.go
index 2711259..c4afbdc 100644
--- a/src/http/tpl.go
+++ b/src/http/tpl.go
@@ -135,6 +135,8 @@ func (a *api) newTPLData(r *http.Request, payload interface{}) tplData {
r.Context(),
r.URL,
a.params.PublicURL,
+ a.params.PublicURL, // httpURL
+ a.params.GeminiPublicURL,
a.params.GeminiGatewayURL,
a.params.PostStore,
a.params.PostAssetStore,
diff --git a/src/http/tpl/admin.html b/src/http/tpl/admin.html
index 0b4b4e3..2dfab0f 100644
--- a/src/http/tpl/admin.html
+++ b/src/http/tpl/admin.html
@@ -7,9 +7,9 @@ mostly left open to inspection, but you will not able to change
anything without providing credentials.
<ul>
- <li><a href="{{ BlogURL "posts?method=manage" }}">Posts</a></li>
- <li><a href="{{ BlogURL "assets?method=manage" }}">Assets</a></li>
- <li><a href="{{ BlogURL "drafts?method=manage" }}">Drafts</a> (private)</li>
+ <li><a href="{{ .RootURL.Posts.MethodManage }}">Posts</a></li>
+ <li><a href="{{ .RootURL.Assets.MethodManage }}">Assets</a></li>
+ <li><a href="{{ .RootURL.Drafts.MethodManage }}">Drafts</a> (private)</li>
</ul>
{{ end }}
diff --git a/src/http/tpl/base.html b/src/http/tpl/base.html
index 47644f7..f0419d5 100644
--- a/src/http/tpl/base.html
+++ b/src/http/tpl/base.html
@@ -3,12 +3,12 @@
<head>
<title>{{ .Title }}</title>
- <link rel="stylesheet" type="text/css" href="{{ StaticURL "new.css" }}" />
- <link rel="stylesheet" type="text/css" href="{{ StaticURL "mediocre.css" }}" />
- <link rel="apple-touch-icon" sizes="180x180" href="{{ StaticURL "favicon/apple-touch-icon.png" }}">
- <link rel="icon" type="image/png" sizes="32x32" href="{{ StaticURL "favicon/favicon-32x32.png" }}">
- <link rel="icon" type="image/png" sizes="16x16" href="{{ StaticURL "favicon/favicon-16x16.png" }}">
- <link rel="manifest" href="{{ StaticURL "favicon/site.webmanifest" }}">
+ <link rel="stylesheet" type="text/css" href="{{ .RootURL.Static "new.css" }}" />
+ <link rel="stylesheet" type="text/css" href="{{ .RootURL.Static "mediocre.css" }}" />
+ <link rel="apple-touch-icon" sizes="180x180" href="{{ .RootURL.Static "favicon/apple-touch-icon.png" }}">
+ <link rel="icon" type="image/png" sizes="32x32" href="{{ .RootURL.Static "favicon/favicon-32x32.png" }}">
+ <link rel="icon" type="image/png" sizes="16x16" href="{{ .RootURL.Static "favicon/favicon-16x16.png" }}">
+ <link rel="manifest" href="{{ .RootURL.Static "favicon/site.webmanifest" }}">
</head>
<body>
@@ -105,17 +105,17 @@
<strong>mediocregopher</strong>'s lil web corner
<br/>
<br/>
- <a href="{{ BlogURL "/" }}">Home</a>
+ <a href="{{ .RootURL }}">Home</a>
&nbsp;//&nbsp;
- <a href="{{ BlogURL "/posts" }}">Posts</a>
+ <a href="{{ .RootURL.Posts }}">Posts</a>
&nbsp;/&nbsp;
- <a href="{{ BlogURL "follow" }}">Follow</a>
+ <a href="{{ .RootURL.Path "follow" }}">Follow</a>
&nbsp;/&nbsp;
- <a href="{{ BlogURL "feed.xml" }}">RSS</a>
+ <a href="{{ .RootURL.Path "feed.xml" }}">RSS</a>
&nbsp;//&nbsp;
<a href="https://dev.mediocregopher.com/mediocre-blog.git">Source</a>
&nbsp;/&nbsp;
- <a href="{{ StaticURL "wtfpl.txt" }}">License</a>
+ <a href="{{ .RootURL.Static "wtfpl.txt" }}">License</a>
</header>
{{ template "body" . }}
diff --git a/src/http/tpl/draft-posts-manage.html b/src/http/tpl/draft-posts-manage.html
index b1b4362..417f716 100644
--- a/src/http/tpl/draft-posts-manage.html
+++ b/src/http/tpl/draft-posts-manage.html
@@ -1,6 +1,6 @@
{{ define "body" }}
- {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $page := .GetQueryIntValue "page" 0 -}}
{{ $getPostsRes := .GetDraftPosts $page 20 -}}
<script>
@@ -11,18 +11,18 @@
</script>
<p>
- <a href="{{ BlogURL "admin" }}">Back to Admin</a>
+ <a href="{{ .RootURL.Path "admin" }}">Back to Admin</a>
</p>
<h1>Drafts</h1>
<p>
- <a href="{{ BlogURL "drafts" }}?method=edit">New Draft</a>
+ <a href="{{ .RootURL.Drafts.MethodEdit }}">New Draft</a>
</p>
{{ if gt $page 0 }}
<p>
- <a href="?method=manage&p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
+ <a href="{{ .RootURL.Drafts.MethodManage.Page (.Add $page -1) }}">&lt; &lt; Previous Page</a>
</p>
{{ end }}
@@ -32,13 +32,13 @@
<tr>
<td>{{ .Title }}</td>
<td>
- <a href="{{ DraftURL .ID }}?method=edit">
+ <a href="{{ ($.RootURL.Draft .ID).MethodEdit }}">
Edit
</a>
</td>
<td>
<form
- action="{{ DraftURL .ID }}?method=delete"
+ action="{{ ($.RootURL.Draft .ID).MethodDelete }}"
method="POST"
>
<input
@@ -55,7 +55,7 @@
{{ if $getPostsRes.HasMore }}
<p>
- <a href="?method=manage&p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
+ <a href="{{ .RootURL.Drafts.MethodManage.Page (.Add $page 1) }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/http/tpl/follow.html b/src/http/tpl/follow.html
index 1958f95..091af49 100644
--- a/src/http/tpl/follow.html
+++ b/src/http/tpl/follow.html
@@ -6,7 +6,7 @@
</p>
<p>
- <a href="{{ BlogHTTPURL "feed.xml" }}">{{ BlogHTTPURL "feed.xml" }}</a>
+ <a href="{{ .RootURL.Absolute.Path "feed.xml" }}">{{ .RootURL.Absolute.Path "feed.xml" }}</a>
</p>
<p>
diff --git a/src/http/tpl/gemini-cta.html b/src/http/tpl/gemini-cta.html
index 89b8e8b..77c1114 100644
--- a/src/http/tpl/gemini-cta.html
+++ b/src/http/tpl/gemini-cta.html
@@ -2,11 +2,9 @@
<p>
This site can also be accessed via the gemini protocol:
- <a href="{{ BlogGeminiURL "/" | .URLIsSafe }}">
- {{ BlogGeminiURL "/" }}
- </a>
+ <a href="{{ .RootURL.Gemini.HTMLSafe }}">{{ .RootURL.Gemini.HTMLSafe }}</a>
</p>
<p>
- <a href="{{ PostURL "gemspace-tour" }}">What is gemini?</a>
+ <a href="{{ .RootURL.Post "gemspace-tour" }}">What is gemini?</a>
</p>
diff --git a/src/http/tpl/image.html b/src/http/tpl/image.html
index c6c19b3..7778625 100644
--- a/src/http/tpl/image.html
+++ b/src/http/tpl/image.html
@@ -1,7 +1,7 @@
<div style="text-align: center;">
- <a href="{{ AssetURL .ID }}" target="_blank">
+ <a href="{{ .RootURL.Asset .ID }}" target="_blank">
<img
- src="{{ AssetURL .ID }}{{ if .Resizable }}?w=800{{ end }}"
+ src="{{ .RootURL.Asset .ID }}{{ if .Resizable }}?w=800{{ end }}"
alt="{{ .Descr }}"
/>
</a>
diff --git a/src/http/tpl/index.html b/src/http/tpl/index.html
index 7f6399a..2685f4f 100644
--- a/src/http/tpl/index.html
+++ b/src/http/tpl/index.html
@@ -2,9 +2,9 @@
<p>
This here's my little corner of the web, where I publish
- <a href="{{ BlogURL "posts" }}">posts</a>
+ <a href="{{ .RootURL.Posts }}">posts</a>
about projects I'm working on and things that interest me (which you can
- <a href="{{ BlogURL "follow" }}">follow</a>,
+ <a href="{{ .RootURL.Path "follow" }}">follow</a>,
if you like).
</p>
@@ -12,7 +12,7 @@
<p>Feel free to hmu over email or Signal if you'd like to get in touch.</p>
<ul>
<li>Email: <a href="mailto:me@mediocregopher.com">me@mediocregopher.com</a></li>
- <li><a href="{{ StaticURL "me@mediocregopher.com.gpg" }}">GPG Key</a></li>
+ <li><a href="{{ .RootURL.Static "me@mediocregopher.com.gpg" }}">GPG Key</a></li>
<li>Signal:
<a href="https://signal.me/#eu/x5psueq2E3WfFwwEgFDoWeSZx9k4u8vFBaiMSa4Lo0cvluHkb-dIpJp1wfdJsdie">
mediocregopher.01
diff --git a/src/http/tpl/post-assets-manage.html b/src/http/tpl/post-assets-manage.html
index a0b0da0..7e01ff4 100644
--- a/src/http/tpl/post-assets-manage.html
+++ b/src/http/tpl/post-assets-manage.html
@@ -3,7 +3,7 @@
{{ $assetIDs := .GetPostAssetIDs }}
<p>
- <a href="{{ BlogURL "admin" }}">Back to Admin</a>
+ <a href="{{ .RootURL.Path "admin" }}">Back to Admin</a>
</p>
<h1>Assets</h1>
@@ -15,7 +15,7 @@
overwritten.
</p>
-<form action="{{ BlogURL "assets/" }}" method="POST" enctype="multipart/form-data">
+<form action="{{ .RootURL.Assets }}" method="POST" enctype="multipart/form-data">
<div class="row">
<div class="four columns">
<input type="text" placeholder="Unique ID" name="id" />
@@ -37,10 +37,10 @@
{{ range $assetIDs }}
<tr>
- <td><a href="{{ AssetURL . }}">{{ . }}</a></td>
+ <td><a href="{{ $.RootURL.Asset . }}">{{ . }}</a></td>
<td>
<form
- action="{{ AssetURL . }}?method=delete"
+ action="{{ ($.RootURL.Asset .).MethodDelete }}"
method="POST"
style="margin-bottom: 0;"
>
diff --git a/src/http/tpl/post-edit.html b/src/http/tpl/post-edit.html
index 28dcd0e..1c40a3a 100644
--- a/src/http/tpl/post-edit.html
+++ b/src/http/tpl/post-edit.html
@@ -6,17 +6,17 @@
<p>
{{ if .Payload.IsDraft }}
- <a href="{{ BlogURL "drafts?method=manage" }}">
+ <a href="{{ .RootURL.Drafts.MethodManage }}">
Back to Drafts
</a>
{{ else }}
- <a href="{{ BlogURL "posts?method=manage" }}">
+ <a href="{{ .RootURL.Posts.MethodManage }}">
Back to Posts
</a>
{{ end }}
</p>
-<form method="POST" action="{{ BlogURL "posts/" }}">
+<form method="POST" action="{{ .RootURL.Posts }}">
<table>
@@ -36,7 +36,7 @@
{{ $post.ID }}
<input name="id" type="hidden" value="{{ $post.ID }}" />
{{ else }}
- <a href="{{ PostURL $post.ID }}">{{ $post.ID }}</a>
+ <a href="{{ .RootURL.Post $post.ID }}">{{ $post.ID }}</a>
<input name="id" type="hidden" value="{{ $post.ID }}" />
{{ end }}
</td>
@@ -135,12 +135,12 @@
<input
type="submit"
value="Preview"
- formaction="{{ BlogURL "posts/" }}{{ $post.ID }}?method=preview"
+ formaction="{{ (.RootURL.Post $post.ID).MethodPreview }}"
formtarget="_blank"
/>
{{ if .Payload.IsDraft }}
- <input type="submit" value="Save" formaction="{{ BlogURL "drafts/" }}" />
+ <input type="submit" value="Save" formaction="{{ .RootURL.Drafts }}" />
<script>
@@ -154,12 +154,12 @@
<input
type="submit"
value="Publish"
- formaction="{{ BlogURL "posts/" }}"
+ formaction="{{ .RootURL.Posts }}"
onclick="confirmPublish(event)"
/>
{{ else }}
- <input type="submit" value="Update" formaction="{{ BlogURL "posts/" }}" />
+ <input type="submit" value="Update" formaction="{{ .RootURL.Posts }}" />
{{ end }}
</p>
diff --git a/src/http/tpl/post.html b/src/http/tpl/post.html
index 46a24fc..1bda8c9 100644
--- a/src/http/tpl/post.html
+++ b/src/http/tpl/post.html
@@ -27,7 +27,7 @@
This post is part of a series.<br/>
{{ if $seriesNextPrev.Next }}
- Next: <a href="{{ PostURL $seriesNextPrev.Next.ID }}">{{ $seriesNextPrev.Next.Title }}</a>
+ Next: <a href="{{ .RootURL.Post $seriesNextPrev.Next.ID }}">{{ $seriesNextPrev.Next.Title }}</a>
{{ end }}
{{ if and $seriesNextPrev.Next $seriesNextPrev.Previous }}
@@ -35,7 +35,7 @@
{{ end }}
{{ if $seriesNextPrev.Previous }}
- Previously: <a href="{{ PostURL $seriesNextPrev.Previous.ID }}">{{ $seriesNextPrev.Previous.Title }}</a>
+ Previously: <a href="{{ .RootURL.Post $seriesNextPrev.Previous.ID }}">{{ $seriesNextPrev.Previous.Title }}</a>
<br/>
{{ end }}
diff --git a/src/http/tpl/posts-manage.html b/src/http/tpl/posts-manage.html
index f9adbc1..ad9c9d7 100644
--- a/src/http/tpl/posts-manage.html
+++ b/src/http/tpl/posts-manage.html
@@ -1,6 +1,6 @@
{{ define "body" }}
- {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $page := .GetQueryIntValue "page" 0 -}}
{{ $getPostsRes := .GetPosts $page 20 -}}
<script>
@@ -11,14 +11,14 @@
</script>
<p>
- <a href="{{ BlogURL "admin" }}">Back to Admin</a>
+ <a href="{{ .RootURL.Path "admin" }}">Back to Admin</a>
</p>
<h1>Posts</h1>
{{ if gt $page 0 }}
<p>
- <a href="?method=manage&p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
+ <a href="{{ .RootURL.Posts.MethodManage.Page (.Add $page -1) }}">&lt; &lt; Previous Page</a>
</p>
{{ end }}
@@ -33,15 +33,15 @@
{{ range $getPostsRes.Posts }}
<tr>
<td>{{ .PublishedAt.Local.Format "2006-01-02 15:04:05 MST" }}</td>
- <td><a href="{{ PostURL .ID }}">{{ .Title }}</a></td>
+ <td><a href="{{ $.RootURL.Post .ID }}">{{ .Title }}</a></td>
<td>
- <a href="{{ PostURL .ID }}?method=edit">
+ <a href="{{ ($.RootURL.Post .ID).MethodEdit }}">
Edit
</a>
</td>
<td>
<form
- action="{{ PostURL .ID }}?method=delete"
+ action="{{ ($.RootURL.Post .ID).MethodDelete }}"
method="POST"
>
<input
@@ -58,7 +58,7 @@
{{ if $getPostsRes.HasMore }}
<p>
- <a href="?method=manage&p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
+ <a href="{{ .RootURL.Posts.MethodManage.Page (.Add $page 1) }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/http/tpl/posts.html b/src/http/tpl/posts.html
index 2fa336d..0df166a 100644
--- a/src/http/tpl/posts.html
+++ b/src/http/tpl/posts.html
@@ -1,11 +1,11 @@
{{ define "body" }}
- {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $page := .GetQueryIntValue "page" 0 -}}
{{ $getPostsRes := .GetPosts $page 20 -}}
{{ if gt $page 0 }}
<p>
- <a href="?p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
+ <a href="{{ .RootURL.Posts.Page (.Add $page -1) }}">&lt; &lt; Previous Page</a>
</p>
{{ else }}
<p>
@@ -17,7 +17,7 @@
<ul>
{{ range $getPostsRes.Posts }}
<li>
- <strong><a href="{{ PostURL .ID }}">
+ <strong><a href="{{ $.RootURL.Post .ID }}">
{{ .PublishedAt.Format "2006-01-02" }} - {{ .Title }}
</a></strong>
{{ if .Description }}
@@ -29,7 +29,7 @@
{{ if $getPostsRes.HasMore }}
<p>
- <a href="?p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
+ <a href="{{ .RootURL.Posts.Page (.Add $page 1) }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/render/methods.go b/src/render/methods.go
index 9b5a41e..ee22dfd 100644
--- a/src/render/methods.go
+++ b/src/render/methods.go
@@ -56,6 +56,8 @@ type Methods struct {
ctx context.Context
url *url.URL
publicURL *url.URL
+ httpURL *url.URL
+ geminiURL *url.URL
geminiGatewayURL *url.URL
postStore post.Store
postAssetStore asset.Store
@@ -71,6 +73,8 @@ func NewMethods(
ctx context.Context,
url *url.URL,
publicURL *url.URL,
+ httpURL *url.URL,
+ geminiURL *url.URL,
geminiGatewayURL *url.URL,
postStore post.Store,
postAssetStore asset.Store,
@@ -81,6 +85,8 @@ func NewMethods(
ctx,
url,
publicURL,
+ httpURL,
+ geminiURL,
geminiGatewayURL,
postStore,
postAssetStore,
@@ -91,6 +97,10 @@ func NewMethods(
}
}
+func (m *Methods) RootURL() URLBuilder {
+ return NewURLBuilder(m.publicURL, m.httpURL, m.geminiURL)
+}
+
func (m *Methods) GetTags() ([]string, error) {
return m.postStore.GetTags()
}
@@ -263,7 +273,3 @@ func (m *Methods) GetPath() (string, error) {
}
func (m *Methods) Add(a, b int) int { return a + b }
-
-func (m *Methods) URLIsSafe(s string) template.URL {
- return template.URL(s)
-}
diff --git a/src/render/url.go b/src/render/url.go
new file mode 100644
index 0000000..eb9756b
--- /dev/null
+++ b/src/render/url.go
@@ -0,0 +1,168 @@
+package render
+
+import (
+ "html/template"
+ "net/url"
+ "path"
+ "strconv"
+ "strings"
+)
+
+const (
+ urlBasePublic = iota
+ urlBaseHTTP
+ urlBaseGemini
+)
+
+// URLBuilder is used to construct a URL for the site. The API of URLBuilder is
+// designed to be convenient to used from a go template.
+type URLBuilder struct {
+ publicURL, httpURL, geminiURL *url.URL
+
+ abs bool
+ base int
+ path, method string
+ page int
+}
+
+func NewURLBuilder(publicURL, httpURL, geminiURL *url.URL) URLBuilder {
+ return URLBuilder{
+ publicURL: publicURL,
+ httpURL: httpURL,
+ geminiURL: geminiURL,
+ }
+}
+
+func (b URLBuilder) String() string {
+ var u *url.URL
+ switch b.base {
+ case urlBasePublic:
+ u = b.publicURL
+ case urlBaseHTTP:
+ u = b.httpURL
+ case urlBaseGemini:
+ u = b.geminiURL
+ }
+
+ u = u.JoinPath(b.path)
+
+ if u.Scheme == "gemini" &&
+ u.Host == b.geminiURL.Host &&
+ !strings.HasSuffix(u.Path, "/") &&
+ path.Ext(u.Path) == "" {
+ u.Path += ".gmi"
+ }
+
+ {
+ query := url.Values{}
+ if b.method != "" {
+ query.Set("method", b.method)
+ }
+ if b.page > 0 {
+ query.Set("page", strconv.Itoa(b.page))
+ }
+ if len(query) > 0 {
+ u.RawQuery = query.Encode()
+ }
+ }
+
+ if abs := b.abs || u.Scheme != b.publicURL.Scheme; !abs {
+ u.Scheme = ""
+ u.Host = ""
+ }
+
+ return u.String()
+}
+
+func (b URLBuilder) HTMLSafe() template.URL {
+ return template.URL(b.String())
+}
+
+// Absolute returns a URLBuilder which will always construct a URL containing
+// scheme and host.
+func (b URLBuilder) Absolute() URLBuilder {
+ b.abs = true
+ return b
+}
+
+func (b URLBuilder) Gemini() URLBuilder {
+ b.base = urlBaseGemini
+ return b
+}
+
+func (b URLBuilder) HTTP() URLBuilder {
+ b.base = urlBaseHTTP
+ return b
+}
+
+func (b URLBuilder) Assets() URLBuilder {
+ b.path = "assets/"
+ return b
+}
+
+func (b URLBuilder) Asset(id string) URLBuilder {
+ b.path = "assets/" + id
+ return b
+}
+
+func (b URLBuilder) Posts() URLBuilder {
+ b.path = "posts/"
+ return b
+}
+
+func (b URLBuilder) Post(id string) URLBuilder {
+ b.path = "posts/" + id
+ return b
+}
+
+func (b URLBuilder) Drafts() URLBuilder {
+ b.base = urlBaseHTTP
+ b.path = "drafts/"
+ return b
+}
+
+func (b URLBuilder) Draft(id string) URLBuilder {
+ b.base = urlBaseHTTP
+ b.path = "drafts/" + id
+ return b
+}
+
+func (b URLBuilder) Static(staticPath string) URLBuilder {
+ b.base = urlBaseHTTP
+ b.path = path.Join("static", staticPath)
+ return b
+}
+
+func (b URLBuilder) Path(p string) URLBuilder {
+ b.path = p
+ return b
+}
+
+func (b URLBuilder) Page(page int) URLBuilder {
+ b.page = page
+ return b
+}
+
+func (b URLBuilder) MethodEdit() URLBuilder {
+ b.base = urlBaseHTTP
+ b.method = "edit"
+ return b
+}
+
+func (b URLBuilder) MethodManage() URLBuilder {
+ b.base = urlBaseHTTP
+ b.method = "manage"
+ return b
+}
+
+func (b URLBuilder) MethodDelete() URLBuilder {
+ b.base = urlBaseHTTP
+ b.method = "delete"
+ return b
+}
+
+func (b URLBuilder) MethodPreview() URLBuilder {
+ b.base = urlBaseHTTP
+ b.method = "preview"
+ return b
+}