summaryrefslogtreecommitdiff
path: root/src/render/url.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/url.go')
-rw-r--r--src/render/url.go168
1 files changed, 168 insertions, 0 deletions
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
+}