mirror of https://github.com/jlelse/GoBlog
Add a list of features to the docs and some small code improvements
This commit is contained in:
parent
9815abf4bb
commit
e9632720a3
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
|
|
12
config.go
12
config.go
|
@ -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]
|
||||
}
|
||||
|
|
10
contact.go
10
contact.go
|
@ -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)
|
||||
|
|
|
@ -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
2
go.mod
|
@ -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
4
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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/\">"+
|
||||
|
|
|
@ -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"))
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue