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(`

`))
 				} else {
 					if img.Title != nil {
 						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), + ) +}