mirror of https://github.com/jlelse/GoBlog
Improve live editor preview to show real post preview
This commit is contained in:
parent
bbfc68d145
commit
a3f2a5090b
3
app.go
3
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
|
||||
}
|
||||
|
|
46
editor.go
46
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
|
||||
}
|
||||
|
|
5
go.mod
5
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
|
||||
|
|
11
go.sum
11
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=
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,9 @@ form {
|
|||
input, textarea, select {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
textarea {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
form.fw {
|
||||
|
|
|
@ -39,6 +39,7 @@ const (
|
|||
templateBlogroll = "blogroll"
|
||||
templateGeoMap = "geomap"
|
||||
templateContact = "contact"
|
||||
templateEditorPreview = "editorpreview"
|
||||
)
|
||||
|
||||
func (a *goBlog) initRendering() error {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
})()
|
|
@ -0,0 +1,10 @@
|
|||
{{ define "editorpreview" }}
|
||||
{{ with .Data.RenderedTitle }}<h1>{{ . }}</h1>{{ end }}
|
||||
{{ include "summaryandpostmeta" . }}
|
||||
{{ if .Data.Content }}
|
||||
<div>
|
||||
{{ content .Data true }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ include "posttax" . }}
|
||||
{{ end }}
|
|
@ -3,12 +3,13 @@
|
|||
{{ $blog := .Blog }}
|
||||
{{ range $i, $tax := $blog.Taxonomies }}
|
||||
{{ $tvs := sort (ps $post $tax.Name) }}
|
||||
{{ if $tvs }}
|
||||
<p><b>{{ mdtitle $tax.Title }}</b>:
|
||||
{{ if $tvs }}{{ if not (eq (len $tvs) 0) }}
|
||||
<p>
|
||||
<b>{{ mdtitle $tax.Title }}</b>:
|
||||
{{ range $j, $tv := $tvs }}
|
||||
<a class="p-category" rel="tag" href="{{ $blog.RelativePath ( printf "/%s/%s" $tax.Name (urlize $tv) ) }}">{{ mdtitle $tv }}</a>
|
||||
{{ end }}
|
||||
</p>
|
||||
{{ end }}
|
||||
{{ end }}{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue