diff --git a/activityStreams.go b/activityStreams.go
index 43b58f5..96e2479 100644
--- a/activityStreams.go
+++ b/activityStreams.go
@@ -150,5 +150,4 @@ func (b *configBlog) serveActivityStreams(blog string, w http.ResponseWriter) {
}
}
_ = json.NewEncoder(w).Encode(asBlog)
-
}
diff --git a/config.go b/config.go
index 49bca57..cb9b3c2 100644
--- a/config.go
+++ b/config.go
@@ -44,6 +44,7 @@ type configCache struct {
type configBlog struct {
Path string `mapstructure:"path"`
Lang string `mapstructure:"lang"`
+ TimeLang string `mapstructure:"timelang"`
Title string `mapstructure:"title"`
Description string `mapstructure:"description"`
Pagination int `mapstructure:"pagination"`
@@ -104,6 +105,7 @@ type configUser struct {
Name string `mapstructure:"name"`
Password string `mapstructure:"password"`
Picture string `mapstructure:"picture"`
+ Link string `mapstructure:"link"`
}
type configHooks struct {
diff --git a/customPages.go b/customPages.go
index 4e45207..df35f4a 100644
--- a/customPages.go
+++ b/customPages.go
@@ -5,8 +5,9 @@ import "net/http"
func serveCustomPage(blog *configBlog, page *customPage) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
render(w, page.Template, &renderData{
- Blog: blog,
- Data: page.Data,
+ Blog: blog,
+ Canonical: appConfig.Server.PublicAddress + page.Path,
+ Data: page.Data,
})
}
}
diff --git a/example-config.yaml b/example-config.yaml
deleted file mode 100644
index 159ff06..0000000
--- a/example-config.yaml
+++ /dev/null
@@ -1,70 +0,0 @@
-server:
- logging: false
- debug: false
- port: 8080
- domain: example.com
- publicAddress: http://localhost:8080
- publicHttps: false
- letsEncryptMail: mail@example.com
- localHttps: false
-database:
- file: data/db.sqlite
-cache:
- enable: true
- expiration: 600
-blogs:
- main:
- path: /
- lang: en_US
- title: My blog
- description: This is my blog
- sections:
- - name: posts
- title: Posts
- description: "**Posts** on this blog"
- taxonomies:
- - name: tags
- title: Tags
- description: "**Tags** on this blog"
- menus:
- main:
- items:
- - title: Home
- link: /
- - title: Posts
- link: /posts
- photos:
- enable: true
- parameter: images
- path: /photos
- title: Photos
- description: "Photos on this blog"
- activitystreams:
- enable: true
- replyParameter: replylink
- imagesParameter: images
-user:
- nick: admin
- name: Admin
- password: secret
-hugo:
- frontmatter:
- - meta: title
- parameter: title
- - meta: tags
- parameter: tags
-micropub:
- categoryParam: tags
- replyParam: replylink
- likeParam: likelink
- bookmarkParam: link
- audioParam: audio
- photoParam: images
- photoDescriptionParam: imagealts
-pathRedirects:
- - from: "\\/index\\.xml"
- to: ".rss"
- - from: "\\/feed\\.json"
- to: ".json"
- - from: "\\/(feed|rss)\\/?$"
- to: ".rss"
\ No newline at end of file
diff --git a/feeds.go b/feeds.go
index b51deeb..d84f2f9 100644
--- a/feeds.go
+++ b/feeds.go
@@ -5,6 +5,7 @@ import (
"strings"
"time"
+ "github.com/araddon/dateparse"
"github.com/gorilla/feeds"
)
@@ -15,6 +16,10 @@ const (
rssFeed feedType = "rss"
atomFeed feedType = "atom"
jsonFeed feedType = "json"
+
+ feedAudioURL = "audio"
+ feedAudioType = "audiomime"
+ feedAudioLength = "audiolength"
)
func generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*post, title string, description string) {
@@ -30,14 +35,33 @@ func generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Reques
Description: description,
Link: &feeds.Link{Href: appConfig.Server.PublicAddress + strings.TrimSuffix(r.URL.Path, "."+string(f))},
Created: now,
+ Author: &feeds.Author{
+ Name: appConfig.User.Name,
+ },
+ Image: &feeds.Image{
+ Url: appConfig.User.Picture,
+ },
}
for _, p := range posts {
+ created, _ := dateparse.ParseIn(p.Published, time.Local)
+ updated, _ := dateparse.ParseIn(p.Updated, time.Local)
+ var enc *feeds.Enclosure
+ if p.firstParameter(feedAudioURL) != "" {
+ enc = &feeds.Enclosure{
+ Url: p.firstParameter(feedAudioURL),
+ Type: p.firstParameter(feedAudioType),
+ Length: p.firstParameter(feedAudioLength),
+ }
+ }
feed.Add(&feeds.Item{
Title: p.title(),
Link: &feeds.Link{Href: appConfig.Server.PublicAddress + p.Path},
Description: p.summary(),
Id: p.Path,
Content: string(p.html()),
+ Created: created,
+ Updated: updated,
+ Enclosure: enc,
})
}
var feedStr string
diff --git a/go.mod b/go.mod
index a25d9bc..abd2c79 100644
--- a/go.mod
+++ b/go.mod
@@ -36,9 +36,10 @@ require (
github.com/yuin/goldmark v1.2.1
github.com/yuin/goldmark-emoji v1.0.1
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
- golang.org/x/net v0.0.0-20201026091529-146b70c837a4 // indirect
+ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
- golang.org/x/sys v0.0.0-20201026133411-418715ba6fdd // indirect
+ golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect
+ golang.org/x/text v0.3.4 // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
diff --git a/go.sum b/go.sum
index 2a22108..3797872 100644
--- a/go.sum
+++ b/go.sum
@@ -342,8 +342,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201026091529-146b70c837a4 h1:awiuzyrRjJDb+OXi9ceHO3SDxVoN3JER57mhtqkdQBs=
-golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -374,14 +374,16 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201026133411-418715ba6fdd h1:+7OQgGrJBd80e8ASl94G3xIpokulXXzB/dikfre4ho0=
-golang.org/x/sys v0.0.0-20201026133411-418715ba6fdd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
+golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/http.go b/http.go
index fb468ef..f8cf1b3 100644
--- a/http.go
+++ b/http.go
@@ -6,7 +6,6 @@ import (
"net/http"
"os"
"strconv"
- "strings"
"sync/atomic"
"github.com/go-chi/chi"
@@ -185,9 +184,10 @@ func buildHandler() (http.Handler, error) {
for _, section := range blogConfig.Sections {
if section.Name != "" {
path := blogPath + "/" + section.Name
- r.With(cacheMiddleware, minifier.Middleware).Get(path, serveSection(blog, path, section))
- r.With(cacheMiddleware, minifier.Middleware).Get(path+feedPath, serveSection(blog, path, section))
- r.With(cacheMiddleware, minifier.Middleware).Get(path+paginationPath, serveSection(blog, path, section))
+ handler := serveSection(blog, path, section)
+ r.With(cacheMiddleware, minifier.Middleware).Get(path, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(path+feedPath, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(path+paginationPath, handler)
}
}
@@ -201,17 +201,19 @@ func buildHandler() (http.Handler, error) {
}
for _, tv := range values {
vPath := path + "/" + urlize(tv)
- r.With(cacheMiddleware, minifier.Middleware).Get(vPath, serveTaxonomyValue(blog, vPath, taxonomy, tv))
- r.With(cacheMiddleware, minifier.Middleware).Get(vPath+feedPath, serveTaxonomyValue(blog, vPath, taxonomy, tv))
- r.With(cacheMiddleware, minifier.Middleware).Get(vPath+paginationPath, serveTaxonomyValue(blog, vPath, taxonomy, tv))
+ handler := serveTaxonomyValue(blog, vPath, taxonomy, tv)
+ r.With(cacheMiddleware, minifier.Middleware).Get(vPath, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(vPath+feedPath, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(vPath+paginationPath, handler)
}
}
}
// Photos
if blogConfig.Photos.Enabled {
- r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+blogConfig.Photos.Path, servePhotos(blog))
- r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+blogConfig.Photos.Path+paginationPath, servePhotos(blog))
+ handler := servePhotos(blog)
+ r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+blogConfig.Photos.Path, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+blogConfig.Photos.Path+paginationPath, handler)
}
// Blog
@@ -221,17 +223,18 @@ func buildHandler() (http.Handler, error) {
} else {
mw = []func(http.Handler) http.Handler{cacheMiddleware, minifier.Middleware}
}
- r.With(mw...).Get(fullBlogPath, serveHome(blog, blogPath))
- r.With(cacheMiddleware, minifier.Middleware).Get(fullBlogPath+feedPath, serveHome(blog, blogPath))
- r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+paginationPath, serveHome(blog, blogPath))
+ handler := serveHome(blog, blogPath)
+ r.With(mw...).Get(fullBlogPath, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(fullBlogPath+feedPath, handler)
+ r.With(cacheMiddleware, minifier.Middleware).Get(blogPath+paginationPath, handler)
// Custom pages
for _, cp := range blogConfig.CustomPages {
- serveFunc := serveCustomPage(blogConfig, cp)
+ handler := serveCustomPage(blogConfig, cp)
if cp.Cache {
- r.With(cacheMiddleware, minifier.Middleware).Get(cp.Path, serveFunc)
+ r.With(cacheMiddleware, minifier.Middleware).Get(cp.Path, handler)
} else {
- r.With(minifier.Middleware).Get(cp.Path, serveFunc)
+ r.With(minifier.Middleware).Get(cp.Path, handler)
}
}
}
@@ -268,14 +271,3 @@ func (d *dynamicHandler) swapHandler(h http.Handler) {
func (d *dynamicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
d.realHandler.Load().(http.Handler).ServeHTTP(w, r)
}
-
-func slashTrimmedPath(r *http.Request) string {
- return trimSlash(r.URL.Path)
-}
-
-func trimSlash(s string) string {
- if len(s) > 1 {
- s = strings.TrimSuffix(s, "/")
- }
- return s
-}
diff --git a/posts.go b/posts.go
index 8cd0cf1..e4f3604 100644
--- a/posts.go
+++ b/posts.go
@@ -46,8 +46,13 @@ func servePost(w http.ResponseWriter, r *http.Request) {
p.serveActivityStreams(w)
return
}
+ canonical := p.firstParameter("original")
+ if canonical == "" {
+ canonical = appConfig.Server.PublicAddress + p.Path
+ }
render(w, templatePost, &renderData{
blogString: p.Blog,
+ Canonical: canonical,
Data: p,
})
}
@@ -121,6 +126,7 @@ func serveTaxonomy(blog string, tax *taxonomy) func(w http.ResponseWriter, r *ht
}
render(w, templateTaxonomy, &renderData{
blogString: blog,
+ Canonical: appConfig.Server.PublicAddress + slashTrimmedPath(r),
Data: struct {
Taxonomy *taxonomy
TaxonomyValues []string
@@ -214,6 +220,7 @@ func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) {
}
render(w, template, &renderData{
blogString: ic.blog,
+ Canonical: appConfig.Server.PublicAddress + slashTrimmedPath(r),
Data: &indexTemplateData{
Title: title,
Description: description,
diff --git a/postsDb.go b/postsDb.go
index 375a663..f8f0978 100644
--- a/postsDb.go
+++ b/postsDb.go
@@ -66,21 +66,6 @@ func (p *post) checkPost() error {
p.Slug = fmt.Sprintf("%v-%02d-%02d-%v", now.Year(), int(now.Month()), now.Day(), random)
}
published, _ := dateparse.ParseIn(p.Published, time.Local)
- pathVars := struct {
- BlogPath string
- Year int
- Month int
- Day int
- Slug string
- Section string
- }{
- BlogPath: appConfig.Blogs[p.Blog].Path,
- Year: published.Year(),
- Month: int(published.Month()),
- Day: published.Day(),
- Slug: p.Slug,
- Section: p.Section,
- }
pathTmplString := appConfig.Blogs[p.Blog].Sections[p.Section].PathTemplate
if pathTmplString == "" {
return errors.New("path template empty")
@@ -90,7 +75,14 @@ func (p *post) checkPost() error {
return errors.New("failed to parse location template")
}
var pathBuffer bytes.Buffer
- err = pathTmpl.Execute(&pathBuffer, pathVars)
+ err = pathTmpl.Execute(&pathBuffer, map[string]interface{}{
+ "BlogPath": appConfig.Blogs[p.Blog].Path,
+ "Year": published.Year(),
+ "Month": int(published.Month()),
+ "Day": published.Day(),
+ "Slug": p.Slug,
+ "Section": p.Section,
+ })
if err != nil {
return errors.New("failed to execute location template")
}
diff --git a/render.go b/render.go
index 7069a7a..852a695 100644
--- a/render.go
+++ b/render.go
@@ -2,6 +2,7 @@ package main
import (
"bytes"
+ "errors"
"fmt"
"html/template"
"io/ioutil"
@@ -10,6 +11,7 @@ import (
"os"
"path"
"path/filepath"
+ "reflect"
"strings"
"time"
@@ -39,6 +41,9 @@ func initRendering() error {
"menu": func(blog *configBlog, id string) *menu {
return blog.Menus[id]
},
+ "user": func() *configUser {
+ return appConfig.User
+ },
"md": func(content string) template.HTML {
htmlContent, err := renderMarkdown(content)
if err != nil {
@@ -85,18 +90,61 @@ func initRendering() error {
ml := monday.Locale(localeString)
return monday.Format(d, monday.LongFormatsByLocale[ml], ml)
},
+ "now": func() string {
+ return time.Now().String()
+ },
"asset": assetFile,
"string": getTemplateStringVariant,
- "include": func(templateName string, blog *configBlog, data interface{}) (template.HTML, error) {
- buf := new(bytes.Buffer)
- err := templates[templateName].ExecuteTemplate(buf, templateName, &renderData{
- Blog: blog,
- Data: data,
- })
- return template.HTML(buf.String()), err
+ "include": func(templateName string, data ...interface{}) (template.HTML, error) {
+ if len(data) == 1 {
+ if rd, ok := data[0].(*renderData); ok {
+ buf := new(bytes.Buffer)
+ err := templates[templateName].ExecuteTemplate(buf, templateName, rd)
+ return template.HTML(buf.String()), err
+ }
+ return "", errors.New("wrong argument")
+ } else if len(data) == 2 {
+ if blog, ok := data[0].(*configBlog); ok {
+ buf := new(bytes.Buffer)
+ err := templates[templateName].ExecuteTemplate(buf, templateName, &renderData{
+ Blog: blog,
+ Data: data[1],
+ })
+ return template.HTML(buf.String()), err
+ }
+ return "", errors.New("wrong arguments")
+ }
+ return "", errors.New("wrong argument count")
+ },
+ "default": func(dflt interface{}, given ...interface{}) interface{} {
+ if len(given) == 0 {
+ return dflt
+ }
+ g := reflect.ValueOf(given[0])
+ if !g.IsValid() {
+ return dflt
+ }
+ set := false
+ switch g.Kind() {
+ case reflect.Bool:
+ set = true
+ case reflect.String, reflect.Array, reflect.Slice, reflect.Map:
+ set = g.Len() != 0
+ case reflect.Int:
+ set = g.Int() != 0
+ default:
+ set = !g.IsNil()
+ }
+ if set {
+ return given[0]
+ }
+ return dflt
},
"urlize": urlize,
"sort": sortedStrings,
+ "absolute": func(path string) string {
+ return appConfig.Server.PublicAddress + path
+ },
"blogRelative": func(blog *configBlog, path string) string {
return blog.getRelativePath(path)
},
@@ -138,6 +186,7 @@ func initRendering() error {
type renderData struct {
blogString string
+ Canonical string
Blog *configBlog
Data interface{}
}
diff --git a/templates/assets/js/speak.js b/templates/assets/js/speak.js
new file mode 100644
index 0000000..18f0911
--- /dev/null
+++ b/templates/assets/js/speak.js
@@ -0,0 +1,45 @@
+"use strict";
+
+function getVoice() {
+ if (window.speechSynthesis) {
+ return window.speechSynthesis.getVoices().filter(voice => voice.lang.startsWith(document.querySelector('html').lang))[0];
+ }
+ return false;
+}
+
+function initSpeak() {
+ if (window.speechSynthesis) {
+ let speakBtn = document.querySelector('#speakBtn');
+ speakBtn.style.display = '';
+ speakBtn.onclick = function() { speak() };
+ speakBtn.textContent = speakText;
+ }
+}
+
+function speak() {
+ console.log("Start speaking")
+ let speakBtn = document.querySelector('#speakBtn');
+ speakBtn.onclick = function() { stopSpeak() };
+ speakBtn.textContent = stopSpeakText;
+ let textContent =
+ ((document.querySelector('article .p-name')) ? document.querySelector('article .p-name').innerText + "\n\n" : "")
+ + document.querySelector('article .e-content').innerText;
+ let utterThis = new SpeechSynthesisUtterance(textContent);
+ utterThis.voice = getVoice();
+ utterThis.onerror = stopSpeak;
+ utterThis.onend = stopSpeak;
+ window.speechSynthesis.speak(utterThis);
+}
+
+function stopSpeak() {
+ console.log("Stop speaking")
+ window.speechSynthesis.cancel();
+ let speakBtn = document.querySelector('#speakBtn');
+ speakBtn.onclick = function() { speak() };
+ speakBtn.textContent = speakText;
+}
+
+window.onbeforeunload = function () {
+ stopSpeak();
+}
+initSpeak();
\ No newline at end of file
diff --git a/templates/author.gohtml b/templates/author.gohtml
new file mode 100644
index 0000000..e5cfa06
--- /dev/null
+++ b/templates/author.gohtml
@@ -0,0 +1,10 @@
+{{ define "author" }}
+ {{ with user }}
+
+ {{ with .Picture }}
{{ end }}
+ {{ if .Name }}
+
{{ .Name }}
+ {{ end }}
+
+ {{ end }}
+{{ end }}
\ No newline at end of file
diff --git a/templates/base.gohtml b/templates/base.gohtml
index d8ee40b..e7ae1f0 100644
--- a/templates/base.gohtml
+++ b/templates/base.gohtml
@@ -5,8 +5,11 @@
+ {{ with user.Picture }} {{ end }}
+ {{ with .Canonical }} {{ end }}
{{ template "title" . }}
- {{ include "micropub" .Blog .Data }}
- {{ include "header" .Blog .Data }}
+ {{ include "micropub" . }}
+ {{ include "header" . }}
{{ template "main" . }}
+ {{ include "footer" . }}
{{ end }}
\ No newline at end of file
diff --git a/templates/footer.gohtml b/templates/footer.gohtml
new file mode 100644
index 0000000..24b4f85
--- /dev/null
+++ b/templates/footer.gohtml
@@ -0,0 +1,12 @@
+{{ define "footer" }}
+
+{{ end }}
\ No newline at end of file
diff --git a/templates/header.gohtml b/templates/header.gohtml
index c100edb..2a1e1b4 100644
--- a/templates/header.gohtml
+++ b/templates/header.gohtml
@@ -2,6 +2,14 @@
{{ with .Blog.Description }}{{ . }}
{{ end }}
- {{ include "menu" .Blog .Data }}
+
+ {{ with menu .Blog "main" }}
+ {{ $first := true }}
+ {{ range $i, $item := .Items }}
+ {{ if ne $first true }} • {{ end }}{{ $item.Title }} {{ $first = false }}
+ {{ end }}
+ {{ end }}
+
{{ end }}
\ No newline at end of file
diff --git a/templates/menu.gohtml b/templates/menu.gohtml
deleted file mode 100644
index bd599f3..0000000
--- a/templates/menu.gohtml
+++ /dev/null
@@ -1,11 +0,0 @@
-{{ define "menu" }}
-
- {{ with menu .Blog "main" }}
- {{ $first := true }}
- {{ range $i, $item := .Items }}
- {{ if ne $first true }} • {{ end }}{{ $item.Title }} {{ $first = false }}
- {{ end }}
- {{ end }}
-
-{{ end }}
\ No newline at end of file
diff --git a/templates/photosummary.gohtml b/templates/photosummary.gohtml
index 7c2f81a..6efa673 100644
--- a/templates/photosummary.gohtml
+++ b/templates/photosummary.gohtml
@@ -1,12 +1,11 @@
{{ define "photosummary" }}
-
- {{ with p .Data "title" }}{{ . }} {{ end }}
- {{ if .Data.Published }}{{ longDate .Data.Published .Blog.Lang }}
{{ end }}
- {{ range $i, $photo := ( ps .Data .Blog.Photos.Parameter ) }}
- {{ md ( printf "![](%s)" $photo ) }}
- {{ end }}
- {{ summary .Data }}
- {{ string .Blog.Lang "view" }}
+
+ {{ with p .Data "title" }}{{ . }} {{ end }}
+ {{ include "postmeta" . }}
+ {{ range $i, $photo := ( ps .Data .Blog.Photos.Parameter ) }}
+ {{ md ( printf "![](%s)" $photo ) }}
+ {{ end }}
+ {{ summary .Data }}
+ {{ if (hasp .Data "images") }}🖼️ {{ end }}{{ string .Blog.Lang "view" }}
-
{{ end }}
\ No newline at end of file
diff --git a/templates/post.gohtml b/templates/post.gohtml
index 38b2658..e3cf916 100644
--- a/templates/post.gohtml
+++ b/templates/post.gohtml
@@ -1,34 +1,29 @@
{{ define "title" }}
{{ with p .Data "title" }}{{ . }} - {{end}}{{ .Blog.Title }}
+ {{ include "postheadmeta" . }}
{{ end }}
{{ define "main" }}
- {{ with title .Data }}{{ . }} {{ end }}
- {{ if .Data.Published }}
- {{ string .Blog.Lang "publishedon" }} {{ longDate .Data.Published .Blog.Lang }}
{{ end }}
- {{ if .Data.Updated }}
- {{ string .Blog.Lang "updatedon" }} {{ longDate .Data.Updated .Blog.Lang }}
{{ end }}
- {{ if .Data.Content }}
- {{ content .Data }}
- {{ end }}
-
- {{ $post := .Data }}
- {{ $blog := .Blog }}
- {{ range $i, $tax := $blog.Taxonomies }}
- {{ $tvs := ps $post $tax.Name }}
- {{ if gt (len $tvs) 0 }}
- In {{ $tax.Title }} :
- {{ range $j, $tv := $tvs }}
- {{ $tv }}
- {{ end }}
-
+
+ {{ with title .Data }}{{ . }} {{ end }}
+ {{ include "postmeta" . }}
+ {{ include "postactions" . }}
+ {{ if .Data.Content }}
+
+ {{ with p .Data "audio" }}
+
{{ end }}
+ {{ content .Data }}
+ {{ with p .Data "link" }}
+
{{ . }}
+ {{ end }}
+
{{ end }}
- {{ range $i, $t := (translations .Data) }}
- {{ (blog $t.Blog).Title }}
- {{ end }}
+ {{ include "posttax" . }}
+
+ {{ include "author" . }}
{{ end }}
diff --git a/templates/postactions.gohtml b/templates/postactions.gohtml
new file mode 100644
index 0000000..a9511d5
--- /dev/null
+++ b/templates/postactions.gohtml
@@ -0,0 +1,8 @@
+{{ define "postactions" }}
+
+{{ end }}
\ No newline at end of file
diff --git a/templates/postheadmeta.gohtml b/templates/postheadmeta.gohtml
new file mode 100644
index 0000000..376fe08
--- /dev/null
+++ b/templates/postheadmeta.gohtml
@@ -0,0 +1,13 @@
+{{ define "postheadmeta" }}
+
+ {{ $ISO8601 := "2006-01-02T15:04:05-07:00" }}
+ {{ if .Data.Published }}
+
+ {{ end }}
+ {{ if .Data.Updated }}
+
+ {{ end }}
+ {{ range $key, $image := ps .Data "images" }}
+
+ {{ end }}
+{{ end }}
\ No newline at end of file
diff --git a/templates/postmeta.gohtml b/templates/postmeta.gohtml
new file mode 100644
index 0000000..9770349
--- /dev/null
+++ b/templates/postmeta.gohtml
@@ -0,0 +1,17 @@
+{{ define "postmeta" }}
+
+ {{ $section := (index .Blog.Sections .Data.Section) }}
+ {{ if .Data.Published }}
{{ string .Blog.Lang "publishedon" }}
{{ longDate .Data.Published .Blog.TimeLang }} {{ if $section }} in
{{ $section.Title }} {{ end }}
{{ end }}
+ {{ if .Data.Updated }}
{{ string .Blog.Lang "updatedon" }} {{ longDate .Data.Updated .Blog.TimeLang }}
{{ end }}
+ {{ if p .Data "replylink" }}
+
+ {{ end }}
+ {{ if p .Data "likelink" }}
+
+ {{ end }}
+ {{ $translations := (translations .Data) }}
+ {{ if gt (len $translations) 0 }}
+
{{ string .Blog.Lang "translations" }}: {{ $delimiter := "" }}{{ range $i, $t := $translations }}{{ $delimiter }}
{{ title $t }} {{ $delimiter = ", " }}{{ end }}
+ {{ end }}
+
+{{ end }}
\ No newline at end of file
diff --git a/templates/posttax.gohtml b/templates/posttax.gohtml
new file mode 100644
index 0000000..ed1917c
--- /dev/null
+++ b/templates/posttax.gohtml
@@ -0,0 +1,14 @@
+{{ define "posttax" }}
+ {{ $post := .Data }}
+ {{ $blog := .Blog }}
+ {{ range $i, $tax := $blog.Taxonomies }}
+ {{ $tvs := ps $post $tax.Name }}
+ {{ if gt (len $tvs) 0 }}
+ {{ $tax.Title }} :
+ {{ range $j, $tv := $tvs }}
+ {{ $tv }}
+ {{ end }}
+
+ {{ end }}
+ {{ end }}
+{{ end }}
\ No newline at end of file
diff --git a/templates/strings/de.yaml b/templates/strings/de.yaml
new file mode 100644
index 0000000..fcbd9e1
--- /dev/null
+++ b/templates/strings/de.yaml
@@ -0,0 +1,11 @@
+publishedon: "Veröffentlicht am"
+updatedon: "Aktualisiert am"
+next: "Weiter"
+prev: "Zurück"
+view: "Anschauen"
+replyto: "Antwort an"
+likeof: "Gefällt mir von"
+translations: "Übersetzungen"
+share: "Teilen"
+speak: "Lies mir bitte vor."
+stopspeak: "Hör auf zu sprechen!"
\ No newline at end of file
diff --git a/templates/strings/de_DE.yaml b/templates/strings/de_DE.yaml
deleted file mode 100644
index 097df98..0000000
--- a/templates/strings/de_DE.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-publishedon: "Veröffentlicht am"
-updatedon: "Aktualisiert am"
-next: "Weiter"
-prev: "Zurück"
-view: "Anschauen"
\ No newline at end of file
diff --git a/templates/strings/default.yaml b/templates/strings/default.yaml
index bb50490..532c577 100644
--- a/templates/strings/default.yaml
+++ b/templates/strings/default.yaml
@@ -5,4 +5,10 @@ prev: "Previous"
view: "View"
authenticate: "Authenticate"
scopes: "Scopes"
-indieauth: "IndieAuth"
\ No newline at end of file
+indieauth: "IndieAuth"
+replyto: "Reply to"
+likeof: "Like of"
+translations: "Translations"
+share: "Share"
+speak: "Read to me, please."
+stopspeak: "Stop speaking!"
\ No newline at end of file
diff --git a/templates/summary.gohtml b/templates/summary.gohtml
index ffa19b0..ca8087e 100644
--- a/templates/summary.gohtml
+++ b/templates/summary.gohtml
@@ -1,13 +1,13 @@
{{ define "summary" }}
- {{ if p .Data "title" }}
+ {{ if p .Data "title" }}
- {{ end }}
- {{ include "summarymeta" .Blog .Data }}
+ {{ end }}
+ {{ include "postmeta" . }}
{{ summary .Data }}
{{ if (hasp .Data "images") }}🖼️ {{ end }}{{ string .Blog.Lang "view" }}
diff --git a/templates/summarymeta.gohtml b/templates/summarymeta.gohtml
deleted file mode 100644
index af560b8..0000000
--- a/templates/summarymeta.gohtml
+++ /dev/null
@@ -1,11 +0,0 @@
-{{ define "summarymeta" }}
-
- {{ $section := (index .Blog.Sections .Data.Section) }}
- {{ if .Data.Published }}
-
- {{ end }}
- {{ if .Data.Updated }}
-
{{ string .Blog.Lang "updatedon" }} {{ longDate .Data.Updated .Blog.Lang }}
- {{ end }}
-
-{{ end }}
\ No newline at end of file
diff --git a/utils.go b/utils.go
index 5f64218..850279b 100644
--- a/utils.go
+++ b/utils.go
@@ -2,6 +2,7 @@ package main
import (
"math/rand"
+ "net/http"
"sort"
"strings"
"time"
@@ -35,3 +36,14 @@ func generateRandomString(chars int) string {
}
return string(b)
}
+
+func slashTrimmedPath(r *http.Request) string {
+ return trimSlash(r.URL.Path)
+}
+
+func trimSlash(s string) string {
+ if len(s) > 1 {
+ s = strings.TrimSuffix(s, "/")
+ }
+ return s
+}