Add a list of features to the docs and some small code improvements

This commit is contained in:
Jan-Lukas Else 2021-11-04 08:52:16 +01:00
parent 9815abf4bb
commit e9632720a3
10 changed files with 72 additions and 19 deletions

View File

@ -17,7 +17,7 @@ import (
const defaultBlogrollPath = "/blogroll"
func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogKey).(string)
blog, bc := a.getBlog(r)
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (interface{}, error) {
return a.getBlogrollOutlines(blog)
})
@ -26,7 +26,7 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, "", http.StatusInternalServerError)
return
}
c := a.cfg.Blogs[blog].Blogroll
c := bc.Blogroll
can := a.getRelativePath(blog, defaultIfEmpty(c.Path, defaultBlogrollPath))
a.render(w, r, templateBlogroll, &renderData{
BlogString: blog,
@ -41,7 +41,7 @@ func (a *goBlog) serveBlogroll(w http.ResponseWriter, r *http.Request) {
}
func (a *goBlog) serveBlogrollExport(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogKey).(string)
blog, _ := a.getBlog(r)
outlines, err, _ := a.blogrollCacheGroup.Do(blog, func() (interface{}, error) {
return a.getBlogrollOutlines(blog)
})

View File

@ -22,8 +22,7 @@ func (a *goBlog) initBlogStats() {
}
func (a *goBlog) serveBlogStats(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogKey).(string)
bc := a.cfg.Blogs[blog]
blog, bc := a.getBlog(r)
canonical := bc.getRelativePath(defaultIfEmpty(bc.BlogStats.Path, defaultBlogStatsPath))
a.render(w, r, templateBlogStats, &renderData{
BlogString: blog,

View File

@ -3,6 +3,7 @@ package main
import (
"errors"
"log"
"net/http"
"net/url"
"strings"
@ -375,3 +376,14 @@ func (a *goBlog) httpsConfigured(checkAddress bool) bool {
a.cfg.Server.SecurityHeaders ||
(checkAddress && strings.HasPrefix(a.cfg.Server.PublicAddress, "https"))
}
func (a *goBlog) getBlog(r *http.Request) (string, *configBlog) {
if r == nil {
return a.cfg.DefaultBlog, a.cfg.Blogs[a.cfg.DefaultBlog]
}
blog := r.Context().Value(blogKey).(string)
if blog == "" {
return a.cfg.DefaultBlog, a.cfg.Blogs[a.cfg.DefaultBlog]
}
return blog, a.cfg.Blogs[blog]
}

View File

@ -13,8 +13,8 @@ import (
const defaultContactPath = "/contact"
func (a *goBlog) serveContactForm(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogKey).(string)
cc := a.cfg.Blogs[blog].Contact
blog, bc := a.getBlog(r)
cc := bc.Contact
a.render(w, r, templateContact, &renderData{
BlogString: blog,
Data: map[string]interface{}{
@ -58,12 +58,12 @@ func (a *goBlog) sendContactSubmission(w http.ResponseWriter, r *http.Request) {
}
_, _ = message.WriteString(formMessage)
// Send submission
blog := r.Context().Value(blogKey).(string)
if cc := a.cfg.Blogs[blog].Contact; cc != nil && cc.SMTPHost != "" && cc.EmailFrom != "" && cc.EmailTo != "" {
blog, bc := a.getBlog(r)
if cc := bc.Contact; cc != nil && cc.SMTPHost != "" && cc.EmailFrom != "" && cc.EmailTo != "" {
// Build email
var email bytes.Buffer
if ef := cc.EmailFrom; ef != "" {
_, _ = fmt.Fprintf(&email, "From: %s <%s>", defaultIfEmpty(a.cfg.Blogs[blog].Title, "GoBlog"), cc.EmailFrom)
_, _ = fmt.Fprintf(&email, "From: %s <%s>", defaultIfEmpty(bc.Title, "GoBlog"), cc.EmailFrom)
_, _ = fmt.Fprintln(&email)
}
_, _ = fmt.Fprintf(&email, "To: %s", cc.EmailTo)

View File

@ -10,7 +10,47 @@ License: MIT License
[GitHub mirror](https://github.com/jlelse/GoBlog)
[Codeberg mirror](https://codeberg.org/jlelse/GoBlog)
More information about GoBlog:
## Features
Here's an (incomplete) list of features:
- Single user with multiple blogs
- Publish, edit and delete Markdown posts using Micropub or the web-based editor
- Editor with live preview
- Drafts, private and unlisted posts
- SQLite database for storing posts and data
- Built-in full-text search
- Micropub with media endpoint for uploads
- Local storage for uploads or remote storage via FTP or BunnyCDN
- Automatic image resizing and compression
- Uploads possible via the web-based editor
- Send and receive Webmentions
- Webmention-based commenting
- IndieAuth
- Login with your own blog as an identity on the internet
- Two-factor authentication
- ActivityPub
- Publish posts to the Fediverse (Mastodon etc.)
- ActivityPub-based commenting
- Web feeds
- Multiple feed formats: RSS, Atom, JSON
- Feeds on any archive page
- Sitemap
- Automatic HTTPS using Let's Encrypt
- Tor Hidden Service
- Tailscale integration for private blogs with HTTPS
- Fast in-memory caching for even faster performance
- Automatic asset minification of HTML, CSS and JavaScript
- Statistics page with information about posts
- Map page with a map of all posts with a location
- Option to create post aliases for automatic redirects
- Redirects using regular expressions
- Hooks to execute custom commands on certain events
- Short URLs with option for a separate short domain
- Command to check for broken links
- Command to export all posts to Markdown files
## More information about GoBlog:
- [How to install and run GoBlog](./install.md)
- [How to build GoBlog](./build.md)

2
go.mod
View File

@ -99,7 +99,7 @@ require (
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 // indirect
go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 // indirect
golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c // indirect
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect
golang.zx2c4.com/wireguard v0.0.0-20210905140043-2ef39d47540c // indirect

4
go.sum
View File

@ -682,8 +682,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c h1:QOfDMdrf/UwlVR0UBq2Mpr58UzNtvgJRXA4BgPfFACs=
golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=

View File

@ -8,6 +8,9 @@ import (
"golang.org/x/crypto/acme/autocert"
)
// Make sure the httpsCache type implements the Cache interface
var _ autocert.Cache = &httpsCache{}
type httpsCache struct {
db *database
}

View File

@ -8,8 +8,7 @@ import (
)
func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogKey).(string)
b := a.cfg.Blogs[blog]
_, b := a.getBlog(r)
title := a.renderMdTitle(b.Title)
sURL := a.getFullAddress(b.getRelativePath(defaultIfEmpty(b.Search.Path, defaultSearchPath)))
xml := fmt.Sprintf("<?xml version=\"1.0\"?><OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\" xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">"+

View File

@ -12,14 +12,14 @@ import (
func TestMapRouter(t *testing.T) {
router := &MapRouter{
DefaultHandler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("Default"))
_, _ = rw.Write([]byte("Default"))
}),
Handlers: map[string]http.Handler{
"a.example.org": http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("a"))
_, _ = rw.Write([]byte("a"))
}),
"b.example.org": http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Write([]byte("b"))
_, _ = rw.Write([]byte("b"))
}),
},
}