Render mentions inline

This commit is contained in:
Daniele Tonon
2023-09-03 02:04:22 +02:00
parent 92d1944e69
commit 1f4f39b1e4
8 changed files with 88 additions and 15 deletions

View File

@@ -21,7 +21,7 @@ func generate(w http.ResponseWriter, r *http.Request) {
return return
} }
lines := normalizeText(event.Content) lines := normalizeText(renderInlineMentions(event.Content))
img, err := drawImage(lines, getPreviewStyle(r)) img, err := drawImage(lines, getPreviewStyle(r))
if err != nil { if err != nil {

View File

@@ -72,6 +72,7 @@ func main() {
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"basicFormatting": basicFormatting, "basicFormatting": basicFormatting,
"renderInlineMentions": renderInlineMentions,
"mdToHTML": mdToHTML, "mdToHTML": mdToHTML,
"escapeString": html.EscapeString, "escapeString": html.EscapeString,
"sanitizeXSS": sanitizeXSS, "sanitizeXSS": sanitizeXSS,

View File

@@ -465,6 +465,20 @@ iframe {
.theme--dark .container .column_content .field blockquote { .theme--dark .container .column_content .field blockquote {
border-left: 0.5rem solid #2d2d2d; border-left: 0.5rem solid #2d2d2d;
} }
.container .column_content .field blockquote.mention {
border-left: 0.5rem solid #e32a6d;
padding: 0rem 0 0.5rem 1rem;
}
.theme--default .container .column_content .field blockquote.mention div {
padding: 0.5rem 0.5rem 0.5rem 1rem;
margin: 0 0 1rem -1rem;
background-color: #f3f3f3;
}
.theme--dark .container .column_content .field blockquote.mention div {
padding: 0.5rem 0.5rem 0.5rem 1rem;
margin: 0 0 1rem -1rem;
background-color: #2d2d2d;
}
.container .column_content .field blockquote p { .container .column_content .field blockquote p {
margin: 0 0 0.5rem 0; margin: 0 0 0.5rem 0;
} }

View File

@@ -455,6 +455,17 @@ iframe {
padding: 0.5rem 0 0.5rem 1rem; padding: 0.5rem 0 0.5rem 1rem;
margin: 2rem 0; margin: 2rem 0;
font-style: italic; font-style: italic;
&.mention {
border-left: 0.5rem solid $color-accent1;
padding: 0rem 0 0.5rem 1rem;
div {
@include themed() {
padding: 0.5rem 0.5rem 0.5rem 1rem;
margin: 0 0 1rem -1rem;
background-color: t($over-bg);
}
}
}
p { p {
margin: 0 0 0.5rem 0; margin: 0 0 0.5rem 0;
} }

View File

@@ -1,2 +1,2 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/njump/static/styles.css?v=20230716" /> <link rel="stylesheet" href="/njump/static/styles.css?v=20230902" />

View File

@@ -77,7 +77,7 @@
{{ if (or (eq .kindID 30023) (eq .kindID 30024))}} {{ if (or (eq .kindID 30023) (eq .kindID 30024))}}
{{.content | mdToHTML }} {{.content | mdToHTML }}
{{ else }} {{ else }}
{{.content | escapeString | basicFormatting }} {{.content | renderInlineMentions | escapeString | basicFormatting}}
{{ end }} {{ end }}
</article> </article>

20
text.go
View File

@@ -3,6 +3,7 @@ package main
import ( import (
"image" "image"
"image/draw" "image/draw"
"regexp"
"strings" "strings"
"github.com/apatters/go-wordwrap" "github.com/apatters/go-wordwrap"
@@ -17,10 +18,27 @@ const (
) )
func normalizeText(t string) []string { func normalizeText(t string) []string {
re := regexp.MustCompile(`{div}.*?{/div}`)
t = re.ReplaceAllString(t, "")
lines := make([]string, 0, MAX_LINES) lines := make([]string, 0, MAX_LINES)
mention := false
maxChars := MAX_CHARS_PER_LINE
for _, line := range strings.Split(t, "\n") { for _, line := range strings.Split(t, "\n") {
line = wordwrap.Wrap(MAX_CHARS_PER_LINE, line) line = wordwrap.Wrap(maxChars, line)
for _, subline := range strings.Split(line, "\n") { for _, subline := range strings.Split(line, "\n") {
if strings.HasPrefix(subline, "{blockquote}") {
mention = true
subline = strings.ReplaceAll(subline, "{blockquote}", "")
subline = strings.ReplaceAll(subline, "{/blockquote}", "")
maxChars = MAX_CHARS_PER_LINE - 1
} else if strings.HasSuffix(subline, "{/blockquote}") {
mention = false
subline = strings.ReplaceAll(subline, "{/blockquote}", "")
maxChars = MAX_CHARS_PER_LINE
}
if mention {
subline = "> " + subline
}
lines = append(lines, subline) lines = append(lines, subline)
} }
} }

View File

@@ -10,7 +10,7 @@ import (
"time" "time"
"github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html" mdhtml "github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser" "github.com/gomarkdown/markdown/parser"
"github.com/microcosm-cc/bluemonday" "github.com/microcosm-cc/bluemonday"
@@ -258,6 +258,32 @@ func replaceNostrURLsWithTags(input string) string {
return input return input
} }
func renderInlineMentions(input string) string {
lines := strings.Split(input, "\n")
var processedLines []string
for _, line := range lines {
nostrRegexPattern := `\S*(nostr:)?((note|nevent)1[a-z0-9]+)\b`
nostrRegex := regexp.MustCompile(nostrRegexPattern)
input = nostrRegex.ReplaceAllStringFunc(line, func(match string) string {
submatch := nostrRegex.FindStringSubmatch(match)
if len(submatch) < 2 || strings.Contains(submatch[0], "/") {
return match
}
capturedGroup := submatch[2]
replacement := ""
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
event, _ := getEvent(ctx, capturedGroup)
cancel()
replacement = fmt.Sprintf(`{blockquote} {div}From: %s {/div} %s {/blockquote}`, capturedGroup, event.Content)
return replacement
})
processedLines = append(processedLines, input)
}
return strings.Join(processedLines, "\n")
}
func replaceURLsWithTags(line string) string { func replaceURLsWithTags(line string) string {
var rline string var rline string
@@ -293,8 +319,11 @@ func sanitizeXSS(html string) string {
} }
func basicFormatting(input string) string { func basicFormatting(input string) string {
input = strings.ReplaceAll(input, "{blockquote}", "<blockquote class='mention'>")
input = strings.ReplaceAll(input, "{/blockquote}", "</blockquote>")
input = strings.ReplaceAll(input, "{div}", "<div>")
input = strings.ReplaceAll(input, "{/div}", "</div>")
lines := strings.Split(input, "\n") lines := strings.Split(input, "\n")
var processedLines []string var processedLines []string
for _, line := range lines { for _, line := range lines {
processedLine := replaceURLsWithTags(line) processedLine := replaceURLsWithTags(line)
@@ -316,9 +345,9 @@ func mdToHTML(md string) string {
doc := p.Parse([]byte(md)) doc := p.Parse([]byte(md))
// create HTML renderer with extensions // create HTML renderer with extensions
htmlFlags := html.CommonFlags | html.HrefTargetBlank htmlFlags := mdhtml.CommonFlags | mdhtml.HrefTargetBlank
opts := html.RendererOptions{Flags: htmlFlags} opts := mdhtml.RendererOptions{Flags: htmlFlags}
renderer := html.NewRenderer(opts) renderer := mdhtml.NewRenderer(opts)
output := string(markdown.Render(doc, renderer)) output := string(markdown.Render(doc, renderer))
// Sanitize content // Sanitize content