syntax-highlight event JSON on the server.

This commit is contained in:
fiatjaf
2023-10-24 21:04:19 -03:00
parent 2b9c45d854
commit 660952a338
7 changed files with 50 additions and 151 deletions

View File

@@ -58,7 +58,7 @@ var (
type DetailsPartial struct {
HideDetails bool
CreatedAt string
EventJSON string
EventJSON template.HTML
Nevent string
Kind int
KindNIP string

View File

@@ -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,
},

View File

@@ -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{

View File

@@ -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;

View File

@@ -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 {

View File

@@ -61,39 +61,6 @@
>
Event JSON
</div>
<div class="json" _="on load call syntaxHighlight(me)">
{{- .EventJSON}}
</div>
<div>{{- .EventJSON}}</div>
</div>
</div>
<script>
function syntaxHighlight(elt) {
elt.innerHTML = elt.innerHTML
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(
/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
function (match, p1) {
var cls = 'number'
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key'
} else {
if (p1.length < 100) {
cls = 'string'
} else {
cls = 'string content'
}
}
} else if (/true|false/.test(match)) {
cls = 'boolean'
} else if (/null/.test(match)) {
cls = 'null'
}
return '<span class="' + cls + '">' + match + '</span>'
}
)
}
</script>

View File

@@ -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 <p><img></p>)
// 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(`</p><img src="`))
html.EscLink(w, src)
mdhtml.EscLink(w, src)
w.Write([]byte(`" alt="`))
} else {
if img.Title != nil {
w.Write([]byte(`" title="`))
html.EscapeHTML(w, img.Title)
mdhtml.EscapeHTML(w, img.Title)
}
w.Write([]byte(`" /><p>`))
}
@@ -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 <span class=" + cls + ">" + 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(
`{
<span class="`+keyCls+`">"id":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"pubkey":</span> <span class="text-zinc-500 dark:text-zinc-50">"%s"</span>,
<span class="`+keyCls+`">"created_at":</span> <span class="text-green-600">%d</span>,
<span class="`+keyCls+`">"kind":</span> <span class="text-amber-500 dark:text-amber-200">%d</span>,
<span class="`+keyCls+`">"tags":</span> %s,
<span class="`+keyCls+`">"content":</span> <span class="text-zinc-500 dark:text-zinc-50">%s</span>,
<span class="`+keyCls+`">"sig":</span> <span class="text-zinc-500 dark:text-zinc-50 content">"%s"</span>
}`, evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsHTML, html.EscapeString(string(contentJSON)), evt.Sig),
)
}