From 660952a3383c13b3ef7b2396fc3a3df653e995f2 Mon Sep 17 00:00:00 2001
From: fiatjaf
Date: Tue, 24 Oct 2023 21:04:19 -0300
Subject: [PATCH] syntax-highlight event JSON on the server.
---
pages.go | 2 +-
render_event.go | 7 ++---
render_profile.go | 6 +---
static/styles.css | 71 ------------------------------------------
static/styles.scss | 31 ------------------
templates/details.html | 35 +--------------------
utils.go | 49 ++++++++++++++++++++++++++---
7 files changed, 50 insertions(+), 151 deletions(-)
diff --git a/pages.go b/pages.go
index 4e37750..b0f8071 100644
--- a/pages.go
+++ b/pages.go
@@ -58,7 +58,7 @@ var (
type DetailsPartial struct {
HideDetails bool
CreatedAt string
- EventJSON string
+ EventJSON template.HTML
Nevent string
Kind int
KindNIP string
diff --git a/render_event.go b/render_event.go
index da3f5b0..45990ee 100644
--- a/render_event.go
+++ b/render_event.go
@@ -196,9 +196,6 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=60")
}
- // pretty JSON
- eventJSON, _ := json.MarshalIndent(data.event, "", " ")
-
// oembed discovery
oembed := ""
if data.templateId == Note {
@@ -237,7 +234,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
CreatedAt: data.createdAt,
KindDescription: data.kindDescription,
KindNIP: data.kindNIP,
- EventJSON: string(eventJSON),
+ EventJSON: eventToHTML(data.event),
Kind: data.event.Kind,
},
ClientsPartial: ClientsPartial{
@@ -274,7 +271,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
CreatedAt: data.createdAt,
KindDescription: data.kindDescription,
KindNIP: data.kindNIP,
- EventJSON: string(eventJSON),
+ EventJSON: eventToHTML(data.event),
Kind: data.event.Kind,
},
diff --git a/render_profile.go b/render_profile.go
index e3db295..5439919 100644
--- a/render_profile.go
+++ b/render_profile.go
@@ -1,7 +1,6 @@
package main
import (
- "encoding/json"
"fmt"
"html"
"html/template"
@@ -30,9 +29,6 @@ func renderProfile(w http.ResponseWriter, r *http.Request, code string) {
w.Header().Set("Cache-Control", "max-age=3600")
}
- // pretty JSON
- eventJSON, _ := json.MarshalIndent(data.event, "", " ")
-
if !isSitemap {
err = ProfileTemplate.Render(w, &ProfilePage{
HeadCommonPartial: HeadCommonPartial{IsProfile: true},
@@ -41,7 +37,7 @@ func renderProfile(w http.ResponseWriter, r *http.Request, code string) {
CreatedAt: data.createdAt,
KindDescription: data.kindDescription,
KindNIP: data.kindNIP,
- EventJSON: string(eventJSON),
+ EventJSON: eventToHTML(data.event),
Kind: data.event.Kind,
},
ClientsPartial: ClientsPartial{
diff --git a/static/styles.css b/static/styles.css
index 376f00c..e316a6b 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -165,37 +165,12 @@ body {
margin-top: 0rem;
}
}
-.columnA .last_update {
- font-size: 0.8em;
- margin-top: 0.5rem;
- text-align: center;
-}
-.theme--default .columnA .last_update {
- color: #c9c9c9;
-}
-.theme--dark .columnA .last_update {
- color: #969696;
-}
-@media (max-width: 580px) {
- .columnA .last_update {
- display: none;
- }
-}
.column_content {
flex-grow: 0;
flex-shrink: 0;
word-wrap: break-word;
}
-.column_content a.nostr {
- border-bottom: none;
-}
-.theme--default .column_content a.nostr {
- background-color: #fdf0f5;
-}
-.theme--dark .column_content a.nostr {
- background-color: #42091e;
-}
.column_content a.button {
display: inline-block;
max-width: 100%;
@@ -211,15 +186,6 @@ body {
background-color: #e32a6d;
border: 1px solid #e32a6d;
}
-.column_content .label {
- font-size: 0.8rem;
-}
-.theme--default .column_content .label {
- color: #e32a6d;
-}
-.theme--dark .column_content .label {
- color: #e32a6d;
-}
.column_content blockquote {
padding: 0.5rem 0 0.5rem 1rem;
margin: 2rem 0;
@@ -285,43 +251,6 @@ body {
.theme--dark .column_content .footnotes {
border-top: 6px solid #2d2d2d;
}
-.column_content .json {
- font-family: "Courier New", Courier, monospace;
- font-size: 0.9rem;
- white-space: pre-wrap;
- word-break: break-all;
- margin-top: 1rem;
-}
-.column_content .json .key {
- display: inline-block;
-}
-.theme--default .column_content .json .key {
- color: #e32a6d;
-}
-.theme--dark .column_content .json .key {
- color: #e32a6d;
-}
-.theme--default .column_content .json .string {
- color: #373737;
-}
-.theme--dark .column_content .json .string {
- color: #fafafa;
-}
-.column_content .json .number {
- color: darkorange;
-}
-.theme--default .column_content .json .boolean {
- color: #373737;
-}
-.theme--dark .column_content .json .boolean {
- color: #fafafa;
-}
-.theme--default .column_content .json .null {
- color: #373737;
-}
-.theme--dark .column_content .json .null {
- color: #fafafa;
-}
.column_clients {
position: -webkit-sticky;
diff --git a/static/styles.scss b/static/styles.scss
index 612a32d..a2b1cf7 100644
--- a/static/styles.scss
+++ b/static/styles.scss
@@ -300,37 +300,6 @@ body {
font-size: 0.9rem;
line-height: 1.2rem;
}
- .json {
- font-family: 'Courier New', Courier, monospace;
- font-size: 0.9rem;
- white-space: pre-wrap;
- word-break: break-all;
- margin-top: 1rem;
- .key {
- display: inline-block;
- @include themed() {
- color: t($accent1);
- }
- }
- .string {
- @include themed() {
- color: t($base7);
- }
- }
- .number {
- color: darkorange;
- }
- .boolean {
- @include themed() {
- color: t($base7);
- }
- }
- .null {
- @include themed() {
- color: t($base7);
- }
- }
- }
}
.column_clients {
diff --git a/templates/details.html b/templates/details.html
index 49888ca..c7b4a94 100644
--- a/templates/details.html
+++ b/templates/details.html
@@ -61,39 +61,6 @@
>
Event JSON
-
- {{- .EventJSON}}
-
+ {{- .EventJSON}}
-
-
diff --git a/utils.go b/utils.go
index 89fea10..8778135 100644
--- a/utils.go
+++ b/utils.go
@@ -2,7 +2,10 @@ package main
import (
"context"
+ "encoding/json"
"fmt"
+ html "html"
+ "html/template"
"io"
"net/http"
"regexp"
@@ -11,7 +14,6 @@ import (
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
- "github.com/gomarkdown/markdown/html"
mdhtml "github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"github.com/microcosm-cc/bluemonday"
@@ -380,7 +382,7 @@ func mdToHTML(md string, usingTelegramInstantView bool) string {
parser.CommonExtensions | parser.AutoHeadingIDs | parser.NoEmptyLineBeforeBlock | parser.Footnotes)
doc := p.Parse([]byte(md))
- var customNodeHook html.RenderNodeFunc = nil
+ var customNodeHook mdhtml.RenderNodeFunc = nil
if usingTelegramInstantView {
// telegram instant view really doesn't like when there is an image inside a paragraph (like ![]()
)
// so we use this custom thing to stop all paragraphs before the images, print the images then start a new
@@ -390,12 +392,12 @@ func mdToHTML(md string, usingTelegramInstantView bool) string {
if entering {
src := img.Destination
w.Write([]byte(`
![`))
- html.EscapeHTML(w, img.Title)
+ mdhtml.EscapeHTML(w, img.Title)
}
w.Write([]byte(` `))
} else {
if img.Title != nil {
w.Write([]byte(`](`))
- html.EscLink(w, src)
+ mdhtml.EscLink(w, src)
w.Write([]byte(`)
`))
}
@@ -492,3 +494,42 @@ func loadRelaysArchive(ctx context.Context) {
cache.SetWithTTL("ra:"+relay, nil, time.Hour*24*7)
}
}
+
+func eventToHTML(evt *nostr.Event) template.HTML {
+ tagsHTML := "["
+ for t, tag := range evt.Tags {
+ tagsHTML += "\n ["
+ for i, item := range tag {
+ cls := `"text-zinc-500 dark:text-zinc-50"`
+ if i == 0 {
+ cls = `"text-amber-500 dark:text-amber-200"`
+ }
+ itemJSON, _ := json.Marshal(item)
+ tagsHTML += "\n " + html.EscapeString(string(itemJSON))
+ if i < len(tag)-1 {
+ tagsHTML += ","
+ }
+ }
+ tagsHTML += "\n ]"
+ if t < len(evt.Tags)-1 {
+ tagsHTML += ","
+ }
+ }
+ tagsHTML += "\n ]"
+
+ contentJSON, _ := json.Marshal(evt.Content)
+
+ keyCls := "text-purple-700 dark:text-purple-300"
+
+ return template.HTML(fmt.Sprintf(
+ `{
+ "id": "%s",
+ "pubkey": "%s",
+ "created_at": %d,
+ "kind": %d,
+ "tags": %s,
+ "content": %s,
+ "sig": "%s"
+}`, evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsHTML, html.EscapeString(string(contentJSON)), evt.Sig),
+ )
+}