Add markdown support for long format content

This commit is contained in:
Daniele Tonon
2023-06-02 15:52:06 +02:00
parent 82ea89443e
commit c292a67bc0
7 changed files with 87 additions and 7 deletions

1
go.mod
View File

@@ -24,6 +24,7 @@ require (
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.2.0 // 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/josharian/intern v1.0.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect

2
go.sum
View File

@@ -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.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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/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.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.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=

View File

@@ -87,12 +87,11 @@ func render(w http.ResponseWriter, r *http.Request) {
} }
maxAge = 900 maxAge = 900
} else { } 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" typ = "note"
note, _ = nip19.EncodeNote(event.ID) note, _ = nip19.EncodeNote(event.ID)
content = event.Content content = event.Content
parentNevent = findParentNevent(event) parentNevent = findParentNevent(event)
} else if event.Kind == 6 { } else if event.Kind == 6 {
typ = "note" typ = "note"
if reposted := event.Tags.GetFirst([]string{"e", ""}); reposted != nil { if reposted := event.Tags.GetFirst([]string{"e", ""}); reposted != nil {
@@ -223,6 +222,7 @@ func render(w http.ResponseWriter, r *http.Request) {
"naddr": naddr, "naddr": naddr,
"metadata": metadata, "metadata": metadata,
"authorLong": authorLong, "authorLong": authorLong,
"subject": subject,
"description": description, "description": description,
"content": content, "content": content,
"textImageURL": textImageURL, "textImageURL": textImageURL,
@@ -251,6 +251,7 @@ func render(w http.ResponseWriter, r *http.Request) {
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"basicFormatting": basicFormatting, "basicFormatting": basicFormatting,
"mdToHTML": mdToHTML,
"sanitizeString": html.EscapeString, "sanitizeString": html.EscapeString,
} }

View File

@@ -34,6 +34,7 @@ body {
h1, h2 { h1, h2 {
font-weight: 100; font-weight: 100;
line-height: 1.1em;
} }
.theme--default a { .theme--default a {
@@ -337,6 +338,34 @@ h1, h2 {
.theme--dark .container .column_content .field.boxed .label { .theme--dark .container .column_content .field.boxed .label {
background: #191919; 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 { .container .column_content .field.last_notes a {
display: block; display: block;
text-decoration: none; text-decoration: none;

View File

@@ -114,6 +114,7 @@ body {
} }
h1, h2 { h1, h2 {
font-weight: 100; font-weight: 100;
line-height: 1.1em;
} }
a { a {
@include themed() { @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 { &.last_notes {
a { a {
display: block; display: block;

View File

@@ -36,7 +36,14 @@
<div class="field separator"></div> <div class="field separator"></div>
<div class="field content"> <div class="field content">
{{.content | sanitizeString | basicFormatting }} {{ if (not (eq .subject ""))}}
<h1>{{.subject | sanitizeString}}</h1>
{{ end }}
{{ if (or (eq .kindID 30023) (eq .kindID 30024))}}
{{.content | sanitizeString | mdToHTML }}
{{ else }}
{{.content | sanitizeString | basicFormatting }}
{{ end }}
</div> </div>
<div class="field separator"></div> <div class="field separator"></div>

View File

@@ -7,6 +7,9 @@ import (
"regexp" "regexp"
"strings" "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"
"github.com/nbd-wtf/go-nostr/nip10" "github.com/nbd-wtf/go-nostr/nip10"
"github.com/nbd-wtf/go-nostr/nip19" "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") { } else if strings.HasPrefix(code, "npub") || strings.HasPrefix(code, "nprofile") {
return []map[string]string{ 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": "Snort", "url": "https://snort.social/p/" + code},
{"name": "Coracle", "url": "https://coracle.social/" + code}, {"name": "Coracle", "url": "https://coracle.social/" + code},
{"name": "Satellite", "url": "https://satellite.earth/@" + 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") { } else if strings.HasPrefix(code, "naddr") {
return []map[string]string{ return []map[string]string{
{"name": "native client", "url": "nostr:" + code}, {"name": "Your native client", "url": "nostr:" + code},
{"name": "habla", "url": "https://habla.news/a/" + code}, {"name": "Habla", "url": "https://habla.news/a/" + code},
{"name": "blogstack", "url": "https://blogstack.io/" + code}, {"name": "Blogstack", "url": "https://blogstack.io/" + code},
} }
} else { } else {
return []map[string]string{ return []map[string]string{
@@ -254,3 +257,17 @@ func findParentNevent(event *nostr.Event) string {
} }
return parentNevent 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))
}