diff --git a/app.go b/app.go index e4c58a8..5ed2910 100644 --- a/app.go +++ b/app.go @@ -10,6 +10,7 @@ import ( ts "git.jlel.se/jlelse/template-strings" ct "github.com/elnormous/contenttype" "github.com/go-fed/httpsig" + "github.com/gorilla/websocket" rotatelogs "github.com/lestrrat-go/file-rotatelogs" "github.com/yuin/goldmark" "go.goblog.app/app/pkgs/minify" @@ -77,4 +78,6 @@ type goBlog struct { // Tor torAddress string torHostname string + // WebSockets + wsUpgrader *websocket.Upgrader } diff --git a/editor.go b/editor.go index 0ba269d..0f46af3 100644 --- a/editor.go +++ b/editor.go @@ -3,6 +3,7 @@ package main import ( "bytes" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -10,7 +11,6 @@ import ( "net/url" "strings" - "github.com/gorilla/websocket" "github.com/microcosm-cc/bluemonday" "go.goblog.app/app/pkgs/contenttype" "gopkg.in/yaml.v3" @@ -26,12 +26,9 @@ func (a *goBlog) serveEditor(w http.ResponseWriter, r *http.Request) { }) } -var upgrader = websocket.Upgrader{ - EnableCompression: true, -} - func (a *goBlog) serveEditorPreview(w http.ResponseWriter, r *http.Request) { - c, err := upgrader.Upgrade(w, r, nil) + blog := r.Context().Value(blogKey).(string) + c, err := a.webSocketUpgrader().Upgrade(w, r, nil) if err != nil { return } @@ -43,9 +40,9 @@ func (a *goBlog) serveEditorPreview(w http.ResponseWriter, r *http.Request) { break } // Create preview - preview, err := a.createMarkdownPreview(message) + preview, err := a.createMarkdownPreview(blog, message) if err != nil { - continue + preview = []byte(err.Error()) } // Write preview to socket err = c.WriteMessage(mt, preview) @@ -55,14 +52,33 @@ func (a *goBlog) serveEditorPreview(w http.ResponseWriter, r *http.Request) { } } -func (a *goBlog) createMarkdownPreview(markdown []byte) (rendered []byte, err error) { - mdString := string(markdown) - if split := strings.Split(mdString, "---\n"); len(split) >= 3 && len(strings.TrimSpace(split[0])) == 0 { - // Remove frontmatter from content - mdString = strings.Join(split[2:], "---\n") +func (a *goBlog) createMarkdownPreview(blog string, markdown []byte) (rendered []byte, err error) { + p := post{ + Content: string(markdown), + Blog: blog, + Path: "/editor/preview", + Published: localNowString(), } - // Render markdown - rendered, err = a.renderMarkdown(mdString, true) + err = a.computeExtraPostParameters(&p) + if err != nil { + return nil, err + } + if t := p.Title(); t != "" { + p.RenderedTitle = a.renderMdTitle(t) + } + // Render post + rec := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodGet, "/editor/preview", nil) + a.render(rec, req, templateEditorPreview, &renderData{ + BlogString: p.Blog, + Data: &p, + }) + res := rec.Result() + if res.StatusCode != http.StatusOK { + return nil, errors.New("failed to render preview") + } + defer res.Body.Close() + rendered, err = io.ReadAll(res.Body) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index 64162b8..ab57961 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( // master github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 - golang.org/x/net v0.0.0-20211029224645-99673261e6eb + golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b tailscale.com v1.16.2 @@ -90,7 +90,6 @@ require ( github.com/spf13/afero v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.3.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/tailscale/certstore v0.0.0-20210528134328-066c94b793d3 // indirect github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect @@ -100,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-20211031064116-611d5d643895 // indirect + golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c // 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 diff --git a/go.sum b/go.sum index 7fde606..1b533d0 100644 --- a/go.sum +++ b/go.sum @@ -79,7 +79,6 @@ github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 h1:t8KYCwSKsOEZBFELI4Pn/phbp38iJ1RRAkDFNin1aak= github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -424,8 +423,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= -github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -585,8 +582,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 h1:VrJZAjbekhoRn7n5FBujY31gboH+iB3pdLxn3gE9FjU= +golang.org/x/net v0.0.0-20211101193420-4a448f8816b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -685,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-20211031064116-611d5d643895 h1:iaNpwpnrgL5jzWS0vCNnfa8HqzxveCFpFx3uC/X4Tps= -golang.org/x/sys v0.0.0-20211031064116-611d5d643895/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/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= diff --git a/micropub.go b/micropub.go index 3a2ad51..915d732 100644 --- a/micropub.go +++ b/micropub.go @@ -407,6 +407,12 @@ func (a *goBlog) computeExtraPostParameters(p *post) error { } } } + // Remove all parameters where there are just empty strings + for pk, pvs := range p.Parameters { + if len(pvs) == 0 || strings.Join(pvs, "") == "" { + delete(p.Parameters, pk) + } + } return nil } diff --git a/original-assets/styles/styles.scss b/original-assets/styles/styles.scss index 62300cf..0eb51b2 100644 --- a/original-assets/styles/styles.scss +++ b/original-assets/styles/styles.scss @@ -113,6 +113,9 @@ form { input, textarea, select { margin-bottom: 5px; } + textarea { + display: block; + } } form.fw { diff --git a/render.go b/render.go index 6cda5e8..ab6ed93 100644 --- a/render.go +++ b/render.go @@ -39,6 +39,7 @@ const ( templateBlogroll = "blogroll" templateGeoMap = "geomap" templateContact = "contact" + templateEditorPreview = "editorpreview" ) func (a *goBlog) initRendering() error { diff --git a/templates/assets/css/styles.css b/templates/assets/css/styles.css index 648f8cc..d926115 100644 --- a/templates/assets/css/styles.css +++ b/templates/assets/css/styles.css @@ -77,6 +77,9 @@ button:focus, .button:focus, input:focus, textarea:focus, select:focus { form input, form textarea, form select { margin-bottom: 5px; } +form textarea { + display: block; +} blockquote { border-left: 5px solid #000; diff --git a/templates/assets/js/mdpreview.js b/templates/assets/js/mdpreview.js index d47fba8..6a04f6d 100644 --- a/templates/assets/js/mdpreview.js +++ b/templates/assets/js/mdpreview.js @@ -24,6 +24,7 @@ console.log("Preview-Websocket closed") previewContainer.classList.add('hide') previewContainer.classList.remove('preview') + previewContainer.innerHTML = '' ws = null } ws.onmessage = function (evt) { @@ -34,10 +35,14 @@ console.log("Preview-Websocket error: " + evt.data) } // Add listener + let timeout = null element.addEventListener('input', function () { - if (ws) { - ws.send(element.value) - } + clearTimeout(timeout) + timeout = setTimeout(function () { + if (ws) { + ws.send(element.value) + } + }, 500) }) }) })() \ No newline at end of file diff --git a/templates/editorpreview.gohtml b/templates/editorpreview.gohtml new file mode 100644 index 0000000..41c90aa --- /dev/null +++ b/templates/editorpreview.gohtml @@ -0,0 +1,10 @@ +{{ define "editorpreview" }} + {{ with .Data.RenderedTitle }}

{{ . }}

{{ end }} + {{ include "summaryandpostmeta" . }} + {{ if .Data.Content }} +
+ {{ content .Data true }} +
+ {{ end }} + {{ include "posttax" . }} +{{ end }} \ No newline at end of file diff --git a/templates/posttax.gohtml b/templates/posttax.gohtml index 5f2acf9..8cb2544 100644 --- a/templates/posttax.gohtml +++ b/templates/posttax.gohtml @@ -3,12 +3,13 @@ {{ $blog := .Blog }} {{ range $i, $tax := $blog.Taxonomies }} {{ $tvs := sort (ps $post $tax.Name) }} - {{ if $tvs }} -

{{ mdtitle $tax.Title }}: + {{ if $tvs }}{{ if not (eq (len $tvs) 0) }} +

+ {{ mdtitle $tax.Title }}: {{ range $j, $tv := $tvs }} {{ end }}

- {{ end }} + {{ end }}{{ end }} {{ end }} {{ end }} \ No newline at end of file diff --git a/websockets.go b/websockets.go new file mode 100644 index 0000000..5d68eaa --- /dev/null +++ b/websockets.go @@ -0,0 +1,12 @@ +package main + +import "github.com/gorilla/websocket" + +func (a *goBlog) webSocketUpgrader() *websocket.Upgrader { + if a.wsUpgrader == nil { + a.wsUpgrader = &websocket.Upgrader{ + EnableCompression: true, + } + } + return a.wsUpgrader +}