From c292a67bc083e78c68679d08202d9e5793b5f62a Mon Sep 17 00:00:00 2001 From: Daniele Tonon Date: Fri, 2 Jun 2023 15:52:06 +0200 Subject: [PATCH] Add markdown support for long format content --- go.mod | 1 + go.sum | 2 ++ render.go | 5 +++-- static/styles.css | 29 +++++++++++++++++++++++++++++ static/styles.scss | 23 +++++++++++++++++++++++ templates/note.html | 9 ++++++++- utils.go | 25 +++++++++++++++++++++---- 7 files changed, 87 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 34c1ddb..029f4ea 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.2.0 // indirect + github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a github.com/josharian/intern v1.0.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect diff --git a/go.sum b/go.sum index bf6a445..8baaa03 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a h1:AWZzzFrqyjYlRloN6edwTLTUbKxf5flLXNuTBDm3Ews= +github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= diff --git a/render.go b/render.go index 5fe2cc4..dcc089c 100644 --- a/render.go +++ b/render.go @@ -87,12 +87,11 @@ func render(w http.ResponseWriter, r *http.Request) { } maxAge = 900 } else { - if event.Kind == 1 || event.Kind == 7 || event.Kind == 30023 { + if event.Kind == 1 || event.Kind == 7 || event.Kind == 30023 || event.Kind == 30024 { typ = "note" note, _ = nip19.EncodeNote(event.ID) content = event.Content parentNevent = findParentNevent(event) - } else if event.Kind == 6 { typ = "note" if reposted := event.Tags.GetFirst([]string{"e", ""}); reposted != nil { @@ -223,6 +222,7 @@ func render(w http.ResponseWriter, r *http.Request) { "naddr": naddr, "metadata": metadata, "authorLong": authorLong, + "subject": subject, "description": description, "content": content, "textImageURL": textImageURL, @@ -251,6 +251,7 @@ func render(w http.ResponseWriter, r *http.Request) { funcMap := template.FuncMap{ "basicFormatting": basicFormatting, + "mdToHTML": mdToHTML, "sanitizeString": html.EscapeString, } diff --git a/static/styles.css b/static/styles.css index 6ed58f8..44aec04 100644 --- a/static/styles.css +++ b/static/styles.css @@ -34,6 +34,7 @@ body { h1, h2 { font-weight: 100; + line-height: 1.1em; } .theme--default a { @@ -337,6 +338,34 @@ h1, h2 { .theme--dark .container .column_content .field.boxed .label { background: #191919; } +.container .column_content .field pre { + overflow-x: scroll; + padding: 1rem; +} +.theme--default .container .column_content .field pre { + background: #f3f3f3; +} +.theme--dark .container .column_content .field pre { + background: #2d2d2d; +} +.container .column_content .field hr { + display: none; +} +.container .column_content .field .footnotes { + padding-top: 1rem; + margin-top: 2rem; + font-size: 0.8rem; +} +.theme--default .container .column_content .field .footnotes { + border-top: 6px solid #f3f3f3; +} +.theme--dark .container .column_content .field .footnotes { + border-top: 6px solid #2d2d2d; +} +.container .column_content .field .footnotes ol { + margin: 0; + padding: 0 0 0 1rem; +} .container .column_content .field.last_notes a { display: block; text-decoration: none; diff --git a/static/styles.scss b/static/styles.scss index 585a28e..251f5f2 100644 --- a/static/styles.scss +++ b/static/styles.scss @@ -114,6 +114,7 @@ body { } h1, h2 { font-weight: 100; + line-height: 1.1em; } a { @include themed() { @@ -356,6 +357,28 @@ a { } } } + pre { + overflow-x: scroll; + @include themed() { + background: t($over-bg); + } + padding: 1rem; + } + hr { + display: none; + } + .footnotes { + padding-top: 1rem; + margin-top: 2rem; + @include themed() { + border-top: 6px solid t($over-bg); + } + font-size: 0.8rem; + ol { + margin: 0; + padding: 0 0 0 1rem; + } + } &.last_notes { a { display: block; diff --git a/templates/note.html b/templates/note.html index 0aa5edf..17c257d 100644 --- a/templates/note.html +++ b/templates/note.html @@ -36,7 +36,14 @@
- {{.content | sanitizeString | basicFormatting }} + {{ if (not (eq .subject ""))}} +

{{.subject | sanitizeString}}

+ {{ end }} + {{ if (or (eq .kindID 30023) (eq .kindID 30024))}} + {{.content | sanitizeString | mdToHTML }} + {{ else }} + {{.content | sanitizeString | basicFormatting }} + {{ end }}
diff --git a/utils.go b/utils.go index 4eaf4de..6da822e 100644 --- a/utils.go +++ b/utils.go @@ -7,6 +7,9 @@ import ( "regexp" "strings" + "github.com/gomarkdown/markdown" + "github.com/gomarkdown/markdown/html" + "github.com/gomarkdown/markdown/parser" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip10" "github.com/nbd-wtf/go-nostr/nip19" @@ -103,7 +106,7 @@ func generateClientList(code string, event *nostr.Event) []map[string]string { } } else if strings.HasPrefix(code, "npub") || strings.HasPrefix(code, "nprofile") { return []map[string]string{ - {"name": "native client", "url": "nostr:" + code}, + {"name": "Your native client", "url": "nostr:" + code}, {"name": "Snort", "url": "https://snort.social/p/" + code}, {"name": "Coracle", "url": "https://coracle.social/" + code}, {"name": "Satellite", "url": "https://satellite.earth/@" + code}, @@ -116,9 +119,9 @@ func generateClientList(code string, event *nostr.Event) []map[string]string { } } else if strings.HasPrefix(code, "naddr") { return []map[string]string{ - {"name": "native client", "url": "nostr:" + code}, - {"name": "habla", "url": "https://habla.news/a/" + code}, - {"name": "blogstack", "url": "https://blogstack.io/" + code}, + {"name": "Your native client", "url": "nostr:" + code}, + {"name": "Habla", "url": "https://habla.news/a/" + code}, + {"name": "Blogstack", "url": "https://blogstack.io/" + code}, } } else { return []map[string]string{ @@ -254,3 +257,17 @@ func findParentNevent(event *nostr.Event) string { } return parentNevent } + +func mdToHTML(md string) string { + // create markdown parser with extensions + extensions := parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock | parser.Footnotes + p := parser.NewWithExtensions(extensions) + doc := p.Parse([]byte(md)) + + // create HTML renderer with extensions + htmlFlags := html.CommonFlags | html.HrefTargetBlank + opts := html.RendererOptions{Flags: htmlFlags} + renderer := html.NewRenderer(opts) + + return string(markdown.Render(doc, renderer)) +}