mirror of https://github.com/jlelse/GoBlog
Fix minify
This commit is contained in:
parent
8d60057590
commit
f42b3256a4
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/go-fed/httpsig"
|
"github.com/go-fed/httpsig"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -89,7 +90,10 @@ func (a *goBlog) apHandleWebfinger(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
apIri := a.apIri(blog)
|
apIri := a.apIri(blog)
|
||||||
b, _ := json.Marshal(map[string]any{
|
// Encode
|
||||||
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
if err := xml.NewEncoder(buf).Encode(map[string]any{
|
||||||
"subject": a.webfingerAccts[apIri],
|
"subject": a.webfingerAccts[apIri],
|
||||||
"aliases": []string{
|
"aliases": []string{
|
||||||
a.webfingerAccts[apIri],
|
a.webfingerAccts[apIri],
|
||||||
|
@ -107,9 +111,12 @@ func (a *goBlog) apHandleWebfinger(w http.ResponseWriter, r *http.Request) {
|
||||||
"href": apIri,
|
"href": apIri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
}); err != nil {
|
||||||
|
a.serveError(w, r, "Encoding failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, "application/jrd+json"+contenttype.CharsetUtf8Suffix)
|
w.Header().Set(contentType, "application/jrd+json"+contenttype.CharsetUtf8Suffix)
|
||||||
_, _ = a.min.Write(w, contenttype.JSON, b)
|
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/araddon/dateparse"
|
"github.com/araddon/dateparse"
|
||||||
ct "github.com/elnormous/contenttype"
|
ct "github.com/elnormous/contenttype"
|
||||||
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -90,9 +91,14 @@ type asEndpoints struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveActivityStreamsPost(p *post, w http.ResponseWriter) {
|
func (a *goBlog) serveActivityStreamsPost(p *post, w http.ResponseWriter) {
|
||||||
b, _ := json.Marshal(a.toASNote(p))
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
if err := json.NewEncoder(buf).Encode(a.toASNote(p)); err != nil {
|
||||||
|
http.Error(w, "Encoding failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, contenttype.ASUTF8)
|
w.Header().Set(contentType, contenttype.ASUTF8)
|
||||||
_, _ = a.min.Write(w, contenttype.AS, b)
|
_ = a.min.Get().Minify(contenttype.AS, w, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) toASNote(p *post) *asNote {
|
func (a *goBlog) toASNote(p *post) *asNote {
|
||||||
|
@ -195,7 +201,13 @@ func (a *goBlog) serveActivityStreams(blog string, w http.ResponseWriter, r *htt
|
||||||
URL: a.cfg.User.Picture,
|
URL: a.cfg.User.Picture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jb, _ := json.Marshal(asBlog)
|
// Encode
|
||||||
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
if err := json.NewEncoder(buf).Encode(asBlog); err != nil {
|
||||||
|
a.serveError(w, r, "Encoding failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, contenttype.ASUTF8)
|
w.Header().Set(contentType, contenttype.ASUTF8)
|
||||||
_, _ = a.min.Write(w, contenttype.AS, jb)
|
a.min.Get().Minify(contenttype.AS, w, buf)
|
||||||
}
|
}
|
||||||
|
|
10
blogroll.go
10
blogroll.go
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -54,20 +53,17 @@ func (a *goBlog) serveBlogrollExport(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
opmlBuf := bufferpool.Get()
|
opmlBuf := bufferpool.Get()
|
||||||
defer bufferpool.Put(opmlBuf)
|
defer bufferpool.Put(opmlBuf)
|
||||||
mw := a.min.Writer(contenttype.XML, opmlBuf)
|
if err = opml.Render(opmlBuf, &opml.OPML{
|
||||||
err = opml.Render(mw, &opml.OPML{
|
|
||||||
Version: "2.0",
|
Version: "2.0",
|
||||||
DateCreated: time.Now().UTC(),
|
DateCreated: time.Now().UTC(),
|
||||||
Outlines: outlines.([]*opml.Outline),
|
Outlines: outlines.([]*opml.Outline),
|
||||||
})
|
}); err != nil {
|
||||||
_ = mw.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to render OPML: %v", err)
|
log.Printf("Failed to render OPML: %v", err)
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
a.serveError(w, r, "", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set(contentType, contenttype.XMLUTF8)
|
w.Header().Set(contentType, contenttype.XMLUTF8)
|
||||||
_, _ = io.Copy(w, opmlBuf)
|
_ = a.min.Get().Minify(contenttype.XML, w, opmlBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) getBlogrollOutlines(blog string) ([]*opml.Outline, error) {
|
func (a *goBlog) getBlogrollOutlines(blog string) ([]*opml.Outline, error) {
|
||||||
|
|
|
@ -138,7 +138,7 @@ func (a *goBlog) serveEditorPost(w http.ResponseWriter, r *http.Request) {
|
||||||
a.serveError(w, r, err.Error(), http.StatusBadRequest)
|
a.serveError(w, r, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gpx, err := io.ReadAll(a.min.Reader(contenttype.XML, file))
|
gpx, err := io.ReadAll(a.min.Get().Reader(contenttype.XML, file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.serveError(w, r, err.Error(), http.StatusBadRequest)
|
a.serveError(w, r, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
|
2
feeds.go
2
feeds.go
|
@ -74,6 +74,6 @@ func (a *goBlog) generateFeed(blog string, f feedType, w http.ResponseWriter, r
|
||||||
_ = pipeWriter.CloseWithError(writeErr)
|
_ = pipeWriter.CloseWithError(writeErr)
|
||||||
}()
|
}()
|
||||||
w.Header().Set(contentType, feedMediaType+contenttype.CharsetUtf8Suffix)
|
w.Header().Set(contentType, feedMediaType+contenttype.CharsetUtf8Suffix)
|
||||||
minifyErr := a.min.Minify(feedMediaType, w, pipeReader)
|
minifyErr := a.min.Get().Minify(feedMediaType, w, pipeReader)
|
||||||
_ = pipeReader.CloseWithError(minifyErr)
|
_ = pipeReader.CloseWithError(minifyErr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,15 @@ func (a *goBlog) serveFs(f fs.FS, basePath string) http.HandlerFunc {
|
||||||
a.serve404(w, r)
|
a.serve404(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var read io.Reader = file
|
|
||||||
switch path.Ext(fileName) {
|
switch path.Ext(fileName) {
|
||||||
case ".js":
|
case ".js":
|
||||||
w.Header().Set(contentType, contenttype.JSUTF8)
|
w.Header().Set(contentType, contenttype.JSUTF8)
|
||||||
read = a.min.Reader(contenttype.JS, read)
|
_ = a.min.Get().Minify(contenttype.JS, w, file)
|
||||||
case ".css":
|
case ".css":
|
||||||
w.Header().Set(contentType, contenttype.CSSUTF8)
|
w.Header().Set(contentType, contenttype.CSSUTF8)
|
||||||
read = a.min.Reader(contenttype.CSS, read)
|
_ = a.min.Get().Minify(contenttype.CSS, w, file)
|
||||||
|
default:
|
||||||
|
_, _ = io.Copy(w, file)
|
||||||
}
|
}
|
||||||
_, _ = io.Copy(w, read)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/hacdias/indieauth/v2"
|
"github.com/hacdias/indieauth/v2"
|
||||||
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,9 +138,14 @@ func (a *goBlog) indieAuthVerification(w http.ResponseWriter, r *http.Request, w
|
||||||
resp.Token = token
|
resp.Token = token
|
||||||
resp.Scope = strings.Join(data.Scopes, " ")
|
resp.Scope = strings.Join(data.Scopes, " ")
|
||||||
}
|
}
|
||||||
b, _ := json.Marshal(resp)
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
if err = json.NewEncoder(buf).Encode(resp); err != nil {
|
||||||
|
a.serveError(w, r, "Encoding failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
_, _ = a.min.Write(w, contenttype.JSON, b)
|
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the authorization request and return the code
|
// Save the authorization request and return the code
|
||||||
|
@ -196,9 +202,14 @@ func (a *goBlog) indieAuthTokenVerification(w http.ResponseWriter, r *http.Reque
|
||||||
Me: a.getFullAddress("") + "/", // MUST contain a path component / trailing slash
|
Me: a.getFullAddress("") + "/", // MUST contain a path component / trailing slash
|
||||||
ClientID: data.ClientID,
|
ClientID: data.ClientID,
|
||||||
}
|
}
|
||||||
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
if err = json.NewEncoder(buf).Encode(res); err != nil {
|
||||||
|
a.serveError(w, r, "Encoding failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
b, _ := json.Marshal(res)
|
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
||||||
_, _ = a.min.Write(w, contenttype.JSON, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the database for the token and returns the indieAuthData with client and scope.
|
// Checks the database for the token and returns the indieAuthData with client and scope.
|
||||||
|
|
|
@ -73,15 +73,12 @@ func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
buf := bufferpool.Get()
|
buf := bufferpool.Get()
|
||||||
defer bufferpool.Put(buf)
|
defer bufferpool.Put(buf)
|
||||||
mw := a.min.Writer(contenttype.JSON, buf)
|
if err := json.NewEncoder(buf).Encode(result); err != nil {
|
||||||
err := json.NewEncoder(mw).Encode(result)
|
|
||||||
_ = mw.Close()
|
|
||||||
if err != nil {
|
|
||||||
a.serveError(w, r, "Failed to encode json", http.StatusInternalServerError)
|
a.serveError(w, r, "Failed to encode json", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
_, _ = io.Copy(w, buf)
|
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveMicropubPost(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveMicropubPost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -38,22 +38,22 @@ func Test_micropubQuery(t *testing.T) {
|
||||||
testCases := []testCase{
|
testCases := []testCase{
|
||||||
{
|
{
|
||||||
query: "config",
|
query: "config",
|
||||||
want: "{\"media-endpoint\":\"http://localhost:8080/micropub/media\"}\n",
|
want: "{\"media-endpoint\":\"http://localhost:8080/micropub/media\"}",
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
query: "source&url=http://localhost:8080/test/post",
|
query: "source&url=http://localhost:8080/test/post",
|
||||||
want: "{\"type\":[\"h-entry\"],\"properties\":{\"published\":[\"\"],\"updated\":[\"\"],\"post-status\":[\"published\"],\"visibility\":[\"public\"],\"category\":[\"test\",\"test2\"],\"content\":[\"---\\nblog: default\\npath: /test/post\\npriority: 0\\npublished: \\\"\\\"\\nsection: \\\"\\\"\\nstatus: published\\ntags:\\n - test\\n - test2\\nupdated: \\\"\\\"\\n---\\nTest post\"],\"url\":[\"http://localhost:8080/test/post\"],\"mp-slug\":[\"\"]}}\n",
|
want: "{\"type\":[\"h-entry\"],\"properties\":{\"published\":[\"\"],\"updated\":[\"\"],\"post-status\":[\"published\"],\"visibility\":[\"public\"],\"category\":[\"test\",\"test2\"],\"content\":[\"---\\nblog: default\\npath: /test/post\\npriority: 0\\npublished: \\\"\\\"\\nsection: \\\"\\\"\\nstatus: published\\ntags:\\n - test\\n - test2\\nupdated: \\\"\\\"\\n---\\nTest post\"],\"url\":[\"http://localhost:8080/test/post\"],\"mp-slug\":[\"\"]}}",
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
query: "source",
|
query: "source",
|
||||||
want: "{\"items\":[{\"type\":[\"h-entry\"],\"properties\":{\"published\":[\"\"],\"updated\":[\"\"],\"post-status\":[\"published\"],\"visibility\":[\"public\"],\"category\":[\"test\",\"test2\"],\"content\":[\"---\\nblog: default\\npath: /test/post\\npriority: 0\\npublished: \\\"\\\"\\nsection: \\\"\\\"\\nstatus: published\\ntags:\\n - test\\n - test2\\nupdated: \\\"\\\"\\n---\\nTest post\"],\"url\":[\"http://localhost:8080/test/post\"],\"mp-slug\":[\"\"]}}]}\n",
|
want: "{\"items\":[{\"type\":[\"h-entry\"],\"properties\":{\"published\":[\"\"],\"updated\":[\"\"],\"post-status\":[\"published\"],\"visibility\":[\"public\"],\"category\":[\"test\",\"test2\"],\"content\":[\"---\\nblog: default\\npath: /test/post\\npriority: 0\\npublished: \\\"\\\"\\nsection: \\\"\\\"\\nstatus: published\\ntags:\\n - test\\n - test2\\nupdated: \\\"\\\"\\n---\\nTest post\"],\"url\":[\"http://localhost:8080/test/post\"],\"mp-slug\":[\"\"]}}]}",
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
query: "category",
|
query: "category",
|
||||||
want: "{\"categories\":[\"test\",\"test2\"]}\n",
|
want: "{\"categories\":[\"test\",\"test2\"]}",
|
||||||
wantStatus: http.StatusOK,
|
wantStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
11
nodeinfo.go
11
nodeinfo.go
|
@ -25,7 +25,7 @@ func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
mw := a.min.Writer(contenttype.JSON, w)
|
mw := a.min.Get().Writer(contenttype.JSON, w)
|
||||||
_, _ = io.Copy(mw, buf)
|
_, _ = io.Copy(mw, buf)
|
||||||
_ = mw.Close()
|
_ = mw.Close()
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
})
|
})
|
||||||
buf := bufferpool.Get()
|
buf := bufferpool.Get()
|
||||||
defer bufferpool.Put(buf)
|
defer bufferpool.Put(buf)
|
||||||
err := json.NewEncoder(buf).Encode(map[string]any{
|
if err := json.NewEncoder(buf).Encode(map[string]any{
|
||||||
"version": "2.1",
|
"version": "2.1",
|
||||||
"software": map[string]any{
|
"software": map[string]any{
|
||||||
"name": "goblog",
|
"name": "goblog",
|
||||||
|
@ -54,13 +54,10 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
"webmention",
|
"webmention",
|
||||||
},
|
},
|
||||||
"metadata": map[string]any{},
|
"metadata": map[string]any{},
|
||||||
})
|
}); err != nil {
|
||||||
if err != nil {
|
|
||||||
a.serveError(w, r, "", http.StatusInternalServerError)
|
a.serveError(w, r, "", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set(contentType, contenttype.JSONUTF8)
|
w.Header().Set(contentType, contenttype.JSONUTF8)
|
||||||
mw := a.min.Writer(contenttype.JSON, w)
|
_ = a.min.Get().Minify(contenttype.JSON, w, buf)
|
||||||
_, _ = io.Copy(mw, buf)
|
|
||||||
_ = mw.Close()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
_, b := a.getBlog(r)
|
_, b := a.getBlog(r)
|
||||||
title := a.renderMdTitle(b.Title)
|
title := a.renderMdTitle(b.Title)
|
||||||
sURL := a.getFullAddress(b.getRelativePath(defaultIfEmpty(b.Search.Path, defaultSearchPath)))
|
sURL := a.getFullAddress(b.getRelativePath(defaultIfEmpty(b.Search.Path, defaultSearchPath)))
|
||||||
w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix)
|
|
||||||
openSearch := &openSearchDescription{
|
openSearch := &openSearchDescription{
|
||||||
ShortName: title,
|
ShortName: title,
|
||||||
Description: title,
|
Description: title,
|
||||||
|
@ -50,10 +49,15 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
},
|
},
|
||||||
SearchForm: sURL,
|
SearchForm: sURL,
|
||||||
}
|
}
|
||||||
mw := a.min.Writer(contenttype.XML, w)
|
buf := bufferpool.Get()
|
||||||
_, _ = io.WriteString(mw, xml.Header)
|
defer bufferpool.Put(buf)
|
||||||
_ = xml.NewEncoder(mw).Encode(openSearch)
|
_, _ = buf.WriteString(xml.Header)
|
||||||
_ = mw.Close()
|
if err := xml.NewEncoder(buf).Encode(openSearch); err != nil {
|
||||||
|
a.serveError(w, r, "", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix)
|
||||||
|
_ = a.min.Get().Minify(contenttype.XML, w, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openSearchUrl(b *configBlog) string {
|
func openSearchUrl(b *configBlog) string {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package minify
|
package minify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/tdewolff/minify/v2"
|
"github.com/tdewolff/minify/v2"
|
||||||
|
@ -21,12 +20,18 @@ type Minifier struct {
|
||||||
func (m *Minifier) init() {
|
func (m *Minifier) init() {
|
||||||
m.i.Do(func() {
|
m.i.Do(func() {
|
||||||
m.m = minify.New()
|
m.m = minify.New()
|
||||||
|
// HTML
|
||||||
m.m.AddFunc(contenttype.HTML, mHtml.Minify)
|
m.m.AddFunc(contenttype.HTML, mHtml.Minify)
|
||||||
|
// CSS
|
||||||
m.m.AddFunc(contenttype.CSS, mCss.Minify)
|
m.m.AddFunc(contenttype.CSS, mCss.Minify)
|
||||||
m.m.AddFunc(contenttype.XML, mXml.Minify)
|
// JS
|
||||||
m.m.AddFunc(contenttype.JS, mJs.Minify)
|
m.m.AddFunc(contenttype.JS, mJs.Minify)
|
||||||
|
// XML
|
||||||
|
m.m.AddFunc(contenttype.XML, mXml.Minify)
|
||||||
m.m.AddFunc(contenttype.RSS, mXml.Minify)
|
m.m.AddFunc(contenttype.RSS, mXml.Minify)
|
||||||
m.m.AddFunc(contenttype.ATOM, mXml.Minify)
|
m.m.AddFunc(contenttype.ATOM, mXml.Minify)
|
||||||
|
// JSON
|
||||||
|
m.m.AddFunc(contenttype.JSON, mJson.Minify)
|
||||||
m.m.AddFunc(contenttype.JSONFeed, mJson.Minify)
|
m.m.AddFunc(contenttype.JSONFeed, mJson.Minify)
|
||||||
m.m.AddFunc(contenttype.AS, mJson.Minify)
|
m.m.AddFunc(contenttype.AS, mJson.Minify)
|
||||||
})
|
})
|
||||||
|
@ -36,21 +41,3 @@ func (m *Minifier) Get() *minify.M {
|
||||||
m.init()
|
m.init()
|
||||||
return m.m
|
return m.m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Minifier) Write(w io.Writer, mediatype string, b []byte) (int, error) {
|
|
||||||
mw := m.Writer(mediatype, w)
|
|
||||||
defer mw.Close()
|
|
||||||
return mw.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Minifier) Minify(mediatype string, w io.Writer, r io.Reader) error {
|
|
||||||
return m.Get().Minify(mediatype, w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Minifier) Writer(mediatype string, w io.Writer) io.WriteCloser {
|
|
||||||
return m.Get().Writer(mediatype, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Minifier) Reader(mediatype string, r io.Reader) io.Reader {
|
|
||||||
return m.Get().Reader(mediatype, r)
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,13 +41,10 @@ func (a *goBlog) renderWithStatusCode(w http.ResponseWriter, r *http.Request, st
|
||||||
// Render
|
// Render
|
||||||
pipeReader, pipeWriter := io.Pipe()
|
pipeReader, pipeWriter := io.Pipe()
|
||||||
go func() {
|
go func() {
|
||||||
minifyWriter := a.min.Writer(contenttype.HTML, pipeWriter)
|
f(newHtmlBuilder(pipeWriter), data)
|
||||||
f(newHtmlBuilder(minifyWriter), data)
|
|
||||||
_ = minifyWriter.Close()
|
|
||||||
_ = pipeWriter.Close()
|
_ = pipeWriter.Close()
|
||||||
}()
|
}()
|
||||||
_, readErr := io.Copy(w, pipeReader)
|
_ = pipeReader.CloseWithError(a.min.Get().Minify(contenttype.HTML, w, pipeReader))
|
||||||
_ = pipeReader.CloseWithError(readErr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) checkRenderData(r *http.Request, data *renderData) {
|
func (a *goBlog) checkRenderData(r *http.Request, data *renderData) {
|
||||||
|
|
40
sitemap.go
40
sitemap.go
|
@ -3,12 +3,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/araddon/dateparse"
|
"github.com/araddon/dateparse"
|
||||||
"github.com/snabb/sitemap"
|
"github.com/snabb/sitemap"
|
||||||
|
"go.goblog.app/app/pkgs/bufferpool"
|
||||||
"go.goblog.app/app/pkgs/contenttype"
|
"go.goblog.app/app/pkgs/contenttype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const (
|
||||||
sitemapBlogPostsPath = "/sitemap-blog-posts.xml"
|
sitemapBlogPostsPath = "/sitemap-blog-posts.xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *goBlog) serveSitemap(w http.ResponseWriter, _ *http.Request) {
|
func (a *goBlog) serveSitemap(w http.ResponseWriter, r *http.Request) {
|
||||||
// Create sitemap
|
// Create sitemap
|
||||||
sm := sitemap.NewSitemapIndex()
|
sm := sitemap.NewSitemapIndex()
|
||||||
// Add blog sitemap indices
|
// Add blog sitemap indices
|
||||||
|
@ -32,7 +32,7 @@ func (a *goBlog) serveSitemap(w http.ResponseWriter, _ *http.Request) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Write sitemap
|
// Write sitemap
|
||||||
a.writeSitemapXML(w, sm)
|
a.writeSitemapXML(w, r, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveSitemapBlog(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveSitemapBlog(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -54,7 +54,7 @@ func (a *goBlog) serveSitemapBlog(w http.ResponseWriter, r *http.Request) {
|
||||||
LastMod: &now,
|
LastMod: &now,
|
||||||
})
|
})
|
||||||
// Write sitemap
|
// Write sitemap
|
||||||
a.writeSitemapXML(w, sm)
|
a.writeSitemapXML(w, r, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -103,7 +103,7 @@ func (a *goBlog) serveSitemapBlogFeatures(w http.ResponseWriter, r *http.Request
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Write sitemap
|
// Write sitemap
|
||||||
a.writeSitemapXML(w, sm)
|
a.writeSitemapXML(w, r, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) serveSitemapBlogArchives(w http.ResponseWriter, r *http.Request) {
|
func (a *goBlog) serveSitemapBlogArchives(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -145,7 +145,7 @@ func (a *goBlog) serveSitemapBlogArchives(w http.ResponseWriter, r *http.Request
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Write sitemap
|
// Write sitemap
|
||||||
a.writeSitemapXML(w, sm)
|
a.writeSitemapXML(w, r, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve sitemap with all the blog's posts
|
// Serve sitemap with all the blog's posts
|
||||||
|
@ -169,24 +169,22 @@ func (a *goBlog) serveSitemapBlogPosts(w http.ResponseWriter, r *http.Request) {
|
||||||
sm.Add(item)
|
sm.Add(item)
|
||||||
}
|
}
|
||||||
// Write sitemap
|
// Write sitemap
|
||||||
a.writeSitemapXML(w, sm)
|
a.writeSitemapXML(w, r, sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, sm any) {
|
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) {
|
||||||
|
buf := bufferpool.Get()
|
||||||
|
defer bufferpool.Put(buf)
|
||||||
|
_, _ = buf.WriteString(xml.Header)
|
||||||
|
_, _ = buf.WriteString(`<?xml-stylesheet type="text/xsl" href="`)
|
||||||
|
_, _ = buf.WriteString(a.assetFileName("sitemap.xsl"))
|
||||||
|
_, _ = buf.WriteString(`" ?>`)
|
||||||
|
if err := xml.NewEncoder(buf).Encode(sm); err != nil {
|
||||||
|
a.serveError(w, r, "Failed to encode sitemap", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Header().Set(contentType, contenttype.XMLUTF8)
|
w.Header().Set(contentType, contenttype.XMLUTF8)
|
||||||
pipeReader, pipeWriter := io.Pipe()
|
_ = a.min.Get().Minify(contenttype.XML, w, buf)
|
||||||
go func() {
|
|
||||||
mw := a.min.Writer(contenttype.XML, pipeWriter)
|
|
||||||
_, _ = io.WriteString(mw, xml.Header)
|
|
||||||
_, _ = io.WriteString(mw, `<?xml-stylesheet type="text/xsl" href="`)
|
|
||||||
_, _ = io.WriteString(mw, a.assetFileName("sitemap.xsl"))
|
|
||||||
_, _ = io.WriteString(mw, `" ?>`)
|
|
||||||
writeErr := xml.NewEncoder(mw).Encode(sm)
|
|
||||||
_ = mw.Close()
|
|
||||||
_ = pipeWriter.CloseWithError(writeErr)
|
|
||||||
}()
|
|
||||||
_, copyErr := io.Copy(w, pipeReader)
|
|
||||||
_ = pipeReader.CloseWithError(copyErr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sitemapDatePathsSql = `
|
const sitemapDatePathsSql = `
|
||||||
|
|
|
@ -53,11 +53,11 @@ func (a *goBlog) compileAsset(name string, read io.Reader) error {
|
||||||
ext := path.Ext(name)
|
ext := path.Ext(name)
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".js":
|
case ".js":
|
||||||
read = a.min.Reader(contenttype.JS, read)
|
read = a.min.Get().Reader(contenttype.JS, read)
|
||||||
case ".css":
|
case ".css":
|
||||||
read = a.min.Reader(contenttype.CSS, read)
|
read = a.min.Get().Reader(contenttype.CSS, read)
|
||||||
case ".xml", ".xsl":
|
case ".xml", ".xsl":
|
||||||
read = a.min.Reader(contenttype.XML, read)
|
read = a.min.Get().Reader(contenttype.XML, read)
|
||||||
}
|
}
|
||||||
// Read file
|
// Read file
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
|
|
Loading…
Reference in New Issue