tmpl migration: note.html

This commit is contained in:
fiatjaf
2023-10-21 07:45:30 -03:00
parent 493ee21465
commit 6aa1440b05
7 changed files with 171 additions and 100 deletions

View File

@@ -146,11 +146,11 @@ func grabData(ctx context.Context, code string, isProfileSitemap bool) (*Data, e
return nil, err
}
case 1, 7, 30023, 30024:
typ = "note"
templateId = Note
content = event.Content
parentNevent = getParentNevent(event)
case 6:
typ = "note"
templateId = Note
if reposted := event.Tags.GetFirst([]string{"e", ""}); reposted != nil {
original_nevent, _ := nip19.EncodeEvent((*reposted)[1], []string{}, "")
content = "Repost of nostr:" + original_nevent

View File

@@ -73,7 +73,6 @@ func main() {
"homepage": "homepage.html",
"profile": "profile.html",
"profile_sitemap": "sitemap.xml",
"note": "note.html",
"relay": "relay.html",
"relay_sitemap": "sitemap.xml",
"archive": "archive.html",

View File

@@ -54,7 +54,7 @@ var (
DetailsTemplate = tmpl.MustCompile(&DetailsPartial{})
)
//tmpl:bind footer.html
//tmpl:bind details.html
type DetailsPartial struct {
HideDetails bool
CreatedAt string
@@ -69,6 +69,21 @@ func (*DetailsPartial) TemplateText() string {
return tmplDetails
}
var (
//go:embed templates/clients.html
tmplClients string
ClientsTemplate = tmpl.MustCompile(&ClientsPartial{})
)
//tmpl:bind clients.html
type ClientsPartial struct {
Clients []ClientReference
}
func (*ClientsPartial) TemplateText() string {
return tmplClients
}
var (
//go:embed templates/footer.html
tmplFooter string
@@ -151,3 +166,43 @@ type OtherPage struct {
func (*OtherPage) TemplateText() string {
return tmplOther
}
var (
//go:embed templates/note.html
tmplNote string
NoteTemplate = tmpl.MustCompile(&NotePage{})
)
type NotePage struct {
HeadCommonPartial `tmpl:"head_common"`
TopPartial `tmpl:"top"`
DetailsPartial `tmpl:"details"`
ClientsPartial `tmpl:"clients"`
FooterPartial `tmpl:"footer"`
AuthorLong string
Content template.HTML
CreatedAt string
Description string
Image string
Metadata nostr.ProfileMetadata
Nevent string
Npub string
NpubShort string
Oembed string
ParentLink template.HTML
Proxy string
SeenOn []string
Style string
Subject string
TextImageURL string
Title string
TitleizedContent string
TwitterTitle string
Video string
VideoType string
}
func (*NotePage) TemplateText() string {
return tmplNote
}

View File

@@ -218,7 +218,7 @@ func render(w http.ResponseWriter, r *http.Request) {
// oembed discovery
oembed := ""
if data.typ == "note" {
if data.templateId == Note {
oembed = (&url.URL{
Scheme: "https",
Host: host,
@@ -289,11 +289,50 @@ func render(w http.ResponseWriter, r *http.Request) {
AuthorLong: data.authorLong,
CreatedAt: data.createdAt,
})
case Note:
err = NoteTemplate.Render(w, &NotePage{
HeadCommonPartial: HeadCommonPartial{IsProfile: false},
DetailsPartial: DetailsPartial{
HideDetails: true,
CreatedAt: data.createdAt,
KindDescription: data.kindDescription,
KindNIP: data.kindNIP,
EventJSON: string(eventJSON),
Kind: data.event.Kind,
},
ClientsPartial: ClientsPartial{
Clients: generateClientList(code, data.event),
},
AuthorLong: data.authorLong,
Content: template.HTML(data.content),
CreatedAt: data.createdAt,
Description: description,
Image: data.image,
Metadata: data.metadata,
Nevent: data.nevent,
Npub: data.npub,
NpubShort: data.npubShort,
Oembed: oembed,
ParentLink: template.HTML(
replaceNostrURLsWithTags(nostrNoteNeventMatcher, "nostr:"+data.parentNevent),
),
Proxy: "https://" + host + "/njump/proxy?src=",
SeenOn: data.relays,
Style: style,
Subject: subject,
TextImageURL: textImageURL,
Title: title,
TitleizedContent: titleizedContent,
TwitterTitle: twitterTitle,
Video: data.video,
VideoType: data.videoType,
})
case Other:
err = OtherTemplate.Render(w, &OtherPage{
HeadCommonPartial: HeadCommonPartial{IsProfile: false},
DetailsPartial: DetailsPartial{
HideDetails: false,
HideDetails: true,
CreatedAt: data.createdAt,
KindDescription: data.kindDescription,
KindNIP: data.kindNIP,

View File

@@ -1,6 +1,6 @@
<aside class="column column_clients">
<div class="title open-list">
<span class="text">Open {{.type}} in</span>
<span class="text">Open in</span>
<span class="open">
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -33,10 +33,10 @@
</span>
</div>
<div class="clients_wrapper">
{{range .clients}}
{{range .Clients}}
<div class="btn">
<a class="client" data-client="{{.Name}}" href="{{.URL}}"
><span>Open {{$.type}} in</span> {{.Name}}</a
><span>Open in</span> {{.Name}}</a
>
</div>
{{end}}

View File

@@ -1,122 +1,112 @@
<!doctype html>
<!DOCTYPE html>
<html class="theme--default">
<meta charset="UTF-8" />
<head>
<title>{{.titleizedContent}}</title>
<title>
{{.nevent | escapeString}} by {{.metadata.Name | escapeString}} is this
note nostr ”nevent"
</title>
<title>{{.TitleizedContent}}</title>
<title>{{.Nevent}} by {{.Metadata.Name}} is this note nostr ”nevent"</title>
<meta property="og:title" content="{{.title | escapeString}}" />
{{ if eq .style "twitter" }}
<meta name="twitter:title" content="{{.twitterTitle | escapeString}}" />
<meta property="og:title" content="{{.Title}}" />
{{ if eq .Style "twitter" }}
<meta name="twitter:title" content="{{.TwitterTitle}}" />
{{ end }}
<meta property="og:site_name" content="{{.authorLong | escapeString}}" />
{{ if .textImageURL }}
<meta property="og:site_name" content="{{.AuthorLong}}" />
{{ if not (eq "" .TextImageURL) }}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@nostrprotocol" />
<meta property="og:image" content="{{.textImageURL | escapeString}}" />
<meta name="twitter:image" content="{{.textImageURL | escapeString}}" />
<meta property="og:image" content="{{.TextImageURL}}" />
<meta name="twitter:image" content="{{.TextImageURL}}" />
{{ else }}
<!---->
<meta property="twitter:card" content="summary" />
{{ if .image }}
<meta property="og:image" content="{{.image | escapeString}}" />
<meta name="twitter:image" content="{{.proxy}}{{.image | escapeString}}" />
{{ end }} {{ if .video }}
<meta property="og:video" content="{{.video | escapeString}}" />
<meta property="og:video:secure_url" content="{{.video | escapeString}}" />
<meta
property="og:video:type"
content="video/{{.videoType | escapeString}}"
/>
{{ if not (eq "" .Image) }}
<meta property="og:image" content="{{.Image}}" />
<meta name="twitter:image" content="{{.Proxy}}{{.Image}}" />
{{ end }} {{ if not (eq "" .Video) }}
<meta property="og:video" content="{{.Video}}" />
<meta property="og:video:secure_url" content="{{.Video}}" />
<meta property="og:video:type" content="video/{{.VideoType}}" />
{{ end }} {{ end }}
<!---->
{{ if .description }}
<meta property="og:description" content="{{.description | escapeString}}" />
<meta
name="twitter:description"
content="{{.description | escapeString}}"
/>
{{ if not (eq "" .Description) }}
<meta property="og:description" content="{{.Description}}" />
<meta name="twitter:description" content="{{.Description}}" />
{{ end }}
<link
rel="canonical"
href="https://{{s.CanonicalHost}}/{{.nevent | escapeString }}"
/>
<link rel="canonical" href="https://njump.me/{{.Nevent }}" />
<!---->
{{ if .oembed }}
{{ if not (eq "" .Oembed) }}
<link
rel="alternate"
type="application/json+oembed"
href="{{.oembed}}&format=json"
href="{{.Oembed}}&format=json"
/>
<link
rel="alternate"
type="text/xml+oembed"
href="{{.oembed}}&format=xml"
href="{{.Oembed}}&format=xml"
/>
{{ end }} {{template "head_common.html" .}}
{{ end }}
<!---->
{{template "head_common" .}}
</head>
<body class="note">
{{template "top.html" .}}
{{template "top" .}}
<div class="container_wrapper">
<div class="container">
<div class="column column_content">
<header class="profile_intro">
<a href="/{{.npub | escapeString}}">
<a href="/{{.Npub}}">
<div class="pic-wrapper">
<img class="pic" src="{{.metadata.Picture | escapeString}}" />
<img class="pic" src="{{.Metadata.Picture}}" />
</div>
<div class="info-wrapper">
<div class="name">
{{.metadata.Name | escapeString}} {{if not (eq .metadata.Name
.metadata.DisplayName)}}
<span class="display"
>{{.metadata.DisplayName | escapeString}}</span
>
{{.Metadata.Name}}
<!---->
{{if not (eq .Metadata.Name .Metadata.DisplayName)}}
<span class="display">{{.Metadata.DisplayName}}</span>
{{end}}
</div>
<div class="npub">{{.npubShort | escapeString}}</div>
<div class="npub">{{.NpubShort}}</div>
</div>
</a>
</header>
<div class="published_at">{{.createdAt | escapeString}}</div>
<div class="published_at">{{.CreatedAt}}</div>
<div class="reply_of">
{{ if .parentNevent }} In reply to {{ printf "%s%s" "nostr:"
.parentNevent | escapeString | basicFormatting }} {{ end }}
{{ if not (eq "" .ParentLink) }} In reply to {{ .ParentLink }} {{
end }}
</div>
<div class="field separator"></div>
<article class="field content">
{{ if (not (eq .subject ""))}}
<h1>{{.subject | escapeString}}</h1>
{{ if (not (eq "" .Subject))}}
<h1>{{.Subject}}</h1>
{{ else }}
<h1 class="h">
{{.metadata.Name | escapeString}} on Nostr: {{.titleizedContent}}
{{.Metadata.Name}} on Nostr: {{.TitleizedContent}}
</h1>
{{ end }}
<!-- main content -->
{{ .content }}
{{ .Content }}
</article>
<div class="field separator"></div>
<div class="field">
<div class="label">Author Public key</div>
{{.npub | escapeString}}
{{.Npub}}
</div>
{{ if .seenOn }}
{{ if not (eq 0 (len .SeenOn)) }}
<div class="field">
<div class="label">Seen on</div>
{{ range .seenOn }}<a href="/r/{{.}}">{{.}}</a>
{{ range .SeenOn }}<a href="/r/{{.}}">{{.}}</a>
{{ end }}
</div>
{{ end }}
@@ -131,19 +121,17 @@
<label for="advanced-switch">Show more details</label>
</div>
{{template "details.html" .}}
{{template "details" .}}
<div class="field separator"></div>
</div>
{{template "column_clients.html" .}}
{{template "clients" .ClientsPartial}}
</div>
</div>
{{template "footer.html"}}
{{template "footer" .}}
<script>
{{template "scripts.js"}}
</script>
<script src="/njump/static/scripts.js"></script>
</body>
</html>

View File

@@ -226,45 +226,35 @@ func replaceURLsWithTags(input string, imageReplacementTemplate, videoReplacemen
})
}
func replaceNostrURLs(matcher *regexp.Regexp, input string, style string) string {
// Match and replace npup1, nprofile1, note1, nevent1, etc
input = matcher.ReplaceAllStringFunc(input, func(match string) string {
func replaceNostrURLsWithTags(matcher *regexp.Regexp, input string) string {
// match and replace npup1, nprofile1, note1, nevent1, etc
return matcher.ReplaceAllStringFunc(input, func(match string) string {
nip19 := match[len("nostr:"):]
first_chars := nip19[:8]
last_chars := nip19[len(nip19)-4:]
replacement := ""
if strings.HasPrefix(nip19, "npub1") || strings.HasPrefix(nip19, "nprofile1") {
if style == "tags" {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*4)
defer cancel()
name := getNameFromNip19(ctx, nip19)
replacement = fmt.Sprintf(`<a href="/%s" class="nostr" ><strong>%s</strong> (<i>%s</i>)</a>`, nip19, name, first_chars+"…"+last_chars)
} else if style == "short" {
replacement = "@" + first_chars + "…" + last_chars
} else {
replacement = nip19
}
return replacement
ctx, cancel := context.WithTimeout(context.Background(), time.Second*4)
defer cancel()
name := getNameFromNip19(ctx, nip19)
return fmt.Sprintf(`<a href="/%s" class="nostr" ><strong>%s</strong> (<i>%s</i>)</a>`, nip19, name, first_chars+"…"+last_chars)
} else {
if style == "tags" {
replacement = fmt.Sprintf(`<a href="/%s" class="nostr">%s</a>`, nip19, first_chars+"…"+last_chars)
} else if style == "short" {
replacement = "#" + first_chars + "…" + last_chars
} else {
replacement = nip19
}
return replacement
return fmt.Sprintf(`<a href="/%s" class="nostr">%s</a>`, nip19, first_chars+"…"+last_chars)
}
})
return input
}
func replaceNostrURLsWithTags(matcher *regexp.Regexp, input string) string {
return replaceNostrURLs(matcher, input, "tags")
}
func shortenNostrURLs(input string) string {
return replaceNostrURLs(nostrEveryMatcher, input, "short")
// match and replace npup1, nprofile1, note1, nevent1, etc
return nostrEveryMatcher.ReplaceAllStringFunc(input, func(match string) string {
nip19 := match[len("nostr:"):]
first_chars := nip19[:8]
last_chars := nip19[len(nip19)-4:]
if strings.HasPrefix(nip19, "npub1") || strings.HasPrefix(nip19, "nprofile1") {
return "@" + first_chars + "…" + last_chars
} else {
return "#" + first_chars + "…" + last_chars
}
})
}
func getNameFromNip19(ctx context.Context, nip19 string) string {