mirror of
https://github.com/aljazceru/njump.git
synced 2025-12-17 06:14:22 +01:00
refactor so embedded note and profile are rendered similarly to their non-embedded versions.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
templ embeddedNoteTemplate(params EmbeddedNoteParams) {
|
||||
templ embeddedNoteTemplate(params NotePageParams) {
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default text-lg font-light print:text-base sm:text-xl">
|
||||
<meta charset="UTF-8"/>
|
||||
@@ -15,9 +15,9 @@ templ embeddedNoteTemplate(params EmbeddedNoteParams) {
|
||||
<body class="relative bg-white text-gray-600 dark:bg-neutral-900 dark:text-neutral-50 print:text-black sm:items-center sm:justify-center">
|
||||
<style> ::-webkit-scrollbar { display: none; } </style>
|
||||
<div class="mx-auto w-full max-w-screen-2xl justify-between gap-10 overflow-visible px-4 pb-4 pt-4 print:w-full sm:w-11/12 md:w-10/12 lg:w-9/12">
|
||||
<a href={ templ.URL("/" + params.Url) } target="_new" class="no-underline">
|
||||
<a href={ templ.URL("/" + params.NeventNaked) } target="_blank" class="no-underline">
|
||||
<div class="w-full break-words">
|
||||
@authorHeaderTemplate(params.Metadata)
|
||||
@authorHeaderTemplate(params.Event.author)
|
||||
<div class="-ml-4 mb-6 h-1.5 w-1/3 bg-zinc-100 dark:bg-zinc-700 sm:-ml-2.5"></div>
|
||||
<article class="prose-cite:text-sm prose mb-6 leading-5 dark:prose-invert prose-headings:font-light prose-p:m-0 prose-p:mb-2 prose-blockquote:mx-0 prose-blockquote:my-8 prose-blockquote:mb-2 prose-blockquote:mt-2 prose-blockquote:border-l-05rem prose-blockquote:border-solid prose-blockquote:border-l-neutral-200 prose-blockquote:py-2 prose-blockquote:pl-4 prose-blockquote:pr-0 prose-blockquote:pt-0 prose-blockquote:font-light prose-blockquote:not-italic prose-ol:m-0 prose-ol:p-0 prose-ol:pl-4 prose-ul:m-0 prose-ul:p-0 prose-ul:pl-4 prose-li:mb-2 dark:prose-blockquote:border-l-neutral-700 sm:prose-a:text-justify">
|
||||
if params.Subject != "" {
|
||||
@@ -28,7 +28,7 @@ templ embeddedNoteTemplate(params EmbeddedNoteParams) {
|
||||
@templ.Raw(params.Content)
|
||||
</div>
|
||||
<div class="mt-2 w-full text-right text-sm text-stone-400">
|
||||
{ params.CreatedAt }
|
||||
{ params.Event.CreatedAtStr() }
|
||||
</div>
|
||||
</article>
|
||||
<div class="-ml-4 mb-6 h-1.5 w-1/3 bg-zinc-100 dark:bg-zinc-700 sm:-ml-2.5"></div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
templ embeddedProfileTemplate(params EmbeddedProfileParams) {
|
||||
templ embeddedProfileTemplate(params ProfilePageParams) {
|
||||
<!DOCTYPE html>
|
||||
<html class="theme--default text-lg font-light print:text-base sm:text-xl">
|
||||
<meta charset="UTF-8"/>
|
||||
|
||||
6
main.go
6
main.go
@@ -140,8 +140,10 @@ func main() {
|
||||
mux.HandleFunc("/e/", redirectFromESlash)
|
||||
mux.HandleFunc("/p/", redirectFromPSlash)
|
||||
mux.HandleFunc("/favicon.ico", redirectToFavicon)
|
||||
mux.HandleFunc("/embed/", renderEmbedjs)
|
||||
mux.HandleFunc("/", renderEvent)
|
||||
mux.HandleFunc("/embed/{code}", renderEmbedjs)
|
||||
mux.HandleFunc("/about", renderAbout)
|
||||
mux.HandleFunc("/{code}", renderEvent)
|
||||
mux.HandleFunc("/{$}", renderHomepage)
|
||||
|
||||
corsHandler := cors.Default().Handler(relay)
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"html"
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
)
|
||||
|
||||
func renderEmbedjs(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -13,61 +9,3 @@ func renderEmbedjs(w http.ResponseWriter, r *http.Request) {
|
||||
fileContent, _ := static.ReadFile("static/embed.js")
|
||||
w.Write(fileContent)
|
||||
}
|
||||
|
||||
func renderEmbedded(w http.ResponseWriter, r *http.Request, code string) {
|
||||
ctx := r.Context()
|
||||
|
||||
data, err := grabData(ctx, code)
|
||||
if err != nil {
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
errorTemplate(ErrorPageParams{Errors: err.Error()}).Render(ctx, w)
|
||||
return
|
||||
}
|
||||
|
||||
var subject string
|
||||
for _, tag := range data.event.Tags {
|
||||
if tag[0] == "subject" || tag[0] == "title" {
|
||||
subject = tag[1]
|
||||
}
|
||||
}
|
||||
|
||||
if data.event.Kind == 30023 || data.event.Kind == 30024 {
|
||||
data.content = mdToHTML(data.content, data.templateId == TelegramInstantView, true)
|
||||
} else {
|
||||
// first we run basicFormatting, which turns URLs into their appropriate HTML tags
|
||||
data.content = basicFormatting(html.EscapeString(data.content), true, false, false)
|
||||
// then we render quotes as HTML, which will also apply basicFormatting to all the internal quotes
|
||||
data.content = renderQuotesAsHTML(ctx, data.content, data.templateId == TelegramInstantView)
|
||||
// we must do this because inside <blockquotes> we must treat <img>s differently when telegram_instant_view
|
||||
}
|
||||
|
||||
var component templ.Component
|
||||
switch data.templateId {
|
||||
case Note:
|
||||
component = embeddedNoteTemplate(EmbeddedNoteParams{
|
||||
Content: template.HTML(data.content),
|
||||
CreatedAt: data.createdAt,
|
||||
Metadata: data.event.author,
|
||||
Subject: subject,
|
||||
Url: code,
|
||||
})
|
||||
|
||||
case Profile:
|
||||
component = embeddedProfileTemplate(EmbeddedProfileParams{
|
||||
Metadata: data.event.author,
|
||||
NormalizedAuthorWebsiteURL: normalizeWebsiteURL(data.event.author.Website),
|
||||
RenderedAuthorAboutText: template.HTML(basicFormatting(html.EscapeString(data.event.author.About), false, false, true)),
|
||||
AuthorRelays: relaysPretty(ctx, data.event.author.PubKey),
|
||||
})
|
||||
default:
|
||||
log.Error().Int("templateId", int(data.templateId)).Msg("no way to render")
|
||||
http.Error(w, "tried to render an unsupported template at render_event.go", 500)
|
||||
return
|
||||
}
|
||||
|
||||
if err := component.Render(ctx, w); err != nil {
|
||||
log.Warn().Err(err).Msg("error rendering tmpl")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -19,29 +19,11 @@ import (
|
||||
"github.com/pelletier/go-toml"
|
||||
)
|
||||
|
||||
func isValidShortcode(s string) bool {
|
||||
for _, r := range s {
|
||||
if !('a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' || r == '_') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
code := r.URL.Path[1:] // hopefully a nip19 code
|
||||
code := r.PathValue("code")
|
||||
|
||||
// it's the homepage
|
||||
if code == "" {
|
||||
renderHomepage(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if code == "about" {
|
||||
renderAbout(w, r)
|
||||
return
|
||||
}
|
||||
isEmbed := r.URL.Query().Get("embed") != ""
|
||||
|
||||
if strings.HasPrefix(code, "nostr:") {
|
||||
// remove the "nostr:" prefix
|
||||
@@ -61,7 +43,7 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// it may be a NIP-05
|
||||
if nip05.IsValidIdentifier(code) {
|
||||
renderProfile(ctx, w, code)
|
||||
renderProfile(ctx, r, w, code)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,17 +54,10 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the embed parameter is set to "yes"
|
||||
embedParam := r.URL.Query().Get("embed")
|
||||
if embedParam == "yes" {
|
||||
renderEmbedded(w, r, code)
|
||||
return
|
||||
}
|
||||
|
||||
// render npub and nprofile using a separate function
|
||||
if prefix == "npub" || prefix == "nprofile" {
|
||||
// it's a profile
|
||||
renderProfile(ctx, w, code)
|
||||
renderProfile(ctx, r, w, code)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -370,7 +345,8 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
}
|
||||
component = noteTemplate(NotePageParams{
|
||||
|
||||
params := NotePageParams{
|
||||
BaseEventPageParams: baseEventPageParams,
|
||||
OpenGraphParams: opengraph,
|
||||
HeadParams: HeadParams{
|
||||
@@ -384,7 +360,13 @@ func renderEvent(w http.ResponseWriter, r *http.Request) {
|
||||
Content: template.HTML(content),
|
||||
Cover: data.cover,
|
||||
TitleizedContent: titleizedContent,
|
||||
})
|
||||
}
|
||||
|
||||
if isEmbed {
|
||||
component = embeddedNoteTemplate(params)
|
||||
} else {
|
||||
component = noteTemplate(params)
|
||||
}
|
||||
case FileMetadata:
|
||||
opengraph.Image = data.kind1063Metadata.DisplayImage()
|
||||
params := FileMetadataPageParams{
|
||||
|
||||
@@ -8,7 +8,9 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func renderProfile(ctx context.Context, w http.ResponseWriter, code string) {
|
||||
func renderProfile(ctx context.Context, r *http.Request, w http.ResponseWriter, code string) {
|
||||
isEmbed := r.URL.Query().Get("embed") != ""
|
||||
|
||||
isSitemap := false
|
||||
if strings.HasSuffix(code, ".xml") {
|
||||
code = code[:len(code)-4]
|
||||
@@ -37,7 +39,10 @@ func renderProfile(ctx context.Context, w http.ResponseWriter, code string) {
|
||||
createdAt := profile.Event.CreatedAt.Time().Format("2006-01-02T15:04:05Z07:00")
|
||||
modifiedAt := profile.Event.CreatedAt.Time().Format("2006-01-02T15:04:05Z07:00")
|
||||
|
||||
lastNotes := authorLastNotes(ctx, profile.PubKey, isSitemap)
|
||||
var lastNotes []EnhancedEvent
|
||||
if !isEmbed {
|
||||
lastNotes = authorLastNotes(ctx, profile.PubKey, isSitemap)
|
||||
}
|
||||
|
||||
if isSitemap {
|
||||
w.Header().Add("content-type", "text/xml")
|
||||
@@ -63,8 +68,7 @@ func renderProfile(ctx context.Context, w http.ResponseWriter, code string) {
|
||||
w.Header().Set("Cache-Control", "max-age=86400")
|
||||
|
||||
nprofile := profile.Nprofile(ctx, sys, 2)
|
||||
|
||||
err = profileTemplate(ProfilePageParams{
|
||||
params := ProfilePageParams{
|
||||
HeadParams: HeadParams{IsProfile: true},
|
||||
Details: DetailsParams{
|
||||
HideDetails: true,
|
||||
@@ -94,7 +98,13 @@ func renderProfile(ctx context.Context, w http.ResponseWriter, code string) {
|
||||
return s
|
||||
},
|
||||
),
|
||||
}).Render(ctx, w)
|
||||
}
|
||||
|
||||
if isEmbed {
|
||||
err = embeddedProfileTemplate(params).Render(ctx, w)
|
||||
} else {
|
||||
err = profileTemplate(params).Render(ctx, w)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
9
utils.go
9
utils.go
@@ -550,3 +550,12 @@ func toJSONHTML(evt *nostr.Event) template.HTML {
|
||||
}`, evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsHTML, html.EscapeString(string(contentJSON)), evt.Sig),
|
||||
)
|
||||
}
|
||||
|
||||
func isValidShortcode(s string) bool {
|
||||
for _, r := range s {
|
||||
if !('a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' || r == '_') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user